package api import ( "sort" "github.com/mayswind/ezbookkeeping/pkg/auth/oauth2" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/log" "github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/services" ) // UserExternalAuthsApi represents user external auth api type UserExternalAuthsApi struct { users *services.UserService userExternalAuths *services.UserExternalAuthService } // Initialize a user external auth api singleton instance var ( UserExternalAuths = &UserExternalAuthsApi{ users: services.Users, userExternalAuths: services.UserExternalAuths, } ) // ExternalAuthListHanlder returns external authentications list of current user func (a *UserExternalAuthsApi) ExternalAuthListHanlder(c *core.WebContext) (any, *errs.Error) { uid := c.GetCurrentUid() userExternalAuths, err := a.userExternalAuths.GetUserAllExternalAuthsByUid(c, uid) if err != nil { log.Errorf(c, "[user_external_auths.ExternalAuthListHanlder] failed to get all external authentications for user \"uid:%d\", because %s", uid, err.Error()) return nil, errs.Or(err, errs.ErrOperationFailed) } userExternalAuthResps := make(models.UserExternalAuthInfoResponsesSlice, 0, len(userExternalAuths)+1) currentExternalAuthType := oauth2.GetExternalUserAuthType() hasCurrentExternalAuth := false for i := 0; i < len(userExternalAuths); i++ { userExternalAuth := userExternalAuths[i] if userExternalAuth.ExternalAuthType == currentExternalAuthType { hasCurrentExternalAuth = true } userExternalAuthResps = append(userExternalAuthResps, userExternalAuth.ToUserExternalAuthInfoResponse()) } if !hasCurrentExternalAuth { userExternalAuthResps = append(userExternalAuthResps, &models.UserExternalAuthInfoResponse{ ExternalAuthCategory: currentExternalAuthType.GetCategory(), ExternalAuthType: currentExternalAuthType, Linked: false, }) } sort.Sort(userExternalAuthResps) return userExternalAuthResps, nil } // UnlinkExternalAuthHandler unlinks external authentication for current user func (a *UserExternalAuthsApi) UnlinkExternalAuthHandler(c *core.WebContext) (any, *errs.Error) { var externalAuthLinkReq models.UserExternalAuthUnlinkRequest err := c.ShouldBindJSON(&externalAuthLinkReq) if err != nil { log.Warnf(c, "[user_external_auths.UnlinkExternalAuthHandler] parse request failed, because %s", err.Error()) return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) } uid := c.GetCurrentUid() user, err := a.users.GetUserById(c, uid) if err != nil { if !errs.IsCustomError(err) { log.Warnf(c, "[user_external_auths.UnlinkExternalAuthHandler] failed to get user for user \"uid:%d\", because %s", uid, err.Error()) } return nil, errs.ErrUserNotFound } if !a.users.IsPasswordEqualsUserPassword(externalAuthLinkReq.Password, user) { return nil, errs.ErrUserPasswordWrong } if user.FeatureRestriction.Contains(core.USER_FEATURE_RESTRICTION_TYPE_UNLINK_THIRD_PARTY_LOGIN) { return nil, errs.ErrNotPermittedToPerformThisAction } externalAuthType := core.UserExternalAuthType(externalAuthLinkReq.ExternalAuthType) if !externalAuthType.IsValid() { return nil, errs.ErrUserExternalAuthNotFound } err = a.userExternalAuths.DeleteUserExternalAuth(c, uid, externalAuthType) if err != nil { log.Errorf(c, "[user_external_auths.UnlinkExternalAuthHandler] failed to unlink external authentication \"%s\" for user \"uid:%d\", because %s", externalAuthLinkReq.ExternalAuthType, uid, err.Error()) return nil, errs.Or(err, errs.ErrOperationFailed) } return true, nil }