From 313cf898c1838213593c7e66e1937620454b397a Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Tue, 9 Jun 2020 17:27:51 -0600 Subject: [PATCH] Refactor some code to make it reuseable Building server's nkeys and users map out of slices form options has been made a function so it can be used for the server and websocket (and in future for mqtt) Signed-off-by: Ivan Kozlovic --- server/auth.go | 94 +++++++++++++++++++++++++-------------------- server/websocket.go | 46 ++++------------------ 2 files changed, 61 insertions(+), 79 deletions(-) diff --git a/server/auth.go b/server/auth.go index eb4c3b58..11f3a799 100644 --- a/server/auth.go +++ b/server/auth.go @@ -181,16 +181,16 @@ func (s *Server) checkAuthforWarnings() { } } -// If opts.Users or opts.Nkeys have definitions without an account -// defined assign them to the default global account. +// If Users or Nkeys options have definitions without an account defined, +// assign them to the default global account. // Lock should be held. -func (s *Server) assignGlobalAccountToOrphanUsers() { - for _, u := range s.users { +func (s *Server) assignGlobalAccountToOrphanUsers(nkeys map[string]*NkeyUser, users map[string]*User) { + for _, u := range users { if u.Account == nil { u.Account = s.gacc } } - for _, u := range s.nkeys { + for _, u := range nkeys { if u.Account == nil { u.Account = s.gacc } @@ -225,13 +225,11 @@ func validateResponsePermissions(p *Permissions) { // configureAuthorization will do any setup needed for authorization. // Lock is assumed held. func (s *Server) configureAuthorization() { - if s.opts == nil { + opts := s.getOpts() + if opts == nil { return } - // Snapshot server options. - opts := s.getOpts() - // Check for multiple users first // This just checks and sets up the user map if we have multiple users. if opts.CustomClientAuthentication != nil { @@ -239,43 +237,13 @@ func (s *Server) configureAuthorization() { } else if len(s.trustedKeys) > 0 { s.info.AuthRequired = true } else if opts.Nkeys != nil || opts.Users != nil { - // Support both at the same time. - if opts.Nkeys != nil { - s.nkeys = make(map[string]*NkeyUser) - for _, u := range opts.Nkeys { - copy := u.clone() - if u.Account != nil { - if v, ok := s.accounts.Load(u.Account.Name); ok { - copy.Account = v.(*Account) - } - } - if copy.Permissions != nil { - validateResponsePermissions(copy.Permissions) - } - s.nkeys[u.Nkey] = copy - } - } - if opts.Users != nil { - s.users = make(map[string]*User) - for _, u := range opts.Users { - copy := u.clone() - if u.Account != nil { - if v, ok := s.accounts.Load(u.Account.Name); ok { - copy.Account = v.(*Account) - } - } - if copy.Permissions != nil { - validateResponsePermissions(copy.Permissions) - } - s.users[u.Username] = copy - } - } - s.assignGlobalAccountToOrphanUsers() + s.nkeys, s.users = s.buildNkeysAndUsersFromOptions(opts.Nkeys, opts.Users) s.info.AuthRequired = true } else if opts.Username != "" || opts.Authorization != "" { s.info.AuthRequired = true } else { s.users = nil + s.nkeys = nil s.info.AuthRequired = false } @@ -283,6 +251,50 @@ func (s *Server) configureAuthorization() { s.wsConfigAuth(&opts.Websocket) } +// Takes the given slices of NkeyUser and User options and build +// corresponding maps used by the server. The users are cloned +// so that server does not reference options. +// The global account is assigned to users that don't have an +// existing account. +// Server lock is held on entry. +func (s *Server) buildNkeysAndUsersFromOptions(nko []*NkeyUser, uo []*User) (map[string]*NkeyUser, map[string]*User) { + var nkeys map[string]*NkeyUser + var users map[string]*User + + if len(nko) > 0 { + nkeys = make(map[string]*NkeyUser, len(nko)) + for _, u := range nko { + copy := u.clone() + if u.Account != nil { + if v, ok := s.accounts.Load(u.Account.Name); ok { + copy.Account = v.(*Account) + } + } + if copy.Permissions != nil { + validateResponsePermissions(copy.Permissions) + } + nkeys[u.Nkey] = copy + } + } + if len(uo) > 0 { + users = make(map[string]*User, len(uo)) + for _, u := range uo { + copy := u.clone() + if u.Account != nil { + if v, ok := s.accounts.Load(u.Account.Name); ok { + copy.Account = v.(*Account) + } + } + if copy.Permissions != nil { + validateResponsePermissions(copy.Permissions) + } + users[u.Username] = copy + } + } + s.assignGlobalAccountToOrphanUsers(nkeys, users) + return nkeys, users +} + // checkAuthentication will check based on client type and // return boolean indicating if client is authorized. func (s *Server) checkAuthentication(c *client) bool { diff --git a/server/websocket.go b/server/websocket.go index 3eacbd43..33990f61 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -772,46 +772,16 @@ func (s *Server) wsSetOriginOptions(o *WebsocketOpts) { // Also update a boolean that indicates if auth is required for // websocket clients. func (s *Server) wsConfigAuth(opts *WebsocketOpts) { - if opts.Nkeys != nil || opts.Users != nil { - // Support both at the same time. - if opts.Nkeys != nil { - s.websocket.nkeys = make(map[string]*NkeyUser) - for _, u := range opts.Nkeys { - copy := u.clone() - if u.Account != nil { - if v, ok := s.accounts.Load(u.Account.Name); ok { - copy.Account = v.(*Account) - } - } - if copy.Permissions != nil { - validateResponsePermissions(copy.Permissions) - } - s.websocket.nkeys[u.Nkey] = copy - } - } - if opts.Users != nil { - s.websocket.users = make(map[string]*User) - for _, u := range opts.Users { - copy := u.clone() - if u.Account != nil { - if v, ok := s.accounts.Load(u.Account.Name); ok { - copy.Account = v.(*Account) - } - } - if copy.Permissions != nil { - validateResponsePermissions(copy.Permissions) - } - s.websocket.users[u.Username] = copy - } - } - s.assignGlobalAccountToOrphanUsers() - s.websocket.authRequired = true + ws := &s.websocket + if len(opts.Nkeys) > 0 || len(opts.Users) > 0 { + ws.nkeys, ws.users = s.buildNkeysAndUsersFromOptions(opts.Nkeys, opts.Users) + ws.authRequired = true } else if opts.Username != "" || opts.Token != "" { - s.websocket.authRequired = true + ws.authRequired = true } else { - s.websocket.users = nil - s.websocket.nkeys = nil - s.websocket.authRequired = false + ws.users = nil + ws.nkeys = nil + ws.authRequired = false } }