Move EmailAddress & UserRedirect into models/user/ (#17607)
* Move EmailAddress into models/user/ * Fix test * rename user_mail to user_email * Fix test * Move UserRedirect into models/user/ * Fix lint & test * Fix lint * Fix lint * remove nolint comment * Fix lint
This commit is contained in:
parent
492e1c2fbd
commit
90eb9fb889
|
@ -123,21 +123,6 @@ func (err ErrUserNotExist) Error() string {
|
||||||
return fmt.Sprintf("user does not exist [uid: %d, name: %s, keyid: %d]", err.UID, err.Name, err.KeyID)
|
return fmt.Sprintf("user does not exist [uid: %d, name: %s, keyid: %d]", err.UID, err.Name, err.KeyID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrUserRedirectNotExist represents a "UserRedirectNotExist" kind of error.
|
|
||||||
type ErrUserRedirectNotExist struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrUserRedirectNotExist check if an error is an ErrUserRedirectNotExist.
|
|
||||||
func IsErrUserRedirectNotExist(err error) bool {
|
|
||||||
_, ok := err.(ErrUserRedirectNotExist)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrUserRedirectNotExist) Error() string {
|
|
||||||
return fmt.Sprintf("user redirect does not exist [name: %s]", err.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrUserProhibitLogin represents a "ErrUserProhibitLogin" kind of error.
|
// ErrUserProhibitLogin represents a "ErrUserProhibitLogin" kind of error.
|
||||||
type ErrUserProhibitLogin struct {
|
type ErrUserProhibitLogin struct {
|
||||||
UID int64
|
UID int64
|
||||||
|
@ -170,66 +155,6 @@ func (err ErrUserInactive) Error() string {
|
||||||
return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name)
|
return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrEmailAlreadyUsed represents a "EmailAlreadyUsed" kind of error.
|
|
||||||
type ErrEmailAlreadyUsed struct {
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrEmailAlreadyUsed checks if an error is a ErrEmailAlreadyUsed.
|
|
||||||
func IsErrEmailAlreadyUsed(err error) bool {
|
|
||||||
_, ok := err.(ErrEmailAlreadyUsed)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrEmailAlreadyUsed) Error() string {
|
|
||||||
return fmt.Sprintf("e-mail already in use [email: %s]", err.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrEmailInvalid represents an error where the email address does not comply with RFC 5322
|
|
||||||
type ErrEmailInvalid struct {
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrEmailInvalid checks if an error is an ErrEmailInvalid
|
|
||||||
func IsErrEmailInvalid(err error) bool {
|
|
||||||
_, ok := err.(ErrEmailInvalid)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrEmailInvalid) Error() string {
|
|
||||||
return fmt.Sprintf("e-mail invalid [email: %s]", err.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrEmailAddressNotExist email address not exist
|
|
||||||
type ErrEmailAddressNotExist struct {
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrEmailAddressNotExist checks if an error is an ErrEmailAddressNotExist
|
|
||||||
func IsErrEmailAddressNotExist(err error) bool {
|
|
||||||
_, ok := err.(ErrEmailAddressNotExist)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrEmailAddressNotExist) Error() string {
|
|
||||||
return fmt.Sprintf("Email address does not exist [email: %s]", err.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrPrimaryEmailCannotDelete primary email address cannot be deleted
|
|
||||||
type ErrPrimaryEmailCannotDelete struct {
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrPrimaryEmailCannotDelete checks if an error is an ErrPrimaryEmailCannotDelete
|
|
||||||
func IsErrPrimaryEmailCannotDelete(err error) bool {
|
|
||||||
_, ok := err.(ErrPrimaryEmailCannotDelete)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrPrimaryEmailCannotDelete) Error() string {
|
|
||||||
return fmt.Sprintf("Primary email address cannot be deleted [email: %s]", err.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrOpenIDAlreadyUsed represents a "OpenIDAlreadyUsed" kind of error.
|
// ErrOpenIDAlreadyUsed represents a "OpenIDAlreadyUsed" kind of error.
|
||||||
type ErrOpenIDAlreadyUsed struct {
|
type ErrOpenIDAlreadyUsed struct {
|
||||||
OpenID string
|
OpenID string
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ type GPGKey struct {
|
||||||
ExpiredUnix timeutil.TimeStamp
|
ExpiredUnix timeutil.TimeStamp
|
||||||
AddedUnix timeutil.TimeStamp
|
AddedUnix timeutil.TimeStamp
|
||||||
SubsKey []*GPGKey `xorm:"-"`
|
SubsKey []*GPGKey `xorm:"-"`
|
||||||
Emails []*EmailAddress
|
Emails []*user_model.EmailAddress
|
||||||
Verified bool `xorm:"NOT NULL DEFAULT false"`
|
Verified bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
CanSign bool
|
CanSign bool
|
||||||
CanEncryptComms bool
|
CanEncryptComms bool
|
||||||
|
@ -148,12 +149,12 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity, verified bool) (*GPGKey, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check emails
|
// Check emails
|
||||||
userEmails, err := GetEmailAddresses(ownerID)
|
userEmails, err := user_model.GetEmailAddresses(ownerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
emails := make([]*EmailAddress, 0, len(e.Identities))
|
emails := make([]*user_model.EmailAddress, 0, len(e.Identities))
|
||||||
for _, ident := range e.Identities {
|
for _, ident := range e.Identities {
|
||||||
if ident.Revocation != nil {
|
if ident.Revocation != nil {
|
||||||
continue
|
continue
|
||||||
|
@ -242,7 +243,7 @@ func DeleteGPGKey(doer *User, id int64) (err error) {
|
||||||
|
|
||||||
func checkKeyEmails(email string, keys ...*GPGKey) (bool, string) {
|
func checkKeyEmails(email string, keys ...*GPGKey) (bool, string) {
|
||||||
uid := int64(0)
|
uid := int64(0)
|
||||||
var userEmails []*EmailAddress
|
var userEmails []*user_model.EmailAddress
|
||||||
var user *User
|
var user *User
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
for _, e := range key.Emails {
|
for _, e := range key.Emails {
|
||||||
|
@ -252,7 +253,7 @@ func checkKeyEmails(email string, keys ...*GPGKey) (bool, string) {
|
||||||
}
|
}
|
||||||
if key.Verified && key.OwnerID != 0 {
|
if key.Verified && key.OwnerID != 0 {
|
||||||
if uid != key.OwnerID {
|
if uid != key.OwnerID {
|
||||||
userEmails, _ = GetEmailAddresses(key.OwnerID)
|
userEmails, _ = user_model.GetEmailAddresses(key.OwnerID)
|
||||||
uid = key.OwnerID
|
uid = key.OwnerID
|
||||||
user = &User{ID: uid}
|
user = &User{ID: uid}
|
||||||
_, _ = GetUser(user)
|
_, _ = GetUser(user)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -167,7 +168,7 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
committerEmailAddresses, _ := GetEmailAddresses(committer.ID)
|
committerEmailAddresses, _ := user_model.GetEmailAddresses(committer.ID)
|
||||||
activated := false
|
activated := false
|
||||||
for _, e := range committerEmailAddresses {
|
for _, e := range committerEmailAddresses {
|
||||||
if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) {
|
if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
@ -163,25 +164,25 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||||
org.NumMembers = 1
|
org.NumMembers = 1
|
||||||
org.Type = UserTypeOrganization
|
org.Type = UserTypeOrganization
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
if err = user_model.DeleteUserRedirect(ctx, org.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = deleteUserRedirect(sess, org.Name); err != nil {
|
if err = db.Insert(ctx, org); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = sess.Insert(org); err != nil {
|
|
||||||
return fmt.Errorf("insert organization: %v", err)
|
return fmt.Errorf("insert organization: %v", err)
|
||||||
}
|
}
|
||||||
if err = org.generateRandomAvatar(sess); err != nil {
|
if err = org.generateRandomAvatar(db.GetEngine(ctx)); err != nil {
|
||||||
return fmt.Errorf("generate random avatar: %v", err)
|
return fmt.Errorf("generate random avatar: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add initial creator to organization and owner team.
|
// Add initial creator to organization and owner team.
|
||||||
if _, err = sess.Insert(&OrgUser{
|
if err = db.Insert(ctx, &OrgUser{
|
||||||
UID: owner.ID,
|
UID: owner.ID,
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -198,7 +199,7 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||||
IncludesAllRepositories: true,
|
IncludesAllRepositories: true,
|
||||||
CanCreateOrgRepo: true,
|
CanCreateOrgRepo: true,
|
||||||
}
|
}
|
||||||
if _, err = sess.Insert(t); err != nil {
|
if err = db.Insert(ctx, t); err != nil {
|
||||||
return fmt.Errorf("insert owner team: %v", err)
|
return fmt.Errorf("insert owner team: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,14 +213,11 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.Insert(&units); err != nil {
|
if err = db.Insert(ctx, &units); err != nil {
|
||||||
if err := sess.Rollback(); err != nil {
|
|
||||||
log.Error("CreateOrganization: sess.Rollback: %v", err)
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.Insert(&TeamUser{
|
if err = db.Insert(ctx, &TeamUser{
|
||||||
UID: owner.ID,
|
UID: owner.ID,
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
TeamID: t.ID,
|
TeamID: t.ID,
|
||||||
|
@ -227,7 +225,7 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||||
return fmt.Errorf("insert team-user relation: %v", err)
|
return fmt.Errorf("insert team-user relation: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrgByName returns organization by given name.
|
// GetOrgByName returns organization by given name.
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ func CheckPrincipalKeyString(user *User, content string) (_ string, err error) {
|
||||||
case "anything":
|
case "anything":
|
||||||
return content, nil
|
return content, nil
|
||||||
case "email":
|
case "email":
|
||||||
emails, err := GetEmailAddresses(user.ID)
|
emails, err := user_model.GetEmailAddresses(user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -77,9 +78,6 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrEmailNotActivated e-mail address has not been activated error
|
|
||||||
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
|
|
||||||
|
|
||||||
// ErrUserNameIllegal user name contains illegal characters error
|
// ErrUserNameIllegal user name contains illegal characters error
|
||||||
ErrUserNameIllegal = errors.New("User name contains illegal characters")
|
ErrUserNameIllegal = errors.New("User name contains illegal characters")
|
||||||
|
|
||||||
|
@ -890,14 +888,15 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
u.Visibility = overwriteDefault[0].Visibility
|
u.Visibility = overwriteDefault[0].Visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
// validate data
|
// validate data
|
||||||
|
|
||||||
if err := validateUser(u); err != nil {
|
if err := validateUser(u); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -909,11 +908,13 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
return ErrUserAlreadyExist{u.Name}
|
return ErrUserAlreadyExist{u.Name}
|
||||||
}
|
}
|
||||||
|
|
||||||
isExist, err = isEmailUsed(sess, u.Email)
|
isExist, err = user_model.IsEmailUsed(ctx, u.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if isExist {
|
} else if isExist {
|
||||||
return ErrEmailAlreadyUsed{u.Email}
|
return user_model.ErrEmailAlreadyUsed{
|
||||||
|
Email: u.Email,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare for database
|
// prepare for database
|
||||||
|
@ -929,16 +930,16 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
|
|
||||||
// save changes to database
|
// save changes to database
|
||||||
|
|
||||||
if err = deleteUserRedirect(sess, u.Name); err != nil {
|
if err = user_model.DeleteUserRedirect(ctx, u.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.Insert(u); err != nil {
|
if err = db.Insert(ctx, u); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert email address
|
// insert email address
|
||||||
if _, err := sess.Insert(&EmailAddress{
|
if err := db.Insert(ctx, &user_model.EmailAddress{
|
||||||
UID: u.ID,
|
UID: u.ID,
|
||||||
Email: u.Email,
|
Email: u.Email,
|
||||||
LowerEmail: strings.ToLower(u.Email),
|
LowerEmail: strings.ToLower(u.Email),
|
||||||
|
@ -948,7 +949,7 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func countUsers(e db.Engine) int64 {
|
func countUsers(e db.Engine) int64 {
|
||||||
|
@ -998,7 +999,7 @@ func VerifyUserActiveCode(code string) (user *User) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyActiveEmailCode verifies active email code when active account
|
// VerifyActiveEmailCode verifies active email code when active account
|
||||||
func VerifyActiveEmailCode(code, email string) *EmailAddress {
|
func VerifyActiveEmailCode(code, email string) *user_model.EmailAddress {
|
||||||
minutes := setting.Service.ActiveCodeLives
|
minutes := setting.Service.ActiveCodeLives
|
||||||
|
|
||||||
if user := getVerifyUser(code); user != nil {
|
if user := getVerifyUser(code); user != nil {
|
||||||
|
@ -1007,7 +1008,7 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress {
|
||||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
|
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
|
||||||
|
|
||||||
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
||||||
emailAddress := &EmailAddress{UID: user.ID, Email: email}
|
emailAddress := &user_model.EmailAddress{UID: user.ID, Email: email}
|
||||||
if has, _ := db.GetEngine(db.DefaultContext).Get(emailAddress); has {
|
if has, _ := db.GetEngine(db.DefaultContext).Get(emailAddress); has {
|
||||||
return emailAddress
|
return emailAddress
|
||||||
}
|
}
|
||||||
|
@ -1023,11 +1024,12 @@ func ChangeUserName(u *User, newUserName string) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
isExist, err := isUserExist(sess, 0, newUserName)
|
isExist, err := isUserExist(sess, 0, newUserName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1045,11 +1047,11 @@ func ChangeUserName(u *User, newUserName string) (err error) {
|
||||||
return fmt.Errorf("Rename user directory: %v", err)
|
return fmt.Errorf("Rename user directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = newUserRedirect(sess, u.ID, oldUserName, newUserName); err != nil {
|
if err = user_model.NewUserRedirect(ctx, u.ID, oldUserName, newUserName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
if err = committer.Commit(); err != nil {
|
||||||
if err2 := util.Rename(UserPath(newUserName), UserPath(oldUserName)); err2 != nil && !os.IsNotExist(err2) {
|
if err2 := util.Rename(UserPath(newUserName), UserPath(oldUserName)); err2 != nil && !os.IsNotExist(err2) {
|
||||||
log.Critical("Unable to rollback directory change during failed username change from: %s to: %s. DB Error: %v. Filesystem Error: %v", oldUserName, newUserName, err, err2)
|
log.Critical("Unable to rollback directory change during failed username change from: %s to: %s. DB Error: %v. Filesystem Error: %v", oldUserName, newUserName, err, err2)
|
||||||
return fmt.Errorf("failed to rollback directory change during failed username change from: %s to: %s. DB Error: %w. Filesystem Error: %v", oldUserName, newUserName, err, err2)
|
return fmt.Errorf("failed to rollback directory change during failed username change from: %s to: %s. DB Error: %w. Filesystem Error: %v", oldUserName, newUserName, err, err2)
|
||||||
|
@ -1071,7 +1073,9 @@ func checkDupEmail(e db.Engine, u *User) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if has {
|
} else if has {
|
||||||
return ErrEmailAlreadyUsed{u.Email}
|
return user_model.ErrEmailAlreadyUsed{
|
||||||
|
Email: u.Email,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1083,7 +1087,7 @@ func validateUser(u *User) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Email = strings.ToLower(u.Email)
|
u.Email = strings.ToLower(u.Email)
|
||||||
return ValidateEmail(u.Email)
|
return user_model.ValidateEmail(u.Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUser(e db.Engine, u *User) error {
|
func updateUser(e db.Engine, u *User) error {
|
||||||
|
@ -1211,7 +1215,7 @@ func deleteUser(e db.Engine, u *User) error {
|
||||||
&Follow{FollowID: u.ID},
|
&Follow{FollowID: u.ID},
|
||||||
&Action{UserID: u.ID},
|
&Action{UserID: u.ID},
|
||||||
&IssueUser{UID: u.ID},
|
&IssueUser{UID: u.ID},
|
||||||
&EmailAddress{UID: u.ID},
|
&user_model.EmailAddress{UID: u.ID},
|
||||||
&UserOpenID{UID: u.ID},
|
&UserOpenID{UID: u.ID},
|
||||||
&Reaction{UserID: u.ID},
|
&Reaction{UserID: u.ID},
|
||||||
&TeamUser{UID: u.ID},
|
&TeamUser{UID: u.ID},
|
||||||
|
@ -1370,7 +1374,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) (err erro
|
||||||
|
|
||||||
_, err = db.GetEngine(db.DefaultContext).
|
_, err = db.GetEngine(db.DefaultContext).
|
||||||
Where("is_activated = ?", false).
|
Where("is_activated = ?", false).
|
||||||
Delete(new(EmailAddress))
|
Delete(new(user_model.EmailAddress))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1576,7 +1580,7 @@ func GetUserByEmailContext(ctx context.Context, email string) (*User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, check in alternative list for activated email addresses
|
// Otherwise, check in alternative list for activated email addresses
|
||||||
emailAddress := &EmailAddress{Email: email, IsActivated: true}
|
emailAddress := &user_model.EmailAddress{Email: email, IsActivated: true}
|
||||||
has, err = db.GetEngine(ctx).Get(emailAddress)
|
has, err = db.GetEngine(ctx).Get(emailAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
269
models/user/email_address.go
Normal file
269
models/user/email_address.go
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/mail"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrEmailNotActivated e-mail address has not been activated error
|
||||||
|
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrEmailInvalid represents an error where the email address does not comply with RFC 5322
|
||||||
|
type ErrEmailInvalid struct {
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrEmailInvalid checks if an error is an ErrEmailInvalid
|
||||||
|
func IsErrEmailInvalid(err error) bool {
|
||||||
|
_, ok := err.(ErrEmailInvalid)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrEmailInvalid) Error() string {
|
||||||
|
return fmt.Sprintf("e-mail invalid [email: %s]", err.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrEmailAlreadyUsed represents a "EmailAlreadyUsed" kind of error.
|
||||||
|
type ErrEmailAlreadyUsed struct {
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrEmailAlreadyUsed checks if an error is a ErrEmailAlreadyUsed.
|
||||||
|
func IsErrEmailAlreadyUsed(err error) bool {
|
||||||
|
_, ok := err.(ErrEmailAlreadyUsed)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrEmailAlreadyUsed) Error() string {
|
||||||
|
return fmt.Sprintf("e-mail already in use [email: %s]", err.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrEmailAddressNotExist email address not exist
|
||||||
|
type ErrEmailAddressNotExist struct {
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrEmailAddressNotExist checks if an error is an ErrEmailAddressNotExist
|
||||||
|
func IsErrEmailAddressNotExist(err error) bool {
|
||||||
|
_, ok := err.(ErrEmailAddressNotExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrEmailAddressNotExist) Error() string {
|
||||||
|
return fmt.Sprintf("Email address does not exist [email: %s]", err.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrPrimaryEmailCannotDelete primary email address cannot be deleted
|
||||||
|
type ErrPrimaryEmailCannotDelete struct {
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrPrimaryEmailCannotDelete checks if an error is an ErrPrimaryEmailCannotDelete
|
||||||
|
func IsErrPrimaryEmailCannotDelete(err error) bool {
|
||||||
|
_, ok := err.(ErrPrimaryEmailCannotDelete)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrPrimaryEmailCannotDelete) Error() string {
|
||||||
|
return fmt.Sprintf("Primary email address cannot be deleted [email: %s]", err.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmailAddress is the list of all email addresses of a user. It also contains the
|
||||||
|
// primary email address which is saved in user table.
|
||||||
|
type EmailAddress struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
UID int64 `xorm:"INDEX NOT NULL"`
|
||||||
|
Email string `xorm:"UNIQUE NOT NULL"`
|
||||||
|
LowerEmail string `xorm:"UNIQUE NOT NULL"`
|
||||||
|
IsActivated bool
|
||||||
|
IsPrimary bool `xorm:"DEFAULT(false) NOT NULL"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
db.RegisterModel(new(EmailAddress))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeInsert will be invoked by XORM before inserting a record
|
||||||
|
func (email *EmailAddress) BeforeInsert() {
|
||||||
|
if email.LowerEmail == "" {
|
||||||
|
email.LowerEmail = strings.ToLower(email.Email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateEmail check if email is a allowed address
|
||||||
|
func ValidateEmail(email string) error {
|
||||||
|
if len(email) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := mail.ParseAddress(email); err != nil {
|
||||||
|
return ErrEmailInvalid{email}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add an email allow/block list
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailAddresses returns all email addresses belongs to given user.
|
||||||
|
func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
|
||||||
|
emails := make([]*EmailAddress, 0, 5)
|
||||||
|
if err := db.GetEngine(db.DefaultContext).
|
||||||
|
Where("uid=?", uid).
|
||||||
|
Asc("id").
|
||||||
|
Find(&emails); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emails, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailAddressByID gets a user's email address by ID
|
||||||
|
func GetEmailAddressByID(uid, id int64) (*EmailAddress, error) {
|
||||||
|
// User ID is required for security reasons
|
||||||
|
email := &EmailAddress{UID: uid}
|
||||||
|
if has, err := db.GetEngine(db.DefaultContext).ID(id).Get(email); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !has {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return email, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmailActive check if email is activated with a different emailID
|
||||||
|
func IsEmailActive(ctx context.Context, email string, excludeEmailID int64) (bool, error) {
|
||||||
|
if len(email) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't filter by boolean field unless it's explicit
|
||||||
|
cond := builder.NewCond()
|
||||||
|
cond = cond.And(builder.Eq{"lower_email": strings.ToLower(email)}, builder.Neq{"id": excludeEmailID})
|
||||||
|
if setting.Service.RegisterEmailConfirm {
|
||||||
|
// Inactive (unvalidated) addresses don't count as active if email validation is required
|
||||||
|
cond = cond.And(builder.Eq{"is_activated": true})
|
||||||
|
}
|
||||||
|
|
||||||
|
var em EmailAddress
|
||||||
|
if has, err := db.GetEngine(ctx).Where(cond).Get(&em); has || err != nil {
|
||||||
|
if has {
|
||||||
|
log.Info("isEmailActive(%q, %d) found duplicate in email ID %d", email, excludeEmailID, em.ID)
|
||||||
|
}
|
||||||
|
return has, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmailUsed returns true if the email has been used.
|
||||||
|
func IsEmailUsed(ctx context.Context, email string) (bool, error) {
|
||||||
|
if len(email) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.GetEngine(ctx).Where("lower_email=?", strings.ToLower(email)).Get(&EmailAddress{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func addEmailAddress(ctx context.Context, email *EmailAddress) error {
|
||||||
|
email.Email = strings.TrimSpace(email.Email)
|
||||||
|
used, err := IsEmailUsed(ctx, email.Email)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if used {
|
||||||
|
return ErrEmailAlreadyUsed{email.Email}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ValidateEmail(email.Email); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.Insert(ctx, email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEmailAddress adds an email address to given user.
|
||||||
|
func AddEmailAddress(email *EmailAddress) error {
|
||||||
|
return addEmailAddress(db.DefaultContext, email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEmailAddresses adds an email address to given user.
|
||||||
|
func AddEmailAddresses(emails []*EmailAddress) error {
|
||||||
|
if len(emails) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if any of them has been used
|
||||||
|
for i := range emails {
|
||||||
|
emails[i].Email = strings.TrimSpace(emails[i].Email)
|
||||||
|
used, err := IsEmailUsed(db.DefaultContext, emails[i].Email)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if used {
|
||||||
|
return ErrEmailAlreadyUsed{emails[i].Email}
|
||||||
|
}
|
||||||
|
if err = ValidateEmail(emails[i].Email); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Insert(db.DefaultContext, emails); err != nil {
|
||||||
|
return fmt.Errorf("Insert: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailAddress deletes an email address of given user.
|
||||||
|
func DeleteEmailAddress(email *EmailAddress) (err error) {
|
||||||
|
if email.IsPrimary {
|
||||||
|
return ErrPrimaryEmailCannotDelete{Email: email.Email}
|
||||||
|
}
|
||||||
|
|
||||||
|
var deleted int64
|
||||||
|
// ask to check UID
|
||||||
|
address := EmailAddress{
|
||||||
|
UID: email.UID,
|
||||||
|
}
|
||||||
|
if email.ID > 0 {
|
||||||
|
deleted, err = db.GetEngine(db.DefaultContext).ID(email.ID).Delete(&address)
|
||||||
|
} else {
|
||||||
|
if email.Email != "" && email.LowerEmail == "" {
|
||||||
|
email.LowerEmail = strings.ToLower(email.Email)
|
||||||
|
}
|
||||||
|
deleted, err = db.GetEngine(db.DefaultContext).
|
||||||
|
Where("lower_email=?", email.LowerEmail).
|
||||||
|
Delete(&address)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if deleted != 1 {
|
||||||
|
return ErrEmailAddressNotExist{Email: email.Email}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailAddresses deletes multiple email addresses
|
||||||
|
func DeleteEmailAddresses(emails []*EmailAddress) (err error) {
|
||||||
|
for i := range emails {
|
||||||
|
if err = DeleteEmailAddress(emails[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
131
models/user/email_address_test.go
Normal file
131
models/user/email_address_test.go
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
// 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetEmailAddresses(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
emails, _ := GetEmailAddresses(int64(1))
|
||||||
|
if assert.Len(t, emails, 3) {
|
||||||
|
assert.True(t, emails[0].IsPrimary)
|
||||||
|
assert.True(t, emails[2].IsActivated)
|
||||||
|
assert.False(t, emails[2].IsPrimary)
|
||||||
|
}
|
||||||
|
|
||||||
|
emails, _ = GetEmailAddresses(int64(2))
|
||||||
|
if assert.Len(t, emails, 2) {
|
||||||
|
assert.True(t, emails[0].IsPrimary)
|
||||||
|
assert.True(t, emails[0].IsActivated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsEmailUsed(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
isExist, _ := IsEmailUsed(db.DefaultContext, "")
|
||||||
|
assert.True(t, isExist)
|
||||||
|
isExist, _ = IsEmailUsed(db.DefaultContext, "user11@example.com")
|
||||||
|
assert.True(t, isExist)
|
||||||
|
isExist, _ = IsEmailUsed(db.DefaultContext, "user1234567890@example.com")
|
||||||
|
assert.False(t, isExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddEmailAddress(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
assert.NoError(t, AddEmailAddress(&EmailAddress{
|
||||||
|
Email: "user1234567890@example.com",
|
||||||
|
LowerEmail: "user1234567890@example.com",
|
||||||
|
IsPrimary: true,
|
||||||
|
IsActivated: true,
|
||||||
|
}))
|
||||||
|
|
||||||
|
// ErrEmailAlreadyUsed
|
||||||
|
err := AddEmailAddress(&EmailAddress{
|
||||||
|
Email: "user1234567890@example.com",
|
||||||
|
LowerEmail: "user1234567890@example.com",
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrEmailAlreadyUsed(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddEmailAddresses(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
// insert multiple email address
|
||||||
|
emails := make([]*EmailAddress, 2)
|
||||||
|
emails[0] = &EmailAddress{
|
||||||
|
Email: "user1234@example.com",
|
||||||
|
LowerEmail: "user1234@example.com",
|
||||||
|
IsActivated: true,
|
||||||
|
}
|
||||||
|
emails[1] = &EmailAddress{
|
||||||
|
Email: "user5678@example.com",
|
||||||
|
LowerEmail: "user5678@example.com",
|
||||||
|
IsActivated: true,
|
||||||
|
}
|
||||||
|
assert.NoError(t, AddEmailAddresses(emails))
|
||||||
|
|
||||||
|
// ErrEmailAlreadyUsed
|
||||||
|
err := AddEmailAddresses(emails)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrEmailAlreadyUsed(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteEmailAddress(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
assert.NoError(t, DeleteEmailAddress(&EmailAddress{
|
||||||
|
UID: int64(1),
|
||||||
|
ID: int64(33),
|
||||||
|
Email: "user1-2@example.com",
|
||||||
|
LowerEmail: "user1-2@example.com",
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert.NoError(t, DeleteEmailAddress(&EmailAddress{
|
||||||
|
UID: int64(1),
|
||||||
|
Email: "user1-3@example.com",
|
||||||
|
LowerEmail: "user1-3@example.com",
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Email address does not exist
|
||||||
|
err := DeleteEmailAddress(&EmailAddress{
|
||||||
|
UID: int64(1),
|
||||||
|
Email: "user1234567890@example.com",
|
||||||
|
LowerEmail: "user1234567890@example.com",
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteEmailAddresses(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
// delete multiple email address
|
||||||
|
emails := make([]*EmailAddress, 2)
|
||||||
|
emails[0] = &EmailAddress{
|
||||||
|
UID: int64(2),
|
||||||
|
ID: int64(3),
|
||||||
|
Email: "user2@example.com",
|
||||||
|
LowerEmail: "user2@example.com",
|
||||||
|
}
|
||||||
|
emails[1] = &EmailAddress{
|
||||||
|
UID: int64(2),
|
||||||
|
Email: "user2-2@example.com",
|
||||||
|
LowerEmail: "user2-2@example.com",
|
||||||
|
}
|
||||||
|
assert.NoError(t, DeleteEmailAddresses(emails))
|
||||||
|
|
||||||
|
// ErrEmailAlreadyUsed
|
||||||
|
err := DeleteEmailAddresses(emails)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
19
models/user/main_test.go
Normal file
19
models/user/main_test.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2020 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
db.MainTest(m, filepath.Join("..", ".."),
|
||||||
|
"email_address.yml",
|
||||||
|
"user_redirect.yml",
|
||||||
|
)
|
||||||
|
}
|
79
models/user/redirect.go
Normal file
79
models/user/redirect.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright 2020 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrUserRedirectNotExist represents a "UserRedirectNotExist" kind of error.
|
||||||
|
type ErrUserRedirectNotExist struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrUserRedirectNotExist check if an error is an ErrUserRedirectNotExist.
|
||||||
|
func IsErrUserRedirectNotExist(err error) bool {
|
||||||
|
_, ok := err.(ErrUserRedirectNotExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrUserRedirectNotExist) Error() string {
|
||||||
|
return fmt.Sprintf("user redirect does not exist [name: %s]", err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect represents that a user name should be redirected to another
|
||||||
|
type Redirect struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||||
|
RedirectUserID int64 // userID to redirect to
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName provides the real table name
|
||||||
|
func (Redirect) TableName() string {
|
||||||
|
return "user_redirect"
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
db.RegisterModel(new(Redirect))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupUserRedirect look up userID if a user has a redirect name
|
||||||
|
func LookupUserRedirect(userName string) (int64, error) {
|
||||||
|
userName = strings.ToLower(userName)
|
||||||
|
redirect := &Redirect{LowerName: userName}
|
||||||
|
if has, err := db.GetEngine(db.DefaultContext).Get(redirect); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if !has {
|
||||||
|
return 0, ErrUserRedirectNotExist{Name: userName}
|
||||||
|
}
|
||||||
|
return redirect.RedirectUserID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUserRedirect create a new user redirect
|
||||||
|
func NewUserRedirect(ctx context.Context, ID int64, oldUserName, newUserName string) error {
|
||||||
|
oldUserName = strings.ToLower(oldUserName)
|
||||||
|
newUserName = strings.ToLower(newUserName)
|
||||||
|
|
||||||
|
if err := DeleteUserRedirect(ctx, newUserName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.Insert(ctx, &Redirect{
|
||||||
|
LowerName: oldUserName,
|
||||||
|
RedirectUserID: ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUserRedirect delete any redirect from the specified user name to
|
||||||
|
// anything else
|
||||||
|
func DeleteUserRedirect(ctx context.Context, userName string) error {
|
||||||
|
userName = strings.ToLower(userName)
|
||||||
|
_, err := db.GetEngine(ctx).Delete(&Redirect{LowerName: userName})
|
||||||
|
return err
|
||||||
|
}
|
23
models/user/redirect_test.go
Normal file
23
models/user/redirect_test.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2020 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLookupUserRedirect(t *testing.T) {
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
userID, err := LookupUserRedirect("olduser1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, userID)
|
||||||
|
|
||||||
|
_, err = LookupUserRedirect("doesnotexist")
|
||||||
|
assert.True(t, IsErrUserRedirectNotExist(err))
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,179 +6,28 @@ package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/mail"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EmailAddress is the list of all email addresses of a user. It also contains the
|
// ActivateEmail activates the email address to given user.
|
||||||
// primary email address which is saved in user table.
|
func ActivateEmail(email *user_model.EmailAddress) error {
|
||||||
type EmailAddress struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
UID int64 `xorm:"INDEX NOT NULL"`
|
|
||||||
Email string `xorm:"UNIQUE NOT NULL"`
|
|
||||||
LowerEmail string `xorm:"UNIQUE NOT NULL"`
|
|
||||||
IsActivated bool
|
|
||||||
IsPrimary bool `xorm:"DEFAULT(false) NOT NULL"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
db.RegisterModel(new(EmailAddress))
|
|
||||||
}
|
|
||||||
|
|
||||||
// BeforeInsert will be invoked by XORM before inserting a record
|
|
||||||
func (email *EmailAddress) BeforeInsert() {
|
|
||||||
if email.LowerEmail == "" {
|
|
||||||
email.LowerEmail = strings.ToLower(email.Email)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateEmail check if email is a allowed address
|
|
||||||
func ValidateEmail(email string) error {
|
|
||||||
if len(email) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := mail.ParseAddress(email); err != nil {
|
|
||||||
return ErrEmailInvalid{email}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add an email allow/block list
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEmailAddresses returns all email addresses belongs to given user.
|
|
||||||
func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
|
|
||||||
emails := make([]*EmailAddress, 0, 5)
|
|
||||||
if err := db.GetEngine(db.DefaultContext).
|
|
||||||
Where("uid=?", uid).
|
|
||||||
Asc("id").
|
|
||||||
Find(&emails); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return emails, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEmailAddressByID gets a user's email address by ID
|
|
||||||
func GetEmailAddressByID(uid, id int64) (*EmailAddress, error) {
|
|
||||||
// User ID is required for security reasons
|
|
||||||
email := &EmailAddress{UID: uid}
|
|
||||||
if has, err := db.GetEngine(db.DefaultContext).ID(id).Get(email); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !has {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return email, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isEmailActive check if email is activated with a different emailID
|
|
||||||
func isEmailActive(e db.Engine, email string, excludeEmailID int64) (bool, error) {
|
|
||||||
if len(email) == 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't filter by boolean field unless it's explicit
|
|
||||||
cond := builder.NewCond()
|
|
||||||
cond = cond.And(builder.Eq{"lower_email": strings.ToLower(email)}, builder.Neq{"id": excludeEmailID})
|
|
||||||
if setting.Service.RegisterEmailConfirm {
|
|
||||||
// Inactive (unvalidated) addresses don't count as active if email validation is required
|
|
||||||
cond = cond.And(builder.Eq{"is_activated": true})
|
|
||||||
}
|
|
||||||
|
|
||||||
var em EmailAddress
|
|
||||||
if has, err := e.Where(cond).Get(&em); has || err != nil {
|
|
||||||
if has {
|
|
||||||
log.Info("isEmailActive(%q, %d) found duplicate in email ID %d", email, excludeEmailID, em.ID)
|
|
||||||
}
|
|
||||||
return has, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isEmailUsed(e db.Engine, email string) (bool, error) {
|
|
||||||
if len(email) == 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.Where("lower_email=?", strings.ToLower(email)).Get(&EmailAddress{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmailUsed returns true if the email has been used.
|
|
||||||
func IsEmailUsed(email string) (bool, error) {
|
|
||||||
return isEmailUsed(db.GetEngine(db.DefaultContext), email)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addEmailAddress(e db.Engine, email *EmailAddress) error {
|
|
||||||
email.Email = strings.TrimSpace(email.Email)
|
|
||||||
used, err := isEmailUsed(e, email.Email)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if used {
|
|
||||||
return ErrEmailAlreadyUsed{email.Email}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = ValidateEmail(email.Email); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = e.Insert(email)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddEmailAddress adds an email address to given user.
|
|
||||||
func AddEmailAddress(email *EmailAddress) error {
|
|
||||||
return addEmailAddress(db.GetEngine(db.DefaultContext), email)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddEmailAddresses adds an email address to given user.
|
|
||||||
func AddEmailAddresses(emails []*EmailAddress) error {
|
|
||||||
if len(emails) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any of them has been used
|
|
||||||
for i := range emails {
|
|
||||||
emails[i].Email = strings.TrimSpace(emails[i].Email)
|
|
||||||
used, err := IsEmailUsed(emails[i].Email)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if used {
|
|
||||||
return ErrEmailAlreadyUsed{emails[i].Email}
|
|
||||||
}
|
|
||||||
if err = ValidateEmail(emails[i].Email); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := db.GetEngine(db.DefaultContext).Insert(emails); err != nil {
|
|
||||||
return fmt.Errorf("Insert: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activate activates the email address to given user.
|
|
||||||
func (email *EmailAddress) Activate() error {
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
sess := db.NewSession(db.DefaultContext)
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err := sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := email.updateActivation(sess, true); err != nil {
|
if err := updateActivation(sess, email, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (email *EmailAddress) updateActivation(e db.Engine, activate bool) error {
|
func updateActivation(e db.Engine, email *user_model.EmailAddress, activate bool) error {
|
||||||
user, err := getUserByID(e, email.UID)
|
user, err := getUserByID(e, email.UID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -194,58 +42,17 @@ func (email *EmailAddress) updateActivation(e db.Engine, activate bool) error {
|
||||||
return updateUserCols(e, user, "rands")
|
return updateUserCols(e, user, "rands")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteEmailAddress deletes an email address of given user.
|
|
||||||
func DeleteEmailAddress(email *EmailAddress) (err error) {
|
|
||||||
if email.IsPrimary {
|
|
||||||
return ErrPrimaryEmailCannotDelete{Email: email.Email}
|
|
||||||
}
|
|
||||||
|
|
||||||
var deleted int64
|
|
||||||
// ask to check UID
|
|
||||||
address := EmailAddress{
|
|
||||||
UID: email.UID,
|
|
||||||
}
|
|
||||||
if email.ID > 0 {
|
|
||||||
deleted, err = db.GetEngine(db.DefaultContext).ID(email.ID).Delete(&address)
|
|
||||||
} else {
|
|
||||||
if email.Email != "" && email.LowerEmail == "" {
|
|
||||||
email.LowerEmail = strings.ToLower(email.Email)
|
|
||||||
}
|
|
||||||
deleted, err = db.GetEngine(db.DefaultContext).
|
|
||||||
Where("lower_email=?", email.LowerEmail).
|
|
||||||
Delete(&address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if deleted != 1 {
|
|
||||||
return ErrEmailAddressNotExist{Email: email.Email}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteEmailAddresses deletes multiple email addresses
|
|
||||||
func DeleteEmailAddresses(emails []*EmailAddress) (err error) {
|
|
||||||
for i := range emails {
|
|
||||||
if err = DeleteEmailAddress(emails[i]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeEmailPrimary sets primary email address of given user.
|
// MakeEmailPrimary sets primary email address of given user.
|
||||||
func MakeEmailPrimary(email *EmailAddress) error {
|
func MakeEmailPrimary(email *user_model.EmailAddress) error {
|
||||||
has, err := db.GetEngine(db.DefaultContext).Get(email)
|
has, err := db.GetEngine(db.DefaultContext).Get(email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
return ErrEmailAddressNotExist{Email: email.Email}
|
return user_model.ErrEmailAddressNotExist{Email: email.Email}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !email.IsActivated {
|
if !email.IsActivated {
|
||||||
return ErrEmailNotActivated
|
return user_model.ErrEmailNotActivated
|
||||||
}
|
}
|
||||||
|
|
||||||
user := &User{}
|
user := &User{}
|
||||||
|
@ -269,7 +76,7 @@ func MakeEmailPrimary(email *EmailAddress) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Update old primary email
|
// 2. Update old primary email
|
||||||
if _, err = sess.Where("uid=? AND is_primary=?", email.UID, true).Cols("is_primary").Update(&EmailAddress{
|
if _, err = sess.Where("uid=? AND is_primary=?", email.UID, true).Cols("is_primary").Update(&user_model.EmailAddress{
|
||||||
IsPrimary: false,
|
IsPrimary: false,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -347,7 +154,7 @@ func SearchEmails(opts *SearchEmailOptions) ([]*SearchEmailResult, int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := db.GetEngine(db.DefaultContext).Join("INNER", "`user`", "`user`.ID = email_address.uid").
|
count, err := db.GetEngine(db.DefaultContext).Join("INNER", "`user`", "`user`.ID = email_address.uid").
|
||||||
Where(cond).Count(new(EmailAddress))
|
Where(cond).Count(new(user_model.EmailAddress))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("Count: %v", err)
|
return nil, 0, fmt.Errorf("Count: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -374,15 +181,16 @@ func SearchEmails(opts *SearchEmailOptions) ([]*SearchEmailResult, int64, error)
|
||||||
// ActivateUserEmail will change the activated state of an email address,
|
// ActivateUserEmail will change the activated state of an email address,
|
||||||
// either primary or secondary (all in the email_address table)
|
// either primary or secondary (all in the email_address table)
|
||||||
func ActivateUserEmail(userID int64, email string, activate bool) (err error) {
|
func ActivateUserEmail(userID int64, email string, activate bool) (err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
// Activate/deactivate a user's secondary email address
|
// Activate/deactivate a user's secondary email address
|
||||||
// First check if there's another user active with the same address
|
// First check if there's another user active with the same address
|
||||||
addr := EmailAddress{UID: userID, LowerEmail: strings.ToLower(email)}
|
addr := user_model.EmailAddress{UID: userID, LowerEmail: strings.ToLower(email)}
|
||||||
if has, err := sess.Get(&addr); err != nil {
|
if has, err := sess.Get(&addr); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
|
@ -393,13 +201,13 @@ func ActivateUserEmail(userID int64, email string, activate bool) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if activate {
|
if activate {
|
||||||
if used, err := isEmailActive(sess, email, addr.ID); err != nil {
|
if used, err := user_model.IsEmailActive(ctx, email, addr.ID); err != nil {
|
||||||
return fmt.Errorf("unable to check isEmailActive() for %s: %v", email, err)
|
return fmt.Errorf("unable to check isEmailActive() for %s: %v", email, err)
|
||||||
} else if used {
|
} else if used {
|
||||||
return ErrEmailAlreadyUsed{Email: email}
|
return user_model.ErrEmailAlreadyUsed{Email: email}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = addr.updateActivation(sess, activate); err != nil {
|
if err = updateActivation(sess, &addr, activate); err != nil {
|
||||||
return fmt.Errorf("unable to updateActivation() for %d:%s: %w", addr.ID, addr.Email, err)
|
return fmt.Errorf("unable to updateActivation() for %d:%s: %w", addr.ID, addr.Email, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,5 +231,5 @@ func ActivateUserEmail(userID int64, email string, activate bool) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -8,154 +8,37 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetEmailAddresses(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
emails, _ := GetEmailAddresses(int64(1))
|
|
||||||
if assert.Len(t, emails, 3) {
|
|
||||||
assert.True(t, emails[0].IsPrimary)
|
|
||||||
assert.True(t, emails[2].IsActivated)
|
|
||||||
assert.False(t, emails[2].IsPrimary)
|
|
||||||
}
|
|
||||||
|
|
||||||
emails, _ = GetEmailAddresses(int64(2))
|
|
||||||
if assert.Len(t, emails, 2) {
|
|
||||||
assert.True(t, emails[0].IsPrimary)
|
|
||||||
assert.True(t, emails[0].IsActivated)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsEmailUsed(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
isExist, _ := IsEmailUsed("")
|
|
||||||
assert.True(t, isExist)
|
|
||||||
isExist, _ = IsEmailUsed("user11@example.com")
|
|
||||||
assert.True(t, isExist)
|
|
||||||
isExist, _ = IsEmailUsed("user1234567890@example.com")
|
|
||||||
assert.False(t, isExist)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddEmailAddress(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
assert.NoError(t, AddEmailAddress(&EmailAddress{
|
|
||||||
Email: "user1234567890@example.com",
|
|
||||||
LowerEmail: "user1234567890@example.com",
|
|
||||||
IsPrimary: true,
|
|
||||||
IsActivated: true,
|
|
||||||
}))
|
|
||||||
|
|
||||||
// ErrEmailAlreadyUsed
|
|
||||||
err := AddEmailAddress(&EmailAddress{
|
|
||||||
Email: "user1234567890@example.com",
|
|
||||||
LowerEmail: "user1234567890@example.com",
|
|
||||||
})
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrEmailAlreadyUsed(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddEmailAddresses(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
// insert multiple email address
|
|
||||||
emails := make([]*EmailAddress, 2)
|
|
||||||
emails[0] = &EmailAddress{
|
|
||||||
Email: "user1234@example.com",
|
|
||||||
LowerEmail: "user1234@example.com",
|
|
||||||
IsActivated: true,
|
|
||||||
}
|
|
||||||
emails[1] = &EmailAddress{
|
|
||||||
Email: "user5678@example.com",
|
|
||||||
LowerEmail: "user5678@example.com",
|
|
||||||
IsActivated: true,
|
|
||||||
}
|
|
||||||
assert.NoError(t, AddEmailAddresses(emails))
|
|
||||||
|
|
||||||
// ErrEmailAlreadyUsed
|
|
||||||
err := AddEmailAddresses(emails)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrEmailAlreadyUsed(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteEmailAddress(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
assert.NoError(t, DeleteEmailAddress(&EmailAddress{
|
|
||||||
UID: int64(1),
|
|
||||||
ID: int64(33),
|
|
||||||
Email: "user1-2@example.com",
|
|
||||||
LowerEmail: "user1-2@example.com",
|
|
||||||
}))
|
|
||||||
|
|
||||||
assert.NoError(t, DeleteEmailAddress(&EmailAddress{
|
|
||||||
UID: int64(1),
|
|
||||||
Email: "user1-3@example.com",
|
|
||||||
LowerEmail: "user1-3@example.com",
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Email address does not exist
|
|
||||||
err := DeleteEmailAddress(&EmailAddress{
|
|
||||||
UID: int64(1),
|
|
||||||
Email: "user1234567890@example.com",
|
|
||||||
LowerEmail: "user1234567890@example.com",
|
|
||||||
})
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteEmailAddresses(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
// delete multiple email address
|
|
||||||
emails := make([]*EmailAddress, 2)
|
|
||||||
emails[0] = &EmailAddress{
|
|
||||||
UID: int64(2),
|
|
||||||
ID: int64(3),
|
|
||||||
Email: "user2@example.com",
|
|
||||||
LowerEmail: "user2@example.com",
|
|
||||||
}
|
|
||||||
emails[1] = &EmailAddress{
|
|
||||||
UID: int64(2),
|
|
||||||
Email: "user2-2@example.com",
|
|
||||||
LowerEmail: "user2-2@example.com",
|
|
||||||
}
|
|
||||||
assert.NoError(t, DeleteEmailAddresses(emails))
|
|
||||||
|
|
||||||
// ErrEmailAlreadyUsed
|
|
||||||
err := DeleteEmailAddresses(emails)
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakeEmailPrimary(t *testing.T) {
|
func TestMakeEmailPrimary(t *testing.T) {
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
email := &EmailAddress{
|
email := &user_model.EmailAddress{
|
||||||
Email: "user567890@example.com",
|
Email: "user567890@example.com",
|
||||||
}
|
}
|
||||||
err := MakeEmailPrimary(email)
|
err := MakeEmailPrimary(email)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.EqualError(t, err, ErrEmailAddressNotExist{email.Email}.Error())
|
assert.EqualError(t, err, user_model.ErrEmailAddressNotExist{Email: email.Email}.Error())
|
||||||
|
|
||||||
email = &EmailAddress{
|
email = &user_model.EmailAddress{
|
||||||
Email: "user11@example.com",
|
Email: "user11@example.com",
|
||||||
}
|
}
|
||||||
err = MakeEmailPrimary(email)
|
err = MakeEmailPrimary(email)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.EqualError(t, err, ErrEmailNotActivated.Error())
|
assert.EqualError(t, err, user_model.ErrEmailNotActivated.Error())
|
||||||
|
|
||||||
email = &EmailAddress{
|
email = &user_model.EmailAddress{
|
||||||
Email: "user9999999@example.com",
|
Email: "user9999999@example.com",
|
||||||
}
|
}
|
||||||
err = MakeEmailPrimary(email)
|
err = MakeEmailPrimary(email)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrUserNotExist(err))
|
assert.True(t, IsErrUserNotExist(err))
|
||||||
|
|
||||||
email = &EmailAddress{
|
email = &user_model.EmailAddress{
|
||||||
Email: "user101@example.com",
|
Email: "user101@example.com",
|
||||||
}
|
}
|
||||||
err = MakeEmailPrimary(email)
|
err = MakeEmailPrimary(email)
|
||||||
|
@ -168,14 +51,14 @@ func TestMakeEmailPrimary(t *testing.T) {
|
||||||
func TestActivate(t *testing.T) {
|
func TestActivate(t *testing.T) {
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
email := &EmailAddress{
|
email := &user_model.EmailAddress{
|
||||||
ID: int64(1),
|
ID: int64(1),
|
||||||
UID: int64(1),
|
UID: int64(1),
|
||||||
Email: "user11@example.com",
|
Email: "user11@example.com",
|
||||||
}
|
}
|
||||||
assert.NoError(t, email.Activate())
|
assert.NoError(t, ActivateEmail(email))
|
||||||
|
|
||||||
emails, _ := GetEmailAddresses(int64(1))
|
emails, _ := user_model.GetEmailAddresses(int64(1))
|
||||||
assert.Len(t, emails, 3)
|
assert.Len(t, emails, 3)
|
||||||
assert.True(t, emails[0].IsActivated)
|
assert.True(t, emails[0].IsActivated)
|
||||||
assert.True(t, emails[0].IsPrimary)
|
assert.True(t, emails[0].IsPrimary)
|
|
@ -1,60 +0,0 @@
|
||||||
// Copyright 2020 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 (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UserRedirect represents that a user name should be redirected to another
|
|
||||||
type UserRedirect struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
|
||||||
RedirectUserID int64 // userID to redirect to
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
db.RegisterModel(new(UserRedirect))
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupUserRedirect look up userID if a user has a redirect name
|
|
||||||
func LookupUserRedirect(userName string) (int64, error) {
|
|
||||||
userName = strings.ToLower(userName)
|
|
||||||
redirect := &UserRedirect{LowerName: userName}
|
|
||||||
if has, err := db.GetEngine(db.DefaultContext).Get(redirect); err != nil {
|
|
||||||
return 0, err
|
|
||||||
} else if !has {
|
|
||||||
return 0, ErrUserRedirectNotExist{Name: userName}
|
|
||||||
}
|
|
||||||
return redirect.RedirectUserID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// newUserRedirect create a new user redirect
|
|
||||||
func newUserRedirect(e db.Engine, ID int64, oldUserName, newUserName string) error {
|
|
||||||
oldUserName = strings.ToLower(oldUserName)
|
|
||||||
newUserName = strings.ToLower(newUserName)
|
|
||||||
|
|
||||||
if err := deleteUserRedirect(e, newUserName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := e.Insert(&UserRedirect{
|
|
||||||
LowerName: oldUserName,
|
|
||||||
RedirectUserID: ID,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteUserRedirect delete any redirect from the specified user name to
|
|
||||||
// anything else
|
|
||||||
func deleteUserRedirect(e db.Engine, userName string) error {
|
|
||||||
userName = strings.ToLower(userName)
|
|
||||||
_, err := e.Delete(&UserRedirect{LowerName: userName})
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
// Copyright 2020 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLookupUserRedirect(t *testing.T) {
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
userID, err := LookupUserRedirect("olduser1")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, 1, userID)
|
|
||||||
|
|
||||||
_, err = LookupUserRedirect("doesnotexist")
|
|
||||||
assert.True(t, IsErrUserRedirectNotExist(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewUserRedirect(t *testing.T) {
|
|
||||||
// redirect to a completely new name
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
user := db.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
|
|
||||||
assert.NoError(t, newUserRedirect(db.GetEngine(db.DefaultContext), user.ID, user.Name, "newusername"))
|
|
||||||
|
|
||||||
db.AssertExistsAndLoadBean(t, &UserRedirect{
|
|
||||||
LowerName: user.LowerName,
|
|
||||||
RedirectUserID: user.ID,
|
|
||||||
})
|
|
||||||
db.AssertExistsAndLoadBean(t, &UserRedirect{
|
|
||||||
LowerName: "olduser1",
|
|
||||||
RedirectUserID: user.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewUserRedirect2(t *testing.T) {
|
|
||||||
// redirect to previously used name
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
user := db.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
|
|
||||||
assert.NoError(t, newUserRedirect(db.GetEngine(db.DefaultContext), user.ID, user.Name, "olduser1"))
|
|
||||||
|
|
||||||
db.AssertExistsAndLoadBean(t, &UserRedirect{
|
|
||||||
LowerName: user.LowerName,
|
|
||||||
RedirectUserID: user.ID,
|
|
||||||
})
|
|
||||||
db.AssertNotExistsBean(t, &UserRedirect{
|
|
||||||
LowerName: "olduser1",
|
|
||||||
RedirectUserID: user.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewUserRedirect3(t *testing.T) {
|
|
||||||
// redirect for a previously-unredirected user
|
|
||||||
assert.NoError(t, db.PrepareTestDatabase())
|
|
||||||
|
|
||||||
user := db.AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
|
||||||
assert.NoError(t, newUserRedirect(db.GetEngine(db.DefaultContext), user.ID, user.Name, "newusername"))
|
|
||||||
|
|
||||||
db.AssertExistsAndLoadBean(t, &UserRedirect{
|
|
||||||
LowerName: user.LowerName,
|
|
||||||
RedirectUserID: user.ID,
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
@ -358,7 +359,7 @@ func TestCreateUserInvalidEmail(t *testing.T) {
|
||||||
|
|
||||||
err := CreateUser(user)
|
err := CreateUser(user)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrEmailInvalid(err))
|
assert.True(t, user_model.IsErrEmailInvalid(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateUser_Issue5882(t *testing.T) {
|
func TestCreateUser_Issue5882(t *testing.T) {
|
||||||
|
@ -511,3 +512,50 @@ func TestUpdateUser(t *testing.T) {
|
||||||
user.Email = "no mail@mail.org"
|
user.Email = "no mail@mail.org"
|
||||||
assert.Error(t, UpdateUser(user))
|
assert.Error(t, UpdateUser(user))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewUserRedirect(t *testing.T) {
|
||||||
|
// redirect to a completely new name
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
user := db.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
|
||||||
|
assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "newusername"))
|
||||||
|
|
||||||
|
db.AssertExistsAndLoadBean(t, &user_model.Redirect{
|
||||||
|
LowerName: user.LowerName,
|
||||||
|
RedirectUserID: user.ID,
|
||||||
|
})
|
||||||
|
db.AssertExistsAndLoadBean(t, &user_model.Redirect{
|
||||||
|
LowerName: "olduser1",
|
||||||
|
RedirectUserID: user.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewUserRedirect2(t *testing.T) {
|
||||||
|
// redirect to previously used name
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
user := db.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
|
||||||
|
assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "olduser1"))
|
||||||
|
|
||||||
|
db.AssertExistsAndLoadBean(t, &user_model.Redirect{
|
||||||
|
LowerName: user.LowerName,
|
||||||
|
RedirectUserID: user.ID,
|
||||||
|
})
|
||||||
|
db.AssertNotExistsBean(t, &user_model.Redirect{
|
||||||
|
LowerName: "olduser1",
|
||||||
|
RedirectUserID: user.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewUserRedirect3(t *testing.T) {
|
||||||
|
// redirect for a previously-unredirected user
|
||||||
|
assert.NoError(t, db.PrepareTestDatabase())
|
||||||
|
|
||||||
|
user := db.AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||||
|
assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "newusername"))
|
||||||
|
|
||||||
|
db.AssertExistsAndLoadBean(t, &user_model.Redirect{
|
||||||
|
LowerName: user.LowerName,
|
||||||
|
RedirectUserID: user.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Organization contains organization context
|
// Organization contains organization context
|
||||||
|
@ -51,10 +52,10 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||||
ctx.Org.Organization, err = models.GetUserByName(orgName)
|
ctx.Org.Organization, err = models.GetUserByName(orgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
redirectUserID, err := models.LookupUserRedirect(orgName)
|
redirectUserID, err := user_model.LookupUserRedirect(orgName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
RedirectToUser(ctx, orgName, redirectUserID)
|
RedirectToUser(ctx, orgName, redirectUserID)
|
||||||
} else if models.IsErrUserRedirectNotExist(err) {
|
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||||
ctx.NotFound("GetUserByName", err)
|
ctx.NotFound("GetUserByName", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("LookupUserRedirect", err)
|
ctx.ServerError("LookupUserRedirect", err)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/models/webhook"
|
"code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -23,7 +24,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToEmail convert models.EmailAddress to api.Email
|
// ToEmail convert models.EmailAddress to api.Email
|
||||||
func ToEmail(email *models.EmailAddress) *api.Email {
|
func ToEmail(email *user_model.EmailAddress) *api.Email {
|
||||||
return &api.Email{
|
return &api.Email{
|
||||||
Email: email.Email,
|
Email: email.Email,
|
||||||
Verified: email.IsActivated,
|
Verified: email.IsActivated,
|
||||||
|
@ -219,7 +220,7 @@ func ToGPGKey(key *models.GPGKey) *api.GPGKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToGPGKeyEmail convert models.EmailAddress to api.GPGKeyEmail
|
// ToGPGKeyEmail convert models.EmailAddress to api.GPGKeyEmail
|
||||||
func ToGPGKeyEmail(email *models.EmailAddress) *api.GPGKeyEmail {
|
func ToGPGKeyEmail(email *user_model.EmailAddress) *api.GPGKeyEmail {
|
||||||
return &api.GPGKeyEmail{
|
return &api.GPGKeyEmail{
|
||||||
Email: email.Email,
|
Email: email.Email,
|
||||||
Verified: email.IsActivated,
|
Verified: email.IsActivated,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -109,10 +110,10 @@ func CreateUser(ctx *context.APIContext) {
|
||||||
|
|
||||||
if err := models.CreateUser(u, overwriteDefault); err != nil {
|
if err := models.CreateUser(u, overwriteDefault); err != nil {
|
||||||
if models.IsErrUserAlreadyExist(err) ||
|
if models.IsErrUserAlreadyExist(err) ||
|
||||||
models.IsErrEmailAlreadyUsed(err) ||
|
user_model.IsErrEmailAlreadyUsed(err) ||
|
||||||
models.IsErrNameReserved(err) ||
|
models.IsErrNameReserved(err) ||
|
||||||
models.IsErrNameCharsNotAllowed(err) ||
|
models.IsErrNameCharsNotAllowed(err) ||
|
||||||
models.IsErrEmailInvalid(err) ||
|
user_model.IsErrEmailInvalid(err) ||
|
||||||
models.IsErrNamePatternNotAllowed(err) {
|
models.IsErrNamePatternNotAllowed(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -245,7 +246,7 @@ func EditUser(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.UpdateUser(u); err != nil {
|
if err := models.UpdateUser(u); err != nil {
|
||||||
if models.IsErrEmailAlreadyUsed(err) || models.IsErrEmailInvalid(err) {
|
if user_model.IsErrEmailAlreadyUsed(err) || user_model.IsErrEmailInvalid(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "UpdateUser", err)
|
ctx.Error(http.StatusInternalServerError, "UpdateUser", err)
|
||||||
|
|
|
@ -71,6 +71,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -138,9 +139,9 @@ func repoAssignment() func(ctx *context.APIContext) {
|
||||||
owner, err = models.GetUserByName(userName)
|
owner, err = models.GetUserByName(userName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
if redirectUserID, err := models.LookupUserRedirect(userName); err == nil {
|
if redirectUserID, err := user_model.LookupUserRedirect(userName); err == nil {
|
||||||
context.RedirectToUser(ctx.Context, userName, redirectUserID)
|
context.RedirectToUser(ctx.Context, userName, redirectUserID)
|
||||||
} else if models.IsErrUserRedirectNotExist(err) {
|
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||||
ctx.NotFound("GetUserByName", err)
|
ctx.NotFound("GetUserByName", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
|
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
|
||||||
|
@ -421,10 +422,10 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
|
||||||
ctx.Org.Organization, err = models.GetOrgByName(ctx.Params(":org"))
|
ctx.Org.Organization, err = models.GetOrgByName(ctx.Params(":org"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrOrgNotExist(err) {
|
if models.IsErrOrgNotExist(err) {
|
||||||
redirectUserID, err := models.LookupUserRedirect(ctx.Params(":org"))
|
redirectUserID, err := user_model.LookupUserRedirect(ctx.Params(":org"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
context.RedirectToUser(ctx.Context, ctx.Params(":org"), redirectUserID)
|
context.RedirectToUser(ctx.Context, ctx.Params(":org"), redirectUserID)
|
||||||
} else if models.IsErrUserRedirectNotExist(err) {
|
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||||
ctx.NotFound("GetOrgByName", err)
|
ctx.NotFound("GetOrgByName", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
|
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -28,7 +28,7 @@ func ListEmails(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/EmailList"
|
// "$ref": "#/responses/EmailList"
|
||||||
|
|
||||||
emails, err := models.GetEmailAddresses(ctx.User.ID)
|
emails, err := user_model.GetEmailAddresses(ctx.User.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetEmailAddresses", err)
|
ctx.Error(http.StatusInternalServerError, "GetEmailAddresses", err)
|
||||||
return
|
return
|
||||||
|
@ -68,20 +68,20 @@ func AddEmail(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
emails := make([]*models.EmailAddress, len(form.Emails))
|
emails := make([]*user_model.EmailAddress, len(form.Emails))
|
||||||
for i := range form.Emails {
|
for i := range form.Emails {
|
||||||
emails[i] = &models.EmailAddress{
|
emails[i] = &user_model.EmailAddress{
|
||||||
UID: ctx.User.ID,
|
UID: ctx.User.ID,
|
||||||
Email: form.Emails[i],
|
Email: form.Emails[i],
|
||||||
IsActivated: !setting.Service.RegisterEmailConfirm,
|
IsActivated: !setting.Service.RegisterEmailConfirm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.AddEmailAddresses(emails); err != nil {
|
if err := user_model.AddEmailAddresses(emails); err != nil {
|
||||||
if models.IsErrEmailAlreadyUsed(err) {
|
if user_model.IsErrEmailAlreadyUsed(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", "Email address has been used: "+err.(models.ErrEmailAlreadyUsed).Email)
|
ctx.Error(http.StatusUnprocessableEntity, "", "Email address has been used: "+err.(user_model.ErrEmailAlreadyUsed).Email)
|
||||||
} else if models.IsErrEmailInvalid(err) {
|
} else if user_model.IsErrEmailInvalid(err) {
|
||||||
errMsg := fmt.Sprintf("Email address %s invalid", err.(models.ErrEmailInvalid).Email)
|
errMsg := fmt.Sprintf("Email address %s invalid", err.(user_model.ErrEmailInvalid).Email)
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", errMsg)
|
ctx.Error(http.StatusUnprocessableEntity, "", errMsg)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "AddEmailAddresses", err)
|
ctx.Error(http.StatusInternalServerError, "AddEmailAddresses", err)
|
||||||
|
@ -119,16 +119,16 @@ func DeleteEmail(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
emails := make([]*models.EmailAddress, len(form.Emails))
|
emails := make([]*user_model.EmailAddress, len(form.Emails))
|
||||||
for i := range form.Emails {
|
for i := range form.Emails {
|
||||||
emails[i] = &models.EmailAddress{
|
emails[i] = &user_model.EmailAddress{
|
||||||
Email: form.Emails[i],
|
Email: form.Emails[i],
|
||||||
UID: ctx.User.ID,
|
UID: ctx.User.ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteEmailAddresses(emails); err != nil {
|
if err := user_model.DeleteEmailAddresses(emails); err != nil {
|
||||||
if models.IsErrEmailAddressNotExist(err) {
|
if user_model.IsErrEmailAddressNotExist(err) {
|
||||||
ctx.Error(http.StatusNotFound, "DeleteEmailAddresses", err)
|
ctx.Error(http.StatusNotFound, "DeleteEmailAddresses", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ func GetUserByParamsName(ctx *context.APIContext, name string) *models.User {
|
||||||
user, err := models.GetUserByName(username)
|
user, err := models.GetUserByName(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
if redirectUserID, err2 := models.LookupUserRedirect(username); err2 == nil {
|
if redirectUserID, err2 := user_model.LookupUserRedirect(username); err2 == nil {
|
||||||
context.RedirectToUser(ctx.Context, username, redirectUserID)
|
context.RedirectToUser(ctx.Context, username, redirectUserID)
|
||||||
} else {
|
} else {
|
||||||
ctx.NotFound("GetUserByName", err)
|
ctx.NotFound("GetUserByName", err)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -128,7 +129,7 @@ func ActivateEmail(ctx *context.Context) {
|
||||||
|
|
||||||
if err := models.ActivateUserEmail(uid, email, activate); err != nil {
|
if err := models.ActivateUserEmail(uid, email, activate); err != nil {
|
||||||
log.Error("ActivateUserEmail(%v,%v,%v): %v", uid, email, activate, err)
|
log.Error("ActivateUserEmail(%v,%v,%v): %v", uid, email, activate, err)
|
||||||
if models.IsErrEmailAlreadyUsed(err) {
|
if user_model.IsErrEmailAlreadyUsed(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("admin.emails.duplicate_active"))
|
ctx.Flash.Error(ctx.Tr("admin.emails.duplicate_active"))
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Error(ctx.Tr("admin.emails.not_updated", err))
|
ctx.Flash.Error(ctx.Tr("admin.emails.not_updated", err))
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -159,10 +160,10 @@ func NewUserPost(ctx *context.Context) {
|
||||||
case models.IsErrUserAlreadyExist(err):
|
case models.IsErrUserAlreadyExist(err):
|
||||||
ctx.Data["Err_UserName"] = true
|
ctx.Data["Err_UserName"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplUserNew, &form)
|
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplUserNew, &form)
|
||||||
case models.IsErrEmailAlreadyUsed(err):
|
case user_model.IsErrEmailAlreadyUsed(err):
|
||||||
ctx.Data["Err_Email"] = true
|
ctx.Data["Err_Email"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplUserNew, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplUserNew, &form)
|
||||||
case models.IsErrEmailInvalid(err):
|
case user_model.IsErrEmailInvalid(err):
|
||||||
ctx.Data["Err_Email"] = true
|
ctx.Data["Err_Email"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplUserNew, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplUserNew, &form)
|
||||||
case models.IsErrNameReserved(err):
|
case models.IsErrNameReserved(err):
|
||||||
|
@ -351,10 +352,10 @@ func EditUserPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.UpdateUser(u); err != nil {
|
if err := models.UpdateUser(u); err != nil {
|
||||||
if models.IsErrEmailAlreadyUsed(err) {
|
if user_model.IsErrEmailAlreadyUsed(err) {
|
||||||
ctx.Data["Err_Email"] = true
|
ctx.Data["Err_Email"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplUserEdit, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplUserEdit, &form)
|
||||||
} else if models.IsErrEmailInvalid(err) {
|
} else if user_model.IsErrEmailInvalid(err) {
|
||||||
ctx.Data["Err_Email"] = true
|
ctx.Data["Err_Email"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplUserEdit, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplUserEdit, &form)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -112,7 +113,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
||||||
owner, err := models.GetUserByName(username)
|
owner, err := models.GetUserByName(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
if redirectUserID, err := models.LookupUserRedirect(username); err == nil {
|
if redirectUserID, err := user_model.LookupUserRedirect(username); err == nil {
|
||||||
context.RedirectToUser(ctx, username, redirectUserID)
|
context.RedirectToUser(ctx, username, redirectUserID)
|
||||||
} else {
|
} else {
|
||||||
ctx.NotFound(fmt.Sprintf("User %s does not exist", username), nil)
|
ctx.NotFound(fmt.Sprintf("User %s does not exist", username), nil)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/eventsource"
|
"code.gitea.io/gitea/modules/eventsource"
|
||||||
|
@ -181,7 +182,7 @@ func SignInPost(ctx *context.Context) {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplSignIn, &form)
|
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplSignIn, &form)
|
||||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||||
} else if models.IsErrEmailAlreadyUsed(err) {
|
} else if user_model.IsErrEmailAlreadyUsed(err) {
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignIn, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignIn, &form)
|
||||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||||
} else if models.IsErrUserProhibitLogin(err) {
|
} else if models.IsErrUserProhibitLogin(err) {
|
||||||
|
@ -1273,7 +1274,7 @@ func createAndHandleCreatedUser(ctx *context.Context, tpl base.TplName, form int
|
||||||
// Optionally a template can be specified.
|
// Optionally a template can be specified.
|
||||||
func createUserInContext(ctx *context.Context, tpl base.TplName, form interface{}, u *models.User, gothUser *goth.User, allowLink bool) (ok bool) {
|
func createUserInContext(ctx *context.Context, tpl base.TplName, form interface{}, u *models.User, gothUser *goth.User, allowLink bool) (ok bool) {
|
||||||
if err := models.CreateUser(u); err != nil {
|
if err := models.CreateUser(u); err != nil {
|
||||||
if allowLink && (models.IsErrUserAlreadyExist(err) || models.IsErrEmailAlreadyUsed(err)) {
|
if allowLink && (models.IsErrUserAlreadyExist(err) || user_model.IsErrEmailAlreadyUsed(err)) {
|
||||||
if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingAuto {
|
if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingAuto {
|
||||||
var user *models.User
|
var user *models.User
|
||||||
user = &models.User{Name: u.Name}
|
user = &models.User{Name: u.Name}
|
||||||
|
@ -1307,10 +1308,10 @@ func createUserInContext(ctx *context.Context, tpl base.TplName, form interface{
|
||||||
case models.IsErrUserAlreadyExist(err):
|
case models.IsErrUserAlreadyExist(err):
|
||||||
ctx.Data["Err_UserName"] = true
|
ctx.Data["Err_UserName"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tpl, form)
|
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tpl, form)
|
||||||
case models.IsErrEmailAlreadyUsed(err):
|
case user_model.IsErrEmailAlreadyUsed(err):
|
||||||
ctx.Data["Err_Email"] = true
|
ctx.Data["Err_Email"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tpl, form)
|
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tpl, form)
|
||||||
case models.IsErrEmailInvalid(err):
|
case user_model.IsErrEmailInvalid(err):
|
||||||
ctx.Data["Err_Email"] = true
|
ctx.Data["Err_Email"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tpl, form)
|
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tpl, form)
|
||||||
case models.IsErrNameReserved(err):
|
case models.IsErrNameReserved(err):
|
||||||
|
@ -1499,7 +1500,7 @@ func ActivateEmail(ctx *context.Context) {
|
||||||
|
|
||||||
// Verify code.
|
// Verify code.
|
||||||
if email := models.VerifyActiveEmailCode(code, emailStr); email != nil {
|
if email := models.VerifyActiveEmailCode(code, emailStr); email != nil {
|
||||||
if err := email.Activate(); err != nil {
|
if err := models.ActivateEmail(email); err != nil {
|
||||||
ctx.ServerError("ActivateEmail", err)
|
ctx.ServerError("ActivateEmail", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
"code.gitea.io/gitea/modules/markup/markdown"
|
"code.gitea.io/gitea/modules/markup/markdown"
|
||||||
|
@ -27,7 +28,7 @@ func GetUserByName(ctx *context.Context, name string) *models.User {
|
||||||
user, err := models.GetUserByName(name)
|
user, err := models.GetUserByName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
if redirectUserID, err := models.LookupUserRedirect(name); err == nil {
|
if redirectUserID, err := user_model.LookupUserRedirect(name); err == nil {
|
||||||
context.RedirectToUser(ctx, name, redirectUserID)
|
context.RedirectToUser(ctx, name, redirectUserID)
|
||||||
} else {
|
} else {
|
||||||
ctx.NotFound("GetUserByName", err)
|
ctx.NotFound("GetUserByName", err)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -91,7 +92,7 @@ func EmailPost(ctx *context.Context) {
|
||||||
|
|
||||||
// Make emailaddress primary.
|
// Make emailaddress primary.
|
||||||
if ctx.FormString("_method") == "PRIMARY" {
|
if ctx.FormString("_method") == "PRIMARY" {
|
||||||
if err := models.MakeEmailPrimary(&models.EmailAddress{ID: ctx.FormInt64("id")}); err != nil {
|
if err := models.MakeEmailPrimary(&user_model.EmailAddress{ID: ctx.FormInt64("id")}); err != nil {
|
||||||
ctx.ServerError("MakeEmailPrimary", err)
|
ctx.ServerError("MakeEmailPrimary", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -110,7 +111,7 @@ func EmailPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
id := ctx.FormInt64("id")
|
id := ctx.FormInt64("id")
|
||||||
email, err := models.GetEmailAddressByID(ctx.User.ID, id)
|
email, err := user_model.GetEmailAddressByID(ctx.User.ID, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetEmailAddressByID(%d,%d) error: %v", ctx.User.ID, id, err)
|
log.Error("GetEmailAddressByID(%d,%d) error: %v", ctx.User.ID, id, err)
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
||||||
|
@ -174,18 +175,18 @@ func EmailPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
email := &models.EmailAddress{
|
email := &user_model.EmailAddress{
|
||||||
UID: ctx.User.ID,
|
UID: ctx.User.ID,
|
||||||
Email: form.Email,
|
Email: form.Email,
|
||||||
IsActivated: !setting.Service.RegisterEmailConfirm,
|
IsActivated: !setting.Service.RegisterEmailConfirm,
|
||||||
}
|
}
|
||||||
if err := models.AddEmailAddress(email); err != nil {
|
if err := user_model.AddEmailAddress(email); err != nil {
|
||||||
if models.IsErrEmailAlreadyUsed(err) {
|
if user_model.IsErrEmailAlreadyUsed(err) {
|
||||||
loadAccountData(ctx)
|
loadAccountData(ctx)
|
||||||
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsAccount, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsAccount, &form)
|
||||||
return
|
return
|
||||||
} else if models.IsErrEmailInvalid(err) {
|
} else if user_model.IsErrEmailInvalid(err) {
|
||||||
loadAccountData(ctx)
|
loadAccountData(ctx)
|
||||||
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSettingsAccount, &form)
|
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSettingsAccount, &form)
|
||||||
|
@ -212,7 +213,7 @@ func EmailPost(ctx *context.Context) {
|
||||||
|
|
||||||
// DeleteEmail response for delete user's email
|
// DeleteEmail response for delete user's email
|
||||||
func DeleteEmail(ctx *context.Context) {
|
func DeleteEmail(ctx *context.Context) {
|
||||||
if err := models.DeleteEmailAddress(&models.EmailAddress{ID: ctx.FormInt64("id"), UID: ctx.User.ID}); err != nil {
|
if err := user_model.DeleteEmailAddress(&user_model.EmailAddress{ID: ctx.FormInt64("id"), UID: ctx.User.ID}); err != nil {
|
||||||
ctx.ServerError("DeleteEmail", err)
|
ctx.ServerError("DeleteEmail", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -258,13 +259,13 @@ func DeleteAccount(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAccountData(ctx *context.Context) {
|
func loadAccountData(ctx *context.Context) {
|
||||||
emlist, err := models.GetEmailAddresses(ctx.User.ID)
|
emlist, err := user_model.GetEmailAddresses(ctx.User.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetEmailAddresses", err)
|
ctx.ServerError("GetEmailAddresses", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
type UserEmail struct {
|
type UserEmail struct {
|
||||||
models.EmailAddress
|
user_model.EmailAddress
|
||||||
CanBePrimary bool
|
CanBePrimary bool
|
||||||
}
|
}
|
||||||
pendingActivation := ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName)
|
pendingActivation := ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -60,7 +61,7 @@ func HandleUsernameChange(ctx *context.Context, user *models.User, newName strin
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrUserAlreadyExist(err):
|
case models.IsErrUserAlreadyExist(err):
|
||||||
ctx.Flash.Error(ctx.Tr("form.username_been_taken"))
|
ctx.Flash.Error(ctx.Tr("form.username_been_taken"))
|
||||||
case models.IsErrEmailAlreadyUsed(err):
|
case user_model.IsErrEmailAlreadyUsed(err):
|
||||||
ctx.Flash.Error(ctx.Tr("form.email_been_used"))
|
ctx.Flash.Error(ctx.Tr("form.email_been_used"))
|
||||||
case models.IsErrNameReserved(err):
|
case models.IsErrNameReserved(err):
|
||||||
ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName))
|
ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName))
|
||||||
|
@ -120,7 +121,7 @@ func ProfilePost(ctx *context.Context) {
|
||||||
ctx.User.KeepActivityPrivate = form.KeepActivityPrivate
|
ctx.User.KeepActivityPrivate = form.KeepActivityPrivate
|
||||||
ctx.User.Visibility = form.Visibility
|
ctx.User.Visibility = form.Visibility
|
||||||
if err := models.UpdateUserSetting(ctx.User); err != nil {
|
if err := models.UpdateUserSetting(ctx.User); err != nil {
|
||||||
if _, ok := err.(models.ErrEmailAlreadyUsed); ok {
|
if _, ok := err.(user_model.ErrEmailAlreadyUsed); ok {
|
||||||
ctx.Flash.Error(ctx.Tr("form.email_been_used"))
|
ctx.Flash.Error(ctx.Tr("form.email_been_used"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings")
|
ctx.Redirect(setting.AppSubURL + "/user/settings")
|
||||||
return
|
return
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
// Register the sources
|
// Register the sources
|
||||||
|
@ -32,7 +33,7 @@ func UserSignIn(username, password string) (*models.User, *login.Source, error)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if cnt > 1 {
|
if cnt > 1 {
|
||||||
return nil, nil, models.ErrEmailAlreadyUsed{
|
return nil, nil, user_model.ErrEmailAlreadyUsed{
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/auth/pam"
|
"code.gitea.io/gitea/modules/auth/pam"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/services/mailer"
|
"code.gitea.io/gitea/services/mailer"
|
||||||
|
@ -39,13 +40,13 @@ func (source *Source) Authenticate(user *models.User, userName, password string)
|
||||||
if idx > -1 {
|
if idx > -1 {
|
||||||
username = pamLogin[:idx]
|
username = pamLogin[:idx]
|
||||||
}
|
}
|
||||||
if models.ValidateEmail(email) != nil {
|
if user_model.ValidateEmail(email) != nil {
|
||||||
if source.EmailDomain != "" {
|
if source.EmailDomain != "" {
|
||||||
email = fmt.Sprintf("%s@%s", username, source.EmailDomain)
|
email = fmt.Sprintf("%s@%s", username, source.EmailDomain)
|
||||||
} else {
|
} else {
|
||||||
email = fmt.Sprintf("%s@%s", username, setting.Service.NoReplyAddress)
|
email = fmt.Sprintf("%s@%s", username, setting.Service.NoReplyAddress)
|
||||||
}
|
}
|
||||||
if models.ValidateEmail(email) != nil {
|
if user_model.ValidateEmail(email) != nil {
|
||||||
email = uuid.New().String() + "@localhost"
|
email = uuid.New().String() + "@localhost"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
texttmpl "text/template"
|
texttmpl "text/template"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/emoji"
|
"code.gitea.io/gitea/modules/emoji"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -112,7 +113,7 @@ func SendResetPasswordMail(u *models.User) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendActivateEmailMail sends confirmation email to confirm new email address
|
// SendActivateEmailMail sends confirmation email to confirm new email address
|
||||||
func SendActivateEmailMail(u *models.User, email *models.EmailAddress) {
|
func SendActivateEmailMail(u *models.User, email *user_model.EmailAddress) {
|
||||||
if setting.MailService == nil {
|
if setting.MailService == nil {
|
||||||
// No mail service configured
|
// No mail service configured
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue