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  }