mirror of
https://github.com/binwiederhier/ntfy.git
synced 2025-10-27 19:20:18 +01:00
Change to auth-(users|access), upgrade manually added users to provision users
This commit is contained in:
parent
f3c67f1d71
commit
fe545423c5
5 changed files with 62 additions and 44 deletions
40
cmd/serve.go
40
cmd/serve.go
|
|
@ -48,8 +48,8 @@ var flagsServe = append(
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-file", Aliases: []string{"auth_file", "H"}, EnvVars: []string{"NTFY_AUTH_FILE"}, Usage: "auth database file used for access control"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-file", Aliases: []string{"auth_file", "H"}, EnvVars: []string{"NTFY_AUTH_FILE"}, Usage: "auth database file used for access control"}),
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-startup-queries", Aliases: []string{"auth_startup_queries"}, EnvVars: []string{"NTFY_AUTH_STARTUP_QUERIES"}, Usage: "queries run when the auth database is initialized"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-startup-queries", Aliases: []string{"auth_startup_queries"}, EnvVars: []string{"NTFY_AUTH_STARTUP_QUERIES"}, Usage: "queries run when the auth database is initialized"}),
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-default-access", Aliases: []string{"auth_default_access", "p"}, EnvVars: []string{"NTFY_AUTH_DEFAULT_ACCESS"}, Value: "read-write", Usage: "default permissions if no matching entries in the auth database are found"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-default-access", Aliases: []string{"auth_default_access", "p"}, EnvVars: []string{"NTFY_AUTH_DEFAULT_ACCESS"}, Value: "read-write", Usage: "default permissions if no matching entries in the auth database are found"}),
|
||||||
altsrc.NewStringSliceFlag(&cli.StringSliceFlag{Name: "auth-provision-users", Aliases: []string{"auth_provision_users"}, EnvVars: []string{"NTFY_AUTH_PROVISION_USERS"}, Usage: "pre-provisioned declarative users"}),
|
altsrc.NewStringSliceFlag(&cli.StringSliceFlag{Name: "auth-users", Aliases: []string{"auth_users"}, EnvVars: []string{"NTFY_AUTH_USERS"}, Usage: "pre-provisioned declarative users"}),
|
||||||
altsrc.NewStringSliceFlag(&cli.StringSliceFlag{Name: "auth-provision-access", Aliases: []string{"auth_provision_access"}, EnvVars: []string{"NTFY_AUTH_PROVISION_ACCESS"}, Usage: "pre-provisioned declarative access control entries"}),
|
altsrc.NewStringSliceFlag(&cli.StringSliceFlag{Name: "auth-access", Aliases: []string{"auth_access"}, EnvVars: []string{"NTFY_AUTH_ACCESS"}, Usage: "pre-provisioned declarative access control entries"}),
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "attachment-cache-dir", Aliases: []string{"attachment_cache_dir"}, EnvVars: []string{"NTFY_ATTACHMENT_CACHE_DIR"}, Usage: "cache directory for attached files"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "attachment-cache-dir", Aliases: []string{"attachment_cache_dir"}, EnvVars: []string{"NTFY_ATTACHMENT_CACHE_DIR"}, Usage: "cache directory for attached files"}),
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "attachment-total-size-limit", Aliases: []string{"attachment_total_size_limit", "A"}, EnvVars: []string{"NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT"}, Value: util.FormatSize(server.DefaultAttachmentTotalSizeLimit), Usage: "limit of the on-disk attachment cache"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "attachment-total-size-limit", Aliases: []string{"attachment_total_size_limit", "A"}, EnvVars: []string{"NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT"}, Value: util.FormatSize(server.DefaultAttachmentTotalSizeLimit), Usage: "limit of the on-disk attachment cache"}),
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "attachment-file-size-limit", Aliases: []string{"attachment_file_size_limit", "Y"}, EnvVars: []string{"NTFY_ATTACHMENT_FILE_SIZE_LIMIT"}, Value: util.FormatSize(server.DefaultAttachmentFileSizeLimit), Usage: "per-file attachment size limit (e.g. 300k, 2M, 100M)"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "attachment-file-size-limit", Aliases: []string{"attachment_file_size_limit", "Y"}, EnvVars: []string{"NTFY_ATTACHMENT_FILE_SIZE_LIMIT"}, Value: util.FormatSize(server.DefaultAttachmentFileSizeLimit), Usage: "per-file attachment size limit (e.g. 300k, 2M, 100M)"}),
|
||||||
|
|
@ -156,8 +156,8 @@ func execServe(c *cli.Context) error {
|
||||||
authFile := c.String("auth-file")
|
authFile := c.String("auth-file")
|
||||||
authStartupQueries := c.String("auth-startup-queries")
|
authStartupQueries := c.String("auth-startup-queries")
|
||||||
authDefaultAccess := c.String("auth-default-access")
|
authDefaultAccess := c.String("auth-default-access")
|
||||||
authProvisionUsersRaw := c.StringSlice("auth-provision-users")
|
authUsersRaw := c.StringSlice("auth-users")
|
||||||
authProvisionAccessRaw := c.StringSlice("auth-provision-access")
|
authAccessRaw := c.StringSlice("auth-access")
|
||||||
attachmentCacheDir := c.String("attachment-cache-dir")
|
attachmentCacheDir := c.String("attachment-cache-dir")
|
||||||
attachmentTotalSizeLimitStr := c.String("attachment-total-size-limit")
|
attachmentTotalSizeLimitStr := c.String("attachment-total-size-limit")
|
||||||
attachmentFileSizeLimitStr := c.String("attachment-file-size-limit")
|
attachmentFileSizeLimitStr := c.String("attachment-file-size-limit")
|
||||||
|
|
@ -353,11 +353,11 @@ func execServe(c *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("if set, auth-default-access must start set to 'read-write', 'read-only', 'write-only' or 'deny-all'")
|
return errors.New("if set, auth-default-access must start set to 'read-write', 'read-only', 'write-only' or 'deny-all'")
|
||||||
}
|
}
|
||||||
authProvisionUsers, err := parseProvisionUsers(authProvisionUsersRaw)
|
authUsers, err := parseUsers(authUsersRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
authProvisionAccess, err := parseProvisionAccess(authProvisionUsers, authProvisionAccessRaw)
|
authAccess, err := parseAccess(authUsers, authAccessRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -416,8 +416,8 @@ func execServe(c *cli.Context) error {
|
||||||
conf.AuthFile = authFile
|
conf.AuthFile = authFile
|
||||||
conf.AuthStartupQueries = authStartupQueries
|
conf.AuthStartupQueries = authStartupQueries
|
||||||
conf.AuthDefault = authDefault
|
conf.AuthDefault = authDefault
|
||||||
conf.AuthProvisionUsers = authProvisionUsers
|
conf.AuthUsers = authUsers
|
||||||
conf.AuthProvisionAccess = authProvisionAccess
|
conf.AuthAccess = authAccess
|
||||||
conf.AttachmentCacheDir = attachmentCacheDir
|
conf.AttachmentCacheDir = attachmentCacheDir
|
||||||
conf.AttachmentTotalSizeLimit = attachmentTotalSizeLimit
|
conf.AttachmentTotalSizeLimit = attachmentTotalSizeLimit
|
||||||
conf.AttachmentFileSizeLimit = attachmentFileSizeLimit
|
conf.AttachmentFileSizeLimit = attachmentFileSizeLimit
|
||||||
|
|
@ -531,22 +531,22 @@ func parseIPHostPrefix(host string) (prefixes []netip.Prefix, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProvisionUsers(usersRaw []string) ([]*user.User, error) {
|
func parseUsers(usersRaw []string) ([]*user.User, error) {
|
||||||
provisionUsers := make([]*user.User, 0)
|
provisionUsers := make([]*user.User, 0)
|
||||||
for _, userLine := range usersRaw {
|
for _, userLine := range usersRaw {
|
||||||
parts := strings.Split(userLine, ":")
|
parts := strings.Split(userLine, ":")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-users: %s, expected format: 'name:hash:role'", userLine)
|
return nil, fmt.Errorf("invalid auth-users: %s, expected format: 'name:hash:role'", userLine)
|
||||||
}
|
}
|
||||||
username := strings.TrimSpace(parts[0])
|
username := strings.TrimSpace(parts[0])
|
||||||
passwordHash := strings.TrimSpace(parts[1])
|
passwordHash := strings.TrimSpace(parts[1])
|
||||||
role := user.Role(strings.TrimSpace(parts[2]))
|
role := user.Role(strings.TrimSpace(parts[2]))
|
||||||
if !user.AllowedUsername(username) {
|
if !user.AllowedUsername(username) {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-users: %s, username invalid", userLine)
|
return nil, fmt.Errorf("invalid auth-users: %s, username invalid", userLine)
|
||||||
} else if err := user.AllowedPasswordHash(passwordHash); err != nil {
|
} else if err := user.AllowedPasswordHash(passwordHash); err != nil {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-users: %s, %s", userLine, err.Error())
|
return nil, fmt.Errorf("invalid auth-users: %s, %s", userLine, err.Error())
|
||||||
} else if !user.AllowedRole(role) {
|
} else if !user.AllowedRole(role) {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-users: %s, role %s is not allowed, allowed roles are 'admin' or 'user'", userLine, role)
|
return nil, fmt.Errorf("invalid auth-users: %s, role %s is not allowed, allowed roles are 'admin' or 'user'", userLine, role)
|
||||||
}
|
}
|
||||||
provisionUsers = append(provisionUsers, &user.User{
|
provisionUsers = append(provisionUsers, &user.User{
|
||||||
Name: username,
|
Name: username,
|
||||||
|
|
@ -558,12 +558,12 @@ func parseProvisionUsers(usersRaw []string) ([]*user.User, error) {
|
||||||
return provisionUsers, nil
|
return provisionUsers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProvisionAccess(provisionUsers []*user.User, provisionAccessRaw []string) (map[string][]*user.Grant, error) {
|
func parseAccess(provisionUsers []*user.User, provisionAccessRaw []string) (map[string][]*user.Grant, error) {
|
||||||
access := make(map[string][]*user.Grant)
|
access := make(map[string][]*user.Grant)
|
||||||
for _, accessLine := range provisionAccessRaw {
|
for _, accessLine := range provisionAccessRaw {
|
||||||
parts := strings.Split(accessLine, ":")
|
parts := strings.Split(accessLine, ":")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-access: %s, expected format: 'user:topic:permission'", accessLine)
|
return nil, fmt.Errorf("invalid auth-access: %s, expected format: 'user:topic:permission'", accessLine)
|
||||||
}
|
}
|
||||||
username := strings.TrimSpace(parts[0])
|
username := strings.TrimSpace(parts[0])
|
||||||
if username == userEveryone {
|
if username == userEveryone {
|
||||||
|
|
@ -574,20 +574,20 @@ func parseProvisionAccess(provisionUsers []*user.User, provisionAccessRaw []stri
|
||||||
})
|
})
|
||||||
if username != user.Everyone {
|
if username != user.Everyone {
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-access: %s, user %s is not provisioned", accessLine, username)
|
return nil, fmt.Errorf("invalid auth-access: %s, user %s is not provisioned", accessLine, username)
|
||||||
} else if !user.AllowedUsername(username) {
|
} else if !user.AllowedUsername(username) {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-access: %s, username %s invalid", accessLine, username)
|
return nil, fmt.Errorf("invalid auth-access: %s, username %s invalid", accessLine, username)
|
||||||
} else if provisionUser.Role != user.RoleUser {
|
} else if provisionUser.Role != user.RoleUser {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-access: %s, user %s is not a regular user, only regular users can have ACL entries", accessLine, username)
|
return nil, fmt.Errorf("invalid auth-access: %s, user %s is not a regular user, only regular users can have ACL entries", accessLine, username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
topic := strings.TrimSpace(parts[1])
|
topic := strings.TrimSpace(parts[1])
|
||||||
if !user.AllowedTopicPattern(topic) {
|
if !user.AllowedTopicPattern(topic) {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-access: %s, topic pattern %s invalid", accessLine, topic)
|
return nil, fmt.Errorf("invalid auth-access: %s, topic pattern %s invalid", accessLine, topic)
|
||||||
}
|
}
|
||||||
permission, err := user.ParsePermission(strings.TrimSpace(parts[2]))
|
permission, err := user.ParsePermission(strings.TrimSpace(parts[2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid auth-provision-access: %s, permission %s invalid, %s", accessLine, parts[2], err.Error())
|
return nil, fmt.Errorf("invalid auth-access: %s, permission %s invalid, %s", accessLine, parts[2], err.Error())
|
||||||
}
|
}
|
||||||
if _, exists := access[username]; !exists {
|
if _, exists := access[username]; !exists {
|
||||||
access[username] = make([]*user.Grant, 0)
|
access[username] = make([]*user.Grant, 0)
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,8 @@ type Config struct {
|
||||||
AuthFile string
|
AuthFile string
|
||||||
AuthStartupQueries string
|
AuthStartupQueries string
|
||||||
AuthDefault user.Permission
|
AuthDefault user.Permission
|
||||||
AuthProvisionUsers []*user.User
|
AuthUsers []*user.User
|
||||||
AuthProvisionAccess map[string][]*user.Grant
|
AuthAccess map[string][]*user.Grant
|
||||||
AuthBcryptCost int
|
AuthBcryptCost int
|
||||||
AuthStatsQueueWriterInterval time.Duration
|
AuthStatsQueueWriterInterval time.Duration
|
||||||
AttachmentCacheDir string
|
AttachmentCacheDir string
|
||||||
|
|
|
||||||
|
|
@ -201,8 +201,8 @@ func New(conf *Config) (*Server, error) {
|
||||||
StartupQueries: conf.AuthStartupQueries,
|
StartupQueries: conf.AuthStartupQueries,
|
||||||
DefaultAccess: conf.AuthDefault,
|
DefaultAccess: conf.AuthDefault,
|
||||||
ProvisionEnabled: true, // Enable provisioning of users and access
|
ProvisionEnabled: true, // Enable provisioning of users and access
|
||||||
ProvisionUsers: conf.AuthProvisionUsers,
|
Users: conf.AuthUsers,
|
||||||
ProvisionAccess: conf.AuthProvisionAccess,
|
Access: conf.AuthAccess,
|
||||||
BcryptCost: conf.AuthBcryptCost,
|
BcryptCost: conf.AuthBcryptCost,
|
||||||
QueueWriterInterval: conf.AuthStatsQueueWriterInterval,
|
QueueWriterInterval: conf.AuthStatsQueueWriterInterval,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ const (
|
||||||
selectUserCountQuery = `SELECT COUNT(*) FROM user`
|
selectUserCountQuery = `SELECT COUNT(*) FROM user`
|
||||||
updateUserPassQuery = `UPDATE user SET pass = ? WHERE user = ?`
|
updateUserPassQuery = `UPDATE user SET pass = ? WHERE user = ?`
|
||||||
updateUserRoleQuery = `UPDATE user SET role = ? WHERE user = ?`
|
updateUserRoleQuery = `UPDATE user SET role = ? WHERE user = ?`
|
||||||
|
updateUserProvisionedQuery = `UPDATE user SET provisioned = ? WHERE user = ?`
|
||||||
updateUserPrefsQuery = `UPDATE user SET prefs = ? WHERE id = ?`
|
updateUserPrefsQuery = `UPDATE user SET prefs = ? WHERE id = ?`
|
||||||
updateUserStatsQuery = `UPDATE user SET stats_messages = ?, stats_emails = ?, stats_calls = ? WHERE id = ?`
|
updateUserStatsQuery = `UPDATE user SET stats_messages = ?, stats_emails = ?, stats_calls = ? WHERE id = ?`
|
||||||
updateUserStatsResetAllQuery = `UPDATE user SET stats_messages = 0, stats_emails = 0, stats_calls = 0`
|
updateUserStatsResetAllQuery = `UPDATE user SET stats_messages = 0, stats_emails = 0, stats_calls = 0`
|
||||||
|
|
@ -535,8 +536,8 @@ type Config struct {
|
||||||
StartupQueries string // Queries to run on startup, e.g. to create initial users or tiers
|
StartupQueries string // Queries to run on startup, e.g. to create initial users or tiers
|
||||||
DefaultAccess Permission // Default permission if no ACL matches
|
DefaultAccess Permission // Default permission if no ACL matches
|
||||||
ProvisionEnabled bool // Enable auto-provisioning of users and access grants, disabled for "ntfy user" commands
|
ProvisionEnabled bool // Enable auto-provisioning of users and access grants, disabled for "ntfy user" commands
|
||||||
ProvisionUsers []*User // Predefined users to create on startup
|
Users []*User // Predefined users to create on startup
|
||||||
ProvisionAccess map[string][]*Grant // Predefined access grants to create on startup
|
Access map[string][]*Grant // Predefined access grants to create on startup
|
||||||
QueueWriterInterval time.Duration // Interval for the async queue writer to flush stats and token updates to the database
|
QueueWriterInterval time.Duration // Interval for the async queue writer to flush stats and token updates to the database
|
||||||
BcryptCost int // Cost of generated passwords; lowering makes testing faster
|
BcryptCost int // Cost of generated passwords; lowering makes testing faster
|
||||||
}
|
}
|
||||||
|
|
@ -1374,6 +1375,21 @@ func (a *Manager) changeRoleTx(tx *sql.Tx, username string, role Role) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChangeProvisioned changes the provisioned status of a user. This is used to mark users as
|
||||||
|
// provisioned. A provisioned user is a user defined in the config file.
|
||||||
|
func (a *Manager) ChangeProvisioned(username string, provisioned bool) error {
|
||||||
|
return execTx(a.db, func(tx *sql.Tx) error {
|
||||||
|
return a.changeProvisionedTx(tx, username, provisioned)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Manager) changeProvisionedTx(tx *sql.Tx, username string, provisioned bool) error {
|
||||||
|
if _, err := tx.Exec(updateUserProvisionedQuery, provisioned, username); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ChangeTier changes a user's tier using the tier code. This function does not delete reservations, messages,
|
// ChangeTier changes a user's tier using the tier code. This function does not delete reservations, messages,
|
||||||
// or attachments, even if the new tier has lower limits in this regard. That has to be done elsewhere.
|
// or attachments, even if the new tier has lower limits in this regard. That has to be done elsewhere.
|
||||||
func (a *Manager) ChangeTier(username, tier string) error {
|
func (a *Manager) ChangeTier(username, tier string) error {
|
||||||
|
|
@ -1669,7 +1685,7 @@ func (a *Manager) maybeProvisionUsersAndAccess() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
provisionUsernames := util.Map(a.config.ProvisionUsers, func(u *User) string {
|
provisionUsernames := util.Map(a.config.Users, func(u *User) string {
|
||||||
return u.Name
|
return u.Name
|
||||||
})
|
})
|
||||||
return execTx(a.db, func(tx *sql.Tx) error {
|
return execTx(a.db, func(tx *sql.Tx) error {
|
||||||
|
|
@ -1678,14 +1694,13 @@ func (a *Manager) maybeProvisionUsersAndAccess() error {
|
||||||
if user.Name == Everyone {
|
if user.Name == Everyone {
|
||||||
continue
|
continue
|
||||||
} else if user.Provisioned && !util.Contains(provisionUsernames, user.Name) {
|
} else if user.Provisioned && !util.Contains(provisionUsernames, user.Name) {
|
||||||
log.Tag(tag).Info("Removing previously provisioned user %s", user.Name)
|
|
||||||
if err := a.removeUserTx(tx, user.Name); err != nil {
|
if err := a.removeUserTx(tx, user.Name); err != nil {
|
||||||
return fmt.Errorf("failed to remove provisioned user %s: %v", user.Name, err)
|
return fmt.Errorf("failed to remove provisioned user %s: %v", user.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add or update provisioned users
|
// Add or update provisioned users
|
||||||
for _, user := range a.config.ProvisionUsers {
|
for _, user := range a.config.Users {
|
||||||
if user.Name == Everyone {
|
if user.Name == Everyone {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -1693,18 +1708,21 @@ func (a *Manager) maybeProvisionUsersAndAccess() error {
|
||||||
return u.Name == user.Name
|
return u.Name == user.Name
|
||||||
})
|
})
|
||||||
if !exists {
|
if !exists {
|
||||||
log.Tag(tag).Info("Adding provisioned user %s", user.Name)
|
|
||||||
if err := a.addUserTx(tx, user.Name, user.Hash, user.Role, true, true); err != nil && !errors.Is(err, ErrUserExists) {
|
if err := a.addUserTx(tx, user.Name, user.Hash, user.Role, true, true); err != nil && !errors.Is(err, ErrUserExists) {
|
||||||
return fmt.Errorf("failed to add provisioned user %s: %v", user.Name, err)
|
return fmt.Errorf("failed to add provisioned user %s: %v", user.Name, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !existingUser.Provisioned {
|
if !existingUser.Provisioned {
|
||||||
log.Tag(tag).Warn("Refusing to update manually user %s", user.Name)
|
if err := a.changeProvisionedTx(tx, user.Name, true); err != nil {
|
||||||
} else if existingUser.Hash != user.Hash || existingUser.Role != user.Role {
|
return fmt.Errorf("failed to change provisioned status for user %s: %v", user.Name, err)
|
||||||
log.Tag(tag).Info("Updating provisioned user %s", user.Name)
|
}
|
||||||
|
}
|
||||||
|
if existingUser.Hash != user.Hash {
|
||||||
if err := a.changePasswordTx(tx, user.Name, user.Hash, true); err != nil {
|
if err := a.changePasswordTx(tx, user.Name, user.Hash, true); err != nil {
|
||||||
return fmt.Errorf("failed to change password for provisioned user %s: %v", user.Name, err)
|
return fmt.Errorf("failed to change password for provisioned user %s: %v", user.Name, err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if existingUser.Role != user.Role {
|
||||||
if err := a.changeRoleTx(tx, user.Name, user.Role); err != nil {
|
if err := a.changeRoleTx(tx, user.Name, user.Role); err != nil {
|
||||||
return fmt.Errorf("failed to change role for provisioned user %s: %v", user.Name, err)
|
return fmt.Errorf("failed to change role for provisioned user %s: %v", user.Name, err)
|
||||||
}
|
}
|
||||||
|
|
@ -1715,7 +1733,7 @@ func (a *Manager) maybeProvisionUsersAndAccess() error {
|
||||||
if _, err := tx.Exec(deleteUserAccessProvisionedQuery); err != nil {
|
if _, err := tx.Exec(deleteUserAccessProvisionedQuery); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for username, grants := range a.config.ProvisionAccess {
|
for username, grants := range a.config.Access {
|
||||||
for _, grant := range grants {
|
for _, grant := range grants {
|
||||||
if err := a.allowAccessTx(tx, username, grant.TopicPattern, grant.Permission, true); err != nil {
|
if err := a.allowAccessTx(tx, username, grant.TopicPattern, grant.Permission, true); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -1102,11 +1102,11 @@ func TestManager_WithProvisionedUsers(t *testing.T) {
|
||||||
Filename: f,
|
Filename: f,
|
||||||
DefaultAccess: PermissionReadWrite,
|
DefaultAccess: PermissionReadWrite,
|
||||||
ProvisionEnabled: true,
|
ProvisionEnabled: true,
|
||||||
ProvisionUsers: []*User{
|
Users: []*User{
|
||||||
{Name: "philuser", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
|
{Name: "philuser", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
|
||||||
{Name: "philadmin", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleAdmin},
|
{Name: "philadmin", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleAdmin},
|
||||||
},
|
},
|
||||||
ProvisionAccess: map[string][]*Grant{
|
Access: map[string][]*Grant{
|
||||||
"philuser": {
|
"philuser": {
|
||||||
{TopicPattern: "stats", Permission: PermissionReadWrite},
|
{TopicPattern: "stats", Permission: PermissionReadWrite},
|
||||||
{TopicPattern: "secret", Permission: PermissionRead},
|
{TopicPattern: "secret", Permission: PermissionRead},
|
||||||
|
|
@ -1144,10 +1144,10 @@ func TestManager_WithProvisionedUsers(t *testing.T) {
|
||||||
|
|
||||||
// Re-open the DB (second app start)
|
// Re-open the DB (second app start)
|
||||||
require.Nil(t, a.db.Close())
|
require.Nil(t, a.db.Close())
|
||||||
conf.ProvisionUsers = []*User{
|
conf.Users = []*User{
|
||||||
{Name: "philuser", Hash: "$2a$10$AAAU21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
|
{Name: "philuser", Hash: "$2a$10$AAAU21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
|
||||||
}
|
}
|
||||||
conf.ProvisionAccess = map[string][]*Grant{
|
conf.Access = map[string][]*Grant{
|
||||||
"philuser": {
|
"philuser": {
|
||||||
{TopicPattern: "stats12", Permission: PermissionReadWrite},
|
{TopicPattern: "stats12", Permission: PermissionReadWrite},
|
||||||
{TopicPattern: "secret12", Permission: PermissionRead},
|
{TopicPattern: "secret12", Permission: PermissionRead},
|
||||||
|
|
@ -1178,8 +1178,8 @@ func TestManager_WithProvisionedUsers(t *testing.T) {
|
||||||
|
|
||||||
// Re-open the DB again (third app start)
|
// Re-open the DB again (third app start)
|
||||||
require.Nil(t, a.db.Close())
|
require.Nil(t, a.db.Close())
|
||||||
conf.ProvisionUsers = []*User{}
|
conf.Users = []*User{}
|
||||||
conf.ProvisionAccess = map[string][]*Grant{}
|
conf.Access = map[string][]*Grant{}
|
||||||
a, err = NewManager(conf)
|
a, err = NewManager(conf)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
|
@ -1199,8 +1199,8 @@ func TestManager_DoNotUpdateNonProvisionedUsers(t *testing.T) {
|
||||||
Filename: f,
|
Filename: f,
|
||||||
DefaultAccess: PermissionReadWrite,
|
DefaultAccess: PermissionReadWrite,
|
||||||
ProvisionEnabled: true,
|
ProvisionEnabled: true,
|
||||||
ProvisionUsers: []*User{},
|
Users: []*User{},
|
||||||
ProvisionAccess: map[string][]*Grant{},
|
Access: map[string][]*Grant{},
|
||||||
}
|
}
|
||||||
a, err := NewManager(conf)
|
a, err := NewManager(conf)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
@ -1210,10 +1210,10 @@ func TestManager_DoNotUpdateNonProvisionedUsers(t *testing.T) {
|
||||||
|
|
||||||
// Re-open the DB (second app start)
|
// Re-open the DB (second app start)
|
||||||
require.Nil(t, a.db.Close())
|
require.Nil(t, a.db.Close())
|
||||||
conf.ProvisionUsers = []*User{
|
conf.Users = []*User{
|
||||||
{Name: "philuser", Hash: "$2a$10$AAAU21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleAdmin},
|
{Name: "philuser", Hash: "$2a$10$AAAU21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleAdmin},
|
||||||
}
|
}
|
||||||
conf.ProvisionAccess = map[string][]*Grant{}
|
conf.Access = map[string][]*Grant{}
|
||||||
a, err = NewManager(conf)
|
a, err = NewManager(conf)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue