コード例 #1
0
ファイル: handlers.go プロジェクト: rainycape/gondola
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
}
コード例 #2
0
ファイル: util.go プロジェクト: rainycape/gondola
func validateNewUsername(ctx *app.Context, username string) error {
	userType := getUserType(ctx)
	found, err := ctx.Orm().Exists(ctx.Orm().TypeTable(userType), ByUsername(username))
	if err != nil {
		return err
	}
	if found {
		return i18n.Errorf("username %q is already in use", username)
	}
	return nil
}
コード例 #3
0
ファイル: commands.go プロジェクト: rainycape/gondola
func listUsers(ctx *app.Context) {
	userVal, ptr := newEmptyUser(ctx)
	iter := ctx.Orm().All().Iter()
	w := tabwriter.NewWriter(os.Stdout, 0, 8, 2, '\t', tabwriter.Debug)
	fmt.Fprint(w, "ID\tUsername\tEmail\tAdmin?\n")
	for iter.Next(ptr) {
		val := userVal.Elem().FieldByName("User").Interface().(User)
		fmt.Fprintf(w, "%d\t%s\t%s\t%v\n", val.UserId, val.Username, val.Email, val.Admin)
	}
	if err := w.Flush(); err != nil {
		panic(err)
	}
}
コード例 #4
0
ファイル: util.go プロジェクト: rainycape/gondola
func validateNewEmail(ctx *app.Context, email string) (string, error) {
	addr, err := mail.Validate(email, true)
	if err != nil {
		return "", i18n.Errorf("this does not look like a valid email address")
	}
	userType := getUserType(ctx)
	found, err := ctx.Orm().Exists(ctx.Orm().TypeTable(userType), ByEmail(addr))
	if err != nil {
		return "", err
	}
	if found {
		return "", i18n.Errorf("email %q is already in use", addr)
	}
	return addr, nil
}
コード例 #5
0
ファイル: funcs.go プロジェクト: rainycape/gondola
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
}
コード例 #6
0
ファイル: handlers.go プロジェクト: rainycape/gondola
func ResetHandler(ctx *app.Context) {
	d := data(ctx)
	if !d.allowDirectSignIn() {
		ctx.NotFound("")
		return
	}
	payload := ctx.FormValue("p")
	var valid bool
	var expired bool
	var f *form.Form
	var user reflect.Value
	var err error
	var done bool
	if payload != "" {
		user, err = decodeResetPayload(ctx, payload)
		if err == nil && user.IsValid() {
			valid = true
		} else {
			if err == errResetExpired {
				expired = true
			}
		}
	}
	if valid {
		passwordForm := &PasswordForm{User: user}
		f = form.New(ctx, passwordForm)
		if f.Submitted() && f.IsValid() {
			ctx.Orm().MustSave(user.Interface())
			ctx.MustSignIn(asGondolaUser(user))
			done = true
		}
	}
	data := map[string]interface{}{
		"Valid":        valid,
		"Expired":      expired,
		"Done":         done,
		"User":         user,
		"PasswordForm": f,
		"Payload":      payload,
	}
	ctx.MustExecute(ResetTemplateName, data)
}
コード例 #7
0
ファイル: funcs.go プロジェクト: rainycape/gondola
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
}
コード例 #8
0
ファイル: funcs.go プロジェクト: rainycape/gondola
// Create creates a new user user with the given parameters, previously checking that
// the given username and email aren't already in use. Note that the user is only created,
// no implicit sign in is performed.
func Create(ctx *app.Context, username string, email string, pw string) (app.User, error) {
	if err := validateNewUsername(ctx, username); err != nil {
		return nil, err
	}
	addr, err := validateNewEmail(ctx, email)
	if err != nil {
		return nil, err
	}
	user, userIface := newEmptyUser(ctx)
	setUserValue(user, "Username", username)
	setUserValue(user, "NormalizedUsername", Normalize(username))
	setUserValue(user, "Email", addr)
	setUserValue(user, "NormalizedEmail", Normalize(addr))
	setUserValue(user, "Password", password.New(pw))
	setUserValue(user, "Created", time.Now().UTC())
	if _, err = ctx.Orm().Insert(userIface); err != nil {
		return nil, err
	}
	return userIface.(app.User), nil
}
コード例 #9
0
ファイル: commands.go プロジェクト: rainycape/gondola
func registerUser(ctx *app.Context) {
	username := ctx.RequireIndexValue(0)
	userVal, _ := newEmptyUser(ctx)
	updating := false
	if ctx.Orm().MustOne(ByUsername(username), userVal.Interface()) {
		// Updating existing user
		updating = true
	} else {
		// Creating a new one
		userVal = newUser(ctx, username)
	}
	var askPassword bool
	ctx.ParseParamValue("p", &askPassword)
	if !updating || askPassword {
		password1, err := speakeasy.Ask("Password:"******"Confirm Password:"******"passwords don't match"))
		}
		setUserValue(userVal, "Password", password.New(password1))
	}
	var admin bool
	ctx.ParseParamValue("s", &admin)
	setUserValue(userVal, "Admin", admin)

	var email string
	ctx.ParseParamValue("e", &email)
	if email != "" {
		setUserValue(userVal, "Email", email)
	}

	ctx.Orm().MustSave(userVal.Interface())
	ctx.Logger().Infof("saved user as %+v", userVal.Interface())
}
コード例 #10
0
ファイル: util.go プロジェクト: rainycape/gondola
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
}
コード例 #11
0
ファイル: social.go プロジェクト: rainycape/gondola
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
}
コード例 #12
0
ファイル: handlers.go プロジェクト: rainycape/gondola
func saveNewUser(ctx *app.Context, user reflect.Value) {
	setUserValue(user, "Password", password.New(string(getUserValue(user, "Password").(password.Password))))
	setUserValue(user, "Created", time.Now().UTC())
	ctx.Orm().MustInsert(user.Interface())
	ctx.MustSignIn(asGondolaUser(user))
}