db: add DB migration code and scripts.
This commit is contained in:
parent
abaf76a047
commit
c16e3b5a10
15
build
15
build
|
@ -3,6 +3,21 @@
|
||||||
export GOPATH=${PWD}/Godeps/_workspace
|
export GOPATH=${PWD}/Godeps/_workspace
|
||||||
export GOBIN=${PWD}/bin
|
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
|
rm -rf $GOPATH/src/github.com/coreos/dex
|
||||||
mkdir -p $GOPATH/src/github.com/coreos/
|
mkdir -p $GOPATH/src/github.com/coreos/
|
||||||
ln -s ${PWD} $GOPATH/src/github.com/coreos/dex
|
ln -s ${PWD} $GOPATH/src/github.com/coreos/dex
|
||||||
|
|
|
@ -66,7 +66,7 @@ type clientIdentityModel struct {
|
||||||
ID string `db:"id"`
|
ID string `db:"id"`
|
||||||
Secret []byte `db:"secret"`
|
Secret []byte `db:"secret"`
|
||||||
Metadata string `db:"metadata"`
|
Metadata string `db:"metadata"`
|
||||||
DexAdmin bool `db:"dexAdmin"`
|
DexAdmin bool `db:"dex_admin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClientMetadataJSON(cm *oidc.ClientMetadata) *clientMetadataJSON {
|
func newClientMetadataJSON(cm *oidc.ClientMetadata) *clientMetadataJSON {
|
||||||
|
|
52
db/migrate.go
Normal file
52
db/migrate.go
Normal file
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
42
db/migrate_test.go
Normal file
42
db/migrate_test.go
Normal file
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
47
db/migrations/0001_initial_migration.sql
Normal file
47
db/migrations/0001_initial_migration.sql
Normal file
|
@ -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")) ;
|
2
db/migrations/0002_dex_admin.sql
Normal file
2
db/migrations/0002_dex_admin.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
-- +migrate Up
|
||||||
|
ALTER TABLE client_identity ADD COLUMN "dex_admin" boolean;
|
2
db/migrations/0003_user_created_at.sql
Normal file
2
db/migrations/0003_user_created_at.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
-- +migrate Up
|
||||||
|
ALTER TABLE authd_user ADD COLUMN "created_at" bigint;
|
2
db/migrations/0004_session_nonce.sql
Normal file
2
db/migrations/0004_session_nonce.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
-- +migrate Up
|
||||||
|
ALTER TABLE session ADD COLUMN "nonce" text;
|
21
db/migrations/0005_refresh_token_create.sql
Normal file
21
db/migrations/0005_refresh_token_create.sql
Normal file
|
@ -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);
|
3
db/migrations/0006_user_email_unique.sql
Normal file
3
db/migrations/0006_user_email_unique.sql
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
-- +migrate Up
|
||||||
|
ALTER TABLE ONLY authd_user
|
||||||
|
ADD CONSTRAINT authd_user_email_key UNIQUE (email);
|
377
db/migrations/assets.go
Normal file
377
db/migrations/assets.go
Normal file
File diff suppressed because one or more lines are too long
|
@ -14,7 +14,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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"
|
remoteIdentityMappingTableName = "remote_identity_mapping"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Reference in a new issue