func userWithSocialAccount(ctx *app.Context, name SocialAccountType, acc socialAccount) (reflect.Value, error) { user, userVal := newEmptyUser(ctx) ok, err := ctx.Orm().One(orm.Eq(name.String()+".Id", acc.accountId()), userVal) if err != nil { return reflect.Value{}, err } acVal := reflect.Indirect(reflect.ValueOf(acc)) imageVal := acVal.FieldByName("Image") imageFormatVal := acVal.FieldByName("ImageFormat") imageURLVal := acVal.FieldByName("ImageURL") if ok { prev := getUserValue(user, name.String()) if prev != nil { prevVal := reflect.Indirect(reflect.ValueOf(prev)) prevImage := prevVal.FieldByName("Image").String() prevImageFormat := prevVal.FieldByName("ImageFormat").String() prevImageURL := prevVal.FieldByName("ImageURL").String() image, imageFormat, imageURL := mightFetchImage(ctx, acc.imageURL(), prevImage, prevImageFormat, prevImageURL) imageVal.Set(reflect.ValueOf(image)) imageFormatVal.Set(reflect.ValueOf(imageFormat)) imageURLVal.Set(reflect.ValueOf(imageURL)) } // Note: don't update main email, since it could // cause a conflict if the new email is already in the db. // already registered wi setUserValue(user, name.String(), acc) } else { image, imageFormat, imageURL := fetchImage(ctx, acc.imageURL()) imageVal.Set(reflect.ValueOf(image)) imageFormatVal.Set(reflect.ValueOf(imageFormat)) imageURLVal.Set(reflect.ValueOf(imageURL)) // Check email if email := acc.email(); email != "" { // Check if we have a user with that email. In that case // Add this social account to his account. ok, err = ctx.Orm().One(orm.Eq("User.NormalizedEmail", Normalize(email)), userVal) if err != nil { return reflect.Value{}, err } if ok { setUserValue(user, name.String(), acc) } } if !ok { // This is a bit racy, but we'll live with it for now username := acc.username() freeUsername := FindFreeUsername(ctx, username) user = newUser(ctx, freeUsername) setUserValue(user, "AutomaticUsername", true) setUserValue(user, "Email", acc.email()) setUserValue(user, name.String(), acc) } } ctx.Orm().MustSave(user.Interface()) return user, nil }
func decodeResetPayload(ctx *app.Context, payload string) (reflect.Value, error) { se, err := ctx.App().EncryptSigner(Salt) if err != nil { return reflect.Value{}, err } value, err := se.UnsignDecrypt(payload) if err != nil { return reflect.Value{}, err } qs, err := url.ParseQuery(string(value)) if err != nil { return reflect.Value{}, err } userId, err := strconv.ParseInt(qs.Get("u"), 36, 64) if err != nil { return reflect.Value{}, err } ts, err := strconv.ParseInt(qs.Get("t"), 36, 64) if err != nil { return reflect.Value{}, err } if time.Since(time.Unix(ts, 0)) > PasswordResetExpiry { return reflect.Value{}, errResetExpired } user, userVal := newEmptyUser(ctx) ok := ctx.Orm().MustOne(orm.Eq("User.UserId", userId), userVal) if !ok { return reflect.Value{}, errNoSuchUser } return user, nil }
func getByUsernameOrEmail(ctx *app.Context, usernameOrEmail string) (interface{}, error) { norm := Normalize(usernameOrEmail) _, userVal := newEmptyUser(ctx) var ok bool o := ctx.Orm() q1 := orm.Eq("User.NormalizedUsername", norm) q2 := orm.Eq("User.NormalizedEmail", norm) if o.Driver().Capabilities()&driver.CAP_OR != 0 { ok = o.MustOne(orm.Or(q1, q2), userVal) } else { ok = o.MustOne(q1, userVal) if !ok { ok = o.MustOne(q2, userVal) } } if !ok { return nil, ErrNoUser } return userVal, nil }
func Get(ctx *app.Context, id int64) (app.User, error) { _, userVal := newEmptyUser(ctx) key := "gnd:la:user:"******"User.UserId", id), userVal) if err != nil { return nil, err } if !ok { return nil, errNoSuchUser } ctx.Cache().Set(key, userVal, 300) return userVal.(app.User), nil }
func FindFreeUsername(ctx *app.Context, username string) string { userType := getUserType(ctx) original := username ii := 1 o := ctx.Orm() tbl := o.TypeTable(userType) if tbl == nil { panic(fmt.Errorf("user type %s is not registered with the orm - add orm.Register(&%s{}) somewhere in your app", userType, userType.Name())) } for { exists, err := o.Exists(tbl, orm.Eq("User.NormalizedUsername", Normalize(username))) if err != nil { panic(err) } if !exists { break } username = original + strconv.Itoa(ii) ii++ } return username }
func forgotHandler(ctx *app.Context) { d := data(ctx) if !d.allowDirectSignIn() { ctx.NotFound("") return } var user User var isEmail bool var sent bool var fields struct { Username string `form:",singleline,label=Username or Email"` ValidateUsername func(*app.Context) error } fields.ValidateUsername = func(c *app.Context) error { username := Normalize(fields.Username) isEmail = strings.Contains(username, "@") var field string if isEmail { field = "User.NormalizedEmail" } else { field = "User.NormalizedUsername" } userVal, userIface := newEmptyUser(ctx) ok := c.Orm().MustOne(orm.Eq(field, username), userIface) if !ok { if isEmail { return i18n.Errorf("address %q does not belong to any registered user", username) } return i18n.Errorf("username %q does not belong to any registered user", username) } user = getUserValue(userVal, "User").(User) if user.Email == "" { return i18n.Errorf("username %q does not have any registered emails", username) } return nil } f := form.New(ctx, &fields) if f.Submitted() && f.IsValid() { se, err := ctx.App().EncryptSigner(Salt) if err != nil { panic(err) } values := make(url.Values) values.Add("u", strconv.FormatInt(user.Id(), 36)) values.Add("t", strconv.FormatInt(time.Now().Unix(), 36)) values.Add("n", stringutil.Random(64)) payload := values.Encode() p, err := se.EncryptSign([]byte(payload)) if err != nil { panic(err) } abs := ctx.URL() reset := fmt.Sprintf("%s://%s%s?p=%s", abs.Scheme, abs.Host, ctx.MustReverse(ResetHandlerName), p) data := map[string]interface{}{ "URL": reset, } from := mail.DefaultFrom() if from == "" { from = fmt.Sprintf("no-reply@%s", abs.Host) } msg := &mail.Message{ To: user.Email, From: from, Subject: fmt.Sprintf(ctx.T("Reset your %s password"), d.opts.SiteName), } ctx.MustSendMail("reset_password.txt", data, msg) sent = true } data := map[string]interface{}{ "ForgotForm": f, "IsEmail": isEmail, "Sent": sent, "User": user, } ctx.MustExecute(ForgotTemplateName, data) }
// ByUsername returns a query.Q which finds a user given its // username. func ByUsername(username string) query.Q { return orm.Eq("User.NormalizedUsername", Normalize(username)) }
// ById returns a query.Q which finds a user given its id. func ById(id int64) query.Q { return orm.Eq("User.UserId", id) }
// ByEmail returns a query.Q which finds a user given its // email. func ByEmail(email string) query.Q { return orm.Eq("User.NormalizedEmail", Normalize(email)) }