Add user account roles
This commit is contained in:
parent
b4817546df
commit
7ea66dc02e
10 changed files with 188 additions and 12 deletions
|
|
@ -151,6 +151,7 @@ func SignupUser(ctx context.Context, username string, name string, password stri
|
|||
OrganizationID: omit.From(o.ID),
|
||||
PasswordHash: omit.From(passwordHash),
|
||||
PasswordHashType: omit.From(enums.HashtypeBcrypt14),
|
||||
Role: omit.From(enums.UserroleAccountOwner),
|
||||
Username: omit.From(username),
|
||||
}
|
||||
u, err := models.Users.Insert(&u_setter).One(ctx, db.PGInstance.BobDB)
|
||||
|
|
|
|||
|
|
@ -123,6 +123,15 @@ var Users = Table[
|
|||
Generated: false,
|
||||
AutoIncr: false,
|
||||
},
|
||||
Role: column{
|
||||
Name: "role",
|
||||
DBType: "public.userrole",
|
||||
Default: "",
|
||||
Comment: "",
|
||||
Nullable: false,
|
||||
Generated: false,
|
||||
AutoIncr: false,
|
||||
},
|
||||
},
|
||||
Indexes: userIndexes{
|
||||
UserPkey: index{
|
||||
|
|
@ -200,11 +209,12 @@ type userColumns struct {
|
|||
Username column
|
||||
PasswordHashType column
|
||||
PasswordHash column
|
||||
Role column
|
||||
}
|
||||
|
||||
func (c userColumns) AsSlice() []column {
|
||||
return []column{
|
||||
c.ID, c.ArcgisAccessToken, c.ArcgisLicense, c.ArcgisRefreshToken, c.ArcgisRefreshTokenExpires, c.ArcgisRole, c.DisplayName, c.Email, c.OrganizationID, c.Username, c.PasswordHashType, c.PasswordHash,
|
||||
c.ID, c.ArcgisAccessToken, c.ArcgisLicense, c.ArcgisRefreshToken, c.ArcgisRefreshTokenExpires, c.ArcgisRole, c.DisplayName, c.Email, c.OrganizationID, c.Username, c.PasswordHashType, c.PasswordHash, c.Role,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1437,3 +1437,75 @@ func (e *PublicreportReportstatustype) Scan(value any) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enum values for Userrole
|
||||
const (
|
||||
UserroleRoot Userrole = "root"
|
||||
UserroleAccountOwner Userrole = "account-owner"
|
||||
)
|
||||
|
||||
func AllUserrole() []Userrole {
|
||||
return []Userrole{
|
||||
UserroleRoot,
|
||||
UserroleAccountOwner,
|
||||
}
|
||||
}
|
||||
|
||||
type Userrole string
|
||||
|
||||
func (e Userrole) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (e Userrole) Valid() bool {
|
||||
switch e {
|
||||
case UserroleRoot, UserroleAccountOwner:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// useful when testing in other packages
|
||||
func (e Userrole) All() []Userrole {
|
||||
return AllUserrole()
|
||||
}
|
||||
|
||||
func (e Userrole) MarshalText() ([]byte, error) {
|
||||
return []byte(e), nil
|
||||
}
|
||||
|
||||
func (e *Userrole) UnmarshalText(text []byte) error {
|
||||
return e.Scan(text)
|
||||
}
|
||||
|
||||
func (e Userrole) MarshalBinary() ([]byte, error) {
|
||||
return []byte(e), nil
|
||||
}
|
||||
|
||||
func (e *Userrole) UnmarshalBinary(data []byte) error {
|
||||
return e.Scan(data)
|
||||
}
|
||||
|
||||
func (e Userrole) Value() (driver.Value, error) {
|
||||
return string(e), nil
|
||||
}
|
||||
|
||||
func (e *Userrole) Scan(value any) error {
|
||||
switch x := value.(type) {
|
||||
case string:
|
||||
*e = Userrole(x)
|
||||
case []byte:
|
||||
*e = Userrole(x)
|
||||
case nil:
|
||||
return fmt.Errorf("cannot nil into Userrole")
|
||||
default:
|
||||
return fmt.Errorf("cannot scan type %T: %v", value, value)
|
||||
}
|
||||
|
||||
if !e.Valid() {
|
||||
return fmt.Errorf("invalid Userrole value: %s", *e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3804,6 +3804,7 @@ func (f *Factory) FromExistingUser(m *models.User) *UserTemplate {
|
|||
o.Username = func() string { return m.Username }
|
||||
o.PasswordHashType = func() enums.Hashtype { return m.PasswordHashType }
|
||||
o.PasswordHash = func() string { return m.PasswordHash }
|
||||
o.Role = func() enums.Userrole { return m.Role }
|
||||
|
||||
ctx := context.Background()
|
||||
if len(m.R.PublicUserUser) > 0 {
|
||||
|
|
|
|||
|
|
@ -231,6 +231,16 @@ func random_enums_PublicreportReportstatustype(f *faker.Faker, limits ...string)
|
|||
return all[f.IntBetween(0, len(all)-1)]
|
||||
}
|
||||
|
||||
func random_enums_Userrole(f *faker.Faker, limits ...string) enums.Userrole {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
var e enums.Userrole
|
||||
all := e.All()
|
||||
return all[f.IntBetween(0, len(all)-1)]
|
||||
}
|
||||
|
||||
func random_float32(f *faker.Faker, limits ...string) float32 {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ type UserTemplate struct {
|
|||
Username func() string
|
||||
PasswordHashType func() enums.Hashtype
|
||||
PasswordHash func() string
|
||||
Role func() enums.Userrole
|
||||
|
||||
r userR
|
||||
f *Factory
|
||||
|
|
@ -298,6 +299,10 @@ func (o UserTemplate) BuildSetter() *models.UserSetter {
|
|||
val := o.PasswordHash()
|
||||
m.PasswordHash = omit.From(val)
|
||||
}
|
||||
if o.Role != nil {
|
||||
val := o.Role()
|
||||
m.Role = omit.From(val)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
|
@ -356,6 +361,9 @@ func (o UserTemplate) Build() *models.User {
|
|||
if o.PasswordHash != nil {
|
||||
m.PasswordHash = o.PasswordHash()
|
||||
}
|
||||
if o.Role != nil {
|
||||
m.Role = o.Role()
|
||||
}
|
||||
|
||||
o.setModelRels(m)
|
||||
|
||||
|
|
@ -396,6 +404,10 @@ func ensureCreatableUser(m *models.UserSetter) {
|
|||
val := random_string(nil)
|
||||
m.PasswordHash = omit.From(val)
|
||||
}
|
||||
if !(m.Role.IsValue()) {
|
||||
val := random_enums_Userrole(nil)
|
||||
m.Role = omit.From(val)
|
||||
}
|
||||
}
|
||||
|
||||
// insertOptRels creates and inserts any optional the relationships on *models.User
|
||||
|
|
@ -707,6 +719,7 @@ func (m userMods) RandomizeAllColumns(f *faker.Faker) UserMod {
|
|||
UserMods.RandomUsername(f),
|
||||
UserMods.RandomPasswordHashType(f),
|
||||
UserMods.RandomPasswordHash(f),
|
||||
UserMods.RandomRole(f),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1214,6 +1227,37 @@ func (m userMods) RandomPasswordHash(f *faker.Faker) UserMod {
|
|||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m userMods) Role(val enums.Userrole) UserMod {
|
||||
return UserModFunc(func(_ context.Context, o *UserTemplate) {
|
||||
o.Role = func() enums.Userrole { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m userMods) RoleFunc(f func() enums.Userrole) UserMod {
|
||||
return UserModFunc(func(_ context.Context, o *UserTemplate) {
|
||||
o.Role = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m userMods) UnsetRole() UserMod {
|
||||
return UserModFunc(func(_ context.Context, o *UserTemplate) {
|
||||
o.Role = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m userMods) RandomRole(f *faker.Faker) UserMod {
|
||||
return UserModFunc(func(_ context.Context, o *UserTemplate) {
|
||||
o.Role = func() enums.Userrole {
|
||||
return random_enums_Userrole(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithParentsCascading() UserMod {
|
||||
return UserModFunc(func(ctx context.Context, o *UserTemplate) {
|
||||
if isDone, _ := userWithParentsCascadingCtx.Value(ctx); isDone {
|
||||
|
|
|
|||
11
db/migrations/00065_user_roles.sql
Normal file
11
db/migrations/00065_user_roles.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
-- +goose Up
|
||||
CREATE TYPE UserRole AS ENUM (
|
||||
'root',
|
||||
'account-owner'
|
||||
);
|
||||
ALTER TABLE user_ ADD COLUMN role UserRole;
|
||||
UPDATE user_ SET role = 'account-owner';
|
||||
ALTER TABLE user_ ALTER COLUMN role SET NOT NULL;
|
||||
-- +goose Down
|
||||
ALTER TABLE user_ DROP COLUMN role;
|
||||
DROP TYPE UserRole;
|
||||
|
|
@ -39,6 +39,7 @@ type User struct {
|
|||
Username string `db:"username" `
|
||||
PasswordHashType enums.Hashtype `db:"password_hash_type" `
|
||||
PasswordHash string `db:"password_hash" `
|
||||
Role enums.Userrole `db:"role" `
|
||||
|
||||
R userR `db:"-" `
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ type userR struct {
|
|||
func buildUserColumns(alias string) userColumns {
|
||||
return userColumns{
|
||||
ColumnsExpr: expr.NewColumnsExpr(
|
||||
"id", "arcgis_access_token", "arcgis_license", "arcgis_refresh_token", "arcgis_refresh_token_expires", "arcgis_role", "display_name", "email", "organization_id", "username", "password_hash_type", "password_hash",
|
||||
"id", "arcgis_access_token", "arcgis_license", "arcgis_refresh_token", "arcgis_refresh_token_expires", "arcgis_role", "display_name", "email", "organization_id", "username", "password_hash_type", "password_hash", "role",
|
||||
).WithParent("user_"),
|
||||
tableAlias: alias,
|
||||
ID: psql.Quote(alias, "id"),
|
||||
|
|
@ -87,6 +88,7 @@ func buildUserColumns(alias string) userColumns {
|
|||
Username: psql.Quote(alias, "username"),
|
||||
PasswordHashType: psql.Quote(alias, "password_hash_type"),
|
||||
PasswordHash: psql.Quote(alias, "password_hash"),
|
||||
Role: psql.Quote(alias, "role"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,6 +107,7 @@ type userColumns struct {
|
|||
Username psql.Expression
|
||||
PasswordHashType psql.Expression
|
||||
PasswordHash psql.Expression
|
||||
Role psql.Expression
|
||||
}
|
||||
|
||||
func (c userColumns) Alias() string {
|
||||
|
|
@ -131,10 +134,11 @@ type UserSetter struct {
|
|||
Username omit.Val[string] `db:"username" `
|
||||
PasswordHashType omit.Val[enums.Hashtype] `db:"password_hash_type" `
|
||||
PasswordHash omit.Val[string] `db:"password_hash" `
|
||||
Role omit.Val[enums.Userrole] `db:"role" `
|
||||
}
|
||||
|
||||
func (s UserSetter) SetColumns() []string {
|
||||
vals := make([]string, 0, 12)
|
||||
vals := make([]string, 0, 13)
|
||||
if s.ID.IsValue() {
|
||||
vals = append(vals, "id")
|
||||
}
|
||||
|
|
@ -171,6 +175,9 @@ func (s UserSetter) SetColumns() []string {
|
|||
if s.PasswordHash.IsValue() {
|
||||
vals = append(vals, "password_hash")
|
||||
}
|
||||
if s.Role.IsValue() {
|
||||
vals = append(vals, "role")
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
|
|
@ -211,6 +218,9 @@ func (s UserSetter) Overwrite(t *User) {
|
|||
if s.PasswordHash.IsValue() {
|
||||
t.PasswordHash = s.PasswordHash.MustGet()
|
||||
}
|
||||
if s.Role.IsValue() {
|
||||
t.Role = s.Role.MustGet()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *UserSetter) Apply(q *dialect.InsertQuery) {
|
||||
|
|
@ -219,7 +229,7 @@ func (s *UserSetter) Apply(q *dialect.InsertQuery) {
|
|||
})
|
||||
|
||||
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
|
||||
vals := make([]bob.Expression, 12)
|
||||
vals := make([]bob.Expression, 13)
|
||||
if s.ID.IsValue() {
|
||||
vals[0] = psql.Arg(s.ID.MustGet())
|
||||
} else {
|
||||
|
|
@ -292,6 +302,12 @@ func (s *UserSetter) Apply(q *dialect.InsertQuery) {
|
|||
vals[11] = psql.Raw("DEFAULT")
|
||||
}
|
||||
|
||||
if s.Role.IsValue() {
|
||||
vals[12] = psql.Arg(s.Role.MustGet())
|
||||
} else {
|
||||
vals[12] = psql.Raw("DEFAULT")
|
||||
}
|
||||
|
||||
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
|
@ -301,7 +317,7 @@ func (s UserSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
|||
}
|
||||
|
||||
func (s UserSetter) Expressions(prefix ...string) []bob.Expression {
|
||||
exprs := make([]bob.Expression, 0, 12)
|
||||
exprs := make([]bob.Expression, 0, 13)
|
||||
|
||||
if s.ID.IsValue() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
|
|
@ -387,6 +403,13 @@ func (s UserSetter) Expressions(prefix ...string) []bob.Expression {
|
|||
}})
|
||||
}
|
||||
|
||||
if s.Role.IsValue() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
psql.Quote(append(prefix, "role")...),
|
||||
psql.Arg(s.Role),
|
||||
}})
|
||||
}
|
||||
|
||||
return exprs
|
||||
}
|
||||
|
||||
|
|
@ -1526,6 +1549,7 @@ type userWhere[Q psql.Filterable] struct {
|
|||
Username psql.WhereMod[Q, string]
|
||||
PasswordHashType psql.WhereMod[Q, enums.Hashtype]
|
||||
PasswordHash psql.WhereMod[Q, string]
|
||||
Role psql.WhereMod[Q, enums.Userrole]
|
||||
}
|
||||
|
||||
func (userWhere[Q]) AliasedAs(alias string) userWhere[Q] {
|
||||
|
|
@ -1546,6 +1570,7 @@ func buildUserWhere[Q psql.Filterable](cols userColumns) userWhere[Q] {
|
|||
Username: psql.Where[Q, string](cols.Username),
|
||||
PasswordHashType: psql.Where[Q, enums.Hashtype](cols.PasswordHashType),
|
||||
PasswordHash: psql.Where[Q, string](cols.PasswordHash),
|
||||
Role: psql.Where[Q, enums.Userrole](cols.Role),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
//go:embed user_by_username.bob.sql
|
||||
var formattedQueries_user_by_username string
|
||||
|
||||
var userByUsernameSQL = formattedQueries_user_by_username[152:780]
|
||||
var userByUsernameSQL = formattedQueries_user_by_username[152:806]
|
||||
|
||||
type UserByUsernameQuery = orm.ModQuery[*dialect.SelectQuery, userByUsername, UserByUsernameRow, []UserByUsernameRow, userByUsernameTransformer]
|
||||
|
||||
|
|
@ -55,6 +55,7 @@ func UserByUsername(Username string) *UserByUsernameQuery {
|
|||
row.ScheduleScanByIndex(9, &t.Username)
|
||||
row.ScheduleScanByIndex(10, &t.PasswordHashType)
|
||||
row.ScheduleScanByIndex(11, &t.PasswordHash)
|
||||
row.ScheduleScanByIndex(12, &t.Role)
|
||||
return &t, nil
|
||||
}, func(v any) (UserByUsernameRow, error) {
|
||||
return *(v.(*UserByUsernameRow)), nil
|
||||
|
|
@ -62,9 +63,9 @@ func UserByUsername(Username string) *UserByUsernameQuery {
|
|||
},
|
||||
},
|
||||
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
|
||||
q.AppendSelect(expressionTypArgs.subExpr(7, 551))
|
||||
q.SetTable(expressionTypArgs.subExpr(557, 569))
|
||||
q.AppendWhere(expressionTypArgs.subExpr(577, 628))
|
||||
q.AppendSelect(expressionTypArgs.subExpr(7, 577))
|
||||
q.SetTable(expressionTypArgs.subExpr(583, 595))
|
||||
q.AppendWhere(expressionTypArgs.subExpr(603, 654))
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -82,6 +83,7 @@ type UserByUsernameRow = struct {
|
|||
Username string `db:"username"`
|
||||
PasswordHashType enums.Hashtype `db:"password_hash_type"`
|
||||
PasswordHash string `db:"password_hash"`
|
||||
Role enums.Userrole `db:"role"`
|
||||
}
|
||||
|
||||
type userByUsernameTransformer = bob.SliceTransformer[UserByUsernameRow, []UserByUsernameRow]
|
||||
|
|
@ -94,8 +96,8 @@ func (o userByUsername) args() iter.Seq[orm.ArgWithPosition] {
|
|||
return func(yield func(arg orm.ArgWithPosition) bool) {
|
||||
if !yield(orm.ArgWithPosition{
|
||||
Name: "username",
|
||||
Start: 588,
|
||||
Stop: 590,
|
||||
Start: 614,
|
||||
Stop: 616,
|
||||
Expression: o.Username,
|
||||
}) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
-- This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
-- UserByUsername
|
||||
SELECT "user_"."id" AS "id", "user_"."arcgis_access_token" AS "arcgis_access_token", "user_"."arcgis_license" AS "arcgis_license", "user_"."arcgis_refresh_token" AS "arcgis_refresh_token", "user_"."arcgis_refresh_token_expires" AS "arcgis_refresh_token_expires", "user_"."arcgis_role" AS "arcgis_role", "user_"."display_name" AS "display_name", "user_"."email" AS "email", "user_"."organization_id" AS "organization_id", "user_"."username" AS "username", "user_"."password_hash_type" AS "password_hash_type", "user_"."password_hash" AS "password_hash" FROM public.user_ WHERE
|
||||
SELECT "user_"."id" AS "id", "user_"."arcgis_access_token" AS "arcgis_access_token", "user_"."arcgis_license" AS "arcgis_license", "user_"."arcgis_refresh_token" AS "arcgis_refresh_token", "user_"."arcgis_refresh_token_expires" AS "arcgis_refresh_token_expires", "user_"."arcgis_role" AS "arcgis_role", "user_"."display_name" AS "display_name", "user_"."email" AS "email", "user_"."organization_id" AS "organization_id", "user_"."username" AS "username", "user_"."password_hash_type" AS "password_hash_type", "user_"."password_hash" AS "password_hash", "user_"."role" AS "role" FROM public.user_ WHERE
|
||||
username = $1 AND
|
||||
password_hash_type = 'bcrypt-14';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue