| @@ -11,28 +11,42 @@ type Invitation struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| SrcUserID int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserID int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| Phone string `xorm:"NULL"` | |||
| Phone string `xorm:"INDEX"` | |||
| CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
| } | |||
| func QueryInvitaionByPhone(phone string) []*Invitation { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| cond := "phone ='" + phone + "'" | |||
| invitationList := make([]*Invitation, 0) | |||
| if err := statictisSess.Table(new(Invitation)).Where(cond). | |||
| Find(&invitationList); err != nil { | |||
| return nil | |||
| } else { | |||
| return invitationList | |||
| } | |||
| } | |||
| func QueryInvitaion(start int64, end int64) ([]*Invitation, int) { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| cond := "created_unix >=" + fmt.Sprint(start) + " and created_unix <=" + fmt.Sprint(end) | |||
| userList := make([]*Invitation, 0) | |||
| invitationList := make([]*Invitation, 0) | |||
| if err := statictisSess.Table(new(Invitation)).Where(cond).OrderBy("created_unix desc"). | |||
| Find(&userList); err != nil { | |||
| Find(&invitationList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| return userList, len(userList) | |||
| return invitationList, len(invitationList) | |||
| } | |||
| func InsertInvitaion(invitationUser *Invitation) { | |||
| func InsertInvitaion(invitationUser *Invitation) error { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| statictisSess.Insert(invitationUser) | |||
| _, err := statictisSess.Insert(invitationUser) | |||
| return err | |||
| } | |||
| func QueryInvitaionBySrcUserId(srcUserId int64) ([]*Invitation, int) { | |||
| @@ -40,11 +54,11 @@ func QueryInvitaionBySrcUserId(srcUserId int64) ([]*Invitation, int) { | |||
| defer statictisSess.Close() | |||
| cond := "src_user_id =" + fmt.Sprint(srcUserId) | |||
| userList := make([]*Invitation, 0) | |||
| invitationList := make([]*Invitation, 0) | |||
| if err := statictisSess.Table(new(Invitation)).Where(cond).OrderBy("created_unix desc"). | |||
| Find(&userList); err != nil { | |||
| Find(&invitationList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| return userList, len(userList) | |||
| return invitationList, len(invitationList) | |||
| } | |||
| @@ -86,6 +86,7 @@ type RegisterForm struct { | |||
| Retype string | |||
| GRecaptchaResponse string `form:"g-recaptcha-response"` | |||
| Agree bool | |||
| InvitaionCode string | |||
| } | |||
| // Validate valideates the fields | |||
| @@ -372,7 +373,7 @@ func (f *U2FDeleteForm) Validate(ctx *macaron.Context, errs binding.Errors) bind | |||
| type PhoneNumberForm struct { | |||
| PhoneNumber string `binding:"Required;MaxSize(20)"` | |||
| Mode int `binding:"Required"` | |||
| Mode int `binding:"Required"` | |||
| SlideID string `binding:"Required;MaxSize(100)"` | |||
| } | |||
| @@ -376,6 +376,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/login/cloud_brain", bindIgnErr(auth.SignInForm{}), user.SignInCloudBrainPost) | |||
| m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) | |||
| m.Get("/invitaion", user.GetInvitaionCode) | |||
| m.Get("/login/phone", user.SignInPhone) | |||
| m.Post("/login/phone", bindIgnErr(auth.PhoneNumberCodeForm{}), user.SignInPhonePost) | |||
| m.Group("", func() { | |||
| @@ -1,9 +1,13 @@ | |||
| package user | |||
| import ( | |||
| "errors" | |||
| "strings" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/services/repository" | |||
| ) | |||
| @@ -25,12 +29,43 @@ func GetInvitaionCode(ctx *context.Context) { | |||
| } | |||
| if ctx.IsSigned { | |||
| resultJsonMap["invitaion_code"] = ctx.User.Name | |||
| resultJsonMap["invitaion_code"] = getInvitaionCode(ctx) | |||
| } | |||
| ctx.JSON(200, resultJsonMap) | |||
| } | |||
| func RegisteUserByInvitaionCode(ctx *context.Context) { | |||
| func RegisteUserByInvitaionCode(form auth.RegisterForm, newUserId int64) error { | |||
| invitationcode := form.InvitaionCode | |||
| re := models.QueryInvitaionByPhone(form.PhoneNumber) | |||
| if re != nil { | |||
| if len(re) > 0 { | |||
| log.Info("The phone has been invitated. so ingore it.") | |||
| return errors.New("The phone has been invitated.") | |||
| } | |||
| } | |||
| user := parseInvitaionCode(invitationcode) | |||
| invitation := &models.Invitation{ | |||
| SrcUserID: user.ID, | |||
| UserID: newUserId, | |||
| Phone: form.PhoneNumber, | |||
| } | |||
| err := models.InsertInvitaion(invitation) | |||
| if err != nil { | |||
| log.Info("insert error," + err.Error()) | |||
| } | |||
| return err | |||
| } | |||
| func getInvitaionCode(ctx *context.Context) string { | |||
| return ctx.User.Name | |||
| } | |||
| func parseInvitaionCode(invitationcode string) *models.User { | |||
| user, err := models.GetUserByName(invitationcode) | |||
| if err == nil { | |||
| return user | |||
| } | |||
| return nil | |||
| } | |||
| @@ -8,11 +8,12 @@ package user | |||
| import ( | |||
| "errors" | |||
| "fmt" | |||
| "github.com/gomodule/redigo/redis" | |||
| "net/http" | |||
| "strconv" | |||
| "strings" | |||
| "github.com/gomodule/redigo/redis" | |||
| "code.gitea.io/gitea/modules/slideimage" | |||
| phoneService "code.gitea.io/gitea/services/phone" | |||
| @@ -352,18 +353,17 @@ func SignInPostCommon(ctx *context.Context, form auth.SignInForm) { | |||
| ctx.Redirect(setting.AppSubURL + "/user/two_factor") | |||
| } | |||
| func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) { | |||
| ctx.Data["PageIsCloudBrainLogin"] = true | |||
| ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login/cloud_brain" | |||
| SignInPostCommon(ctx,form) | |||
| SignInPostCommon(ctx, form) | |||
| } | |||
| // SignInPost response for sign in request | |||
| func SignInPost(ctx *context.Context, form auth.SignInForm) { | |||
| ctx.Data["PageIsLogin"] = true | |||
| ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" | |||
| SignInPostCommon(ctx,form) | |||
| SignInPostCommon(ctx, form) | |||
| } | |||
| // TwoFactor shows the user a two-factor authentication page. | |||
| @@ -1337,6 +1337,9 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo | |||
| ctx.RenderWithErr(ctx.Tr("sign_up_agree_tips"), tplSignUp, &form) | |||
| return | |||
| } | |||
| if form.InvitaionCode != "" { | |||
| RegisteUserByInvitaionCode(ctx, form) | |||
| } | |||
| u := &models.User{ | |||
| Name: form.UserName, | |||
| @@ -1919,7 +1922,7 @@ func SendVerifyCode(ctx *context.Context, slideImage *slideimage.SlideImage, for | |||
| return | |||
| } | |||
| if form.Mode==0 { //注册 | |||
| if form.Mode == 0 { //注册 | |||
| if has { | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register"))) | |||
| @@ -1935,32 +1938,31 @@ func SendVerifyCode(ctx *context.Context, slideImage *slideimage.SlideImage, for | |||
| } else { | |||
| //修改手机号 mode=2 绑定手机 | |||
| u, err := models.GetUserByPhoneNumber(phoneNumber) | |||
| if err != nil && !models.IsErrUserNotExist(err) { | |||
| log.Warn("sql err", err) | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err"))) | |||
| return | |||
| } | |||
| if u != nil { | |||
| u, err := models.GetUserByPhoneNumber(phoneNumber) | |||
| if err != nil && !models.IsErrUserNotExist(err) { | |||
| log.Warn("sql err", err) | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err"))) | |||
| return | |||
| } | |||
| if u.ID == ctx.User.ID { //没有修改手机号 | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.not_modify"))) | |||
| return | |||
| } else { //修改的手机已经被别的用户注册 | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register"))) | |||
| return | |||
| } | |||
| if u != nil { | |||
| if u.ID == ctx.User.ID { //没有修改手机号 | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.not_modify"))) | |||
| return | |||
| } else { //修改的手机已经被别的用户注册 | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.already_register"))) | |||
| return | |||
| } | |||
| } | |||
| } | |||
| } | |||
| redisConn := labelmsg.Get() | |||
| defer redisConn.Close() | |||
| sendTimes, err := phoneService.GetPhoneNumberSendTimes(redisConn, phoneNumber) | |||
| if err != nil && err!=redis.ErrNil { | |||
| if err != nil && err != redis.ErrNil { | |||
| log.Warn("redis err", err) | |||
| ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("phone.query_err"))) | |||
| return | |||