9302eba971
* DBContext is just a Context This PR removes some of the specialness from the DBContext and makes it context This allows us to simplify the GetEngine code to wrap around any context in future and means that we can change our loadRepo(e Engine) functions to simply take contexts. Signed-off-by: Andrew Thornton <art27@cantab.net> * fix unit tests Signed-off-by: Andrew Thornton <art27@cantab.net> * another place that needs to set the initial context Signed-off-by: Andrew Thornton <art27@cantab.net> * avoid race Signed-off-by: Andrew Thornton <art27@cantab.net> * change attachment error Signed-off-by: Andrew Thornton <art27@cantab.net>
192 lines
6.2 KiB
Go
192 lines
6.2 KiB
Go
// Copyright 2017 The Gitea Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/modules/structs"
|
|
|
|
"github.com/markbates/goth"
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
// 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
|
|
Location string
|
|
AccessToken string `xorm:"TEXT"`
|
|
AccessTokenSecret string `xorm:"TEXT"`
|
|
RefreshToken string `xorm:"TEXT"`
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
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(e db.Engine, user *User) error {
|
|
_, err := e.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
|
|
}
|
|
|
|
// UpdateExternalUser updates external user's information
|
|
func UpdateExternalUser(user *User, gothUser goth.User) error {
|
|
loginSource, err := GetActiveOAuth2LoginSourceByName(gothUser.Provider)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
externalLoginUser := &ExternalLoginUser{
|
|
ExternalID: gothUser.UserID,
|
|
UserID: user.ID,
|
|
LoginSourceID: loginSource.ID,
|
|
RawData: gothUser.RawData,
|
|
Provider: gothUser.Provider,
|
|
Email: gothUser.Email,
|
|
Name: gothUser.Name,
|
|
FirstName: gothUser.FirstName,
|
|
LastName: gothUser.LastName,
|
|
NickName: gothUser.NickName,
|
|
Description: gothUser.Description,
|
|
AvatarURL: gothUser.AvatarURL,
|
|
Location: gothUser.Location,
|
|
AccessToken: gothUser.AccessToken,
|
|
AccessTokenSecret: gothUser.AccessTokenSecret,
|
|
RefreshToken: gothUser.RefreshToken,
|
|
ExpiresAt: gothUser.ExpiresAt,
|
|
}
|
|
|
|
has, err := db.GetEngine(db.DefaultContext).Where("external_id=? AND login_source_id=?", gothUser.UserID, loginSource.ID).
|
|
NoAutoCondition().
|
|
Exist(externalLoginUser)
|
|
if err != nil {
|
|
return err
|
|
} else if !has {
|
|
return ErrExternalLoginUserNotExist{user.ID, loginSource.ID}
|
|
}
|
|
|
|
_, err = db.GetEngine(db.DefaultContext).Where("external_id=? AND login_source_id=?", gothUser.UserID, loginSource.ID).AllCols().Update(externalLoginUser)
|
|
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
|
|
}
|
|
|
|
// UpdateMigrationsByType updates all migrated repositories' posterid from gitServiceType to replace originalAuthorID to posterID
|
|
func UpdateMigrationsByType(tp structs.GitServiceType, externalUserID string, userID int64) error {
|
|
if err := UpdateIssuesMigrationsByType(tp, externalUserID, userID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := UpdateCommentsMigrationsByType(tp, externalUserID, userID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := UpdateReleasesMigrationsByType(tp, externalUserID, userID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := UpdateReactionsMigrationsByType(tp, externalUserID, userID); err != nil {
|
|
return err
|
|
}
|
|
return UpdateReviewsMigrationsByType(tp, externalUserID, userID)
|
|
}
|