code.gitea.io/gitea@v1.22.3/services/externalaccount/user.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package externalaccount 5 6 import ( 7 "context" 8 "strconv" 9 "strings" 10 11 "code.gitea.io/gitea/models/auth" 12 issues_model "code.gitea.io/gitea/models/issues" 13 repo_model "code.gitea.io/gitea/models/repo" 14 user_model "code.gitea.io/gitea/models/user" 15 "code.gitea.io/gitea/modules/structs" 16 17 "github.com/markbates/goth" 18 ) 19 20 func toExternalLoginUser(ctx context.Context, user *user_model.User, gothUser goth.User) (*user_model.ExternalLoginUser, error) { 21 authSource, err := auth.GetActiveOAuth2SourceByName(ctx, gothUser.Provider) 22 if err != nil { 23 return nil, err 24 } 25 return &user_model.ExternalLoginUser{ 26 ExternalID: gothUser.UserID, 27 UserID: user.ID, 28 LoginSourceID: authSource.ID, 29 RawData: gothUser.RawData, 30 Provider: gothUser.Provider, 31 Email: gothUser.Email, 32 Name: gothUser.Name, 33 FirstName: gothUser.FirstName, 34 LastName: gothUser.LastName, 35 NickName: gothUser.NickName, 36 Description: gothUser.Description, 37 AvatarURL: gothUser.AvatarURL, 38 Location: gothUser.Location, 39 AccessToken: gothUser.AccessToken, 40 AccessTokenSecret: gothUser.AccessTokenSecret, 41 RefreshToken: gothUser.RefreshToken, 42 ExpiresAt: gothUser.ExpiresAt, 43 }, nil 44 } 45 46 // LinkAccountToUser link the gothUser to the user 47 func LinkAccountToUser(ctx context.Context, user *user_model.User, gothUser goth.User) error { 48 externalLoginUser, err := toExternalLoginUser(ctx, user, gothUser) 49 if err != nil { 50 return err 51 } 52 53 if err := user_model.LinkExternalToUser(ctx, user, externalLoginUser); err != nil { 54 return err 55 } 56 57 externalID := externalLoginUser.ExternalID 58 59 var tp structs.GitServiceType 60 for _, s := range structs.SupportedFullGitService { 61 if strings.EqualFold(s.Name(), gothUser.Provider) { 62 tp = s 63 break 64 } 65 } 66 67 if tp.Name() != "" { 68 return UpdateMigrationsByType(ctx, tp, externalID, user.ID) 69 } 70 71 return nil 72 } 73 74 // UpdateExternalUser updates external user's information 75 func UpdateExternalUser(ctx context.Context, user *user_model.User, gothUser goth.User) error { 76 externalLoginUser, err := toExternalLoginUser(ctx, user, gothUser) 77 if err != nil { 78 return err 79 } 80 81 return user_model.UpdateExternalUserByExternalID(ctx, externalLoginUser) 82 } 83 84 // UpdateMigrationsByType updates all migrated repositories' posterid from gitServiceType to replace originalAuthorID to posterID 85 func UpdateMigrationsByType(ctx context.Context, tp structs.GitServiceType, externalUserID string, userID int64) error { 86 // Skip update if externalUserID is not a valid numeric ID or exceeds int64 87 if _, err := strconv.ParseInt(externalUserID, 10, 64); err != nil { 88 return nil 89 } 90 91 if err := issues_model.UpdateIssuesMigrationsByType(ctx, tp, externalUserID, userID); err != nil { 92 return err 93 } 94 95 if err := issues_model.UpdateCommentsMigrationsByType(ctx, tp, externalUserID, userID); err != nil { 96 return err 97 } 98 99 if err := repo_model.UpdateReleasesMigrationsByType(ctx, tp, externalUserID, userID); err != nil { 100 return err 101 } 102 103 if err := issues_model.UpdateReactionsMigrationsByType(ctx, tp, externalUserID, userID); err != nil { 104 return err 105 } 106 return issues_model.UpdateReviewsMigrationsByType(ctx, tp, externalUserID, userID) 107 }