*: add migration to convert all emails to lowercase

Fixes #338
This commit is contained in:
Eric Chiang 2016-03-01 10:51:50 -08:00
parent 118bbb6d18
commit 9bc68edae7
3 changed files with 23 additions and 3 deletions

View file

@ -0,0 +1,18 @@
-- +migrate Up
CREATE OR REPLACE FUNCTION raise_exp() RETURNS VOID AS $$
BEGIN
RAISE EXCEPTION 'Found duplicate emails when using case insensitive comparision, cannot perform migration.';
END;
$$ LANGUAGE plpgsql;
SELECT LOWER(email),
COUNT(email),
CASE
WHEN COUNT(email) > 1 THEN raise_exp()
ELSE NULL
END
FROM authd_user
GROUP BY LOWER(email);
UPDATE authd_user SET email = LOWER(email);

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"reflect"
"strings"
"time"
"github.com/go-gorp/gorp"
@ -400,7 +401,7 @@ func (r *userRepo) getByEmail(tx repo.Transaction, email string) (user.User, err
qt := r.quote(userTableName)
ex := r.executor(tx)
var um userModel
err := ex.SelectOne(&um, fmt.Sprintf("select * from %s where email = $1", qt), email)
err := ex.SelectOne(&um, fmt.Sprintf("select * from %s where email = $1", qt), strings.ToLower(email))
if err != nil {
if err == sql.ErrNoRows {
@ -424,7 +425,7 @@ func (r *userRepo) insertRemoteIdentity(tx repo.Transaction, userID string, ri u
type userModel struct {
ID string `db:"id"`
Email string `db:"email"`
Email string `db:"email"` // NOTE(ericchiang): When making comparisions emails are case insensitive.
EmailVerified bool `db:"email_verified"`
DisplayName string `db:"display_name"`
Disabled bool `db:"disabled"`
@ -453,7 +454,7 @@ func newUserModel(u *user.User) (*userModel, error) {
um := userModel{
ID: u.ID,
DisplayName: u.DisplayName,
Email: u.Email,
Email: strings.ToLower(u.Email),
EmailVerified: u.EmailVerified,
Admin: u.Admin,
Disabled: u.Disabled,

View file

@ -105,6 +105,7 @@ func (u *User) AddToClaims(claims jose.Claims) {
// UserRepo implementations maintain a persistent set of users.
// The following invariants must be maintained:
// * Users must have a unique Email and ID
// * Emails are case insensitive.
// * No other Users may have the same RemoteIdentity as one of the
// users. (This constraint may be relaxed in the future)
type UserRepo interface {