github.com/cs3org/reva/v2@v2.27.7/pkg/siteacc/manager/usersmanager.go (about) 1 // Copyright 2018-2020 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package manager 20 21 import ( 22 "strings" 23 24 "github.com/cs3org/reva/v2/pkg/siteacc/config" 25 "github.com/cs3org/reva/v2/pkg/siteacc/html" 26 "github.com/pkg/errors" 27 "github.com/rs/zerolog" 28 ) 29 30 // UsersManager is responsible for managing logged in users through session objects. 31 type UsersManager struct { 32 conf *config.Configuration 33 log *zerolog.Logger 34 35 sitesManager *SitesManager 36 accountsManager *AccountsManager 37 } 38 39 const ( 40 defaultPasswordLength = 12 41 ) 42 43 func (mngr *UsersManager) initialize(conf *config.Configuration, log *zerolog.Logger, sitesManager *SitesManager, accountsManager *AccountsManager) error { 44 if conf == nil { 45 return errors.Errorf("no configuration provided") 46 } 47 mngr.conf = conf 48 49 if log == nil { 50 return errors.Errorf("no logger provided") 51 } 52 mngr.log = log 53 54 if sitesManager == nil { 55 return errors.Errorf("no sites manager provided") 56 } 57 mngr.sitesManager = sitesManager 58 59 if accountsManager == nil { 60 return errors.Errorf("no accounts manager provided") 61 } 62 mngr.accountsManager = accountsManager 63 64 return nil 65 } 66 67 // LoginUser tries to login a given username/password pair. On success, the corresponding user account is stored in the session and a user token is returned. 68 func (mngr *UsersManager) LoginUser(name, password string, scope string, session *html.Session) (string, error) { 69 account, err := mngr.accountsManager.FindAccountEx(FindByEmail, name, false) 70 if err != nil { 71 return "", errors.Wrap(err, "no account with the specified email exists") 72 } 73 74 // Verify the provided password 75 if !account.Password.Compare(password) { 76 return "", errors.Errorf("invalid password") 77 } 78 79 // Check if the user has access to the specified scope 80 if !account.CheckScopeAccess(scope) { 81 return "", errors.Errorf("no access to the specified scope granted") 82 } 83 84 // Get the site the account belongs to 85 site, err := mngr.sitesManager.GetSite(account.Site, false) 86 if err != nil { 87 return "", errors.Wrap(err, "no site with the specified ID exists") 88 } 89 90 // Store the user account in the session 91 session.LoginUser(account, site) 92 93 // Generate a token that can be used as a "ticket" 94 token, err := generateUserToken(session.LoggedInUser().Account.Email, scope, mngr.conf.Webserver.SessionTimeout) 95 if err != nil { 96 return "", errors.Wrap(err, "unable to generate user token") 97 } 98 99 return token, nil 100 } 101 102 // LogoutUser logs the current user out. 103 func (mngr *UsersManager) LogoutUser(session *html.Session) { 104 // Just unset the user account stored in the session 105 session.LogoutUser() 106 } 107 108 // VerifyUserToken is used to verify a user token against the current session. 109 func (mngr *UsersManager) VerifyUserToken(token string, user string, scope string) (string, error) { 110 // Verify the token by trying to extract it 111 utoken, err := extractUserToken(token) 112 if err != nil { 113 return "", errors.Wrap(err, "unable to verify user token") 114 } 115 116 // Check the provided email against the stored one 117 if !strings.EqualFold(utoken.User, user) { 118 return "", errors.Errorf("mismatching user") 119 } 120 121 // Check if the user account actually exists and has proper scope access 122 if strings.EqualFold(scope, utoken.Scope) { 123 if acc, err := mngr.accountsManager.FindAccount(FindByEmail, utoken.User); err == nil { 124 if !acc.CheckScopeAccess(scope) { 125 return "", errors.Errorf("no scope access") 126 } 127 } else { 128 return "", errors.Errorf("invalid email") 129 } 130 } else { 131 return "", errors.Errorf("invalid scope") 132 } 133 134 // Refresh the user token (as a form of keep-alive, since tokens expire quickly) 135 newToken, err := generateUserToken(utoken.User, utoken.Scope, mngr.conf.Webserver.SessionTimeout) 136 if err != nil { 137 return "", errors.Wrap(err, "unable to refresh user token") 138 } 139 140 return newToken, nil 141 } 142 143 // NewUsersManager creates a new users manager instance. 144 func NewUsersManager(conf *config.Configuration, log *zerolog.Logger, sitesManager *SitesManager, accountsManager *AccountsManager) (*UsersManager, error) { 145 mngr := &UsersManager{} 146 if err := mngr.initialize(conf, log, sitesManager, accountsManager); err != nil { 147 return nil, errors.Wrap(err, "unable to initialize the users manager") 148 } 149 return mngr, nil 150 }