123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- // Copyright 2017 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package user
-
- import (
- "context"
- "fmt"
- "time"
-
- "code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/util"
-
- "xorm.io/builder"
- )
-
- // ErrExternalLoginUserAlreadyExist represents a "ExternalLoginUserAlreadyExist" kind of error.
- type ErrExternalLoginUserAlreadyExist struct {
- ExternalID string
- UserID int64
- LoginSourceID int64
- }
-
- // IsErrExternalLoginUserAlreadyExist checks if an error is a ExternalLoginUserAlreadyExist.
- func IsErrExternalLoginUserAlreadyExist(err error) bool {
- _, ok := err.(ErrExternalLoginUserAlreadyExist)
- return ok
- }
-
- func (err ErrExternalLoginUserAlreadyExist) Error() string {
- return fmt.Sprintf("external login user already exists [externalID: %s, userID: %d, loginSourceID: %d]", err.ExternalID, err.UserID, err.LoginSourceID)
- }
-
- func (err ErrExternalLoginUserAlreadyExist) Unwrap() error {
- return util.ErrAlreadyExist
- }
-
- // ErrExternalLoginUserNotExist represents a "ExternalLoginUserNotExist" kind of error.
- type ErrExternalLoginUserNotExist struct {
- UserID int64
- LoginSourceID int64
- }
-
- // IsErrExternalLoginUserNotExist checks if an error is a ExternalLoginUserNotExist.
- func IsErrExternalLoginUserNotExist(err error) bool {
- _, ok := err.(ErrExternalLoginUserNotExist)
- return ok
- }
-
- func (err ErrExternalLoginUserNotExist) Error() string {
- return fmt.Sprintf("external login user link does not exists [userID: %d, loginSourceID: %d]", err.UserID, err.LoginSourceID)
- }
-
- func (err ErrExternalLoginUserNotExist) Unwrap() error {
- return util.ErrNotExist
- }
-
- // ExternalLoginUser makes the connecting between some existing user and additional external login sources
- type ExternalLoginUser struct {
- ExternalID string `xorm:"pk NOT NULL"`
- UserID int64 `xorm:"INDEX NOT NULL"`
- LoginSourceID int64 `xorm:"pk NOT NULL"`
- RawData map[string]interface{} `xorm:"TEXT JSON"`
- Provider string `xorm:"index VARCHAR(25)"`
- Email string
- Name string
- FirstName string
- LastName string
- NickName string
- Description string
- AvatarURL string `xorm:"TEXT"`
- Location string
- AccessToken string `xorm:"TEXT"`
- AccessTokenSecret string `xorm:"TEXT"`
- RefreshToken string `xorm:"TEXT"`
- ExpiresAt time.Time
- }
-
- type ExternalUserMigrated interface {
- GetExternalName() string
- GetExternalID() int64
- }
-
- type ExternalUserRemappable interface {
- GetUserID() int64
- RemapExternalUser(externalName string, externalID, userID int64) error
- ExternalUserMigrated
- }
-
- func init() {
- db.RegisterModel(new(ExternalLoginUser))
- }
-
- // GetExternalLogin checks if a externalID in loginSourceID scope already exists
- func GetExternalLogin(externalLoginUser *ExternalLoginUser) (bool, error) {
- return db.GetEngine(db.DefaultContext).Get(externalLoginUser)
- }
-
- // ListAccountLinks returns a map with the ExternalLoginUser and its LoginSource
- func ListAccountLinks(user *User) ([]*ExternalLoginUser, error) {
- externalAccounts := make([]*ExternalLoginUser, 0, 5)
- err := db.GetEngine(db.DefaultContext).Where("user_id=?", user.ID).
- Desc("login_source_id").
- Find(&externalAccounts)
- if err != nil {
- return nil, err
- }
-
- return externalAccounts, nil
- }
-
- // LinkExternalToUser link the external user to the user
- func LinkExternalToUser(user *User, externalLoginUser *ExternalLoginUser) error {
- has, err := db.GetEngine(db.DefaultContext).Where("external_id=? AND login_source_id=?", externalLoginUser.ExternalID, externalLoginUser.LoginSourceID).
- NoAutoCondition().
- Exist(externalLoginUser)
- if err != nil {
- return err
- } else if has {
- return ErrExternalLoginUserAlreadyExist{externalLoginUser.ExternalID, user.ID, externalLoginUser.LoginSourceID}
- }
-
- _, err = db.GetEngine(db.DefaultContext).Insert(externalLoginUser)
- return err
- }
-
- // RemoveAccountLink will remove all external login sources for the given user
- func RemoveAccountLink(user *User, loginSourceID int64) (int64, error) {
- deleted, err := db.GetEngine(db.DefaultContext).Delete(&ExternalLoginUser{UserID: user.ID, LoginSourceID: loginSourceID})
- if err != nil {
- return deleted, err
- }
- if deleted < 1 {
- return deleted, ErrExternalLoginUserNotExist{user.ID, loginSourceID}
- }
- return deleted, err
- }
-
- // RemoveAllAccountLinks will remove all external login sources for the given user
- func RemoveAllAccountLinks(ctx context.Context, user *User) error {
- _, err := db.GetEngine(ctx).Delete(&ExternalLoginUser{UserID: user.ID})
- return err
- }
-
- // GetUserIDByExternalUserID get user id according to provider and userID
- func GetUserIDByExternalUserID(provider, userID string) (int64, error) {
- var id int64
- _, err := db.GetEngine(db.DefaultContext).Table("external_login_user").
- Select("user_id").
- Where("provider=?", provider).
- And("external_id=?", userID).
- Get(&id)
- if err != nil {
- return 0, err
- }
- return id, nil
- }
-
- // UpdateExternalUserByExternalID updates an external user's information
- func UpdateExternalUserByExternalID(external *ExternalLoginUser) error {
- has, err := db.GetEngine(db.DefaultContext).Where("external_id=? AND login_source_id=?", external.ExternalID, external.LoginSourceID).
- NoAutoCondition().
- Exist(external)
- if err != nil {
- return err
- } else if !has {
- return ErrExternalLoginUserNotExist{external.UserID, external.LoginSourceID}
- }
-
- _, err = db.GetEngine(db.DefaultContext).Where("external_id=? AND login_source_id=?", external.ExternalID, external.LoginSourceID).AllCols().Update(external)
- return err
- }
-
- // FindExternalUserOptions represents an options to find external users
- type FindExternalUserOptions struct {
- Provider string
- Limit int
- Start int
- }
-
- func (opts FindExternalUserOptions) toConds() builder.Cond {
- cond := builder.NewCond()
- if len(opts.Provider) > 0 {
- cond = cond.And(builder.Eq{"provider": opts.Provider})
- }
- return cond
- }
-
- // FindExternalUsersByProvider represents external users via provider
- func FindExternalUsersByProvider(opts FindExternalUserOptions) ([]ExternalLoginUser, error) {
- var users []ExternalLoginUser
- err := db.GetEngine(db.DefaultContext).Where(opts.toConds()).
- Limit(opts.Limit, opts.Start).
- OrderBy("login_source_id ASC, external_id ASC").
- Find(&users)
- if err != nil {
- return nil, err
- }
- return users, nil
- }
|