From bef682e5cb9c62256d46a87c21f3405890dfb775 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Wed, 30 Oct 2024 21:37:07 +0100 Subject: [PATCH] Move last opened file to workspaces table --- backend/internal/api/file_handlers.go | 21 +++++++------ backend/internal/db/migrations.go | 4 +-- backend/internal/db/users.go | 44 +++++++++------------------ backend/internal/db/workspaces.go | 17 +++++++++++ backend/internal/models/user.go | 15 +++++---- backend/internal/models/workspace.go | 9 +++--- 6 files changed, 57 insertions(+), 53 deletions(-) diff --git a/backend/internal/api/file_handlers.go b/backend/internal/api/file_handlers.go index 1a6e943..dc98752 100644 --- a/backend/internal/api/file_handlers.go +++ b/backend/internal/api/file_handlers.go @@ -120,19 +120,19 @@ func DeleteFile(fs *filesystem.FileSystem) http.HandlerFunc { func GetLastOpenedFile(db *db.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - userID, _, err := getUserAndWorkspaceIDs(r) + _, workspaceID, err := getUserAndWorkspaceIDs(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } - user, err := db.GetUserByID(userID) + filePath, err := db.GetLastOpenedFile(workspaceID) if err != nil { - http.Error(w, "Failed to get user", http.StatusInternalServerError) + http.Error(w, "Failed to get last opened file", http.StatusInternalServerError) return } - respondJSON(w, map[string]string{"lastOpenedFile": user.LastOpenedFilePath}) + respondJSON(w, map[string]string{"lastOpenedFilePath": filePath}) } } @@ -153,14 +153,15 @@ func UpdateLastOpenedFile(db *db.DB, fs *filesystem.FileSystem) http.HandlerFunc return } - // Validate that the file path is valid within the workspace - _, err = fs.ValidatePath(userID, workspaceID, requestBody.FilePath) - if err != nil { - http.Error(w, "Invalid file path", http.StatusBadRequest) - return + // Validate the file path exists in the workspace + if requestBody.FilePath != "" { + if _, err := fs.ValidatePath(userID, workspaceID, requestBody.FilePath); err != nil { + http.Error(w, "Invalid file path", http.StatusBadRequest) + return + } } - if err := db.UpdateLastOpenedFile(userID, requestBody.FilePath); err != nil { + if err := db.UpdateLastOpenedFile(workspaceID, requestBody.FilePath); err != nil { http.Error(w, "Failed to update last opened file", http.StatusInternalServerError) return } diff --git a/backend/internal/db/migrations.go b/backend/internal/db/migrations.go index 4eb9402..4b24d9c 100644 --- a/backend/internal/db/migrations.go +++ b/backend/internal/db/migrations.go @@ -22,8 +22,7 @@ var migrations = []Migration{ password_hash TEXT NOT NULL, role TEXT NOT NULL CHECK(role IN ('admin', 'editor', 'viewer')), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - last_workspace_id INTEGER, - last_opened_file_path TEXT + last_workspace_id INTEGER ); -- Create workspaces table with integrated settings @@ -32,6 +31,7 @@ var migrations = []Migration{ user_id INTEGER NOT NULL, name TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + last_opened_file_path TEXT, -- Settings fields theme TEXT NOT NULL DEFAULT 'light' CHECK(theme IN ('light', 'dark')), auto_save BOOLEAN NOT NULL DEFAULT 0, diff --git a/backend/internal/db/users.go b/backend/internal/db/users.go index 4a0251d..b2c3709 100644 --- a/backend/internal/db/users.go +++ b/backend/internal/db/users.go @@ -81,15 +81,13 @@ func (db *DB) createWorkspaceTx(tx *sql.Tx, workspace *models.Workspace) error { func (db *DB) GetUserByID(id int) (*models.User, error) { user := &models.User{} err := db.QueryRow(` - SELECT - u.id, u.email, u.display_name, u.role, u.created_at, - u.last_workspace_id, u.last_opened_file_path, - COALESCE(w.id, 0) as workspace_id - FROM users u - LEFT JOIN workspaces w ON w.id = u.last_workspace_id - WHERE u.id = ?`, id). + SELECT + id, email, display_name, role, created_at, + last_workspace_id + FROM users + WHERE id = ?`, id). Scan(&user.ID, &user.Email, &user.DisplayName, &user.Role, &user.CreatedAt, - &user.LastWorkspaceID, &user.LastOpenedFilePath, &user.LastWorkspaceID) + &user.LastWorkspaceID) if err != nil { return nil, err } @@ -98,34 +96,27 @@ func (db *DB) GetUserByID(id int) (*models.User, error) { func (db *DB) GetUserByEmail(email string) (*models.User, error) { user := &models.User{} - var lastOpenedFilePath sql.NullString err := db.QueryRow(` - SELECT - u.id, u.email, u.display_name, u.password_hash, u.role, u.created_at, - u.last_workspace_id, u.last_opened_file_path, - COALESCE(w.id, 0) as workspace_id - FROM users u - LEFT JOIN workspaces w ON w.id = u.last_workspace_id - WHERE u.email = ?`, email). + SELECT + id, email, display_name, password_hash, role, created_at, + last_workspace_id + FROM users + WHERE email = ?`, email). Scan(&user.ID, &user.Email, &user.DisplayName, &user.PasswordHash, &user.Role, &user.CreatedAt, - &user.LastWorkspaceID, &lastOpenedFilePath, &user.LastWorkspaceID) + &user.LastWorkspaceID) if err != nil { return nil, err } - if lastOpenedFilePath.Valid { - user.LastOpenedFilePath = lastOpenedFilePath.String - } else { - user.LastOpenedFilePath = "" - } + return user, nil } func (db *DB) UpdateUser(user *models.User) error { _, err := db.Exec(` UPDATE users - SET email = ?, display_name = ?, role = ?, last_workspace_id = ?, last_opened_file_path = ? + SET email = ?, display_name = ?, role = ?, last_workspace_id = ? WHERE id = ?`, - user.Email, user.DisplayName, user.Role, user.LastWorkspaceID, user.LastOpenedFilePath, user.ID) + user.Email, user.DisplayName, user.Role, user.LastWorkspaceID, user.ID) return err } @@ -134,11 +125,6 @@ func (db *DB) UpdateLastWorkspace(userID, workspaceID int) error { return err } -func (db *DB) UpdateLastOpenedFile(userID int, filePath string) error { - _, err := db.Exec("UPDATE users SET last_opened_file_path = ? WHERE id = ?", filePath, userID) - return err -} - func (db *DB) DeleteUser(id int) error { tx, err := db.Begin() if err != nil { diff --git a/backend/internal/db/workspaces.go b/backend/internal/db/workspaces.go index 344e4e2..b3264ae 100644 --- a/backend/internal/db/workspaces.go +++ b/backend/internal/db/workspaces.go @@ -160,3 +160,20 @@ func (db *DB) UpdateLastWorkspaceTx(tx *sql.Tx, userID, workspaceID int) error { _, err := tx.Exec("UPDATE users SET last_workspace_id = ? WHERE id = ?", workspaceID, userID) return err } + +func (db *DB) UpdateLastOpenedFile(workspaceID int, filePath string) error { + _, err := db.Exec("UPDATE workspaces SET last_opened_file_path = ? WHERE id = ?", filePath, workspaceID) + return err +} + +func (db *DB) GetLastOpenedFile(workspaceID int) (string, error) { + var filePath sql.NullString + err := db.QueryRow("SELECT last_opened_file_path FROM workspaces WHERE id = ?", workspaceID).Scan(&filePath) + if err != nil { + return "", err + } + if !filePath.Valid { + return "", nil + } + return filePath.String, nil +} diff --git a/backend/internal/models/user.go b/backend/internal/models/user.go index 8881601..e2efcbb 100644 --- a/backend/internal/models/user.go +++ b/backend/internal/models/user.go @@ -17,14 +17,13 @@ const ( ) type User struct { - ID int `json:"id" validate:"required,min=1"` - Email string `json:"email" validate:"required,email"` - DisplayName string `json:"displayName"` - PasswordHash string `json:"-"` - Role UserRole `json:"role" validate:"required,oneof=admin editor viewer"` - CreatedAt time.Time `json:"createdAt"` - LastWorkspaceID int `json:"lastWorkspaceId"` - LastOpenedFilePath string `json:"lastOpenedFilePath"` + ID int `json:"id" validate:"required,min=1"` + Email string `json:"email" validate:"required,email"` + DisplayName string `json:"displayName"` + PasswordHash string `json:"-"` + Role UserRole `json:"role" validate:"required,oneof=admin editor viewer"` + CreatedAt time.Time `json:"createdAt"` + LastWorkspaceID int `json:"lastWorkspaceId"` } func (u *User) Validate() error { diff --git a/backend/internal/models/workspace.go b/backend/internal/models/workspace.go index 28f1bc5..16e9081 100644 --- a/backend/internal/models/workspace.go +++ b/backend/internal/models/workspace.go @@ -5,10 +5,11 @@ import ( ) type Workspace struct { - ID int `json:"id" validate:"required,min=1"` - UserID int `json:"userId" validate:"required,min=1"` - Name string `json:"name" validate:"required"` - CreatedAt time.Time `json:"createdAt"` + ID int `json:"id" validate:"required,min=1"` + UserID int `json:"userId" validate:"required,min=1"` + Name string `json:"name" validate:"required"` + CreatedAt time.Time `json:"createdAt"` + LastOpenedFilePath string `json:"lastOpenedFilePath"` // Integrated settings Theme string `json:"theme" validate:"oneof=light dark"`