diff --git a/build b/build index ba9e9d5d..899ba9cb 100755 --- a/build +++ b/build @@ -3,6 +3,21 @@ export GOPATH=${PWD}/Godeps/_workspace export GOBIN=${PWD}/bin +if command -v go-bindata &>/dev/null; then + DEX_MIGRATE_FROM_DISK=${DEX_MIGRATE_FROM_DISK:=false} + + echo "Turning migrations into ./db/migrations/assets.go" + if [ "$DEX_MIGRATE_FROM_DISK" = true ]; then + echo "Compiling migrations.go: will read migrations from disk." + else + echo "Compiling migrations into migrations.go" + fi + go-bindata -debug=$DEX_MIGRATE_FROM_DISK -modtime=1 -pkg migrations -o ./db/migrations/assets.go ./db/migrations + gofmt -w ./db/migrations/assets.go +else + echo "Could not find go-bindata in path, will not generate migrations" +fi + rm -rf $GOPATH/src/github.com/coreos/dex mkdir -p $GOPATH/src/github.com/coreos/ ln -s ${PWD} $GOPATH/src/github.com/coreos/dex diff --git a/db/client.go b/db/client.go index dd04a18d..23cc6108 100644 --- a/db/client.go +++ b/db/client.go @@ -66,7 +66,7 @@ type clientIdentityModel struct { ID string `db:"id"` Secret []byte `db:"secret"` Metadata string `db:"metadata"` - DexAdmin bool `db:"dexAdmin"` + DexAdmin bool `db:"dex_admin"` } func newClientMetadataJSON(cm *oidc.ClientMetadata) *clientMetadataJSON { diff --git a/db/migrate.go b/db/migrate.go new file mode 100644 index 00000000..bdb42366 --- /dev/null +++ b/db/migrate.go @@ -0,0 +1,52 @@ +package db + +import ( + "fmt" + + "github.com/coopernurse/gorp" + "github.com/lib/pq" + migrate "github.com/rubenv/sql-migrate" + + "github.com/coreos/dex/db/migrations" +) + +const ( + migrationDialect = "postgres" + migrationTable = "dex_migrations" + migrationDir = "db/migrations" +) + +func init() { + migrate.SetTable(migrationTable) +} + +func MigrateToLatest(dbMap *gorp.DbMap) (int, error) { + source := getSource() + + return migrate.Exec(dbMap.Db, migrationDialect, source, migrate.Up) +} + +func MigrateMaxMigrations(dbMap *gorp.DbMap, max int) (int, error) { + source := getSource() + + return migrate.ExecMax(dbMap.Db, migrationDialect, source, migrate.Up, max) +} + +func GetPlannedMigrations(dbMap *gorp.DbMap) ([]*migrate.PlannedMigration, error) { + migrations, _, err := migrate.PlanMigration(dbMap.Db, migrationDialect, getSource(), migrate.Up, 0) + return migrations, err +} + +func DropMigrationsTable(dbMap *gorp.DbMap) error { + qt := pq.QuoteIdentifier(migrationTable) + _, err := dbMap.Exec(fmt.Sprintf("drop table if exists %s ;", qt)) + return err +} + +func getSource() migrate.MigrationSource { + return &migrate.AssetMigrationSource{ + Dir: migrationDir, + Asset: migrations.Asset, + AssetDir: migrations.AssetDir, + } +} diff --git a/db/migrate_test.go b/db/migrate_test.go new file mode 100644 index 00000000..41c9b51f --- /dev/null +++ b/db/migrate_test.go @@ -0,0 +1,42 @@ +package db + +import ( + "fmt" + "os" + "testing" + + "github.com/coopernurse/gorp" +) + +func initDB(dsn string) *gorp.DbMap { + c, err := NewConnection(Config{DSN: dsn}) + if err != nil { + panic(fmt.Sprintf("error making db connection: %q", err)) + } + if err = c.DropTablesIfExists(); err != nil { + panic(fmt.Sprintf("Unable to drop database tables: %v", err)) + } + + return c +} + +// TestGetPlannedMigrations is a sanity check, ensuring that at least one +// migration can be found. +func TestGetPlannedMigrations(t *testing.T) { + dsn := os.Getenv("DEX_TEST_DSN") + if dsn == "" { + t.Logf("Test will not run without DEX_TEST_DSN environment variable.") + return + } + dbMap := initDB(dsn) + ms, err := GetPlannedMigrations(dbMap) + if err != nil { + pwd, err := os.Getwd() + t.Logf("pwd: %v", pwd) + t.Fatalf("unexpected err: %q", err) + } + + if len(ms) == 0 { + t.Fatalf("expected non-empty migrations") + } +} diff --git a/db/migrations/0001_initial_migration.sql b/db/migrations/0001_initial_migration.sql new file mode 100644 index 00000000..d2350b7a --- /dev/null +++ b/db/migrations/0001_initial_migration.sql @@ -0,0 +1,47 @@ +-- +migrate Up +CREATE TABLE IF NOT EXISTS "authd_user" ( + "id" text not null primary key, + "email" text, + "email_verified" boolean, + "display_name" text, + "admin" boolean) ; + +CREATE TABLE IF NOT EXISTS "client_identity" ( + "id" text not null primary key, + "secret" bytea, + "metadata" text); + +CREATE TABLE IF NOT EXISTS "connector_config" ( + "id" text not null primary key, + "type" text, "config" text) ; + +CREATE TABLE IF NOT EXISTS "key" ( + "value" bytea not null primary key) ; + +CREATE TABLE IF NOT EXISTS "password_info" ( + "user_id" text not null primary key, + "password" text, + "password_expires" bigint) ; + +CREATE TABLE IF NOT EXISTS "session" ( + "id" text not null primary key, + "state" text, + "created_at" bigint, + "expires_at" bigint, + "client_id" text, + "client_state" text, + "redirect_url" text, "identity" text, + "connector_id" text, + "user_id" text, "register" boolean) ; + +CREATE TABLE IF NOT EXISTS "session_key" ( + "key" text not null primary key, + "session_id" text, + "expires_at" bigint, + "stale" boolean) ; + +CREATE TABLE IF NOT EXISTS "remote_identity_mapping" ( + "connector_id" text not null, + "user_id" text, + "remote_id" text not null, + primary key ("connector_id", "remote_id")) ; diff --git a/db/migrations/0002_dex_admin.sql b/db/migrations/0002_dex_admin.sql new file mode 100644 index 00000000..b5651599 --- /dev/null +++ b/db/migrations/0002_dex_admin.sql @@ -0,0 +1,2 @@ +-- +migrate Up +ALTER TABLE client_identity ADD COLUMN "dex_admin" boolean; diff --git a/db/migrations/0003_user_created_at.sql b/db/migrations/0003_user_created_at.sql new file mode 100644 index 00000000..976079bb --- /dev/null +++ b/db/migrations/0003_user_created_at.sql @@ -0,0 +1,2 @@ +-- +migrate Up +ALTER TABLE authd_user ADD COLUMN "created_at" bigint; diff --git a/db/migrations/0004_session_nonce.sql b/db/migrations/0004_session_nonce.sql new file mode 100644 index 00000000..2da5b392 --- /dev/null +++ b/db/migrations/0004_session_nonce.sql @@ -0,0 +1,2 @@ +-- +migrate Up +ALTER TABLE session ADD COLUMN "nonce" text; diff --git a/db/migrations/0005_refresh_token_create.sql b/db/migrations/0005_refresh_token_create.sql new file mode 100644 index 00000000..acda8e29 --- /dev/null +++ b/db/migrations/0005_refresh_token_create.sql @@ -0,0 +1,21 @@ +-- +migrate Up +CREATE TABLE refresh_token ( + id bigint NOT NULL, + payload_hash text, + user_id text, + client_id text +); + +CREATE SEQUENCE refresh_token_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE refresh_token_id_seq OWNED BY refresh_token.id; + +ALTER TABLE ONLY refresh_token ALTER COLUMN id SET DEFAULT nextval('refresh_token_id_seq'::regclass); + +ALTER TABLE ONLY refresh_token + ADD CONSTRAINT refresh_token_pkey PRIMARY KEY (id); diff --git a/db/migrations/0006_user_email_unique.sql b/db/migrations/0006_user_email_unique.sql new file mode 100644 index 00000000..3a42a72c --- /dev/null +++ b/db/migrations/0006_user_email_unique.sql @@ -0,0 +1,3 @@ +-- +migrate Up +ALTER TABLE ONLY authd_user + ADD CONSTRAINT authd_user_email_key UNIQUE (email); diff --git a/db/migrations/assets.go b/db/migrations/assets.go new file mode 100644 index 00000000..33326353 --- /dev/null +++ b/db/migrations/assets.go @@ -0,0 +1,377 @@ +// Code generated by go-bindata. +// sources: +// db/migrations/0001_initial_migration.sql +// db/migrations/0002_dex_admin.sql +// db/migrations/0003_user_created_at.sql +// db/migrations/0004_session_nonce.sql +// db/migrations/0005_refresh_token_create.sql +// db/migrations/0006_user_email_unique.sql +// db/migrations/assets.go +// DO NOT EDIT! + +package migrations + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _dbMigrations0001_initial_migrationSql = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x93\xcf\x8a\xdb\x30\x10\xc6\xef\x79\x0a\x91\xd3\x86\x66\x9f\xa0\xa7\x6d\x71\x61\xa1\xb4\xd0\x75\xa1\x37\x31\xb5\x26\xee\x50\xfd\x43\x1a\x6f\xd7\x6f\x5f\xd9\x4e\x14\xc7\xce\xc6\x26\x81\x84\x58\xd6\xfc\xe6\x9b\x6f\x66\x1e\x1f\xc5\x07\x43\x75\x00\x46\xf1\xd3\x6f\x3e\xff\x28\x9e\xca\x42\x94\x4f\x9f\xbe\x16\xe2\xf9\x8b\xf8\xf6\xbd\x14\xc5\xaf\xe7\x97\xf2\x45\x6c\xa1\xe1\x3f\x4a\x36\x11\xc3\x56\x3c\x6c\xc4\xf0\xd9\x92\xda\x0a\xc6\x37\x16\xd6\xa5\x6f\xa3\xb5\xf0\x81\x0c\x84\x56\xfc\xc5\x76\x9f\xaf\xa1\x01\xd2\xc3\xcd\xc9\xa1\x7c\xc5\x40\x07\xc2\xc4\xf9\xed\x9c\x46\xb0\xe7\x0b\x8a\xa2\xd7\xd0\x4a\x0b\x06\xa7\xc1\xa0\x0c\xd9\x1c\xb3\x13\x1f\x37\x37\xd5\x57\x9a\xd0\xb2\x24\x95\x7e\x89\xdb\x3b\x4a\x88\x58\x05\xe4\x94\xb1\x65\x84\xf3\xb1\x41\x06\x05\x0c\x03\x63\xb7\x24\xc3\x59\x8b\x15\xbb\x20\xd3\xbf\x03\xd5\x77\xe8\xe0\xd6\x9f\xcc\xe8\x79\x3d\xa5\xcf\xbd\xe4\x41\xc2\x8c\xf3\xbd\x82\x6e\xf0\x58\xcf\xd5\x9c\x8b\x40\x0f\x31\xfe\x73\x41\x49\xb2\x07\x37\x46\x77\x53\x22\x57\xd6\x73\x82\x4c\x1b\x9c\xe1\xf8\xe6\x29\x60\x4c\x4a\xa9\x26\xbb\x5c\x66\xc4\x18\xc9\xd9\x7b\x5a\xcc\x69\x0f\xa6\x3a\x52\xd7\xd3\xa9\x92\xc0\x27\x05\xa3\x09\x1e\xa4\x5d\x7d\x97\x27\x6e\x06\x1c\x5e\x5c\x4d\x16\x50\x25\x60\xc5\xb2\x09\x3a\x37\xf9\x3c\xb4\x13\x50\x1e\xa6\x79\x92\x8b\x0e\xec\x3b\x70\x4d\x91\xbb\xdd\x5d\xbb\x31\x47\x1b\xe5\x64\x6a\xfa\xc7\x55\xeb\x32\x84\xcf\xa5\xdd\x32\x2d\x99\xa2\x71\xbd\xc6\x80\xc6\x31\xe6\xad\x96\x06\xbc\x27\x7b\xb1\x55\x73\x93\xb2\xf0\xf7\xdc\x1a\x75\xe3\x88\x7f\x2f\x70\x54\xb9\x78\xb8\x4c\xb5\x1f\x87\xef\xba\x4a\xfe\x07\x00\x00\xff\xff\xae\xbe\x65\x61\x6c\x05\x00\x00") + +func dbMigrations0001_initial_migrationSqlBytes() ([]byte, error) { + return bindataRead( + _dbMigrations0001_initial_migrationSql, + "db/migrations/0001_initial_migration.sql", + ) +} + +func dbMigrations0001_initial_migrationSql() (*asset, error) { + bytes, err := dbMigrations0001_initial_migrationSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/0001_initial_migration.sql", size: 1388, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dbMigrations0002_dex_adminSql = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\xce\xc9\x4c\xcd\x2b\x89\xcf\x4c\x01\x92\x99\x25\x95\x0a\x8e\x2e\x2e\x0a\xce\xfe\x3e\xa1\xbe\x7e\x0a\x4a\x29\xa9\x15\xf1\x89\x29\xb9\x99\x79\x4a\x0a\x49\xf9\xf9\x39\xa9\x89\x79\xd6\x5c\x80\x00\x00\x00\xff\xff\xfd\xb4\x6c\x60\x4b\x00\x00\x00") + +func dbMigrations0002_dex_adminSqlBytes() ([]byte, error) { + return bindataRead( + _dbMigrations0002_dex_adminSql, + "db/migrations/0002_dex_admin.sql", + ) +} + +func dbMigrations0002_dex_adminSql() (*asset, error) { + bytes, err := dbMigrations0002_dex_adminSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/0002_dex_admin.sql", size: 75, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dbMigrations0003_user_created_atSql = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\x2c\x2d\xc9\x48\x89\x2f\x2d\x4e\x2d\x52\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x50\x4a\x2e\x4a\x05\x2a\x4e\x89\x4f\x2c\x51\x52\x48\xca\x4c\xcf\xcc\x2b\xb1\xe6\x02\x04\x00\x00\xff\xff\xf4\xa1\xf0\x95\x46\x00\x00\x00") + +func dbMigrations0003_user_created_atSqlBytes() ([]byte, error) { + return bindataRead( + _dbMigrations0003_user_created_atSql, + "db/migrations/0003_user_created_at.sql", + ) +} + +func dbMigrations0003_user_created_atSql() (*asset, error) { + bytes, err := dbMigrations0003_user_created_atSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/0003_user_created_at.sql", size: 70, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dbMigrations0004_session_nonceSql = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x28\x4e\x2d\x2e\xce\xcc\xcf\x53\x70\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x50\xca\xcb\xcf\x4b\x4e\x55\x52\x28\x49\xad\x28\xb1\xe6\x02\x04\x00\x00\xff\xff\x77\x11\x16\x8b\x3c\x00\x00\x00") + +func dbMigrations0004_session_nonceSqlBytes() ([]byte, error) { + return bindataRead( + _dbMigrations0004_session_nonceSql, + "db/migrations/0004_session_nonce.sql", + ) +} + +func dbMigrations0004_session_nonceSql() (*asset, error) { + bytes, err := dbMigrations0004_session_nonceSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/0004_session_nonce.sql", size: 60, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dbMigrations0005_refresh_token_createSql = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x90\x51\x4f\xc2\x30\x10\xc7\xdf\xf7\x29\xee\x0d\x88\x62\xc2\x2b\x3e\x95\xed\x0c\x8b\x5d\xa7\x5d\x2b\xf2\xb4\x54\x56\x59\xc3\x1c\x73\xad\x46\xbe\xbd\x65\x13\x08\xc4\x68\xdf\xfa\xbb\xfb\xdf\x2f\x77\xe3\x31\x5c\xbd\x99\x75\xab\x9c\x06\xd9\x04\x21\x47\x22\x10\x04\x99\x51\x84\x56\xbf\xb6\xda\x96\xb9\xdb\x6e\x74\x0d\xc3\x00\xfc\x33\x05\xbc\x98\xb5\xa9\x1d\xb0\x54\x00\x93\x94\x5e\x77\xbc\x51\xbb\x6a\xab\x8a\xbc\x54\xb6\x04\xa7\xbf\x5c\x8f\x3f\xac\x6e\x73\x9f\x39\x91\x55\x65\x74\xed\x0e\x2c\x18\xdd\x06\x07\x69\x86\x8f\x12\x59\x78\xe1\xf5\x9d\xb9\xd5\xef\x5d\x36\x13\x84\x0b\x58\xc4\x62\x0e\x93\x0e\xc4\xcc\x67\x13\x64\x02\x66\xcb\x1f\xc4\x52\x48\x62\xf6\x44\xa8\xc4\xe3\x9f\x3c\x9f\xfe\x21\x09\xe7\x08\x13\xaf\x25\x54\x20\xff\xdb\x0a\xe9\x82\x61\xb4\x1f\x7e\x56\xbd\x31\xc5\x31\xdf\x9f\x2a\x65\xf4\xa2\x07\xfa\x72\x98\x52\x99\xb0\xfd\xd9\x32\x14\x10\xe1\x1d\x91\x54\x40\xed\x57\xff\x54\xd5\x70\xf0\x9b\x74\x30\x9d\xb6\x7a\xbd\xaa\x94\xb5\xa3\x7f\x35\xdd\x4e\x24\x8a\xbc\x88\x65\x82\x93\xd8\xdf\xe2\x7c\x68\xb3\xd1\x3b\x78\xe0\x71\x42\xf8\x12\xee\x71\x09\x43\x53\xf8\xb9\xdf\x01\x00\x00\xff\xff\xff\xeb\x3d\xc4\xf9\x01\x00\x00") + +func dbMigrations0005_refresh_token_createSqlBytes() ([]byte, error) { + return bindataRead( + _dbMigrations0005_refresh_token_createSql, + "db/migrations/0005_refresh_token_create.sql", + ) +} + +func dbMigrations0005_refresh_token_createSql() (*asset, error) { + bytes, err := dbMigrations0005_refresh_token_createSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/0005_refresh_token_create.sql", size: 505, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dbMigrations0006_user_email_uniqueSql = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd5\x55\xd0\xce\xcd\x4c\x2f\x4a\x2c\x49\x55\x08\x2d\xe0\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\xf0\xf7\xf3\x89\x54\x48\x2c\x2d\xc9\x48\x89\x2f\x2d\x4e\x2d\xe2\x52\x00\x02\x47\x17\x17\x05\x67\x7f\xbf\xe0\x90\x20\x47\x4f\xbf\x10\x24\xd9\xf8\xd4\xdc\xc4\xcc\x9c\xf8\xec\xd4\x4a\x85\x50\x3f\xcf\xc0\x50\x57\x05\x0d\xb0\x88\xa6\x35\x17\x20\x00\x00\xff\xff\x18\x48\x0d\x30\x63\x00\x00\x00") + +func dbMigrations0006_user_email_uniqueSqlBytes() ([]byte, error) { + return bindataRead( + _dbMigrations0006_user_email_uniqueSql, + "db/migrations/0006_user_email_unique.sql", + ) +} + +func dbMigrations0006_user_email_uniqueSql() (*asset, error) { + bytes, err := dbMigrations0006_user_email_uniqueSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/0006_user_email_unique.sql", size: 99, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dbMigrationsAssetsGo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd4\x99\x5b\x6f\xdb\x46\xf6\xc0\x9f\xad\x4f\xc1\x1a\x68\x21\xfd\xe1\xbf\x4c\xf1\x22\x8a\x06\xfa\xd2\x26\x0b\xe4\xa1\x29\xb0\xcd\x3e\xad\x17\xc2\x90\x1c\xba\x44\x65\xc9\x11\xe5\xae\x93\x20\xdf\x7d\xcf\x6f\xce\x91\xad\xc4\x92\x9d\x38\x1b\x64\xfb\x40\x8b\x9c\x39\x73\xe6\xdc\x6f\x3e\x3d\x8d\x7e\x5e\x35\x3e\xba\xf0\x4b\xbf\x76\x1b\xdf\x44\xd5\x9b\xe8\x62\xf5\xff\x55\xb7\x6c\xdc\xc6\x8d\x07\x02\xd0\xaf\xae\xd7\xb5\xef\xcf\x78\x6f\xaa\xd3\xcb\xee\x42\x20\xbb\xd5\xb2\x3f\x8d\xe3\x78\x32\xef\x96\xdd\xa6\x73\x8b\xf9\xed\xfa\xb8\x7f\xbd\xd8\x0b\x9b\xcc\x1b\x7f\x33\x77\xcd\x65\x77\x18\x26\x9d\x5f\xf7\x7e\x3d\xaf\xd7\x1e\x6a\xe6\x6e\x73\x10\x32\x9b\xf7\xbe\xef\xe5\x6b\xbe\x5c\x2d\x6b\x7f\x10\x2e\x9f\xaf\x7d\xbb\xf6\xfd\xef\xf3\xcd\xea\x0f\xbf\x34\xd4\x07\xc1\xa7\x4a\x80\xbf\x74\xdd\x62\x7e\xbd\xec\x5e\x5f\x1f\x80\x75\x7d\xef\x37\xfd\xf8\x62\xc5\xd6\xb3\x5f\xa3\x97\xbf\xbe\x8a\x9e\x3f\x7b\xf1\xea\xbb\xc1\xe0\xca\xd5\x7f\xb8\x0b\x1f\xdd\x41\x0f\x06\xdd\xe5\xd5\x6a\xbd\x89\x86\x83\xa3\xe3\xea\xcd\xc6\xf7\xc7\xf2\x52\xaf\x2e\xaf\x84\xb2\xfe\xf4\xe2\x6d\x77\xc5\x42\x7b\xb9\xe1\xa7\x5b\xf1\xb7\xdf\xac\xbb\xe5\x45\x00\x5c\x85\xbf\x9b\xee\xd2\xeb\xf6\x69\xb7\xba\xde\x74\x0b\x3e\xae\xdc\xe6\xf7\xd3\xb6\x5b\x78\x5e\x8e\x07\xa3\xc1\xa0\xbd\x5e\xd6\x91\x29\xf0\xef\xde\x35\x43\x5e\xa2\x7f\xfe\x8b\x6b\x4f\xa2\xa5\xbb\xf4\x91\xa2\x1e\x45\xc3\xed\xaa\x5f\xaf\x57\xeb\x51\xf4\x6e\x70\x74\xf1\x36\x7c\x45\x67\x3f\x46\x50\x35\x7e\xe9\xff\x0d\x12\xbf\x1e\x06\xb2\xf9\xfe\xe9\xba\x6d\xe5\x1b\xb4\xa3\xd1\xe0\xa8\x6b\xc3\x81\xef\x7e\x8c\x96\xdd\x02\x14\x47\x6b\xbf\xb9\x5e\x2f\xf9\x3c\x89\x84\xa5\xf1\x73\xb0\xb7\xc3\x63\x10\x45\xdf\xbf\x3e\x8b\xbe\xff\xf3\x58\x29\x09\x77\x09\x8e\xf7\x83\xc1\xd1\x9f\x6e\x1d\x55\xd7\x6d\xa4\xf7\xe8\x25\x83\xa3\xb9\x92\xf3\x63\xd4\xad\xc6\x3f\xaf\xae\xde\x0c\x7f\x10\x98\x13\xa1\x4d\x4e\xd5\x8b\xe7\x5b\x4a\xc7\x3f\x2f\x56\xbd\x1f\x0a\xfb\xff\x25\x7a\x40\xa3\xf8\x0f\x20\x12\x40\xa5\xdb\x16\x85\xac\xf1\x4f\x90\x3e\x1c\x9d\x00\x31\x90\xbd\xcd\x9b\x2b\x1f\x05\x43\x41\xe4\xd7\xf5\x06\x2c\x81\x3f\xd3\x87\x5c\xb3\x6c\x57\x51\xb4\xea\xc7\x7f\x13\x1d\xbe\x90\x8f\xdb\x73\xa6\xc2\xed\xfa\x0e\x86\x1d\x1d\x0e\x8e\xfa\xee\xad\x8f\xba\xe5\x66\x9a\x0d\x8e\x2e\xf1\x65\xc3\xf5\x8b\xbc\x87\x95\x57\x62\x36\x11\xb6\x33\xe6\x0d\xf4\xc1\x42\x86\x6d\xf7\xf1\x15\xa3\xe8\xa5\x60\x1e\x8e\x0c\x37\x57\x19\x73\x6d\x37\xe6\x52\x39\x7c\xf8\xec\x6f\x42\x88\x9c\x0d\xa4\x7c\x78\x14\x12\x1f\x3c\x0a\xad\x72\x74\x87\xf2\x0f\x11\xc0\xd7\x63\x08\x60\x4e\x70\xdc\x32\x7a\x0f\x83\x71\x7f\x18\xc9\x8b\xfe\x59\xb7\x16\x14\xd5\x6a\xb5\xd8\x3d\xed\x16\xfd\x23\x9c\xbf\xe9\x95\x71\xbf\x6e\x5d\xed\xdf\xbd\xdf\x39\x6d\x96\x80\x71\xcf\x9b\xea\x97\xdb\x88\xb0\x3f\x76\xfe\xf6\x7a\x21\xa6\xae\xb6\x31\x3c\x3e\xbf\x99\xb4\xe7\x37\xb3\xea\xfc\x26\x9e\xc9\x13\xdb\x53\x9e\xdf\x4c\xbd\xac\xdb\x5a\x2b\x30\x65\x2d\x4f\x7a\x7e\x53\x03\xef\xce\x6f\x1a\x39\x93\xca\xde\x44\x9e\x7a\x7a\x7e\xe3\x65\xbd\x90\x73\xb1\xec\x95\x13\xd9\x17\xd8\x99\xac\x4f\xe5\x29\x65\xcf\x09\x9c\x2b\xe4\xbb\x11\x38\xd9\x9f\xca\xe3\xe4\xa9\x32\x81\x95\xbd\x22\xd7\xef\x54\x60\x52\xd6\xe5\x3b\x01\xaf\xd0\x91\x43\x83\x9c\xcb\x04\xe7\x44\xf0\x4f\x05\x5f\x53\xe8\x6f\xce\xbb\xdc\x9b\x09\xdc\x44\x70\xd5\xb2\x5e\x7b\xa5\x89\xf3\x33\xc1\x35\x93\xf5\x5c\x78\x69\xe4\xbb\x15\x3e\x3c\x34\x55\x7a\x1e\xfa\x26\x5e\xe5\x50\xcb\x9d\x71\xa1\xf7\x40\x0f\xbc\x67\x9c\x31\x7e\x80\x4f\xbd\xca\x23\x11\x7c\x25\xf7\x08\x3d\x59\x22\xef\x72\x47\xd6\x2a\xaf\x15\xf8\xa0\x5d\xd6\xdb\x52\xe5\xdb\x0a\x7c\x2b\x6b\x55\x63\x74\xc2\xaf\xc0\x7a\xb9\xaf\x94\xa7\x15\xd8\x4c\xd6\xa6\xb5\xca\xc1\x23\x0b\xd9\xcf\x04\x7f\x0a\x8d\xf2\x5d\x0b\x0d\xb9\xbc\xa7\xb5\xc2\xd5\x82\xa7\x8d\x95\xff\x52\xce\x37\x4e\xe5\x0f\xef\xc8\x11\x1a\xe0\xd9\xe5\x4a\xbb\x4b\x55\xae\x9c\x41\x2e\x71\x6d\xb2\x31\xb9\x40\x53\xb1\xd5\x57\xab\x74\xc4\xf0\x9e\xe8\xdd\xb5\xd0\x5e\x97\xba\x5e\x18\x7c\x16\xab\xcc\xea\xc4\xe8\x91\x7d\xdf\xa8\xbd\x20\xbb\x2a\x56\x1e\xe3\x4a\xed\xc6\x25\xaa\x3b\x74\x0e\x6f\xac\xc7\x53\xb5\x8d\x7a\xa2\x76\x02\x5d\xf0\x34\x91\xdf\x0a\x9d\xa7\xaa\x9f\x60\x1b\x9c\x95\x7b\x73\xe4\xe6\x14\x4f\x25\x38\x13\xb9\xbb\x84\x7e\xec\xb6\x34\xfb\xac\xf4\x0e\xec\x18\xfd\xc7\xb2\xef\x33\xd5\x55\x85\x0d\xe6\xca\x7f\x9b\xea\x77\x36\x51\x5a\x80\x83\x86\x18\x9d\xb3\x57\x28\xfe\x20\x7f\xd3\xe7\x44\x60\x2a\xf9\x4d\x62\xb5\x8d\xaa\x55\x78\x68\x2b\x04\xde\xcb\x7d\x3e\x56\xf9\x23\xcf\xba\xd6\x35\x7c\x24\x6d\x54\x27\xf8\x12\xf6\x00\x4d\xdc\x8d\x0c\x67\xb5\xd1\x23\xeb\xb3\x44\xfd\x10\x7d\x41\x3f\xf0\xe0\x47\xb6\xd0\x10\x64\xdf\xaa\xbf\xb4\x02\x57\xa4\x8a\x27\x2b\x55\x26\xb1\xc9\x0b\x3d\x40\x53\x2e\xfb\x49\xa2\xb2\x83\x2e\xe0\xb9\x23\x13\x7c\x93\x4a\xf1\x62\x77\xd8\x2a\x3e\x92\x10\x07\x62\xdd\x47\x8e\xae\x54\x9f\x82\xef\xbc\x56\xdf\x41\xe7\x93\x99\xda\x05\x3a\x2b\xd8\x73\xca\xef\xb4\x54\xfa\x1c\xf6\x28\x6b\xf9\x56\xf7\xa9\xe2\xc2\x66\x6b\xc1\x9f\x14\x2a\x73\xec\x93\xd8\x83\x3f\x3a\xec\x92\x58\xd1\xa8\x7f\x00\x83\x2c\xd0\x0f\x76\x91\x7b\xa5\x21\x6b\xd4\xce\x89\x11\x49\xae\xf4\x62\x97\x81\xff\x52\xef\x45\x06\xd8\x25\x7e\x43\xbc\xc1\x9e\x80\x0f\xf7\x4c\x55\x27\xd0\x12\xe2\xa0\xac\xf9\x5a\x6d\xa7\x88\x15\x3f\xf1\x0c\x9e\x9b\x46\x69\xe2\x1d\x99\x67\x85\xca\xcd\x73\xaf\xe0\x9d\xca\x5d\xad\xd3\x18\x94\x63\x6b\xc0\x25\x6a\x63\xe8\x0e\x9d\x83\x83\xb5\x04\xbc\xa5\xfa\x03\xf1\x10\x7d\xe3\xb7\x33\x8b\xa7\xe0\x47\x07\x0e\xb8\xa9\xf2\x5d\xd5\x2a\x07\x64\x8c\xbd\x72\x07\x3a\x24\x2e\xc3\x2f\x76\xd2\x22\xdf\x5a\xe3\x24\x31\xcc\xa7\x6a\xff\x05\x31\xab\x55\x9e\x72\xec\x1f\x5d\xc9\x7a\x35\x53\xfd\x12\x17\x42\x2e\x28\x34\x96\x57\x4e\x75\x8e\x5d\x61\x47\xdb\xdc\x40\xec\xe3\x71\x5e\xe3\x1c\x3e\x44\x2c\x27\x1e\xc5\xf9\x16\xee\x78\x5b\x25\x7e\x52\x42\xb2\xa2\x66\x5f\xb1\xb8\x2d\x7d\x76\x8a\x4d\xa9\x92\x3e\x2d\xcf\x9d\x08\xe4\xf1\xa7\xf6\x13\xc7\x02\x3d\xba\x2d\x5d\x3e\x09\x3f\x14\xff\x5f\xa8\xbd\x76\x29\x0e\xc5\xd7\x6d\x85\xfb\x39\xfc\x3f\x56\x58\xde\xd6\x83\xa1\xa2\x13\xe4\x1f\x95\x09\xef\x28\xa0\xce\xa2\xcf\x60\x39\xa2\x6e\x3a\x8b\x26\xe9\x6c\x76\x12\x51\x02\x9d\xed\x56\x48\xc3\x2c\x89\x47\x61\x9d\xc2\xe6\x4c\x0b\x9f\x7f\x2c\xbb\x9b\xe1\xe4\x24\x8a\x47\x52\xc1\x3a\xa8\xf8\x21\x88\xe0\x5d\xe0\xfb\x2c\x32\xf6\x21\xf1\x2c\x0a\x3f\xef\x6f\xb5\xe8\x4e\x1e\x2a\x56\x76\x9a\xb7\xa7\x16\x29\x24\xaa\x90\x1c\x72\x4d\x0c\xa1\x10\x68\xd4\xc0\x13\x4b\xa6\x49\xad\x01\x12\x18\xf0\xe1\x88\x04\xea\x02\x07\xca\x14\x2f\x0e\x19\x37\x1a\xb0\x80\xe1\xbb\xc8\x34\x49\x17\xe6\x78\xd9\xcc\xf0\x97\x8a\x9f\x7b\x92\x4a\x93\x0f\xce\xce\x1a\xc9\x93\xc0\x82\xa3\x13\x9c\x48\x50\x24\xe8\x99\x9c\x4b\xec\x09\x09\xdb\xab\xa3\x51\x5c\x84\xa2\xc8\x6b\x22\x8b\xcd\x09\x09\xc4\x04\x4c\x92\x0e\xc5\x08\x77\xb0\x86\x13\x83\x9b\x00\x96\x59\xf2\x87\xb7\xd6\x9e\xd4\xce\xcd\x0c\x86\xa0\x4f\xd0\x9c\xc5\x3b\x72\xdc\x71\x6a\x8a\x2c\x02\x24\xce\x1c\x02\x7f\xb5\x0b\x77\xc8\xa9\x3f\x54\xdc\x17\x3b\xf3\x87\xe8\xf6\x3b\xf1\x47\x8d\xfe\x83\xce\xfb\x21\xbe\x27\x38\xed\x5e\xfe\xbe\x9a\xb3\xde\x63\xcd\x9c\xb4\xc8\xbf\xbd\x8b\xde\x9b\x9d\xfc\x55\x1c\x15\x5c\x89\x55\xaf\x7c\x07\x07\x6a\x75\x8d\xce\x21\x31\x1c\x64\x47\xce\x87\xb3\x13\xfd\xa6\x6a\x27\xab\x72\x5f\x9b\xeb\x93\x5b\x05\x11\xe8\xf4\xe6\x7c\x74\x2c\x4e\xf1\x81\x9f\x6e\x80\x7b\xc1\x03\xee\x10\x30\x9c\x05\x0b\xab\x08\x13\xcb\xe4\x64\xfa\x18\x1e\xb2\x3d\x4e\x99\x69\x50\x20\xbb\x13\x40\xa8\xe6\x1e\x77\xca\x7d\xaa\xfa\x62\xd7\xdc\x87\x74\xbf\x83\xee\x9d\xb2\x3d\xe8\xa6\xfb\x70\x3f\xc1\x59\x1f\xe0\xfb\xab\xb9\xec\x01\x66\xb7\x8e\x1b\x7f\x7b\xc7\xfd\x68\x94\xf9\x57\x70\x5b\x1a\xec\xad\x6b\xe2\x62\xe1\x2e\x73\x1d\xdc\xef\x73\x5d\x15\xd7\xab\x2b\xcb\xcd\x95\xe2\xe6\x1e\x68\x08\x77\x95\x5a\x6c\xf3\xfe\x98\x4b\xd2\x4c\xd1\x90\xd3\x78\x20\x37\x1a\x8b\xc7\x5d\xf2\xbe\x12\xbe\xd8\x21\xef\xa3\xdc\xef\x8e\x7b\x46\xd9\x0f\x3a\xe3\x7d\xbc\x4f\x70\xc5\x83\xfc\x7e\x35\x47\xdc\xcb\xa6\xb9\xe1\xf4\x7f\xc0\x0d\xf7\xff\xa7\xe0\xa9\xde\x48\x5b\x59\xc6\x6a\xfd\x24\x1b\xc6\x07\xb7\x23\x39\xda\xc0\x56\xbd\x81\x4a\x91\x31\x1a\x1e\xc7\xf9\x69\xa2\xb0\x24\x1f\x2a\x4e\x92\x0a\x23\x9b\xd8\xc6\x0a\xb4\xb8\x8c\x63\x72\xab\x68\xf1\x4a\xaa\xc2\xdc\x46\x45\x8c\x40\x18\x85\xd0\x86\xd3\x7e\xe2\x35\x61\xd4\xe3\xb5\x8d\xa5\x25\xa4\xc5\x86\x7e\xc6\x03\xd3\x99\xd1\xe2\xb4\x75\x6e\x2b\xfd\x4e\xcc\x93\x68\x51\x69\x77\xa9\x4c\x2b\x6b\x8b\xc3\x38\xd0\x46\x12\xb4\xbe\x8c\x16\xf0\xc4\xc4\xda\x6e\xc6\x18\xf0\xc9\x1a\xf0\xf9\xe4\x6e\x94\xc5\x28\xa6\x9a\xea\x38\x8c\xd6\xb9\xb2\x71\x10\xf2\x23\x62\x20\x07\xe8\x0f\x72\xa4\xd5\x4f\x35\x79\xd3\x5e\x97\x33\x6d\x85\x43\xb5\xdd\xe8\xf8\x2a\xb7\x08\x40\x9b\xcd\xe8\x88\xd1\x03\x74\x57\x96\xdc\xe1\x89\xd6\xdf\xd9\x88\x2b\xac\x67\x4a\x03\xf4\x21\x4b\x68\x0a\x95\x77\xab\x63\x3d\x57\x1b\x3d\xa9\x8e\x87\xa8\xd4\x4b\x8b\x7c\xc8\x0f\x3a\x83\x4e\xbc\x46\x54\x46\x2c\x8c\x0e\xc2\x78\xaa\xd0\xd1\x0a\xe3\x55\xf0\x4d\x12\xd5\x09\xed\x7c\x18\xdf\xd0\x69\x34\xc6\x77\xae\xed\x3c\xba\x0c\x63\xc4\x54\xe5\xc4\xd8\x2d\xdf\xea\x27\xd1\x7b\xe0\x8f\x5f\xd6\xc2\xf8\xa6\x50\x78\x46\x1b\x44\xc2\x30\xee\xa9\x6c\x54\x9a\xdd\x15\x35\x9c\x27\xf2\x66\xf0\x6a\x38\xfd\x96\xaf\x5a\x7f\xe9\x6e\xd0\x1d\x76\x1c\xc6\x81\x33\xc5\xcd\x98\x91\xce\x08\x79\x25\xdb\x2c\x53\x69\x27\xe3\x4b\x1b\x81\xd9\x98\x98\x7b\xe9\x8a\x72\x1b\xa3\x62\x33\x8c\x7a\xf8\x6d\x6c\xf4\x4a\x01\x86\xfc\x42\xd1\x64\x23\x30\xec\x8e\xec\x83\x6e\x73\xeb\xc6\x2a\x1b\x29\x63\x57\x8c\x63\x18\xc9\x62\x4f\xc8\x6f\x62\x23\x1f\x68\x62\xc4\x86\x1e\x18\x99\x41\x1b\x6b\x61\xc4\x17\x5b\x41\x56\xa9\xae\xf0\xbb\x20\x73\xc6\x49\x4e\xe9\x73\xce\x46\x8d\x36\xda\x62\x04\x93\xda\x08\x28\x64\xb6\xec\xce\x5e\x82\x5f\xe6\xca\x2f\x7a\x68\xcc\x67\x18\x21\x33\x6a\xc5\x87\x18\x85\x36\x13\x1b\x4d\xd9\x78\x91\xec\xc7\xf8\x99\x91\x1d\x76\x80\x9f\x17\x26\x67\xc6\xd8\x64\x3f\xf6\x82\x2d\xb4\xda\x91\xde\x2b\x30\x5b\x1b\x55\x35\x77\x23\xdc\x3b\xb8\x43\xd9\xec\x60\x2c\xfb\xe2\xa4\x76\x10\xf3\xfe\xdc\x76\xf8\xdf\xaf\x0f\xa6\xb8\x83\xb7\x3c\x21\xd3\x3d\x26\x8b\xaf\x96\xf0\x1e\xe2\xdd\xf2\x5e\x1e\x7f\xd3\xc6\xf1\x3f\x01\x00\x00\xff\xff\x49\xb9\xe8\x2d\x00\x20\x00\x00") + +func dbMigrationsAssetsGoBytes() ([]byte, error) { + return bindataRead( + _dbMigrationsAssetsGo, + "db/migrations/assets.go", + ) +} + +func dbMigrationsAssetsGo() (*asset, error) { + bytes, err := dbMigrationsAssetsGoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "db/migrations/assets.go", size: 16384, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "db/migrations/0001_initial_migration.sql": dbMigrations0001_initial_migrationSql, + "db/migrations/0002_dex_admin.sql": dbMigrations0002_dex_adminSql, + "db/migrations/0003_user_created_at.sql": dbMigrations0003_user_created_atSql, + "db/migrations/0004_session_nonce.sql": dbMigrations0004_session_nonceSql, + "db/migrations/0005_refresh_token_create.sql": dbMigrations0005_refresh_token_createSql, + "db/migrations/0006_user_email_unique.sql": dbMigrations0006_user_email_uniqueSql, + "db/migrations/assets.go": dbMigrationsAssetsGo, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "db": &bintree{nil, map[string]*bintree{ + "migrations": &bintree{nil, map[string]*bintree{ + "0001_initial_migration.sql": &bintree{dbMigrations0001_initial_migrationSql, map[string]*bintree{}}, + "0002_dex_admin.sql": &bintree{dbMigrations0002_dex_adminSql, map[string]*bintree{}}, + "0003_user_created_at.sql": &bintree{dbMigrations0003_user_created_atSql, map[string]*bintree{}}, + "0004_session_nonce.sql": &bintree{dbMigrations0004_session_nonceSql, map[string]*bintree{}}, + "0005_refresh_token_create.sql": &bintree{dbMigrations0005_refresh_token_createSql, map[string]*bintree{}}, + "0006_user_email_unique.sql": &bintree{dbMigrations0006_user_email_uniqueSql, map[string]*bintree{}}, + "assets.go": &bintree{dbMigrationsAssetsGo, map[string]*bintree{}}, + }}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/db/user.go b/db/user.go index cff1d3e9..50ee8593 100644 --- a/db/user.go +++ b/db/user.go @@ -14,7 +14,10 @@ import ( ) const ( - userTableName = "dex_user" + // This table is named authd_user for historical reasons; namely, that the + // original name of the project was authd, and there are existing tables out + // there that we don't want to have to rename in production. + userTableName = "authd_user" remoteIdentityMappingTableName = "remote_identity_mapping" )