This repository has been archived on 2022-08-17. You can view files and clone it, but cannot push or open issues or pull requests.
dex/storage/sql/migrate.go
Pavel Borzenkov e53bdfabb9 storage/sql: initial MySQL storage implementation
It will be shared by both Postgres and MySQL configs.

Signed-off-by: Pavel Borzenkov <pavel.borzenkov@gmail.com>
2019-07-23 14:26:21 +02:00

193 lines
4.6 KiB
Go

package sql
import (
"database/sql"
"fmt"
)
func (c *conn) migrate() (int, error) {
_, err := c.Exec(`
create table if not exists migrations (
num integer not null,
at timestamptz not null
);
`)
if err != nil {
return 0, fmt.Errorf("creating migration table: %v", err)
}
i := 0
done := false
for {
err := c.ExecTx(func(tx *trans) error {
// Within a transaction, perform a single migration.
var (
num sql.NullInt64
n int
)
if err := tx.QueryRow(`select max(num) from migrations;`).Scan(&num); err != nil {
return fmt.Errorf("select max migration: %v", err)
}
if num.Valid {
n = int(num.Int64)
}
if n >= len(migrations) {
done = true
return nil
}
migrationNum := n + 1
m := migrations[n]
for i := range m.stmts {
if _, err := tx.Exec(m.stmts[i]); err != nil {
return fmt.Errorf("migration %d statement %d failed: %v", migrationNum, i+1, err)
}
}
q := `insert into migrations (num, at) values ($1, now());`
if _, err := tx.Exec(q, migrationNum); err != nil {
return fmt.Errorf("update migration table: %v", err)
}
return nil
})
if err != nil {
return i, err
}
if done {
break
}
i++
}
return i, nil
}
type migration struct {
stmts []string
// TODO(ericchiang): consider adding additional fields like "forDrivers"
}
// All SQL flavors share migration strategies.
var migrations = []migration{
{
stmts: []string{`
create table client (
id text not null primary key,
secret text not null,
redirect_uris bytea not null, -- JSON array of strings
trusted_peers bytea not null, -- JSON array of strings
public boolean not null,
name text not null,
logo_url text not null
);`,
`
create table auth_request (
id text not null primary key,
client_id text not null,
response_types bytea not null, -- JSON array of strings
scopes bytea not null, -- JSON array of strings
redirect_uri text not null,
nonce text not null,
state text not null,
force_approval_prompt boolean not null,
logged_in boolean not null,
claims_user_id text not null,
claims_username text not null,
claims_email text not null,
claims_email_verified boolean not null,
claims_groups bytea not null, -- JSON array of strings
connector_id text not null,
connector_data bytea,
expiry timestamptz not null
);`,
`
create table auth_code (
id text not null primary key,
client_id text not null,
scopes bytea not null, -- JSON array of strings
nonce text not null,
redirect_uri text not null,
claims_user_id text not null,
claims_username text not null,
claims_email text not null,
claims_email_verified boolean not null,
claims_groups bytea not null, -- JSON array of strings
connector_id text not null,
connector_data bytea,
expiry timestamptz not null
);`,
`
create table refresh_token (
id text not null primary key,
client_id text not null,
scopes bytea not null, -- JSON array of strings
nonce text not null,
claims_user_id text not null,
claims_username text not null,
claims_email text not null,
claims_email_verified boolean not null,
claims_groups bytea not null, -- JSON array of strings
connector_id text not null,
connector_data bytea
);`,
`
create table password (
email text not null primary key,
hash bytea not null,
username text not null,
user_id text not null
);`,
`
-- keys is a weird table because we only ever expect there to be a single row
create table keys (
id text not null primary key,
verification_keys bytea not null, -- JSON array
signing_key bytea not null, -- JSON object
signing_key_pub bytea not null, -- JSON object
next_rotation timestamptz not null
);`,
},
},
{
stmts: []string{`
alter table refresh_token
add column token text not null default '';`,
`
alter table refresh_token
add column created_at timestamptz not null default '0001-01-01 00:00:00 UTC';`,
`
alter table refresh_token
add column last_used timestamptz not null default '0001-01-01 00:00:00 UTC';`,
},
},
{
stmts: []string{`
create table offline_session (
user_id text not null,
conn_id text not null,
refresh bytea not null,
PRIMARY KEY (user_id, conn_id)
);`,
},
},
{
stmts: []string{`
create table connector (
id text not null primary key,
type text not null,
name text not null,
resource_version text not null,
config bytea
);`,
},
},
}