diff --git a/backend/api/backup.go b/backend/api/backup.go index 5e19c60..b208744 100644 --- a/backend/api/backup.go +++ b/backend/api/backup.go @@ -3,6 +3,7 @@ package main import ( "compress/gzip" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" "io" @@ -222,11 +223,18 @@ func backupRestoreEntrypoint(cCtx *cli.Context) error { username = *user.Username } + bcryptPassword, err := hex.DecodeString(user.Password) + + if err != nil { + log.Errorf("Failed to decode hex encoded password: %s", err.Error()) + continue + } + userDatabase := &dbcore.User{ Email: user.Email, Username: username, Name: user.Name, - Password: user.Password, + Password: base64.StdEncoding.EncodeToString(bcryptPassword), IsBot: user.IsBot, Tokens: tokens, @@ -235,6 +243,7 @@ func backupRestoreEntrypoint(cCtx *cli.Context) error { if err := dbcore.DB.Create(userDatabase).Error; err != nil { log.Errorf("Failed to create user: %s", err.Error()) + continue } if uint(bestEffortOwnerUIDFromBackup) == user.ID { @@ -255,6 +264,7 @@ func backupRestoreEntrypoint(cCtx *cli.Context) error { if err := dbcore.DB.Create(backendDatabase).Error; err != nil { log.Errorf("Failed to create backend: %s", err.Error()) + continue } log.Infof("Migrating proxies for backend ID '%d'", backend.ID) diff --git a/backend/api/controllers/v1/backends/remove.go b/backend/api/controllers/v1/backends/remove.go index a44946d..e1ea599 100644 --- a/backend/api/controllers/v1/backends/remove.go +++ b/backend/api/controllers/v1/backends/remove.go @@ -69,7 +69,7 @@ func RemoveBackend(c *gin.Context) { backendRequest := dbcore.DB.Where("id = ?", req.BackendID).Find(&backend) if backendRequest.Error != nil { - log.Warnf("failed to find if backend exists or not: %s", backendRequest.Error) + log.Warnf("failed to find if backend exists or not: %s", backendRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if backend exists", diff --git a/backend/api/controllers/v1/proxies/connections.go b/backend/api/controllers/v1/proxies/connections.go index 7a4585b..68e3639 100644 --- a/backend/api/controllers/v1/proxies/connections.go +++ b/backend/api/controllers/v1/proxies/connections.go @@ -87,7 +87,7 @@ func GetConnections(c *gin.Context) { proxyRequest := dbcore.DB.Where("id = ?", req.Id).First(&proxy) if proxyRequest.Error != nil { - log.Warnf("failed to find proxy: %s", proxyRequest.Error) + log.Warnf("failed to find proxy: %s", proxyRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find forward entry", diff --git a/backend/api/controllers/v1/proxies/create.go b/backend/api/controllers/v1/proxies/create.go index bc710b4..40cea76 100644 --- a/backend/api/controllers/v1/proxies/create.go +++ b/backend/api/controllers/v1/proxies/create.go @@ -84,7 +84,7 @@ func CreateProxy(c *gin.Context) { backendRequest := dbcore.DB.Where("id = ?", req.ProviderID).First(&backend) if backendRequest.Error != nil { - log.Warnf("failed to find if backend exists or not: %s", backendRequest.Error) + log.Warnf("failed to find if backend exists or not: %s", backendRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if backend exists", diff --git a/backend/api/controllers/v1/proxies/remove.go b/backend/api/controllers/v1/proxies/remove.go index 75e3b66..c1b68f3 100644 --- a/backend/api/controllers/v1/proxies/remove.go +++ b/backend/api/controllers/v1/proxies/remove.go @@ -69,7 +69,7 @@ func RemoveProxy(c *gin.Context) { proxyRequest := dbcore.DB.Where("id = ?", req.ID).Find(&proxy) if proxyRequest.Error != nil { - log.Warnf("failed to find if proxy exists or not: %s", proxyRequest.Error) + log.Warnf("failed to find if proxy exists or not: %s", proxyRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if forward rule exists", diff --git a/backend/api/controllers/v1/proxies/start.go b/backend/api/controllers/v1/proxies/start.go index 1aedbfc..ff3e65c 100644 --- a/backend/api/controllers/v1/proxies/start.go +++ b/backend/api/controllers/v1/proxies/start.go @@ -69,7 +69,7 @@ func StartProxy(c *gin.Context) { proxyRequest := dbcore.DB.Where("id = ?", req.ID).Find(&proxy) if proxyRequest.Error != nil { - log.Warnf("failed to find if proxy exists or not: %s", proxyRequest.Error) + log.Warnf("failed to find if proxy exists or not: %s", proxyRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if forward rule exists", diff --git a/backend/api/controllers/v1/proxies/stop.go b/backend/api/controllers/v1/proxies/stop.go index 6bbcfef..c3562a5 100644 --- a/backend/api/controllers/v1/proxies/stop.go +++ b/backend/api/controllers/v1/proxies/stop.go @@ -69,7 +69,7 @@ func StopProxy(c *gin.Context) { proxyRequest := dbcore.DB.Where("id = ?", req.ID).Find(&proxy) if proxyRequest.Error != nil { - log.Warnf("failed to find if proxy exists or not: %s", proxyRequest.Error) + log.Warnf("failed to find if proxy exists or not: %s", proxyRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if forward rule exists", diff --git a/backend/api/controllers/v1/users/create.go b/backend/api/controllers/v1/users/create.go index 55d2a3b..92cb543 100644 --- a/backend/api/controllers/v1/users/create.go +++ b/backend/api/controllers/v1/users/create.go @@ -59,7 +59,7 @@ func CreateUser(c *gin.Context) { userRequest := dbcore.DB.Where("email = ? OR username = ?", req.Email, req.Username).Find(&user) if userRequest.Error != nil { - log.Warnf("failed to find if user exists or not: %s", userRequest.Error) + log.Warnf("failed to find if user exists or not: %s", userRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if user exists", diff --git a/backend/api/controllers/v1/users/login.go b/backend/api/controllers/v1/users/login.go index 2f9922f..1db7a81 100644 --- a/backend/api/controllers/v1/users/login.go +++ b/backend/api/controllers/v1/users/login.go @@ -65,7 +65,7 @@ func LoginUser(c *gin.Context) { userRequest := dbcore.DB.Where(userFindRequest, userFindRequestArguments...).Find(&user) if userRequest.Error != nil { - log.Warnf("failed to find if user exists or not: %s", userRequest.Error) + log.Warnf("failed to find if user exists or not: %s", userRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if user exists", @@ -88,7 +88,7 @@ func LoginUser(c *gin.Context) { _, err := base64.StdEncoding.Decode(decodedPassword, []byte(user.Password)) if err != nil { - log.Warnf("failed to decode password in database: %s", userRequest.Error) + log.Warnf("failed to decode password in database: %s", err.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to parse database result for password", diff --git a/backend/api/controllers/v1/users/refresh.go b/backend/api/controllers/v1/users/refresh.go index e89611b..1bb9c1f 100644 --- a/backend/api/controllers/v1/users/refresh.go +++ b/backend/api/controllers/v1/users/refresh.go @@ -39,7 +39,7 @@ func RefreshUserToken(c *gin.Context) { tokenRequest := dbcore.DB.Where("token = ?", req.Token).Find(&tokenInDatabase) if tokenRequest.Error != nil { - log.Warnf("failed to find if token exists or not: %s", tokenRequest.Error) + log.Warnf("failed to find if token exists or not: %s", tokenRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if token exists", @@ -79,7 +79,7 @@ func RefreshUserToken(c *gin.Context) { userRequest := dbcore.DB.Where("id = ?", tokenInDatabase.UserID).Find(&user) if tokenRequest.Error != nil { - log.Warnf("failed to find if token user or not: %s", userRequest.Error) + log.Warnf("failed to find if token user or not: %s", userRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find user", diff --git a/backend/api/controllers/v1/users/remove.go b/backend/api/controllers/v1/users/remove.go index 4824907..7edcf81 100644 --- a/backend/api/controllers/v1/users/remove.go +++ b/backend/api/controllers/v1/users/remove.go @@ -77,7 +77,7 @@ func RemoveUser(c *gin.Context) { userRequest := dbcore.DB.Where("id = ?", uid).Find(customUser) if userRequest.Error != nil { - log.Warnf("failed to find if user exists or not: %s", userRequest.Error) + log.Warnf("failed to find if user exists or not: %s", userRequest.Error.Error()) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find if user exists", diff --git a/backend/api/jwtcore/jwt.go b/backend/api/jwtcore/jwt.go index 40c3412..44c0f05 100644 --- a/backend/api/jwtcore/jwt.go +++ b/backend/api/jwtcore/jwt.go @@ -77,7 +77,7 @@ func GetUserFromJWT(token string) (*dbcore.User, error) { userRequest := dbcore.DB.Preload("Permissions").Where("id = ?", uint(uid)).Find(&user) if userRequest.Error != nil { - return user, fmt.Errorf("failed to find if user exists or not: %s", userRequest.Error) + return user, fmt.Errorf("failed to find if user exists or not: %s", userRequest.Error.Error()) } userExists := userRequest.RowsAffected > 0 diff --git a/docs/nextnet_to_hermes_migration.md b/docs/nextnet_to_hermes_migration.md index 7c3d2b3..0447469 100644 --- a/docs/nextnet_to_hermes_migration.md +++ b/docs/nextnet_to_hermes_migration.md @@ -31,3 +31,13 @@ Below are new environment variables that may need to be set up: 9. If successful, remove the environment variable `HERMES_MIGRATE_POSTGRES_DATABASE`. 10. Switch the API docker image from `ghcr.io/imterah/hermes-backend-migration:latest` to `ghcr.io/imterah/hermes:latest`. 11. Start the backend. +## Failed Migration / Manual Restoration Steps +1. Get to step 4 in the ordinary migration setps. +2. Add the `entrypoint` option in the API compose section, and set it to `/bin/bash` +3. Add the `command` option in the API compose section, and set it to `"-c 'sleep 10000'"` +4. Get a shell in the container (likely named `nextnet-api`): `docker exec -it nextnet-api /bin/bash` +5. Copy the base64 section (excluding the `BEGIN` and `END` portions) of the backup, and run the following command to begin the transfer: `cat >> /tmp/db.json.gz.b64 << EOF` +6. Paste in the base64 data, and then press enter, type `EOF`, and then press enter again. This should return you to the shell prompt. +7. Decode the base64 backup: `cat /tmp/db.json.gz.b64 | base64 -d > /tmp/db.json.gz` +8. Run the migration script: `./entrypoint.sh` +9. When done, remove the `entrypoint` and `command` sections, and then jump to step 9 in the ordinary migration steps.