This commit is contained in:
+58
-1
@@ -30,6 +30,21 @@ type User struct {
|
||||
Active bool
|
||||
}
|
||||
|
||||
type Workspace struct {
|
||||
ID int64
|
||||
Name string
|
||||
Slug string
|
||||
CreatedAt string
|
||||
}
|
||||
|
||||
type WorkspaceMember struct {
|
||||
WorkspaceID int64
|
||||
UserID int64
|
||||
Role string
|
||||
Workspace Workspace
|
||||
User User
|
||||
}
|
||||
|
||||
type Attendance struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
@@ -187,6 +202,19 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
active INTEGER NOT NULL DEFAULT 1 CHECK(active IN (0,1)),
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS workspaces (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS workspace_members (
|
||||
workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL DEFAULT 'member' CHECK(role IN ('member','admin')),
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(workspace_id,user_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS oauth_accounts (
|
||||
provider TEXT NOT NULL,
|
||||
provider_user_id TEXT NOT NULL,
|
||||
@@ -312,8 +340,14 @@ CREATE INDEX IF NOT EXISTS idx_board_task_tags_tag ON board_task_tags(tag_id,tas
|
||||
}
|
||||
_, err = s.db.Exec(`INSERT INTO users(username,password_hash,display_name,email,role) VALUES(?,?,?,?,?)`,
|
||||
"admin", hash, "Workspace Admin", "admin@localhost", "admin")
|
||||
return err
|
||||
if err != nil { return err }
|
||||
}
|
||||
var workspaceCount int
|
||||
if err := s.db.QueryRow(`SELECT COUNT(*) FROM workspaces`).Scan(&workspaceCount); err != nil { return err }
|
||||
if workspaceCount == 0 {
|
||||
if _, err := s.db.Exec(`INSERT INTO workspaces(name,slug) VALUES(?,?)`, "Hamkar workspace", "hamkar"); err != nil { return err }
|
||||
}
|
||||
if _, err := s.db.Exec(`INSERT OR IGNORE INTO workspace_members(workspace_id,user_id,role) SELECT w.id,u.id,u.role FROM workspaces w CROSS JOIN users u`); err != nil { return err }
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -529,6 +563,29 @@ func (s *Store) Users() ([]User, error) {
|
||||
return s.users(false)
|
||||
}
|
||||
|
||||
func (s *Store) Workspaces(userID int64) ([]Workspace, error) {
|
||||
rows, err := s.db.Query(`SELECT w.id,w.name,w.slug,w.created_at FROM workspaces w JOIN workspace_members m ON m.workspace_id=w.id WHERE m.user_id=? ORDER BY w.name`, userID)
|
||||
if err != nil { return nil, err }
|
||||
defer rows.Close()
|
||||
var out []Workspace
|
||||
for rows.Next() { var w Workspace; if err := rows.Scan(&w.ID,&w.Name,&w.Slug,&w.CreatedAt); err != nil { return nil, err }; out = append(out,w) }
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *Store) CreateWorkspace(name, slug string, ownerID int64) (int64, error) {
|
||||
result, err := s.db.Exec(`INSERT INTO workspaces(name,slug) VALUES(?,?)`, strings.TrimSpace(name), strings.TrimSpace(strings.ToLower(slug)))
|
||||
if err != nil { return 0, err }
|
||||
id, err := result.LastInsertId(); if err != nil { return 0, err }
|
||||
_, err = s.db.Exec(`INSERT INTO workspace_members(workspace_id,user_id,role) VALUES(?,?, 'admin')`, id, ownerID)
|
||||
return id, err
|
||||
}
|
||||
|
||||
func (s *Store) WorkspaceMember(workspaceID, userID int64) (WorkspaceMember, error) {
|
||||
var m WorkspaceMember
|
||||
err := s.db.QueryRow(`SELECT w.id,w.name,w.slug,w.created_at,u.id,u.username,u.display_name,u.email,u.role,u.avatar_url,u.active,m.role FROM workspaces w JOIN workspace_members m ON m.workspace_id=w.id JOIN users u ON u.id=m.user_id WHERE w.id=? AND u.id=?`, workspaceID,userID).Scan(&m.Workspace.ID,&m.Workspace.Name,&m.Workspace.Slug,&m.Workspace.CreatedAt,&m.User.ID,&m.User.Username,&m.User.DisplayName,&m.User.Email,&m.User.Role,&m.User.AvatarURL,&m.User.Active,&m.Role)
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (s *Store) ActiveUsers() ([]User, error) {
|
||||
return s.users(true)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user