Loading folders/folders.go +22 −2 Original line number Diff line number Diff line Loading @@ -46,6 +46,13 @@ const ( FolderPrivate int64 = 2 ) // Values for CreateFolder setting. const ( CreateFolderAdmins int64 = 0 CreateFolderOwners int64 = 1 CreateFolderAnyone int64 = 2 ) // CreateFolder creates a new folder. func CreateFolder(login string, options storage.CreateFolderParams) error { if !IsAlphaNum(options.Name) { Loading @@ -57,9 +64,22 @@ func CreateFolder(login string, options storage.CreateFolderParams) error { if err != nil { return err } switch this.System.CreateFolder { case CreateFolderAnyone: // Anyone can create folders. case CreateFolderOwners: if admin != 1 { owned, err := this.Q.IsAnyFolderOwner(ctx, login) if err != nil || owned != 1 { return errors.New("only admins or folder owners can create folders") } } default: // CreateFolderAdmins if admin != 1 { return errors.New("only admins can create folders") } } options.Name = strings.ToUpper(options.Name) Loading repl/command.go +30 −8 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ The folder-name is limited to 25 letters and must not include spaces or characters that are also invalid in filenames (this is because the folder is stored in a file name created with the folder name). NOTE: Creation of folders is a privileged command.`, NOTE: Who can create folders depends on the SET CREATE policy.`, Action: ActionCreate, MinArgs: 1, MaxArgs: 1, Loading Loading @@ -1158,14 +1158,29 @@ characteristics of the BULLETIN Utility. The following options are available: ACCESS ALWAYS BRIEF DEFAULT_EXPIRE EXPIRE_LIMIT FOLDER NOACCESS NOALWAYS NOBRIEF NOPROMPT_EXPIRE NOREADNEW NOSHOWNEW NOSYSTEM PROMPT_EXPIRE READNEW REGISTRATION SHOWNEW SHIBBOLETH SYSTEM ACCESS ALWAYS BRIEF CREATE DEFAULT_EXPIRE EXPIRE_LIMIT FOLDER NOACCESS NOALWAYS NOBRIEF NOPROMPT_EXPIRE NOREADNEW NOSHOWNEW NOSYSTEM PROMPT_EXPIRE READNEW REGISTRATION SHOWNEW SHIBBOLETH SYSTEM `, Action: ActionSet, Commands: dclish.Commands{ "CREATE": { Description: `Controls who is allowed to create new folders. Format: SET CREATE ANYONE|OWNERS|ADMINS ANYONE - Any user can create a folder. OWNERS - Admins and existing folder owners can create a folder. ADMINS - Only admins can create a folder (default). This is a privileged command.`, MinArgs: 1, MaxArgs: 1, Action: ActionSetCreate, }, "REGISTRATION": { Description: `Controls open registration. When open, unknown SSH keys can self-onboard via the AuthorizedKeysCommand flow. Loading Loading @@ -1551,11 +1566,18 @@ that folder cannot be removed.`, The following options are available: FLAGS FOLDER NEW PRIVILEGES SYSTEM USER VERSION CREATE FLAGS FOLDER NEW PRIVILEGES SYSTEM USER VERSION `, Action: ActionShow, Commands: dclish.Commands{ "CREATE": { Description: `Shows the current folder creation policy. Format: SHOW CREATE`, Action: ActionShowCreate, }, "FLAGS": { Description: `Shows whether BRIEF, READNEW, or SHOWNEW has been set for the currently selected folder. Loading repl/set.go +35 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,41 @@ func ActionSetNosystem(_ *dclish.Command) error { return this.Q.UpdateFolderSystem(ctx, 0, this.Folder.Name) } // ActionSetCreate handles the `SET CREATE` command. func ActionSetCreate(cmd *dclish.Command) error { if this.User.Admin == 0 { return errors.New("privileges needed for changing defaults") } if len(cmd.Args) != 1 { fmt.Println("Usage: SET CREATE ANYONE|OWNERS|ADMINS") return nil } ctx := storage.Context() switch strings.ToUpper(cmd.Args[0]) { case "ANYONE": if err := this.Q.UpdateCreateFolder(ctx, folders.CreateFolderAnyone); err != nil { return err } this.System.CreateFolder = folders.CreateFolderAnyone fmt.Println("Folder creation set to: anyone can create folders.") case "OWNERS": if err := this.Q.UpdateCreateFolder(ctx, folders.CreateFolderOwners); err != nil { return err } this.System.CreateFolder = folders.CreateFolderOwners fmt.Println("Folder creation set to: admins and folder owners can create folders.") case "ADMINS": if err := this.Q.UpdateCreateFolder(ctx, folders.CreateFolderAdmins); err != nil { return err } this.System.CreateFolder = folders.CreateFolderAdmins fmt.Println("Folder creation set to: only admins can create folders.") default: fmt.Println("Usage: SET CREATE ANYONE|OWNERS|ADMINS") } return nil } // ActionSetRegistration handles the `SET REGISTRATION` command. func ActionSetRegistration(cmd *dclish.Command) error { if this.User.Admin == 0 { Loading repl/show.go +13 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,19 @@ func ActionShowFlags(_ *dclish.Command) error { return nil } // ActionShowCreate handles the `SHOW CREATE` command. func ActionShowCreate(_ *dclish.Command) error { switch this.System.CreateFolder { case folders.CreateFolderOwners: fmt.Println("Folder creation: admins and folder owners can create folders.") case folders.CreateFolderAnyone: fmt.Println("Folder creation: anyone can create folders.") default: fmt.Println("Folder creation: only admins can create folders.") } return nil } // ActionShowFolder handles the `SHOW FOLDER` command. This is based on // `SHOW_FOLDER` in bulletin5.for. func ActionShowFolder(cmd *dclish.Command) error { Loading storage/folders.sql.go +14 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,20 @@ func (q *Queries) GetFolderExpire(ctx context.Context, name string) (int64, erro return expire, err } const isAnyFolderOwner = `-- name: IsAnyFolderOwner :one SELECT 1 FROM folders WHERE owner = ? LIMIT 1 ` // IsAnyFolderOwner returns true if a user owns at least one folder. // // SELECT 1 FROM folders WHERE owner = ? LIMIT 1 func (q *Queries) IsAnyFolderOwner(ctx context.Context, owner string) (int64, error) { row := q.db.QueryRowContext(ctx, isAnyFolderOwner, owner) var column_1 int64 err := row.Scan(&column_1) return column_1, err } const isFolderOwner = `-- name: IsFolderOwner :one SELECT 1 FROM folders WHERE name = ? AND owner = ? ` Loading Loading
folders/folders.go +22 −2 Original line number Diff line number Diff line Loading @@ -46,6 +46,13 @@ const ( FolderPrivate int64 = 2 ) // Values for CreateFolder setting. const ( CreateFolderAdmins int64 = 0 CreateFolderOwners int64 = 1 CreateFolderAnyone int64 = 2 ) // CreateFolder creates a new folder. func CreateFolder(login string, options storage.CreateFolderParams) error { if !IsAlphaNum(options.Name) { Loading @@ -57,9 +64,22 @@ func CreateFolder(login string, options storage.CreateFolderParams) error { if err != nil { return err } switch this.System.CreateFolder { case CreateFolderAnyone: // Anyone can create folders. case CreateFolderOwners: if admin != 1 { owned, err := this.Q.IsAnyFolderOwner(ctx, login) if err != nil || owned != 1 { return errors.New("only admins or folder owners can create folders") } } default: // CreateFolderAdmins if admin != 1 { return errors.New("only admins can create folders") } } options.Name = strings.ToUpper(options.Name) Loading
repl/command.go +30 −8 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ The folder-name is limited to 25 letters and must not include spaces or characters that are also invalid in filenames (this is because the folder is stored in a file name created with the folder name). NOTE: Creation of folders is a privileged command.`, NOTE: Who can create folders depends on the SET CREATE policy.`, Action: ActionCreate, MinArgs: 1, MaxArgs: 1, Loading Loading @@ -1158,14 +1158,29 @@ characteristics of the BULLETIN Utility. The following options are available: ACCESS ALWAYS BRIEF DEFAULT_EXPIRE EXPIRE_LIMIT FOLDER NOACCESS NOALWAYS NOBRIEF NOPROMPT_EXPIRE NOREADNEW NOSHOWNEW NOSYSTEM PROMPT_EXPIRE READNEW REGISTRATION SHOWNEW SHIBBOLETH SYSTEM ACCESS ALWAYS BRIEF CREATE DEFAULT_EXPIRE EXPIRE_LIMIT FOLDER NOACCESS NOALWAYS NOBRIEF NOPROMPT_EXPIRE NOREADNEW NOSHOWNEW NOSYSTEM PROMPT_EXPIRE READNEW REGISTRATION SHOWNEW SHIBBOLETH SYSTEM `, Action: ActionSet, Commands: dclish.Commands{ "CREATE": { Description: `Controls who is allowed to create new folders. Format: SET CREATE ANYONE|OWNERS|ADMINS ANYONE - Any user can create a folder. OWNERS - Admins and existing folder owners can create a folder. ADMINS - Only admins can create a folder (default). This is a privileged command.`, MinArgs: 1, MaxArgs: 1, Action: ActionSetCreate, }, "REGISTRATION": { Description: `Controls open registration. When open, unknown SSH keys can self-onboard via the AuthorizedKeysCommand flow. Loading Loading @@ -1551,11 +1566,18 @@ that folder cannot be removed.`, The following options are available: FLAGS FOLDER NEW PRIVILEGES SYSTEM USER VERSION CREATE FLAGS FOLDER NEW PRIVILEGES SYSTEM USER VERSION `, Action: ActionShow, Commands: dclish.Commands{ "CREATE": { Description: `Shows the current folder creation policy. Format: SHOW CREATE`, Action: ActionShowCreate, }, "FLAGS": { Description: `Shows whether BRIEF, READNEW, or SHOWNEW has been set for the currently selected folder. Loading
repl/set.go +35 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,41 @@ func ActionSetNosystem(_ *dclish.Command) error { return this.Q.UpdateFolderSystem(ctx, 0, this.Folder.Name) } // ActionSetCreate handles the `SET CREATE` command. func ActionSetCreate(cmd *dclish.Command) error { if this.User.Admin == 0 { return errors.New("privileges needed for changing defaults") } if len(cmd.Args) != 1 { fmt.Println("Usage: SET CREATE ANYONE|OWNERS|ADMINS") return nil } ctx := storage.Context() switch strings.ToUpper(cmd.Args[0]) { case "ANYONE": if err := this.Q.UpdateCreateFolder(ctx, folders.CreateFolderAnyone); err != nil { return err } this.System.CreateFolder = folders.CreateFolderAnyone fmt.Println("Folder creation set to: anyone can create folders.") case "OWNERS": if err := this.Q.UpdateCreateFolder(ctx, folders.CreateFolderOwners); err != nil { return err } this.System.CreateFolder = folders.CreateFolderOwners fmt.Println("Folder creation set to: admins and folder owners can create folders.") case "ADMINS": if err := this.Q.UpdateCreateFolder(ctx, folders.CreateFolderAdmins); err != nil { return err } this.System.CreateFolder = folders.CreateFolderAdmins fmt.Println("Folder creation set to: only admins can create folders.") default: fmt.Println("Usage: SET CREATE ANYONE|OWNERS|ADMINS") } return nil } // ActionSetRegistration handles the `SET REGISTRATION` command. func ActionSetRegistration(cmd *dclish.Command) error { if this.User.Admin == 0 { Loading
repl/show.go +13 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,19 @@ func ActionShowFlags(_ *dclish.Command) error { return nil } // ActionShowCreate handles the `SHOW CREATE` command. func ActionShowCreate(_ *dclish.Command) error { switch this.System.CreateFolder { case folders.CreateFolderOwners: fmt.Println("Folder creation: admins and folder owners can create folders.") case folders.CreateFolderAnyone: fmt.Println("Folder creation: anyone can create folders.") default: fmt.Println("Folder creation: only admins can create folders.") } return nil } // ActionShowFolder handles the `SHOW FOLDER` command. This is based on // `SHOW_FOLDER` in bulletin5.for. func ActionShowFolder(cmd *dclish.Command) error { Loading
storage/folders.sql.go +14 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,20 @@ func (q *Queries) GetFolderExpire(ctx context.Context, name string) (int64, erro return expire, err } const isAnyFolderOwner = `-- name: IsAnyFolderOwner :one SELECT 1 FROM folders WHERE owner = ? LIMIT 1 ` // IsAnyFolderOwner returns true if a user owns at least one folder. // // SELECT 1 FROM folders WHERE owner = ? LIMIT 1 func (q *Queries) IsAnyFolderOwner(ctx context.Context, owner string) (int64, error) { row := q.db.QueryRowContext(ctx, isAnyFolderOwner, owner) var column_1 int64 err := row.Scan(&column_1) return column_1, err } const isFolderOwner = `-- name: IsFolderOwner :one SELECT 1 FROM folders WHERE name = ? AND owner = ? ` Loading