mirror of
https://github.com/binwiederhier/ntfy.git
synced 2025-07-20 10:04:08 +00:00
WIP: Predefined users
This commit is contained in:
parent
3c8ac4a1e1
commit
efef587671
5 changed files with 48 additions and 21 deletions
|
@ -52,6 +52,7 @@ 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-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.NewStringSliceFlag(&cli.StringSliceFlag{Name: "auth-users", Aliases: []string{"auth_users"}, EnvVars: []string{"NTFY_AUTH_USERS"}, Usage: "pre-provisioned declarative users"}),
|
||||
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-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)"}),
|
||||
|
@ -157,6 +158,7 @@ func execServe(c *cli.Context) error {
|
|||
authFile := c.String("auth-file")
|
||||
authStartupQueries := c.String("auth-startup-queries")
|
||||
authDefaultAccess := c.String("auth-default-access")
|
||||
authUsers := c.StringSlice("auth-users")
|
||||
attachmentCacheDir := c.String("attachment-cache-dir")
|
||||
attachmentTotalSizeLimitStr := c.String("attachment-total-size-limit")
|
||||
attachmentFileSizeLimitStr := c.String("attachment-file-size-limit")
|
||||
|
@ -406,6 +408,7 @@ func execServe(c *cli.Context) error {
|
|||
conf.AuthFile = authFile
|
||||
conf.AuthStartupQueries = authStartupQueries
|
||||
conf.AuthDefault = authDefault
|
||||
conf.AuthUsers = nil // FIXME
|
||||
conf.AttachmentCacheDir = attachmentCacheDir
|
||||
conf.AttachmentTotalSizeLimit = attachmentTotalSizeLimit
|
||||
conf.AttachmentFileSizeLimit = attachmentFileSizeLimit
|
||||
|
|
|
@ -94,7 +94,6 @@ Example:
|
|||
|
||||
You may set the NTFY_PASSWORD environment variable to pass the new password or NTFY_PASSWORD_HASH to pass
|
||||
directly the bcrypt hash. This is useful if you are updating users via scripts.
|
||||
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -93,6 +93,7 @@ type Config struct {
|
|||
AuthFile string
|
||||
AuthStartupQueries string
|
||||
AuthDefault user.Permission
|
||||
AuthUsers []user.User
|
||||
AuthBcryptCost int
|
||||
AuthStatsQueueWriterInterval time.Duration
|
||||
AttachmentCacheDir string
|
||||
|
|
|
@ -189,7 +189,14 @@ func New(conf *Config) (*Server, error) {
|
|||
}
|
||||
var userManager *user.Manager
|
||||
if conf.AuthFile != "" {
|
||||
userManager, err = user.NewManager(conf.AuthFile, conf.AuthStartupQueries, conf.AuthDefault, conf.AuthBcryptCost, conf.AuthStatsQueueWriterInterval)
|
||||
authConfig := &user.Config{
|
||||
Filename: conf.AuthFile,
|
||||
StartupQueries: conf.AuthStartupQueries,
|
||||
DefaultAccess: conf.AuthDefault,
|
||||
BcryptCost: conf.AuthBcryptCost,
|
||||
QueueWriterInterval: conf.AuthStatsQueueWriterInterval,
|
||||
}
|
||||
userManager, err = user.NewManager(authConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -441,36 +441,53 @@ var (
|
|||
// Manager is an implementation of Manager. It stores users and access control list
|
||||
// in a SQLite database.
|
||||
type Manager struct {
|
||||
db *sql.DB
|
||||
defaultAccess Permission // Default permission if no ACL matches
|
||||
statsQueue map[string]*Stats // "Queue" to asynchronously write user stats to the database (UserID -> Stats)
|
||||
tokenQueue map[string]*TokenUpdate // "Queue" to asynchronously write token access stats to the database (Token ID -> TokenUpdate)
|
||||
bcryptCost int // Makes testing easier
|
||||
mu sync.Mutex
|
||||
config *Config
|
||||
db *sql.DB
|
||||
statsQueue map[string]*Stats // "Queue" to asynchronously write user stats to the database (UserID -> Stats)
|
||||
tokenQueue map[string]*TokenUpdate // "Queue" to asynchronously write token access stats to the database (Token ID -> TokenUpdate)
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Filename string
|
||||
StartupQueries string
|
||||
DefaultAccess Permission // Default permission if no ACL matches
|
||||
ProvisionedUsers []*User // Predefined users to create on startup
|
||||
ProvisionedAccess map[string][]*Grant // Predefined access grants to create on startup
|
||||
BcryptCost int // Makes testing easier
|
||||
QueueWriterInterval time.Duration
|
||||
}
|
||||
|
||||
var _ Auther = (*Manager)(nil)
|
||||
|
||||
// NewManager creates a new Manager instance
|
||||
func NewManager(filename, startupQueries string, defaultAccess Permission, bcryptCost int, queueWriterInterval time.Duration) (*Manager, error) {
|
||||
db, err := sql.Open("sqlite3", filename)
|
||||
func NewManager(config *Config) (*Manager, error) {
|
||||
// Set defaults
|
||||
if config.BcryptCost <= 0 {
|
||||
config.BcryptCost = DefaultUserPasswordBcryptCost
|
||||
}
|
||||
if config.QueueWriterInterval.Seconds() <= 0 {
|
||||
config.QueueWriterInterval = DefaultUserStatsQueueWriterInterval
|
||||
}
|
||||
|
||||
// Open DB and run setup queries
|
||||
db, err := sql.Open("sqlite3", config.Filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := setupDB(db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := runStartupQueries(db, startupQueries); err != nil {
|
||||
if err := runStartupQueries(db, config.StartupQueries); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
manager := &Manager{
|
||||
db: db,
|
||||
defaultAccess: defaultAccess,
|
||||
statsQueue: make(map[string]*Stats),
|
||||
tokenQueue: make(map[string]*TokenUpdate),
|
||||
bcryptCost: bcryptCost,
|
||||
db: db,
|
||||
config: config,
|
||||
statsQueue: make(map[string]*Stats),
|
||||
tokenQueue: make(map[string]*TokenUpdate),
|
||||
}
|
||||
go manager.asyncQueueWriter(queueWriterInterval)
|
||||
go manager.asyncQueueWriter(config.QueueWriterInterval)
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
|
@ -843,7 +860,7 @@ func (a *Manager) Authorize(user *User, topic string, perm Permission) error {
|
|||
}
|
||||
defer rows.Close()
|
||||
if !rows.Next() {
|
||||
return a.resolvePerms(a.defaultAccess, perm)
|
||||
return a.resolvePerms(a.config.DefaultAccess, perm)
|
||||
}
|
||||
var read, write bool
|
||||
if err := rows.Scan(&read, &write); err != nil {
|
||||
|
@ -873,7 +890,7 @@ func (a *Manager) AddUser(username, password string, role Role, hashed bool) err
|
|||
if hashed {
|
||||
hash = []byte(password)
|
||||
} else {
|
||||
hash, err = bcrypt.GenerateFromPassword([]byte(password), a.bcryptCost)
|
||||
hash, err = bcrypt.GenerateFromPassword([]byte(password), a.config.BcryptCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1205,7 +1222,7 @@ func (a *Manager) ChangePassword(username, password string, hashed bool) error {
|
|||
if hashed {
|
||||
hash = []byte(password)
|
||||
} else {
|
||||
hash, err = bcrypt.GenerateFromPassword([]byte(password), a.bcryptCost)
|
||||
hash, err = bcrypt.GenerateFromPassword([]byte(password), a.config.BcryptCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1387,7 +1404,7 @@ func (a *Manager) RemoveReservations(username string, topics ...string) error {
|
|||
|
||||
// DefaultAccess returns the default read/write access if no access control entry matches
|
||||
func (a *Manager) DefaultAccess() Permission {
|
||||
return a.defaultAccess
|
||||
return a.config.DefaultAccess
|
||||
}
|
||||
|
||||
// AddTier creates a new tier in the database
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue