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 <ivan@synadia.com>
This commit is contained in:
Ivan Kozlovic
2020-06-09 17:27:51 -06:00
parent d18b013676
commit 313cf898c1
2 changed files with 61 additions and 79 deletions

View File

@@ -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 {

View File

@@ -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
}
}