This repository has been archived on 2024-10-20. You can view files and clone it, but cannot push or open issues or pull requests.
burgerbackup/bin/server/main.go

162 lines
6.0 KiB
Go

package main
import (
"concord.hectabit.org/Hectabit/burgerbackup/lib/common"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"golang.org/x/crypto/argon2"
"io"
"log"
"mime/multipart"
"net/http"
"os"
"strconv"
"time"
)
func main() {
if _, err := os.Stat("config.ini"); err == nil {
log.Println("[INFO] Config loaded at", time.Now().Unix())
} else if os.IsNotExist(err) {
log.Fatalln("[FATAL] config.ini does not exist")
} else {
log.Fatalln("[FATAL] File is in quantum uncertainty:", err)
}
viper.SetConfigName("config")
viper.AddConfigPath("./")
viper.AutomaticEnv()
err := viper.ReadInConfig()
if err != nil {
log.Fatalln("[FATAL] Error in config file at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
}
backupKey := viper.GetString("BACKUP_KEY")
cryptoKey := viper.GetString("CRYPTO_KEY")
port := viper.GetInt("PORT")
host := viper.GetString("HOST")
backupFolder := viper.GetString("BACKUP_FOLDER")
if host == "" {
log.Fatalln("[FATAL] HOST is not set")
}
if port == 0 {
log.Fatalln("[FATAL] PORT is not set")
}
if backupKey == "" {
log.Fatalln("[FATAL] BACKUP_KEY is not set")
} else if backupKey == "supersecretkey" {
log.Println("[WARN] SECRET_KEY is set to a default value. Please set it to another value.")
}
if cryptoKey == "" {
log.Fatalln("[FATAL] CRYPTO_KEY is not set")
} else if cryptoKey == "supersecretkey" {
log.Println("[WARN] SECRET_KEY is set to a default value. If it is also set to this on the client, please set both to another value.")
}
if _, err := os.Stat(backupFolder); os.IsNotExist(err) {
log.Println("[INFO] Backup folder does not exist, creating")
if err := os.Mkdir(backupFolder, 0755); err != nil {
log.Fatalln("[FATAL] Could not create backup folder:", err)
}
}
gin.SetMode(gin.ReleaseMode)
router := gin.Default()
router.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Headers", "*, Authorization")
c.Writer.Header().Set("Access-Control-Allow-Methods", "*")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(200)
return
}
c.Next()
})
router.POST("/api/backup", func(c *gin.Context) {
clientBackupKey := c.GetHeader("Authorization")
if clientBackupKey == "" {
c.JSON(400, gin.H{"error": "BackupKey not found", "goErr": "backupKey not found"})
return
}
var authenticated bool
authenticated, err = common.VerifyHash(clientBackupKey, backupKey)
if err != nil {
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerbackup and refer to the documentation for more info. Your error code is: UNKNOWN-API-BACKUP-VERIFYERR", "goErr": err.Error()})
log.Println("[ERROR] Error in /api/backup hash verify:", err)
return
}
if authenticated {
file, err := c.FormFile("file")
if err != nil {
if errors.Is(err, http.ErrMissingFile) {
c.JSON(400, gin.H{"error": "No file uploaded", "goErr": err.Error()})
} else {
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerbackup and refer to the documentation for more info. Your error code is: UNKNOWN-API-BACKUP-FILEERR", "goErr": err.Error()})
log.Println("[ERROR] Error in /api/backup file upload:", err)
}
return
}
fileName := "database_" + strconv.FormatInt(time.Now().Unix(), 10) + ".db"
encryptedFile, err := file.Open()
if err != nil {
c.JSON(422, gin.H{"error": "Could not open file", "goErr": err.Error()})
}
defer func(encryptedFile multipart.File) {
err := encryptedFile.Close()
if err != nil {
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerbackup and refer to the documentation for more info. Your error code is: UNKNOWN-API-BACKUP-FILEDEFERERR", "goErr": err.Error()})
log.Println("[ERROR] Error in /api/backup file defer:", err)
return
}
}(encryptedFile)
encryptedData, err := io.ReadAll(encryptedFile)
if err != nil {
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerbackup and refer to the documentation for more info. Your error code is: UNKNOWN-API-BACKUP-FILECONTENTERR", "goErr": err.Error()})
log.Println("[ERROR] Error in /api/backup file read:", err)
return
}
cryptoKeyHashed := argon2.IDKey([]byte(cryptoKey), []byte("burgerbackup"), 1, 64*1024, 4, 32)
decryptedData, err := common.DecryptAES(cryptoKeyHashed, encryptedData)
if err != nil {
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerbackup and refer to the documentation for more info. Your error code is: UNKNOWN-API-BACKUP-DECRYPTERR", "goErr": err.Error()})
log.Println("[ERROR] Error in /api/backup file decrypt:", err)
return
}
filePath := backupFolder + "/" + fileName
if err := os.WriteFile(filePath, decryptedData, 0644); err != nil {
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerbackup and refer to the documentation for more info. Your error code is: UNKNOWN-API-BACKUP-WRITEERR", "goErr": err.Error()})
log.Println("[ERROR] Error in /api/backup file write:", err)
return
}
fmt.Println("[INFO] Received and decrypted backup from", c.ClientIP())
c.JSON(200, gin.H{"success": "true", "timeTaken": time.Now().Unix(), "goErr": ""})
} else {
c.JSON(401, gin.H{"error": "Incorrect backup key", "goErr": "incorrect backup key"})
}
})
log.Println("[INFO] Server started at", time.Now().Unix())
log.Println("[INFO] Welcome to Burgerbackup! Today we are running on IP " + host + " on port " + strconv.Itoa(port) + ".")
err = router.Run(host + ":" + strconv.Itoa(port))
if err != nil {
log.Fatalln("[FATAL] Server failed to begin operations at", time.Now().Unix(), err)
}
}