diff --git a/server/internal/db/sessions.go b/server/internal/db/sessions.go index 66c148b..bdf55db 100644 --- a/server/internal/db/sessions.go +++ b/server/internal/db/sessions.go @@ -11,7 +11,7 @@ import ( // CreateSession inserts a new session record into the database func (db *database) CreateSession(session *models.Session) error { query, err := NewQuery(db.dbType). - InsertStruct(session, "sessions") + InsertStruct(session, "sessions", db.secretsService) if err != nil { return fmt.Errorf("failed to create query: %w", err) } diff --git a/server/internal/db/struct_query.go b/server/internal/db/struct_query.go index c18b6d5..68fc7a3 100644 --- a/server/internal/db/struct_query.go +++ b/server/internal/db/struct_query.go @@ -2,6 +2,7 @@ package db import ( "fmt" + "lemma/internal/secrets" "reflect" "strings" "unicode" @@ -14,7 +15,7 @@ type DBField struct { useDefault bool } -func StructTagsToFields(s any) ([]DBField, error) { +func StructTagsToFields(s any, secretsService secrets.Service) ([]DBField, error) { v := reflect.ValueOf(s) if v.Kind() == reflect.Ptr { @@ -49,6 +50,8 @@ func StructTagsToFields(s any) ([]DBField, error) { } useDefault := false + value := v.Field(i).Interface() + if strings.Contains(tag, ",") { parts := strings.Split(tag, ",") tag = parts[0] @@ -61,13 +64,19 @@ func StructTagsToFields(s any) ([]DBField, error) { } case "default": useDefault = true + case "encrypted": + val, err := secretsService.Encrypt(value.(string)) + if err != nil { + return nil, fmt.Errorf("failed to encrypt field %s: %w", f.Name, err) + } + value = val } } } fields = append(fields, DBField{ Name: tag, - Value: v.Field(i).Interface(), + Value: value, Type: f.Type, useDefault: useDefault, }) @@ -91,8 +100,8 @@ func toSnakeCase(s string) string { return res } -func (q *Query) InsertStruct(s any, table string) (*Query, error) { - fields, err := StructTagsToFields(s) +func (q *Query) InsertStruct(s any, table string, secretsService secrets.Service) (*Query, error) { + fields, err := StructTagsToFields(s, secretsService) if err != nil { return nil, err } diff --git a/server/internal/db/users.go b/server/internal/db/users.go index b326949..ed792d6 100644 --- a/server/internal/db/users.go +++ b/server/internal/db/users.go @@ -18,7 +18,7 @@ func (db *database) CreateUser(user *models.User) (*models.User, error) { defer tx.Rollback() query, err := NewQuery(db.dbType). - InsertStruct(user, "users") + InsertStruct(user, "users", db.secretsService) if err != nil { return nil, fmt.Errorf("failed to create query: %w", err) @@ -73,7 +73,7 @@ func (db *database) createWorkspaceTx(tx *sql.Tx, workspace *models.Workspace) e log := getLogger().WithGroup("users") insertQuery, err := NewQuery(db.dbType). - InsertStruct(workspace, "workspaces") + InsertStruct(workspace, "workspaces", db.secretsService) if err != nil { return fmt.Errorf("failed to create query: %w", err) diff --git a/server/internal/db/workspaces.go b/server/internal/db/workspaces.go index dc07911..120033f 100644 --- a/server/internal/db/workspaces.go +++ b/server/internal/db/workspaces.go @@ -19,15 +19,8 @@ func (db *database) CreateWorkspace(workspace *models.Workspace) error { workspace.SetDefaultSettings() } - // Encrypt token if present - encryptedToken, err := db.encryptToken(workspace.GitToken) - if err != nil { - return fmt.Errorf("failed to encrypt token: %w", err) - } - workspace.GitToken = encryptedToken - query, err := NewQuery(db.dbType). - InsertStruct(workspace, "workspaces") + InsertStruct(workspace, "workspaces", db.secretsService) if err != nil { return fmt.Errorf("failed to create query: %w", err) diff --git a/server/internal/models/session.go b/server/internal/models/session.go index 305dd85..60652a7 100644 --- a/server/internal/models/session.go +++ b/server/internal/models/session.go @@ -5,7 +5,7 @@ import "time" // Session represents a user session in the database type Session struct { - ID string `db:"id,default"` // Unique session identifier + ID string `db:"id"` // Unique session identifier UserID int `db:"user_id"` // ID of the user this session belongs to RefreshToken string `db:"refresh_token"` // The refresh token associated with this session ExpiresAt time.Time `db:"expires_at"` // When this session expires diff --git a/server/internal/models/workspace.go b/server/internal/models/workspace.go index 886847b..083a14e 100644 --- a/server/internal/models/workspace.go +++ b/server/internal/models/workspace.go @@ -17,9 +17,9 @@ type Workspace struct { AutoSave bool `json:"autoSave" db:"auto_save"` ShowHiddenFiles bool `json:"showHiddenFiles" db:"show_hidden_files"` GitEnabled bool `json:"gitEnabled" db:"git_enabled"` - GitURL string `json:"gitUrl" db:"git_url" validate:"required_if=GitEnabled true"` - GitUser string `json:"gitUser" db:"git_user" validate:"required_if=GitEnabled true"` - GitToken string `json:"gitToken" db:"git_token" validate:"required_if=GitEnabled true"` + GitURL string `json:"gitUrl" db:"git_url,ommitempty" validate:"required_if=GitEnabled true"` + GitUser string `json:"gitUser" db:"git_user,ommitempty" validate:"required_if=GitEnabled true"` + GitToken string `json:"gitToken" db:"git_token,ommitempty,encrypted" validate:"required_if=GitEnabled true"` GitAutoCommit bool `json:"gitAutoCommit" db:"git_auto_commit"` GitCommitMsgTemplate string `json:"gitCommitMsgTemplate" db:"git_commit_msg_template"` GitCommitName string `json:"gitCommitName" db:"git_commit_name"`