diff --git a/folders/folders.go b/folders/folders.go index ed5cae86fc1f0cd53066f06394cef3e6d0e8e625..d05a5e6c46e918c6fc43dbf546f5eaf06bbbbd33 100644 --- a/folders/folders.go +++ b/folders/folders.go @@ -104,6 +104,10 @@ func IsFolderAccess(name, login string) bool { // IsFolderOwner checks if a user is a folder owner. func IsFolderOwner(folder, login string) bool { ctx := storage.Context() + admin, _ := this.Q.IsUserAdmin(ctx, login) + if admin == 1 { + return true + } found, _ := this.Q.IsFolderOwner(ctx, storage.IsFolderOwnerParams{ Folder: folder, Login: login, diff --git a/repl/command.go b/repl/command.go index e6c448805cbe187606b2efe4a712b843a36ff329..e4b9031651650138a684cf00af0b863d8c8f8058 100644 --- a/repl/command.go +++ b/repl/command.go @@ -270,14 +270,6 @@ BULLCOM.CLD.`, OptArg: true, Default: "14", }, - "/ID": { - Description: ` Designates that the name specified as the owner name is a rights - identifier. The creator's process must have the identifier presently - assigned to it. Any process which has that identifier assigned to it - will be able to control the folder as if it were the folder's owner. - This is used to allow more than one use to control a folder.`, - OptArg: true, - }, "/NOTIFY": { Description: ` Specifies that all users automatically have NOTIFY set for this folder. Only a privileged user can use this qualifier. (See HELP SET @@ -286,8 +278,7 @@ BULLCOM.CLD.`, "/OWNER": { Description: `/OWNER=username - Specifies the owner of the folder. This is a privileged command. See - also /ID.`, + Specifies the owner of the folder. This is a privileged command.`, OptArg: true, }, "/PRIVATE": { @@ -602,15 +593,6 @@ of the folder or a user with privileges can use this command. "/DESCRIPTION": { Description: ` Specifies a new description for the folder. You will be prompted for the text of the description.`, - }, - "/ID": { - Description: ` Designates that the name specified as the owner name is a rights - identifier. The creator's process must have the identifier presently - assigned to it. Any process which has that identifier assigned to it - will be able to control the folder as if it were the folder's owner. - This is used to allow more than one use to control a folder. - - Note: This feature will not work during remote access to the folder.`, }, "/NAME": { Description: `/NAME=foldername @@ -623,7 +605,7 @@ of the folder or a user with privileges can use this command. Specifies a new owner for the folder. If the owner does not have privileges, BULLETIN will prompt for the password of the new owner - account in order to okay the modification. See also /ID.`, + account in order to okay the modification.`, OptArg: true, }, }, @@ -1196,11 +1178,11 @@ READNEW setting (and visa versa). Description: ` Specifies that the SET BRIEF option is the default for all users for the specified folder. This is a privileged qualifier.`, }, - "/DEFAULT": { - Description: ` Specifies that the BRIEF option is the default for the specified - folder. This is a privileged qualifier. It will only affect brand new - users (or those that have never logged in). Use /ALL to modify all - users.`, + "/FOLDER": { + Description: `/FOLDER=foldername + + Specifies the folder for which the option is to modified. If not + specified, the selected folder is modified.`, }, "/PERMANENT": { Description: `/[NO]PERMANENT @@ -1221,12 +1203,6 @@ privileged qualifier.`, "/ALL": { Description: ` Specifies that the SET NOBRIEF option is the default for all users for the specified folder. This is a privileged qualifier.`, - }, - "/DEFAULT": { - Description: ` Specifies that the NOBRIEF option is the default for the specified - folder. This is a privileged qualifier. It will only affect brand new - users (or those that have never logged in). Use /ALL to modify all - users.`, }, "/FOLDER": { Description: `/FOLDER=foldername @@ -1337,6 +1313,7 @@ PROMPT_EXPIRE is the default. Format: SET PROMPT_EXPIRE`, + Action: ActionSetPromptExpire, }, "NOPROMPT_EXPIRE": { Description: `The user will not be prompted, and the default expiration (which is set @@ -1344,6 +1321,7 @@ by SET DEFAULT_EXPIRE) will be used. Format: SET NOPROMPT_EXPIRE`, + Action: ActionSetNoPromptExpire, }, "READNEW": { Description: `Controls whether you will be prompted upon logging in if you wish to @@ -1367,10 +1345,17 @@ present in those other folders. Also, it is not possible to EXIT the READNEW mode if there are SYSTEM folders which have new messages. Typing the EXIT command will cause you to skip to those folders. (See HELP SET SYSTEM for a description of a SYSTEM folder).`, + Action: ActionSetReadNew, Flags: dclish.Flags{ "/ALL": { Description: ` Specifies that the SET READNEW option is the default for all users for the specified folder. This is a privileged qualifier.`, + }, + "/FOLDER": { + Description: `/FOLDER=foldername + + Specifies the folder for which the option is to modified. If not + specified, the selected folder is modified.`, }, "/PERMANENT": { Description: `/[NO]PERMANENT @@ -1384,6 +1369,7 @@ SYSTEM for a description of a SYSTEM folder).`, Description: `Turns off READNEW. Format: SET NOREADNEW`, + Action: ActionSetNoReadNew, Flags: dclish.Flags{ "/ALL": { Description: ` Specifies that the SET NOREADNEW option is the default for all users @@ -1414,6 +1400,12 @@ In order to apply this to a specific folder, first select the folder "/ALL": { Description: ` Specifies that the SET SHOWNEW option is the default for all users for the specified folder. This is a privileged qualifier.`, + }, + "/FOLDER": { + Description: `/FOLDER=foldername + + Specifies the folder for which the option is to modified. If not + specified, the selected folder is modified.`, }, "/PERMANENT": { Description: `/[NO]PERMANENT diff --git a/repl/folders.go b/repl/folders.go index dc67560d00bf770bbf4b735a2de45aeb09b4356d..c8c1e5b509931f9cf920e7668ea4f01675795b20 100644 --- a/repl/folders.go +++ b/repl/folders.go @@ -38,7 +38,7 @@ func ActionCreate(cmd *dclish.Command) error { options.Always = 1 } if cmd.Flags["/BRIEF"].Value == "true" { - options.Brief = 1 + options.Alert = 1 } if cmd.Flags["/DESCRIPTION"].Value != "" { options.Description = cmd.Flags["/DESCRIPTION"].Value @@ -47,10 +47,10 @@ func ActionCreate(cmd *dclish.Command) error { options.Notify = 1 } if cmd.Flags["/READNEW"].Value == "true" { - options.Readnew = 1 + options.Alert = 2 } if cmd.Flags["/SHOWNEW"].Value == "true" { - options.Shownew = 1 + options.Alert = 3 } if cmd.Flags["/SYSTEM"].Value == "true" { options.System = 1 @@ -62,6 +62,11 @@ func ActionCreate(cmd *dclish.Command) error { } options.Expire = int64(expire) } + if (cmd.Flags["/BRIEF"].Set && cmd.Flags["/READNEW"].Set) || + (cmd.Flags["/BRIEF"].Set && cmd.Flags["/SHOWNEW"].Set) || + (cmd.Flags["/READNEW"].Set && cmd.Flags["/SHOWNEW"].Set) { + return errors.New("Can only set one of /BRIEF, /READNEW and /SHOWNEW") + } options.Visibility = folders.FolderPublic if cmd.Flags["/PRIVATE"].Value == "true" && cmd.Flags["/SEMIPRIVATE"].Value == "true" { return errors.New("Private or semi-private - pick one") @@ -92,7 +97,6 @@ func ActionCreate(cmd *dclish.Command) error { return errors.New("Description must exist and be under 53 characters") } err := folders.CreateFolder(owner, options) - // TODO: handle the /ID flag. return err } diff --git a/repl/set.go b/repl/set.go index b41e963ac23063c024828bce5dbb416afd6af0fc..3cd9b8a78f7c6fa9961960cdbdcfda6160505730 100644 --- a/repl/set.go +++ b/repl/set.go @@ -13,6 +13,47 @@ import ( "git.lyda.ie/kevin/bulletin/this" ) +func setAlert(cmd *dclish.Command, alert int64) error { + optAll := cmd.Flags["/ALL"].Value == "true" + + optPerm := false + if f, ok := cmd.Flags["/PERMANENT"]; ok { + optPerm = f.Value == "true" + } + + folder := this.Folder + if cmd.Flags["/FOLDER"].Value != "" { + folder = folders.FindFolder(cmd.Flags["/FOLDER"].Value) + } + if folder.Name == "" { + return errors.New("Folder does not exist") + } + + if optAll || optPerm { + if !folders.IsFolderOwner(folder.Name, this.User.Login) { + return errors.New("Not an admin or folder owner") + } + } + + ctx := storage.Context() + if optAll && optPerm { + return this.Q.UpdateFolderAlert(ctx, storage.UpdateFolderAlertParams{ + Alert: alert + 3, + Name: folder.Name, + }) + } + if optAll { + return this.Q.UpdateFolderAlert(ctx, storage.UpdateFolderAlertParams{ + Alert: alert, + Name: folder.Name, + }) + } + return this.Q.UpdateUserAlert(ctx, storage.UpdateUserAlertParams{ + Alert: alert, + Login: this.User.Login, + }) +} + // ActionSet handles the `SET` command. func ActionSet(cmd *dclish.Command) error { fmt.Println(cmd.Description) @@ -46,25 +87,13 @@ func ActionSetNoalways(_ *dclish.Command) error { } // ActionSetBrief handles the `SET BRIEF` command. -func ActionSetBrief(_ *dclish.Command) error { - // TODO: parse flags. - ctx := storage.Context() - this.Q.UpdateFolderBrief(ctx, storage.UpdateFolderBriefParams{ - Brief: 1, - Name: this.Folder.Name, - }) - return nil +func ActionSetBrief(cmd *dclish.Command) error { + return setAlert(cmd, storage.AlertBrief) } // ActionSetNobrief handles the `SET NOBRIEF` command. -func ActionSetNobrief(_ *dclish.Command) error { - // TODO: parse flags. - ctx := storage.Context() - this.Q.UpdateFolderBrief(ctx, storage.UpdateFolderBriefParams{ - Brief: 1, - Name: this.Folder.Name, - }) - return nil +func ActionSetNobrief(cmd *dclish.Command) error { + return setAlert(cmd, storage.AlertNone) } // ActionSetDefaultExpire handles the `SET DEFAULT_EXPIRE` command. @@ -140,76 +169,44 @@ func ActionSetNonotify(_ *dclish.Command) error { return nil } -// ActionSetPrivileges handles the `SET PRIVILEGES` command. -func ActionSetPrivileges(cmd *dclish.Command) error { - // TODO: OK, need a better parser. - switch cmd.Args[0] { - case "CREATE": - if len(cmd.Args) != 2 { - fmt.Println("ERROR: Must pass single login.") - return nil - } - fmt.Println("TODO: Create user creation routine - see repl/repl.go.") - case "DELETE": - if len(cmd.Args) != 2 { - fmt.Println("ERROR: Must pass single login.") - return nil - } - fmt.Println("TODO: Create user delete routine - see repl/repl.go.") - case "SSH": - fmt.Println("TODO: Create ssh routine.") - case "ADMIN": - fmt.Println("TODO: Create an admin bit set/unset routine.") - case "NOADMIN": - fmt.Println("TODO: Create an admin bit set/unset routine.") - case "MOD": - fmt.Println("TODO: Create a mod bit set/unset routine.") - case "NOMOD": - fmt.Println("TODO: Create a mod bit set/unset routine.") - case "ENABLE": - fmt.Println("TODO: Create a disable bit set/unset routine.") - case "DISABLE": - fmt.Println("TODO: Create a disable bit set/unset routine.") - default: - fmt.Println("ERROR: Command not understood.") - } - return nil -} - // ActionSetPromptExpire handles the `SET PROMPT_EXPIRE` command. func ActionSetPromptExpire(_ *dclish.Command) error { - fmt.Println("TODO: implement ActionSetPromptExpire.") + ctx := storage.Context() + this.Q.UpdateUserPrompt(ctx, storage.UpdateUserPromptParams{ + Login: this.User.Login, + Prompt: 1, + }) return nil } // ActionSetNoPromptExpire handles the `SET NOPROMPT_EXPIRE` command. func ActionSetNoPromptExpire(_ *dclish.Command) error { - fmt.Println("TODO: implement ActionSetNopromptExpire.") + ctx := storage.Context() + this.Q.UpdateUserPrompt(ctx, storage.UpdateUserPromptParams{ + Login: this.User.Login, + Prompt: 0, + }) return nil } // ActionSetReadNew handles the `SET READNEW` command. -func ActionSetReadNew(_ *dclish.Command) error { - fmt.Println("TODO: implement ActionSetReadNew.") - return nil +func ActionSetReadNew(cmd *dclish.Command) error { + return setAlert(cmd, storage.AlertReadNew) } // ActionSetNoReadNew handles the `SET READNEW` command. -func ActionSetNoReadNew(_ *dclish.Command) error { - fmt.Println("TODO: implement ActionSetNoReadNew.") - return nil +func ActionSetNoReadNew(cmd *dclish.Command) error { + return setAlert(cmd, storage.AlertNone) } // ActionSetShowNew handles the `SET SHOWNEW` command. -func ActionSetShowNew(_ *dclish.Command) error { - fmt.Println("TODO: implement ActionSetShowNew.") - return nil +func ActionSetShowNew(cmd *dclish.Command) error { + return setAlert(cmd, storage.AlertShowNew) } // ActionSetNoShowNew handles the `SET SHOWNEW` command. -func ActionSetNoShowNew(_ *dclish.Command) error { - fmt.Println("TODO: implement ActionSetNoShowNew.") - return nil +func ActionSetNoShowNew(cmd *dclish.Command) error { + return setAlert(cmd, storage.AlertNone) } // ActionSetSystem handles the `SET SYSTEM` command. diff --git a/repl/show.go b/repl/show.go index e4c090e92b04f4e87d4858c0a4a9b7aad3c3528b..fdcd1c049d061b934e3a7779f0394a84e023fc11 100644 --- a/repl/show.go +++ b/repl/show.go @@ -28,16 +28,9 @@ func ActionShowFlags(_ *dclish.Command) error { fmt.Println(" NOTIFY is set.") flagset = true } - if this.Folder.Readnew != 0 { - fmt.Println(" READNEW is set.") - flagset = true - } - if this.Folder.Brief != 0 { - fmt.Println(" BRIEF is set.") - flagset = true - } - if this.Folder.Shownew != 0 { - fmt.Println(" SHOWNEW is set.") + if this.Folder.Alert != 0 { + fmt.Printf(" %s is set.\n", + strings.ToUpper(storage.AlertString(this.Folder.Alert))) flagset = true } if !flagset { @@ -100,14 +93,9 @@ func ActionShowFolder(cmd *dclish.Command) error { if this.Folder.Notify != 0 { fmt.Println(" Default is NOTIFY.") } - if this.Folder.Readnew != 0 { - fmt.Println(" Default is READNEW.") - } - if this.Folder.Brief != 0 { - fmt.Println(" Default is BRIEF.") - } - if this.Folder.Shownew != 0 { - fmt.Println(" Default is SHOWNEW.") + if this.Folder.Alert != 0 { + fmt.Printf(" %s is set.\n", + strings.ToUpper(storage.AlertString(this.Folder.Alert))) } return nil diff --git a/storage/display.go b/storage/display.go index b995426bb3c58a04078b96ca9a57dbeab80ae0b6..607b781412ff7bac94c0a38b88eefdf481203f94 100644 --- a/storage/display.go +++ b/storage/display.go @@ -6,6 +6,48 @@ import ( "time" ) +// Alert values. +const ( + AlertNone int64 = iota + AlertBrief + AlertReadNew + AlertShowNew + AlertBriefPerm + AlertReadNewPerm + AlertShowNewPerm +) + +// AlertString translates an alert number to a string. +func AlertString(alert int64) string { + var as = []string{ + "None", + "Brief", + "ReadNew", + "ShowNew", + } + if alert < 0 || alert >= int64(len(as)) { + return "Unknown" + } + return as[alert] +} + +// FolderAlertString translates an alert number to a string. +func FolderAlertString(alert int64) string { + var as = []string{ + "None", + "Brief", + "ReadNew", + "ShowNew", + "Brief (permanent)", + "ReadNew (permanent)", + "ShowNew (permanent)", + } + if alert < 0 || alert >= int64(len(as)) { + return "Unknown" + } + return as[alert] +} + // String renders a message. func (m *Message) String() string { buf := &strings.Builder{} @@ -37,26 +79,25 @@ func (m *Message) OneLine(expire bool) string { // String displays a user (mainly used for debugging). func (u User) String() string { - return fmt.Sprintf("%-12s %-25.25s [a%d, m%d, !%d, d%d] [%s]", + return fmt.Sprintf("%-12s %-25.25s [a%d, m%d, !%d, d%d, p%d] [%s]", u.Login, u.Name, u.Admin, u.Moderator, u.Alert, u.Disabled, + u.Prompt, u.LastLogin.Format("06-01-02 15:04:05")) } // String displays a folder (mainly used for debugging). func (f Folder) String() string { - return fmt.Sprintf("Folder %s (%s) [a%d, b%d, n%d, rn%d, sn%d, sys%d, exp%d, v%d]", + return fmt.Sprintf("Folder %s (%s) [a%d, !<%s>, n%d, sys%d, exp%d, v%d]", f.Name, f.Description, f.Always, - f.Brief, + FolderAlertString(f.Alert), f.Notify, - f.Readnew, - f.Shownew, f.System, f.Expire, f.Visibility) diff --git a/storage/folders.sql.go b/storage/folders.sql.go index 7476fc84eb5a23ee0deaccb009f5d4abaf003895..c24ab006ce87366837486ab4533af63127163386 100644 --- a/storage/folders.sql.go +++ b/storage/folders.sql.go @@ -24,22 +24,18 @@ func (q *Queries) AddFolderOwner(ctx context.Context, arg AddFolderOwnerParams) } const createFolder = `-- name: CreateFolder :exec -INSERT INTO folders ( - name, always, brief, description, notify, readnew, shownew, system, - expire, visibility -) VALUES ( - ?, ?, ?, ?, ?, ?, ?, ?, ?, ? -) +INSERT INTO folders + (name, always, alert, description, notify, system, expire, visibility) + VALUES + (?, ?, ?, ?, ?, ?, ?, ?) ` type CreateFolderParams struct { Name string Always int64 - Brief int64 + Alert int64 Description string Notify int64 - Readnew int64 - Shownew int64 System int64 Expire int64 Visibility int64 @@ -49,11 +45,9 @@ func (q *Queries) CreateFolder(ctx context.Context, arg CreateFolderParams) erro _, err := q.db.ExecContext(ctx, createFolder, arg.Name, arg.Always, - arg.Brief, + arg.Alert, arg.Description, arg.Notify, - arg.Readnew, - arg.Shownew, arg.System, arg.Expire, arg.Visibility, @@ -62,7 +56,7 @@ func (q *Queries) CreateFolder(ctx context.Context, arg CreateFolderParams) erro } const findFolderExact = `-- name: FindFolderExact :one -SELECT name, "always", brief, description, notify, readnew, shownew, system, expire, visibility, create_at, update_at FROM folders where name = ? +SELECT name, "always", alert, description, notify, system, expire, visibility, create_at, update_at FROM folders where name = ? ` func (q *Queries) FindFolderExact(ctx context.Context, name string) (Folder, error) { @@ -71,11 +65,9 @@ func (q *Queries) FindFolderExact(ctx context.Context, name string) (Folder, err err := row.Scan( &i.Name, &i.Always, - &i.Brief, + &i.Alert, &i.Description, &i.Notify, - &i.Readnew, - &i.Shownew, &i.System, &i.Expire, &i.Visibility, @@ -86,7 +78,7 @@ func (q *Queries) FindFolderExact(ctx context.Context, name string) (Folder, err } const findFolderPrefix = `-- name: FindFolderPrefix :one -SELECT name, "always", brief, description, notify, readnew, shownew, system, expire, visibility, create_at, update_at FROM folders where name LIKE ? +SELECT name, "always", alert, description, notify, system, expire, visibility, create_at, update_at FROM folders where name LIKE ? ORDER BY name LIMIT 1 ` @@ -97,11 +89,9 @@ func (q *Queries) FindFolderPrefix(ctx context.Context, name string) (Folder, er err := row.Scan( &i.Name, &i.Always, - &i.Brief, + &i.Alert, &i.Description, &i.Notify, - &i.Readnew, - &i.Shownew, &i.System, &i.Expire, &i.Visibility, @@ -227,31 +217,31 @@ func (q *Queries) ListFolderForAdmin(ctx context.Context) ([]ListFolderForAdminR return items, nil } -const updateFolderAlways = `-- name: UpdateFolderAlways :exec -UPDATE folders SET always = ? WHERE name = ? +const updateFolderAlert = `-- name: UpdateFolderAlert :exec +UPDATE folders SET alert = ? WHERE name = ? ` -type UpdateFolderAlwaysParams struct { - Always int64 - Name string +type UpdateFolderAlertParams struct { + Alert int64 + Name string } -func (q *Queries) UpdateFolderAlways(ctx context.Context, arg UpdateFolderAlwaysParams) error { - _, err := q.db.ExecContext(ctx, updateFolderAlways, arg.Always, arg.Name) +func (q *Queries) UpdateFolderAlert(ctx context.Context, arg UpdateFolderAlertParams) error { + _, err := q.db.ExecContext(ctx, updateFolderAlert, arg.Alert, arg.Name) return err } -const updateFolderBrief = `-- name: UpdateFolderBrief :exec -UPDATE folders SET brief = ? WHERE name = ? +const updateFolderAlways = `-- name: UpdateFolderAlways :exec +UPDATE folders SET always = ? WHERE name = ? ` -type UpdateFolderBriefParams struct { - Brief int64 - Name string +type UpdateFolderAlwaysParams struct { + Always int64 + Name string } -func (q *Queries) UpdateFolderBrief(ctx context.Context, arg UpdateFolderBriefParams) error { - _, err := q.db.ExecContext(ctx, updateFolderBrief, arg.Brief, arg.Name) +func (q *Queries) UpdateFolderAlways(ctx context.Context, arg UpdateFolderAlwaysParams) error { + _, err := q.db.ExecContext(ctx, updateFolderAlways, arg.Always, arg.Name) return err } @@ -283,34 +273,6 @@ func (q *Queries) UpdateFolderNotify(ctx context.Context, arg UpdateFolderNotify return err } -const updateFolderReadnew = `-- name: UpdateFolderReadnew :exec -UPDATE folders SET readnew = ? WHERE name = ? -` - -type UpdateFolderReadnewParams struct { - Readnew int64 - Name string -} - -func (q *Queries) UpdateFolderReadnew(ctx context.Context, arg UpdateFolderReadnewParams) error { - _, err := q.db.ExecContext(ctx, updateFolderReadnew, arg.Readnew, arg.Name) - return err -} - -const updateFolderShownew = `-- name: UpdateFolderShownew :exec -UPDATE folders SET shownew = ? WHERE name = ? -` - -type UpdateFolderShownewParams struct { - Shownew int64 - Name string -} - -func (q *Queries) UpdateFolderShownew(ctx context.Context, arg UpdateFolderShownewParams) error { - _, err := q.db.ExecContext(ctx, updateFolderShownew, arg.Shownew, arg.Name) - return err -} - const updateFolderSystem = `-- name: UpdateFolderSystem :exec UPDATE folders SET system = ? WHERE name = ? ` diff --git a/storage/migrations/1_create_table.up.sql b/storage/migrations/1_create_table.up.sql index 690387f3681729ea3eee826d5ea6c1fbe6f86f6c..9ce50b932e9b810659a5c7e2b840074270bc8800 100644 --- a/storage/migrations/1_create_table.up.sql +++ b/storage/migrations/1_create_table.up.sql @@ -3,8 +3,10 @@ CREATE TABLE users ( name VARCHAR(53) NOT NULL, admin INT DEFAULT 0 NOT NULL, moderator INT DEFAULT 0 NOT NULL, - alert INT DEFAULT 0 NOT NULL, --- 0=no, 1=brief, 2=readnew + --- 0=no, 1=brief, 2=readnew, 3=shownew + alert INT DEFAULT 0 NOT NULL, disabled INT DEFAULT 0 NOT NULL, + prompt INT DEFAULT 0 NOT NULL, last_broadcast TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, @@ -35,11 +37,10 @@ END; CREATE TABLE folders ( name VARCHAR(25) PRIMARY KEY NOT NULL, always INT DEFAULT 0 NOT NULL, - brief INT DEFAULT 0 NOT NULL, + --- 0=no, 1(4)=brief(p), 2(5)=readnew(p), 3(6)=shownew(p) + alert INT DEFAULT 0 NOT NULL, description VARCHAR(53) DEFAULT 0 NOT NULL, notify INT DEFAULT 0 NOT NULL, - readnew INT DEFAULT 0 NOT NULL, - shownew INT DEFAULT 0 NOT NULL, system INT DEFAULT 0 NOT NULL, expire INT DEFAULT 14 NOT NULL, --- public=0, semiprivate=1, private=2 @@ -174,7 +175,8 @@ CREATE TABLE folder_configs ( folder VARCHAR(25) REFERENCES folders(name) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL, always INT DEFAULT 0 NOT NULL, - alert INT DEFAULT 0 NOT NULL, --- 0=no, 1=brief, 2=readnew + --- 0=no, 1=brief, 2=readnew, 3=shownew + alert INT DEFAULT 0 NOT NULL, PRIMARY KEY (login, folder) ) WITHOUT ROWID; diff --git a/storage/models.go b/storage/models.go index 98bbe360c232fa796eb495e419b8b6b4c34d8542..2c0d9c0cc6a133dc1a5c05aa0591475ccf321951 100644 --- a/storage/models.go +++ b/storage/models.go @@ -18,11 +18,9 @@ type Broadcast struct { type Folder struct { Name string Always int64 - Brief int64 + Alert int64 Description string Notify int64 - Readnew int64 - Shownew int64 System int64 Expire int64 Visibility int64 @@ -89,6 +87,7 @@ type User struct { Moderator int64 Alert int64 Disabled int64 + Prompt int64 LastBroadcast time.Time LastLogin time.Time CreateAt time.Time diff --git a/storage/queries/folders.sql b/storage/queries/folders.sql index 3c5f8a26b8c9ebb4304d3eb55853e83e25d793f9..9f7e956081ec075a796dd9782864ff069265ad4a 100644 --- a/storage/queries/folders.sql +++ b/storage/queries/folders.sql @@ -1,10 +1,8 @@ -- name: CreateFolder :exec -INSERT INTO folders ( - name, always, brief, description, notify, readnew, shownew, system, - expire, visibility -) VALUES ( - ?, ?, ?, ?, ?, ?, ?, ?, ?, ? -); +INSERT INTO folders + (name, always, alert, description, notify, system, expire, visibility) + VALUES + (?, ?, ?, ?, ?, ?, ?, ?); -- name: AddFolderOwner :exec INSERT INTO owners (folder, login) VALUES (?, ?); @@ -45,18 +43,12 @@ UPDATE folders SET always = ? WHERE name = ?; -- name: UpdateFolderSystem :exec UPDATE folders SET system = ? WHERE name = ?; --- name: UpdateFolderBrief :exec -UPDATE folders SET brief = ? WHERE name = ?; +-- name: UpdateFolderAlert :exec +UPDATE folders SET alert = ? WHERE name = ?; -- name: UpdateFolderNotify :exec UPDATE folders SET notify = ? WHERE name = ?; --- name: UpdateFolderReadnew :exec -UPDATE folders SET readnew = ? WHERE name = ?; - --- name: UpdateFolderShownew :exec -UPDATE folders SET shownew = ? WHERE name = ?; - -- name: UpdateFolderVisibility :exec UPDATE folders SET visibility = ? WHERE name = ?; diff --git a/storage/queries/seed.sql b/storage/queries/seed.sql index 5772eb0de26d41dd8ac541482fa5e0d8927afa0d..8d765435fe9e9f04912a94d338f1a366ac94c16d 100644 --- a/storage/queries/seed.sql +++ b/storage/queries/seed.sql @@ -1,18 +1,17 @@ -- name: SeedUserSystem :exec - INSERT INTO users (login, name, admin, moderator) - VALUES ('SYSTEM', 'System User', 1, 1); +INSERT INTO users (login, name, admin, moderator) + VALUES ('SYSTEM', 'System User', 1, 1); -- name: SeedFolderGeneral :exec - INSERT INTO folders (name, description, system, shownew) - VALUES ('GENERAL', 'Default general bulletin folder.', 1, 1); +INSERT INTO folders (name, description, system, alert) + VALUES ('GENERAL', 'Default general bulletin folder.', 1, 1); -- name: SeedGeneralOwner :exec - INSERT INTO owners (folder, login) VALUES ('GENERAL', 'SYSTEM'); +INSERT INTO owners (folder, login) VALUES ('GENERAL', 'SYSTEM'); -- name: SeedCreateMessage :exec -INSERT INTO messages ( - id, - folder, author, subject, message, permanent, create_at, update_at, expiration -) VALUES ( - (SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?1), - ?1, ?2, ?3, ?4, 1, ?5, ?5, ?6); +INSERT INTO messages + (id, folder, author, subject, message, permanent, create_at, update_at, expiration) + VALUES + ((SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?1), + ?1, ?2, ?3, ?4, 1, ?5, ?5, ?6); diff --git a/storage/queries/users.sql b/storage/queries/users.sql index d87b01581a25271c33d11dd8a5e0146593dcd12c..ad343c7fb00d5c1d505fdffa7410dc19cac90d29 100644 --- a/storage/queries/users.sql +++ b/storage/queries/users.sql @@ -23,6 +23,9 @@ UPDATE users SET name = ? WHERE login = ? AND login != 'SYSTEM'; -- name: UpdateUserMod :exec UPDATE users SET moderator = ? WHERE login = ? AND login != 'SYSTEM'; +-- name: UpdateUserPrompt :exec +UPDATE users SET prompt = ? WHERE login = ? AND login != 'SYSTEM'; + -- name: UpdateUserLastLogin :one UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE login = ? AND login != 'SYSTEM' RETURNING last_login; diff --git a/storage/seed.sql.go b/storage/seed.sql.go index 0f21d68ea537349116887b5424832bb4378128d2..e33741e616e5f530fd041938e36f4fd25e47494c 100644 --- a/storage/seed.sql.go +++ b/storage/seed.sql.go @@ -11,12 +11,11 @@ import ( ) const seedCreateMessage = `-- name: SeedCreateMessage :exec -INSERT INTO messages ( - id, - folder, author, subject, message, permanent, create_at, update_at, expiration -) VALUES ( - (SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?1), - ?1, ?2, ?3, ?4, 1, ?5, ?5, ?6) +INSERT INTO messages + (id, folder, author, subject, message, permanent, create_at, update_at, expiration) + VALUES + ((SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?1), + ?1, ?2, ?3, ?4, 1, ?5, ?5, ?6) ` type SeedCreateMessageParams struct { @@ -41,8 +40,8 @@ func (q *Queries) SeedCreateMessage(ctx context.Context, arg SeedCreateMessagePa } const seedFolderGeneral = `-- name: SeedFolderGeneral :exec - INSERT INTO folders (name, description, system, shownew) - VALUES ('GENERAL', 'Default general bulletin folder.', 1, 1) +INSERT INTO folders (name, description, system, alert) + VALUES ('GENERAL', 'Default general bulletin folder.', 1, 1) ` func (q *Queries) SeedFolderGeneral(ctx context.Context) error { @@ -51,7 +50,7 @@ func (q *Queries) SeedFolderGeneral(ctx context.Context) error { } const seedGeneralOwner = `-- name: SeedGeneralOwner :exec - INSERT INTO owners (folder, login) VALUES ('GENERAL', 'SYSTEM') +INSERT INTO owners (folder, login) VALUES ('GENERAL', 'SYSTEM') ` func (q *Queries) SeedGeneralOwner(ctx context.Context) error { @@ -60,8 +59,8 @@ func (q *Queries) SeedGeneralOwner(ctx context.Context) error { } const seedUserSystem = `-- name: SeedUserSystem :exec - INSERT INTO users (login, name, admin, moderator) - VALUES ('SYSTEM', 'System User', 1, 1) +INSERT INTO users (login, name, admin, moderator) + VALUES ('SYSTEM', 'System User', 1, 1) ` func (q *Queries) SeedUserSystem(ctx context.Context) error { diff --git a/storage/standard.sql.go b/storage/standard.sql.go index be420e6a039caaa49d4dc16689a8bf454050a882..ea36c688a1a1f2d19e1a6104269888325e5dcd07 100644 --- a/storage/standard.sql.go +++ b/storage/standard.sql.go @@ -209,7 +209,7 @@ func (q *Queries) DeleteUser(ctx context.Context, login string) error { } const getFolder = `-- name: GetFolder :one -SELECT name, "always", brief, description, notify, readnew, shownew, system, expire, visibility, create_at, update_at FROM folders WHERE name = ? +SELECT name, "always", alert, description, notify, system, expire, visibility, create_at, update_at FROM folders WHERE name = ? ` func (q *Queries) GetFolder(ctx context.Context, name string) (Folder, error) { @@ -218,11 +218,9 @@ func (q *Queries) GetFolder(ctx context.Context, name string) (Folder, error) { err := row.Scan( &i.Name, &i.Always, - &i.Brief, + &i.Alert, &i.Description, &i.Notify, - &i.Readnew, - &i.Shownew, &i.System, &i.Expire, &i.Visibility, @@ -460,7 +458,7 @@ func (q *Queries) ListFolderConfig(ctx context.Context) ([]FolderConfig, error) } const listFolders = `-- name: ListFolders :many -SELECT name, "always", brief, description, notify, readnew, shownew, system, expire, visibility, create_at, update_at FROM folders +SELECT name, "always", alert, description, notify, system, expire, visibility, create_at, update_at FROM folders ` func (q *Queries) ListFolders(ctx context.Context) ([]Folder, error) { @@ -475,11 +473,9 @@ func (q *Queries) ListFolders(ctx context.Context) ([]Folder, error) { if err := rows.Scan( &i.Name, &i.Always, - &i.Brief, + &i.Alert, &i.Description, &i.Notify, - &i.Readnew, - &i.Shownew, &i.System, &i.Expire, &i.Visibility, @@ -662,7 +658,7 @@ func (q *Queries) ListSeen(ctx context.Context) ([]Seen, error) { } const listUsers = `-- name: ListUsers :many -SELECT login, name, admin, moderator, alert, disabled, last_broadcast, last_login, create_at, update_at FROM users +SELECT login, name, admin, moderator, alert, disabled, prompt, last_broadcast, last_login, create_at, update_at FROM users ` func (q *Queries) ListUsers(ctx context.Context) ([]User, error) { @@ -681,6 +677,7 @@ func (q *Queries) ListUsers(ctx context.Context) ([]User, error) { &i.Moderator, &i.Alert, &i.Disabled, + &i.Prompt, &i.LastBroadcast, &i.LastLogin, &i.CreateAt, diff --git a/storage/users.sql.go b/storage/users.sql.go index 613b4c13abc8ecd3ccfa6ad4efe0c7b1ca8a7996..b80de521290a6b25f3c341e952782c6556ff7004 100644 --- a/storage/users.sql.go +++ b/storage/users.sql.go @@ -12,7 +12,7 @@ import ( const addUser = `-- name: AddUser :one INSERT INTO users (login, name, admin, disabled, last_login) VALUES (?, ?, ?, ?, ?) -RETURNING login, name, admin, moderator, alert, disabled, last_broadcast, last_login, create_at, update_at +RETURNING login, name, admin, moderator, alert, disabled, prompt, last_broadcast, last_login, create_at, update_at ` type AddUserParams struct { @@ -39,6 +39,7 @@ func (q *Queries) AddUser(ctx context.Context, arg AddUserParams) (User, error) &i.Moderator, &i.Alert, &i.Disabled, + &i.Prompt, &i.LastBroadcast, &i.LastLogin, &i.CreateAt, @@ -128,7 +129,7 @@ func (q *Queries) GetLastLoginByLogin(ctx context.Context, login string) (GetLas } const getUser = `-- name: GetUser :one -SELECT login, name, admin, moderator, alert, disabled, last_broadcast, last_login, create_at, update_at FROM users WHERE login = ? +SELECT login, name, admin, moderator, alert, disabled, prompt, last_broadcast, last_login, create_at, update_at FROM users WHERE login = ? ` func (q *Queries) GetUser(ctx context.Context, login string) (User, error) { @@ -141,6 +142,7 @@ func (q *Queries) GetUser(ctx context.Context, login string) (User, error) { &i.Moderator, &i.Alert, &i.Disabled, + &i.Prompt, &i.LastBroadcast, &i.LastLogin, &i.CreateAt, @@ -241,3 +243,17 @@ func (q *Queries) UpdateUserName(ctx context.Context, arg UpdateUserNameParams) _, err := q.db.ExecContext(ctx, updateUserName, arg.Name, arg.Login) return err } + +const updateUserPrompt = `-- name: UpdateUserPrompt :exec +UPDATE users SET prompt = ? WHERE login = ? AND login != 'SYSTEM' +` + +type UpdateUserPromptParams struct { + Prompt int64 + Login string +} + +func (q *Queries) UpdateUserPrompt(ctx context.Context, arg UpdateUserPromptParams) error { + _, err := q.db.ExecContext(ctx, updateUserPrompt, arg.Prompt, arg.Login) + return err +}