Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
e077803e
Commit
e077803e
authored
Sep 02, 2015
by
Yifan Gu
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #105 from yifan-gu/tests
refresh: bcrypt raw bytes rather than base64 encoded string.
parents
ff71593c
44c6cb44
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
149 additions
and
65 deletions
+149
-65
0005_refresh_token_create.sql
db/migrations/0005_refresh_token_create.sql
+1
-1
assets.go
db/migrations/assets.go
+3
-3
refresh.go
db/refresh.go
+17
-11
db_test.go
functional/db_test.go
+77
-2
repo.go
refresh/refreshtest/repo.go
+2
-2
repo.go
refresh/repo.go
+16
-15
server_test.go
server/server_test.go
+33
-31
No files found.
db/migrations/0005_refresh_token_create.sql
View file @
e077803e
-- +migrate Up
CREATE
TABLE
refresh_token
(
id
bigint
NOT
NULL
,
payload_hash
text
,
payload_hash
bytea
,
user_id
text
,
client_id
text
);
...
...
db/migrations/assets.go
View file @
e077803e
...
...
@@ -155,7 +155,7 @@ func dbMigrations0004_session_nonceSql() (*asset, error) {
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\x
54\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
"
)
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\x
14\x56\xa1\x61\x8e\xb9\x56\xe3\xbe\xbd\x65\x13\x0c\xc4\x68\xdf\xfa\xbb\xfb\xdf\x2f\x77\xe3\x31\x5c\xbd\x9a\x4d\xa3\x9c\x06\x59\x07\x21\x47\x22\x10\x04\x99\x51\x84\x46\xbf\x34\xda\x6e\x73\xb7\xdf\xe9\x0a\x86\x01\xf8\x67\x0a\x58\x99\x8d\xa9\x1c\xb0\x54\x00\x93\x94\x5e\x77\xbc\x56\x6d\xb9\x57\x45\xbe\x55\x76\x0b\xab\xd6\x69\xd5\xf3\x77\xab\x9b\xdc\x87\x9c\xfe\x74\x3d\x59\x97\x46\x57\xee\xc8\x82\xd1\x6d\x70\xb4\x66\xf8\x28\x91\x85\x17\x62\xdf\x99\x5b\xfd\xd6\x65\x33\x41\xb8\x80\x45\x2c\xe6\x30\xe9\x40\xcc\x7c\x36\x41\x26\x60\xb6\xfc\x46\x2c\x85\x24\x66\x4f\x84\x4a\x3c\xfd\xc9\xf3\xcf\x3f\x24\xe1\x1c\x61\xe2\xb5\x84\x0a\xe4\x7f\x5b\x21\x5d\x30\x8c\x0e\xc3\xcf\xaa\x37\xa6\x38\xe5\xfb\x5b\xa5\x8c\x5e\xf4\x40\x5f\x0e\x53\x2a\x13\x76\xb8\x5b\x86\x02\x22\xbc\x23\x92\x0a\xa8\xfc\xea\x1f\xaa\x1c\x0e\x7e\x93\x0e\xa6\xd3\x46\x6f\xd6\xa5\xb2\x76\xf4\xaf\xa6\xdb\x89\x44\x91\x17\xb1\x4c\x70\x12\xfb\x5b\x9c\x0f\xad\x77\xba\x85\x07\x1e\x27\x84\x2f\xe1\x1e\x97\x30\x34\x85\x9f\xfb\x15\x00\x00\xff\xff\xc4\xcc\xa8\xfd\xfa
\x01\x00\x00
"
)
func
dbMigrations0005_refresh_token_createSqlBytes
()
([]
byte
,
error
)
{
return
bindataRead
(
...
...
@@ -170,7 +170,7 @@ func dbMigrations0005_refresh_token_createSql() (*asset, error) {
return
nil
,
err
}
info
:=
bindataFileInfo
{
name
:
"db/migrations/0005_refresh_token_create.sql"
,
size
:
50
5
,
mode
:
os
.
FileMode
(
436
),
modTime
:
time
.
Unix
(
1
,
0
)}
info
:=
bindataFileInfo
{
name
:
"db/migrations/0005_refresh_token_create.sql"
,
size
:
50
6
,
mode
:
os
.
FileMode
(
436
),
modTime
:
time
.
Unix
(
1
,
0
)}
a
:=
&
asset
{
bytes
:
bytes
,
info
:
info
}
return
a
,
nil
}
...
...
@@ -215,7 +215,7 @@ func dbMigrations0007_session_scopeSql() (*asset, error) {
return
a
,
nil
}
var
_dbMigrationsAssetsGo
=
[]
byte
(
"
\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd4\x99\xdf\x6f\xdb\x46\x12\xc7\x9f\xad\xbf\x82\x35\xd0\x42\x3
e\xf8\x64\xfe\x14\x45\x03\x7d\x69\x93\x03\xf2\xd0\x14\xb8\xe6\x9e\xce\x07\x61\x49\x2e\x5d\xa2\xb2\xe4\x88\x72\xcf\x49\x90\xff\xfd\xe6\xb3\x33\xb2\x9d\x58\xb2\x13\xe7\x82\xa0\x0f\x8c\xc5\xe5\xec\xec\xfc\x9e\xd9\x6f\x4e\x4e\xa2\x9f\x57\xad\x8f\xce\xfd\xd2\xaf\xdd\xc6\xb7\x51\xfd\x26\x3a\x5f\xfd\xbd\xee\x97\xad\xdb\xb8\xc9\x48\x08\x86\xd5\xd5\xba\xf1\xc3\x29\xbf\xdb\xfa\xe4\xa2\x3f\x17\xca\x7e\xb5\x1c\x4e\xe2\x38\x4e\xe6\xfd\xb2\xdf\xf4\x6e\x31\xbf\x59\x9f\x0c\xaf\x17\x3b\x69\xd3\x79\xeb\xaf\xe7\xae\xbd\xe8\xf7\xd3\x64\xf3\xab\xc1\xaf\xe7\xcd\xda\x23\xcd\xdc\x6d\xf6\x52\xe6\xf3\xc1\x0f\x83\xbc\xcd\x97\xab\x65\xe3\xf7\xd2\x15\xf3\xb5\xef\xd6\x7e\xf8\x7d\xbe\x59\xfd\xe1\x97\xc6\x7a\x2f\xf9\x54\x05\xf0\x17\xae\x5f\xcc\xaf\x96\xfd\xeb\xab\xfd\xb4\xe5\x8d\x08\x43\xb3\xba\xdc\x43\xe7\x86\xc1\x6f\x86\xc9\xf9\x8a\x4f\xcf\x7e\x8d\x5e\xfe\xfa\x2a\x7a\xfe\xec\xc5\xab\xef\x46\xa3\x4b\xd7\xfc\xe1\xce\x7d\x74\x4b\x3d\x1a\xf5\x17\x97\xab\xf5\x26\x1a\x8f\x0e\x0e\xeb\x37\x1b\x3f\x1c\xca\x8f\x66\x75\x71\x29\x1a\x0c\x27\xe7\x6f\xfb\x4b\x16\xba\x8b\x0d\x7f\xfa\x15\xff\x0e\x9b\x75\xbf\x3c\x0f\x84\xab\xf0\xef\xa6\xbf\xf0\xfa\xf9\xa4\x5f\x5d\x6d\xfa\x05\x2f\x97\x6e\xf3\xfb\x49\xd7\x2f\x3c\x3f\x0e\x47\x47\xa3\x51\x77\xb5\x6c\x22\x73\xf4\x3f\xbd\x6b\xc7\xfc\x88\xfe\xfd\x1f\x8e\x3d\x8e\x96\xee\xc2\x47\xca\xfa\x28\x1a\x6f\x57\xfd\x7a\xbd\x5a\x1f\x45\xef\x46\x07\xe7\x6f\xc3\x5b\x74\xfa\x63\x84\x54\x93\x97\xfe\xbf\x30\xf1\xeb\x71\x10\x9b\xf7\x9f\xae\xba\x4e\xde\x61\x7b\x74\x34\x3a\xe8\xbb\xb0\xe1\xbb\x1f\xa3\x65\xbf\x80\xc5\xc1\xda\x6f\xae\xd6\x4b\x5e\x8f\x23\x51\x69\xf2\x1c\xee\xdd\xf8\x10\x46\xd1\xf7\xaf\x4f\xa3\xef\xff\x3c\x54\x49\xc2\x59\xc2\xe3\xfd\x68\x74\xf0\xa7\x5b\x47\xf5\x55\x17\xe9\x39\x7a\xc8\xe8\x60\xae\xe2\xfc\x18\xf5\xab\xc9\xcf\xab\xcb\x37\xe3\x1f\x84\xe6\x58\x64\x93\x5d\xcd\xe2\xf9\x56\xd2\xc9\xcf\x8b\xd5\xe0\xc7\xa2\xfe\xff\x49\x1e\xd8\x28\xff\x3d\x8c\x84\x50\xe5\xb6\x45\x11\x6b\xf2\x13\xa2\x8f\x8f\x8e\xa1\x18\xc9\xb7\xcd\x9b\x4b\x1f\x85\x40\xc1\xe4\x57\xcd\x06\x2e\x41\x3f\xf3\x87\x1c\xb3\xec\x56\x51\xb4\x1a\x26\xff\x10\x1f\xbe\x90\x97\x9b\x7d\xe6\xc2\xed\xfa\x1d\x0e\x77\x7c\x38\x3a\x18\xfa\xb7\x3e\xea\x97\x9b\x69\x3e\x3a\xb8\x20\xe7\x8d\xd7\x2f\xf2\x3b\xac\xbc\x92\xb0\x89\x88\x9d\x09\xbf\x60\x1f\x22\x64\xdc\xf5\x1f\x1f\x71\x14\xbd\x14\xce\xe3\x23\xe3\xcd\x51\xa6\x5c\xd7\x4f\x38\x54\x36\xef\xdf\xfb\x9b\x08\x22\x7b\x83\x28\x1f\x6e\x45\xc4\x07\xb7\x22\xab\x6c\xbd\x23\xf9\x87\x0c\xd0\xeb\x31\x06\x28\x27\x3c\x6e\x14\xbd\xc7\xc1\xb4\xdf\xcf\xe4\xc5\xf0\xac\x5f\x0b\x8b\x7a\xb5\x5a\xdc\xdd\xed\x16\xc3\x23\x9a\xbf\x19\x54\x71\xbf\xee\x5c\xe3\xdf\xbd\xbf\xb3\xdb\x22\x81\xe0\x9e\xb7\xf5\x2f\x37\x15\x61\x77\x8d\xfd\xed\xf5\x42\x42\x5d\x63\x63\x7c\x78\x76\x9d\x74\x67\xd7\xb3\xfa\xec\x3a\x9e\xc9\x13\xdb\x53\x9d\x5d\x4f\xbd\xac\xdb\x5a\x27\x34\x55\x23\x4f\x76\x76\xdd\x40\xef\xce\xae\x5b\xd9\x93\xc9\xb7\x44\x9e\x66\x7a\x76\xed\x65\xbd\x94\x7d\xb1\x7c\xab\x12\xf9\x2e\xb4\x33\x59\x9f\xca\x53\xc9\x37\x27\x74\xae\x94\xf7\x56\xe8\xe4\xfb\x54\x1e\x27\x4f\x9d\x0b\xad\x7c\x2b\x0b\x7d\xcf\x84\x26\x63\x5d\xde\x53\xf8\x8a\x1c\x05\x32\xc8\xbe\x5c\x78\x26\xc2\x7f\x2a\xfc\xda\x52\xff\x16\xfc\x96\x73\x73\xa1\x4b\x84\x57\x23\xeb\x8d\x57\x99\xd8\x3f\x13\x5e\x33\x59\x2f\x44\x97\x56\xde\x3b\xd1\xc3\x23\x53\xad\xfb\x91\x2f\xf1\x6a\x87\x46\xce\x8c\x4b\x3d\x07\x79\xd0\x3d\x67\x8f\xe9\x03\x7d\xe6\xd5\x1e\xa9\xf0\xab\x38\x47\xe4\xc9\x53\xf9\x2d\x67\xe4\x9d\xea\x5a\xc3\x0f\xd9\x65\xbd\xab\xd4\xbe\x9d\xd0\x77\xb2\x56\xb7\x26\x27\xfa\x0a\xad\x97\xf3\x2a\x79\x3a\xa1\xcd\x65\x6d\xda\xa8\x1d\x3c\xb6\x90\xef\xb9\xf0\xcf\x90\x51\xde\x1b\x91\xa1\x90\xdf\x59\xa3\x74\x8d\xf0\xe9\x62\xd5\xbf\x92\xfd\xad\x53\xfb\xa3\x3b\x76\x44\x06\x74\x76\x85\xca\xee\x32\xb5\x2b\x7b\xb0\x4b\xdc\x98\x6d\xcc\x2e\xc8\x54\x6e\xfd\xd5\xa9\x1c\x31\xba\xa7\x7a\x76\x23\xb2\x37\x95\xae\x97\x46\x9f\xc7\x6a\xb3\x26\x35\x79\xe4\xbb\x6f\x35\x5e\xb0\x5d\x1d\xab\x8e\x71\xad\x71\xe3\x52\xf5\x1d\x3e\x47\x37\xd6\xe3\xa9\xc6\x46\x93\x68\x9c\x20\x17\x3a\x25\xf2\xb7\xc6\xe7\x99\xfa\x27\xc4\x06\x7b\xe5\xdc\x02\xbb\x39\xe5\x53\x0b\xcf\x54\xce\xae\x90\x9f\xb8\xad\x2c\x3e\x6b\x3d\x83\x38\xc6\xff\xb1\x7c\xf7\xb9\xfa\xaa\x26\x06\x0b\xd5\xbf\xcb\xf4\x3d\x4f\x54\x16\xe8\x90\x21\xc6\xe7\x7c\x2b\x95\x7f\xb0\xbf\xf9\x33\x11\x9a\x5a\xfe\xa6\xb1\xc6\x46\xdd\x29\x3d\xb2\x95\x42\xef\xe5\x3c\x1f\xab\xfd\xb1\x67\xd3\xe8\x1a\x39\x92\xb5\xea\x13\x72\x89\x78\x40\x26\xce\xc6\x86\xb3\xc6\xe4\x91\xf5\x59\xaa\x79\x88\xbf\x90\x1f\x7a\xf8\x63\x5b\x64\x08\xb6\xef\x34\x5f\x3a\xa1\x2b\x33\xe5\x93\x57\x6a\x93\xd8\xec\x85\x1f\x90\xa9\x90\xef\x69\xaa\xb6\x43\x2e\xe8\x39\x23\x17\x7e\x49\xad\x7c\x89\x3b\x62\x95\x1c\x49\xa9\x03\xb1\x7e\xc7\x8e\xae\xd2\x9c\x42\xef\xa2\xd1\xdc\xc1\xe7\xc9\x4c\xe3\x02\x9f\x95\x7c\x73\xaa\xef\xb4\x52\xf9\x1c\xf1\x28\x6b\xc5\xd6\xf7\x99\xf2\x22\x66\x1b\xe1\x9f\x96\x6a\x73\xe2\x93\xda\x43\x3e\x3a\xe2\x92\x5a\xd1\x6a\x7e\x40\x83\x2d\xf0\x0f\x71\x51\x78\x95\x21\x6f\x35\xce\xa9\x11\x69\xa1\xf2\x12\x97\x41\xff\x4a\xcf\xc5\x06\xc4\x25\x79\x43\xbd\x21\x9e\xa0\x0f\xe7\x4c\xd5\x27\xc8\x12\xea\xa0\xac\xf9\x46\x63\xa7\x8c\x95\x3f\xf5\x0c\x9d\xdb\x56\x65\xe2\x37\x36\xcf\x4b\xb5\x9b\xe7\x5c\xe1\x3b\x95\xb3\x3a\xa7\x35\xa8\x20\xd6\xa0\x4b\x35\xc6\xf0\x1d\x3e\x87\x07\x6b\x29\x7c\x2b\xcd\x07\xea\x21\xfe\x26\x6f\x67\x56\x4f\xe1\x8f\x0f\x1c\x74\x53\xd5\xbb\x6e\xd4\x0e\xd8\x98\x78\xe5\x0c\x7c\x48\x5d\x46\x5f\xe2\xa4\xc3\xbe\x8d\xd6\x49\x6a\x98\xcf\x34\xfe\x4b\x6a\x56\xa7\x3a\x15\xc4\x3f\xbe\x92\xf5\x7a\xa6\xfe\xa5\x2e\x84\x5e\x50\x6a\x2d\xaf\x9d\xfa\x9c\xb8\x22\x8e\xb6\xbd\x81\xda\xc7\xe3\xbc\xd6\x39\x72\x88\x5a\x4e\x3d\x8a\x8b\x2d\xdd\xe1\x76\x4a\xfc\xa4\x86\x64\x43\xcd\xae\x61\x71\x3b\xfa\xdc\x19\x36\x65\x4a\xfa\xb4\x3e\x77\x2c\x94\x87\x9f\x7a\xef\x38\x14\xea\xa3\x9b\xd1\xe5\x93\xf8\x23\xf1\xdf\xc2\xec\x75\x57\xe2\x30\x7c\xdd\x4c\xb8\x9f\xa3\xff\x63\x83\xe5\xcd\x3c\x18\x26\x3a\x61\xfe\xd1\x98\xf0\x8e\x01\xea\x34\xfa\x0c\x95\x23\xe6\xa6\xd3\x28\xc9\x66\xb3\xe3\x88\x11\xe8\xf4\xee\x84\x34\xce\xb3\xe9\x51\x58\x67\xb0\x39\xd5\xc1\xe7\x5f\xcb\xfe\x7a\x9c\x1c\x47\xf1\x91\x4c\xb0\x0e\x29\x7e\x08\x26\x78\x17\xf4\x3e\x8d\x4c\x7d\x44\x3c\x8d\xc2\x9f\xf7\x37\x5e\x74\xc7\x0f\x0d\x2b\x77\x2e\x79\x4f\x1d\x52\x68\x54\xa1\x39\x14\xda\x18\xc2\x20\xd0\x6a\x80\xa7\xd6\x4c\xd3\x46\x0b\x24\x34\xf0\x23\x11\x29\xd4\x25\x09\x94\x2b\x5f\x12\x32\x6e\xb5\x60\x41\xc3\x7b\x99\x6b\x93\x2e\x2d\xf1\xf2\x99\xf1\xaf\x94\x3f\xe7\xa4\xb5\x36\x1f\x92\x9d\x35\x9a\x27\x85\x85\x44\xa7\x38\xd1\xa0\x68\xd0\x33\xd9\x97\xda\x13\x1a\xb6\xd7\x44\x63\xb8\x08\x43\x91\xd7\x46\x16\x5b\x12\x52\x88\x29\x98\x34\x1d\x86\x11\xce\x60\x8d\x24\x86\x37\x05\x2c\xb7\xe6\x8f\x6e\x9d\x3d\x99\xed\x9b\x19\x0d\x45\x9f\xa2\x59\x34\xb7\xcd\x1d\x19\x82\x3c\x89\x26\xf5\xf6\xcc\xe9\x4c\x8b\x08\x32\x33\xb0\xd0\x28\x0a\x1b\xc2\x28\x9e\x61\x70\xc3\x7e\x4e\x8b\x35\xfa\x51\xb0\xa0\xa5\x99\xd3\x04\x28\x4e\x9c\x11\xa7\xf7\x0b\x08\x32\xd5\xd6\x78\x43\xa1\xf7\x77\x7c\xbb\xb7\x80\x7c\x18\x24\x5f\x5c\x38\x3e\x64\xb7\xbb\x60\x7c\x04\x3e\x3c\x58\x28\x3e\xe4\xf7\x84\x02\xb1\x53\xbf\xaf\x56\x18\xee\xa9\xb6\x2d\x08\xe9\xf4\xdb\xd7\x83\x7b\x80\xce\x5f\xa5\x2a\xc0\x2b\xb5\x51\x99\xf7\x90\xad\x9d\xae\x71\x4d\x49\x8d\x07\xad\x98\xfd\x61\x6f\xa2\xef\x5c\x11\x68\xe1\x9c\xd7\x15\xfa\x14\x96\x71\x41\x4e\x6f\x99\x5e\x68\xe6\xe5\x36\xee\x72\xf5\xe0\x5c\xf8\xc0\x3b\x54\x27\x67\x95\xc9\xc6\xcf\xd4\xc6\x06\x6f\x57\x13\x32\x1d\x7d\x82\x1c\x76\x1d\x60\x7c\x6c\xe5\x49\x52\x1d\x83\xa8\x00\x64\xbe\x73\x56\x3d\xa6\x3a\xa6\x33\xb6\x55\x36\xbe\x27\xf1\xfd\xec\x4e\xad\x3a\x7a\xbb\xca\x70\xfd\x78\x3c\xbb\x77\xb9\xfc\x8b\x73\x7c\x17\xd3\xdd\x99\xbe\x13\x42\x7c\x30\xdf\x77\xf1\x7e\x42\xd6\x3f\xa0\xf7\x57\xcb\xfd\x3d\xca\x6e\x2b\x40\x92\x7c\xfb\x0a\xf0\x11\x50\xfb\x57\xc8\x7f\xe2\x7e\x9b\xe3\xe4\x6a\x38\xcb\x72\x90\x3c\xfe\xdc\x9c\x27\x87\x9b\xda\x26\x8a\x5a\x79\x73\x0e\x32\x84\xb3\x2a\xbd\x22\xf0\x7b\x9b\xdb\xa1\xdb\xe6\xf7\x73\x92\x2b\x20\x30\x02\xd7\x25\xec\xc6\x75\xe8\xf1\x9c\xbc\xef\x84\x2f\xce\xc8\xfb\x2c\x77\xe7\xe3\x0e\xa0\xfe\xc1\x6c\xbc\xcf\xf7\x09\xb9\xb8\x57\xdf\xaf\x96\x89\x3b\xd5\xb4\x3c\x9c\xc6\xdf\x3e\x0d\x77\xff\x3f\xc8\x53\xb3\x91\xcb\x70\x15\x6b\xf4\xd3\xb5\x00\x3d\x6e\x80\x44\x2e\xaf\x9d\x66\x03\xf3\x2d\xe0\x1f\x19\xc7\xfe\x69\xaa\xb4\x74\x31\xe6\x64\xe6\x52\x80\xa6\xd8\xc0\x10\x66\xc8\x30\x77\xda\x1c\x4e\x56\x32\xa3\x16\x06\x70\x01\xdc\x00\xe0\x00\x1e\x30\x97\x92\x35\x01\xa0\xf2\x7a\xf9\xe6\x22\x0b\x30\x80\xfc\x80\x1a\xcc\xbf\x41\x16\xa7\x17\xfe\xae\xd6\xf7\xd4\x32\x89\x8b\x35\x97\x74\x66\xe9\xda\x2e\xf3\x01\xc4\x34\x20\x85\x0b\x3b\x80\x08\x99\x98\x1a\x58\x00\xf8\x12\xba\x65\xae\xf4\x45\x72\x0b\xc0\x01\x20\xd5\x53\x05\xf1\xb8\xf0\xd7\x06\x62\x61\x3f\x2a\x06\x76\x40\xfe\x60\x47\x00\x8a\x4c\xa7\x00\x40\x81\x6a\xa6\x17\xf8\x70\x47\x68\x15\x74\x2b\xac\x02\x00\x0e\x00\x78\x01\x98\x20\x77\x6d\x53\x02\x3a\x01\x58\x38\x03\xe6\xc2\x7a\xae\x32\xc4\x36\xc3\x23\x13\xfa\xcd\x3a\x05\x23\x5d\x63\xf2\x64\x0a\x6a\x71\xbf\xa8\xac\xf2\x61\x3f\xe4\x0c\x3e\xf1\x5a\x51\x01\x86\x00\x3c\x02\xa8\x56\x2a\x20\x04\x28\x0c\x3f\x26\x8c\xc2\x40\x88\x00\x3a\x71\x3f\x6a\x4d\xef\x42\x41\x08\x7c\x19\xc0\xcf\x4c\xed\xc4\xb4\x51\x6c\xfd\x93\xea\x39\xe8\xc7\x5f\xd6\x02\xe8\x54\x2a\x3d\x80\x0c\x95\x30\x80\x54\xb5\x01\xbc\xf9\xed\x74\xc4\x7e\x2a\x6f\x8e\xae\xc6\xd3\x6f\xf5\x6a\xf4\x6f\x67\xf7\x22\xe2\x38\x80\x98\x33\xe5\x0d\x38\xca\x7d\x07\x7b\xa5\xdb\x2e\x53\xeb\x44\xe5\x2b\x03\xee\x0c\xdc\xe6\x5c\xee\x36\x85\x81\xbf\xc4\x0c\x00\x15\x7f\x5b\x03\x8c\x99\xe4\xb0\x1f\x9d\xc6\x19\x70\x47\xdc\xd1\x7d\xf0\x6d\x61\x77\xc8\xda\x80\x70\xe2\x0a\x10\x89\xbb\x16\xf1\x84\xfd\x12\x03\xaa\x90\x09\x60\x10\x3f\x00\xf4\x21\x1b\x6b\x01\x98\x8c\x15\x24\x02\xfc\xc6\x57\xe4\x5d\xb0\x39\x20\x98\x53\xf9\x98\xf4\x02\x40\x6a\x80\x1c\xc0\x51\x66\xc0\x55\xe8\x6c\xf9\x6d\xbc\x84\xbc\x2c\x54\x5f\xfc\xd0\x5a\xce\x30\x5d\x02\x10\x93\x43\xdc\xf1\x98\x28\x03\xa0\x66\xa0\x28\xdd\x0f\xd0\x1c\xa0\x31\x4c\x9a\xde\xba\x6b\x65\xf7\xcb\x4c\xbf\x85\x58\xe8\xec\x0e\xf9\x51\x37\xe3\x09\x00\x5b\x7b\x0b\x3c\xdf\xd2\xed\xeb\x66\x7b\x6b\xd9\x17\x37\xb5\xbd\x9c\x77\xf7\xb6\xfd\xff\xb9\xfc\x60\x8b\xdb\x7b\xca\x13\x3a\xdd\x63\xb6\x78\xb0\xe1\xfd\x2f\x00\x00\xff\xff\xfb\x08\x01\x0a
\x00\x20\x00\x00
"
)
var
_dbMigrationsAssetsGo
=
[]
byte
(
"
\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd4\x99\xdf\x6f\xdb\x46\x12\xc7\x9f\xad\xbf\x82\x35\xd0\x42\x3
a\xf8\x64\x92\xe2\x2f\x19\xe8\x4b\xdb\x1c\x90\x87\xa6\xc0\x35\xf7\x74\x3e\x08\x4b\x72\xe9\x12\x95\x25\x47\x94\x7b\x4e\x82\xfc\xef\x37\x9f\x9d\x91\xeb\xc4\x92\x9d\x38\x17\x04\x7d\x60\x2c\x2e\x67\x67\xe7\xf7\xcc\x7e\x73\x7a\x1a\xfd\xb8\x6e\x7d\x74\xe1\x57\x7e\xe3\xb6\xbe\x8d\xea\xd7\xd1\xc5\xfa\xef\x75\xbf\x6a\xdd\xd6\x4d\x47\x42\x30\xac\xaf\x37\x8d\x1f\xce\xf8\xdd\xd6\xa7\x97\xfd\x85\x50\xf6\xeb\xd5\x70\x1a\xc7\x71\xb2\xe8\x57\xfd\xb6\x77\xcb\xc5\xed\xfa\x74\x78\xb5\xdc\x4b\x9b\x2e\x5a\x7f\xb3\x70\xed\x65\x7f\x98\x66\xb6\xb8\x1e\xfc\x66\xd1\x6c\x3c\xd2\x2c\xdc\xf6\x20\x65\xb6\x18\xfc\x30\xc8\xdb\x62\xb5\x5e\x35\xfe\x20\x5d\xbe\xd8\xf8\x6e\xe3\x87\xdf\x16\xdb\xf5\xef\x7e\x65\xac\x0f\x92\x17\x2a\x80\xbf\x74\xfd\x72\x71\xbd\xea\x5f\x5d\x1f\xa6\x2d\x6f\x45\x18\x9a\xf5\xd5\x01\x3a\x37\x0c\x7e\x3b\x4c\x2f\xd6\x7c\xfa\xe9\x97\xe8\xc5\x2f\x2f\xa3\x67\x3f\x3d\x7f\xf9\xcd\x68\x74\xe5\x9a\xdf\xdd\x85\x8f\xfe\xa4\x1e\x8d\xfa\xcb\xab\xf5\x66\x1b\x8d\x47\x47\xc7\xf5\xeb\xad\x1f\x8e\xe5\x47\xb3\xbe\xbc\x12\x0d\x86\xd3\x8b\x37\xfd\x15\x0b\xdd\xe5\x96\x3f\xfd\x9a\x7f\x87\xed\xa6\x5f\x5d\x04\xc2\x75\xf8\x77\xdb\x5f\x7a\xfd\x7c\xda\xaf\xaf\xb7\xfd\x92\x97\x2b\xb7\xfd\xed\xb4\xeb\x97\x9e\x1f\xc7\xa3\xc9\x68\xd4\x5d\xaf\x9a\xc8\x1c\xfd\x4f\xef\xda\x31\x3f\xa2\x7f\xff\x87\x63\x4f\xa2\x95\xbb\xf4\x91\xb2\x9e\x44\xe3\xdd\xaa\xdf\x6c\xd6\x9b\x49\xf4\x76\x74\x74\xf1\x26\xbc\x45\x67\xdf\x47\x48\x35\x7d\xe1\xff\x0b\x13\xbf\x19\x07\xb1\x79\xff\xe1\xba\xeb\xe4\x1d\xb6\x93\xc9\xe8\xa8\xef\xc2\x86\x6f\xbe\x8f\x56\xfd\x12\x16\x47\x1b\xbf\xbd\xde\xac\x78\x3d\x89\x44\xa5\xe9\x33\xb8\x77\xe3\x63\x18\x45\xdf\xbe\x3a\x8b\xbe\xfd\xe3\x58\x25\x09\x67\x09\x8f\x77\xa3\xd1\xd1\x1f\x6e\x13\xd5\xd7\x5d\xa4\xe7\xe8\x21\xa3\xa3\x85\x8a\xf3\x7d\xd4\xaf\xa7\x3f\xae\xaf\x5e\x8f\xbf\x13\x9a\x13\x91\x4d\x76\x35\xcb\x67\x3b\x49\xa7\x3f\x2e\xd7\x83\x1f\x8b\xfa\xff\x27\x79\x60\xa3\xfc\x0f\x30\x12\x42\x95\xdb\x16\x45\xac\xe9\x0f\x88\x3e\x9e\x9c\x40\x31\x92\x6f\xdb\xd7\x57\x3e\x0a\x81\x82\xc9\xaf\x9b\x2d\x5c\x82\x7e\xe6\x0f\x39\x66\xd5\xad\xa3\x68\x3d\x4c\xff\x21\x3e\x7c\x2e\x2f\xb7\xfb\xcc\x85\xbb\xf5\x3b\x1c\xee\xf8\x70\x74\x34\xf4\x6f\x7c\xd4\xaf\xb6\x45\x36\x3a\xba\x24\xe7\x8d\xd7\xcf\xf2\x3b\xac\xbc\x94\xb0\x89\x88\x9d\x29\xbf\x60\x1f\x22\x64\xdc\xf5\x1f\x1e\x31\x89\x5e\x08\xe7\xf1\xc4\x78\x73\x94\x29\xd7\xf5\x53\x0e\x95\xcd\x87\xf7\xfe\x2a\x82\xc8\xde\x20\xca\xfb\x5b\x11\xf1\xc1\xad\xc8\x2a\x5b\xef\x48\xfe\x3e\x03\xf4\x7a\x8c\x01\xca\x09\x8f\x5b\x45\xef\x71\x30\xed\x0f\x33\x79\x3e\xfc\xd4\x6f\x84\x45\xbd\x5e\x2f\xef\xee\x76\xcb\xe1\x11\xcd\x5f\x0f\xaa\xb8\xdf\x74\xae\xf1\x6f\xdf\xdd\xd9\x6d\x91\x40\x70\x2f\xda\xfa\xe7\xdb\x8a\xb0\xbf\xc6\xfe\xfa\x6a\x29\xa1\xae\xb1\x31\x3e\x3e\xbf\x49\xba\xf3\x9b\xaa\x3e\xbf\x89\x2b\x79\x62\x7b\xe6\xe7\x37\x85\x97\x75\x5b\xeb\x84\x66\xde\xc8\x33\x3b\xbf\x69\xa0\x77\xe7\x37\xad\xec\x99\xc9\xb7\x44\x9e\xa6\x38\xbf\xf1\xb2\x5e\xca\xbe\x58\xbe\xcd\x13\xf9\x2e\xb4\x95\xac\x17\xf2\xcc\xe5\x9b\x13\x3a\x57\xca\x7b\x2b\x74\xf2\xbd\x90\xc7\xc9\x53\x67\x42\x2b\xdf\xca\x5c\xdf\x67\x42\x33\x63\x5d\xde\x53\xf8\x8a\x1c\x39\x32\xc8\xbe\x4c\x78\x26\xc2\xbf\x10\x7e\x6d\xa9\x7f\x73\x7e\xcb\xb9\x99\xd0\x25\xc2\xab\x91\xf5\xc6\xab\x4c\xec\xaf\x84\x57\x25\xeb\xb9\xe8\xd2\xca\x7b\x27\x7a\x78\x64\xaa\x75\x3f\xf2\x25\x5e\xed\xd0\xc8\x99\x71\xa9\xe7\x20\x0f\xba\x67\xec\x31\x7d\xa0\x9f\x79\xb5\x47\x2a\xfc\xe6\x9c\x23\xf2\x64\xa9\xfc\x96\x33\xb2\x4e\x75\xad\xe1\x87\xec\xb2\xde\xcd\xd5\xbe\x9d\xd0\x77\xb2\x56\xb7\x26\x27\xfa\x0a\xad\x97\xf3\xe6\xf2\x74\x42\x9b\xc9\x5a\xd1\xa8\x1d\x3c\xb6\x90\xef\x99\xf0\x9f\x21\xa3\xbc\x37\x22\x43\x2e\xbf\x67\x8d\xd2\x35\xc2\xa7\x8b\x55\xff\xb9\xec\x6f\x9d\xda\x1f\xdd\xb1\x23\x32\xa0\xb3\xcb\x55\x76\x37\x53\xbb\xb2\x07\xbb\xc4\x8d\xd9\xc6\xec\x82\x4c\xe5\xce\x5f\x9d\xca\x11\xa3\x7b\xaa\x67\x37\x22\x7b\x33\xd7\xf5\xd2\xe8\xb3\x58\x6d\xd6\xa4\x26\x8f\x7c\xf7\xad\xc6\x0b\xb6\xab\x63\xd5\x31\xae\x35\x6e\x5c\xaa\xbe\xc3\xe7\xe8\xc6\x7a\x5c\x68\x6c\x34\x89\xc6\x09\x72\xa1\x53\x22\x7f\x6b\x7c\x3e\x53\xff\x84\xd8\x60\xaf\x9c\x9b\x63\x37\xa7\x7c\x6a\xe1\x99\xca\xd9\x73\xe4\x27\x6e\xe7\x16\x9f\xb5\x9e\x41\x1c\xe3\xff\x58\xbe\xfb\x4c\x7d\x55\x13\x83\xb9\xea\xdf\xcd\xf4\x3d\x4b\x54\x16\xe8\x90\x21\xc6\xe7\x7c\x2b\x95\x7f\xb0\xbf\xf9\x33\x11\x9a\x5a\xfe\xa6\xb1\xc6\x46\xdd\x29\x3d\xb2\x95\x42\xef\xe5\x3c\x1f\xab\xfd\xb1\x67\xd3\xe8\x1a\x39\x32\x6b\xd5\x27\xe4\x12\xf1\x80\x4c\x9c\x8d\x0d\xab\xc6\xe4\x91\xf5\x2a\xd5\x3c\xc4\x5f\xc8\x0f\x3d\xfc\xb1\x2d\x32\x04\xdb\x77\x9a\x2f\x9d\xd0\x95\x33\xe5\x93\xcd\xd5\x26\xb1\xd9\x0b\x3f\x20\x53\x2e\xdf\xd3\x54\x6d\x87\x5c\xd0\x73\x46\x26\xfc\x92\x5a\xf9\x12\x77\xc4\x2a\x39\x92\x52\x07\x62\xfd\x8e\x1d\xdd\x5c\x73\x0a\xbd\xf3\x46\x73\x07\x9f\x27\x95\xc6\x05\x3e\x2b\xf9\xe6\x54\xdf\x62\xae\xf2\x39\xe2\x51\xd6\xf2\x9d\xef\x67\xca\x8b\x98\x6d\x84\x7f\x5a\xaa\xcd\x89\x4f\x6a\x0f\xf9\xe8\x88\x4b\x6a\x45\xab\xf9\x01\x0d\xb6\xc0\x3f\xc4\x45\xee\x55\x86\xac\xd5\x38\xa7\x46\xa4\xb9\xca\x4b\x5c\x06\xfd\xe7\x7a\x2e\x36\x20\x2e\xc9\x1b\xea\x0d\xf1\x04\x7d\x38\xa7\x50\x9f\x20\x4b\xa8\x83\xb2\xe6\x1b\x8d\x9d\x32\x56\xfe\xd4\x33\x74\x6e\x5b\x95\x89\xdf\xd8\x3c\x2b\xd5\x6e\x9e\x73\x85\x6f\x21\x67\x75\x4e\x6b\x50\x4e\xac\x41\x97\x6a\x8c\xe1\x3b\x7c\x0e\x0f\xd6\x52\xf8\xce\x35\x1f\xa8\x87\xf8\x9b\xbc\xad\xac\x9e\xc2\x1f\x1f\x38\xe8\x0a\xd5\xbb\x6e\xd4\x0e\xd8\x98\x78\xe5\x0c\x7c\x48\x5d\x46\x5f\xe2\xa4\xc3\xbe\x8d\xd6\x49\x6a\x98\x9f\x69\xfc\x97\xd4\xac\x4e\x75\xca\x89\x7f\x7c\x25\xeb\x75\xa5\xfe\xa5\x2e\x84\x5e\x50\x6a\x2d\xaf\x9d\xfa\x9c\xb8\x22\x8e\x76\xbd\x81\xda\xc7\xe3\xbc\xd6\x39\x72\x88\x5a\x4e\x3d\x8a\xf3\x1d\xdd\xf1\x6e\x4a\xfc\xa8\x86\x64\x43\xcd\xbe\x61\x71\x37\xfa\xdc\x19\x36\x65\x4a\xfa\xb8\x3e\x77\x22\x94\xc7\x1f\x7b\xef\x38\x16\xea\xc9\xed\xe8\xf2\x51\xfc\x91\xf8\x6f\x61\xf6\xba\x2b\x71\x18\xbe\x6e\x27\xdc\x4f\xd1\xff\xb1\xc1\xf2\x76\x1e\x0c\x13\x9d\x30\xff\x60\x4c\x78\xcb\x00\x75\x16\x7d\x82\xca\x11\x73\xd3\x59\x94\xcc\xaa\xea\x24\x62\x04\x3a\xbb\x3b\x21\x8d\xb3\x59\x31\x09\xeb\x0c\x36\x67\x3a\xf8\xfc\x6b\xd5\xdf\x8c\x93\x93\x28\x9e\xc8\x04\xeb\x90\xe2\xbb\x60\x82\xb7\x41\xef\xb3\xc8\xd4\x47\xc4\xb3\x28\xfc\x79\x77\xeb\x45\x77\xf2\xd0\xb0\x72\xe7\x92\xf7\xd4\x21\x85\x46\x15\x9a\x43\xae\x8d\x21\x0c\x02\xad\x06\x78\x6a\xcd\x34\x6d\xb4\x40\x42\x03\x3f\x12\x91\x42\x5d\x92\x40\x99\xf2\x25\x21\xe3\x56\x0b\x16\x34\xbc\x97\x99\x36\xe9\xd2\x12\x2f\xab\x8c\xff\x5c\xf9\x73\x4e\x5a\x6b\xf3\x21\xd9\x59\xa3\x79\x52\x58\x48\x74\x8a\x13\x0d\x8a\x06\x5d\xc9\xbe\xd4\x9e\xd0\xb0\xbd\x26\x1a\xc3\x45\x18\x8a\xbc\x36\xb2\xd8\x92\x90\x42\x4c\xc1\xa4\xe9\x30\x8c\x70\x06\x6b\x24\x31\xbc\x29\x60\x99\x35\x7f\x74\xeb\xec\x99\xd9\xbe\xca\x68\x28\xfa\x14\xcd\xbc\xf9\xb3\xb9\x23\x43\x90\x27\xd1\xa4\xde\x9d\x59\x54\x5a\x44\x90\x99\x81\x85\x46\x91\xdb\x10\x46\xf1\x0c\x83\x1b\xf6\x73\x5a\xac\xd1\x8f\x82\x05\x2d\xcd\x9c\x26\x40\x71\xe2\x8c\x38\xbd\x5f\x40\x90\xa9\xb6\xc6\x1b\x0a\xbd\xbf\xe3\xdb\x83\x05\xe4\xfd\x20\xf9\xec\xc2\xf1\x3e\xbb\xfd\x05\xe3\x03\xf0\xe1\xc1\x42\xf1\x3e\xbf\x27\x14\x88\xbd\xfa\x7d\xb1\xc2\x70\x4f\xb5\x5d\x41\x48\x8b\xaf\x5f\x0f\xee\x01\x3a\x7f\x95\xaa\x00\xaf\xd4\x46\x65\xde\x43\xb6\x76\xba\xc6\x35\x25\x35\x1e\xb4\x62\xf6\x87\xbd\x89\xbe\x73\x45\xa0\x85\x73\x5e\x97\xeb\x93\x5b\xc6\x05\x39\xbd\x65\x7a\xae\x99\x97\xd9\xb8\xcb\xd5\x83\x73\xe1\x03\xef\x50\x9d\x9c\x55\x26\x1b\x3f\x53\x1b\x1b\xbc\x5d\x4d\xc8\x74\xf4\x09\x72\xd8\x75\x80\xf1\xb1\x95\x27\x49\x75\x0c\xa2\x02\x90\xf9\xce\x59\xf5\x28\x74\x4c\x67\x6c\x9b\xdb\xf8\x9e\xc4\xf7\xb3\x3b\xb5\xea\xe8\xed\x2a\xc3\xf5\xe3\xf1\xec\xde\xe7\xf2\xcf\xce\xf1\x7d\x4c\xf7\x67\xfa\x5e\x08\xf1\xc1\x7c\xdf\xc7\xfb\x09\x59\xff\x80\xde\x5f\x2c\xf7\x0f\x28\xbb\xab\x00\x49\xf2\xf5\x2b\xc0\x07\x40\xed\x5f\x21\xff\x89\xfb\x5d\x8e\x93\xab\xe1\x2c\xcb\x41\xf2\xf8\x53\x73\x9e\x1c\x6e\x6a\x9b\x28\x6a\xe5\xcd\x39\xc8\x10\xce\x9a\xeb\x15\x81\xdf\xbb\xdc\x0e\xdd\x36\xbb\x9f\x93\x5c\x01\x81\x11\xb8\x2e\x61\x37\xae\x43\x8f\xe7\xe4\x7d\x27\x7c\x76\x46\xde\x67\xb9\x3f\x1f\xf7\x00\xf5\x0f\x66\xe3\x7d\xbe\x4f\xc8\xc5\x83\xfa\x7e\xb1\x4c\xdc\xab\xa6\xe5\x61\x11\x7f\xfd\x34\xdc\xff\xff\x20\x4f\xcd\x46\x2e\xc3\xf3\x58\xa3\x9f\xae\x05\xe8\x71\x0b\x24\x72\x79\xed\x34\x1b\x98\x6f\x01\xff\xc8\x38\xf6\x17\xa9\xd2\xd2\xc5\x98\x93\x99\x4b\x01\x9a\x62\x03\x43\x98\x21\xc3\xdc\x69\x73\x38\x59\x19\x2e\xfb\x06\x70\x39\x03\x1d\x99\x75\x99\x9b\x59\xe3\x72\xcc\xac\xcd\xe5\x9b\x8b\x2c\xc0\x40\x6c\xc0\x1a\xf3\x6f\x90\xc5\xe9\x85\xbf\xab\xf5\x3d\xb5\x4c\x62\x2f\x97\x74\x66\x69\xf6\xd3\x0d\x01\x0b\x00\x31\x00\x52\xb8\xb0\x03\x16\x71\x79\x4e\x0d\x2c\x00\x7c\x09\xdd\x32\xd3\xb9\x3d\x37\x70\x32\x00\x65\x00\x39\x99\x82\x78\x85\x81\x39\xb5\xd9\xc3\x1b\xb0\x0a\xa0\x1a\x1b\x40\x53\x94\xba\x06\x30\x04\xaf\xaa\xb5\x3b\x42\xa3\xa0\x5b\x6e\x15\x00\x70\x00\xc0\x0b\xc0\x04\xb9\x01\x11\xd0\x1d\x20\x36\xd8\xa1\x54\xe0\xb1\xb6\xca\x02\x00\x48\x57\x77\xb5\x76\x7c\x40\x1c\xaa\x27\xa0\x14\xfb\x59\x07\x3c\x05\x64\x00\x2c\x40\xd7\x00\x3e\x65\x0a\x6c\xa1\xf3\xdc\x40\x27\x78\xe3\xc3\xa6\xd2\x29\x82\xc9\xa2\xb0\x89\x03\xdf\x00\x20\xa1\x4b\x00\x53\xb1\x05\x3e\x28\xd5\xd7\xe8\x1d\x6c\x54\x2b\xf8\x1b\x64\x91\xef\x33\x03\xb9\x00\x2e\x00\x4b\x90\x3d\x35\x50\x97\x38\xc2\x56\x00\x63\x54\x5d\x40\x4a\xc0\x53\xe8\x01\xae\x00\x87\x6a\x03\x3b\x91\x8f\x7d\x9c\x99\x9a\x2c\x99\xc5\x67\x00\x5d\x1b\x3d\x97\x29\xae\x33\xe0\x1b\x40\x16\x5a\x26\x1a\xec\x4c\x3c\x31\x49\xd5\x06\x24\xe2\x0f\xc0\x3c\xc0\x16\xe4\x4e\xed\x6e\x83\x5c\x00\x7b\x80\x4b\x8d\xf1\x72\x06\x4c\x05\x70\xac\x52\x10\x89\x18\x63\x1f\x40\x51\x65\x20\x17\xdd\x07\x7d\x00\xba\xd9\x1f\x40\x3c\xa7\xb1\x8a\xaf\xb0\x03\x7b\x2a\xab\xfc\xc4\x58\x00\x8a\x66\x7a\xf7\x44\x26\x57\x19\xf0\xed\x34\x4f\x39\x3b\x31\x79\xb8\x77\x11\x23\xb1\x81\x61\x80\x73\xd8\x26\x80\xec\x06\x1e\x03\x2e\x71\x16\xb2\x38\x03\xf4\x5a\xbb\xeb\x66\x99\xfa\x0e\xbf\x05\x10\xb5\x51\xff\x32\x41\xee\xf4\x09\xf9\xd0\x69\xa7\x0a\x31\xe8\xd4\xee\xe4\x06\x20\x1c\xa0\x16\xf6\x23\xb7\x82\x6d\xbd\xc6\x10\x76\x23\x27\xa0\x05\x44\xed\x0c\x78\xfd\xb0\xb3\x91\xaf\xf8\x3b\xe8\xd9\x6a\xce\x86\x7b\xe7\x83\x9d\xed\x60\x5d\xfb\xec\x06\x77\x90\xf3\xfe\x3e\x77\xf8\x3f\x9a\x1f\x6c\x77\x07\x4f\x79\x42\xd7\x7b\xcc\x16\xf7\x9a\xdf\xff\x02\x00\x00\xff\xff\x3c\x2b\x49\x80
\x00\x20\x00\x00
"
)
func
dbMigrationsAssetsGoBytes
()
([]
byte
,
error
)
{
return
bindataRead
(
...
...
db/refresh.go
View file @
e077803e
package
db
import
(
"encoding/base64"
"errors"
"fmt"
"strconv"
...
...
@@ -31,7 +32,7 @@ type refreshTokenRepo struct {
type
refreshTokenModel
struct
{
ID
int64
`db:"id"`
PayloadHash
string
`db:"payload_hash"`
PayloadHash
[]
byte
`db:"payload_hash"`
// TODO(yifan): Use some sort of foreign key to manage database level
// data integrity.
UserID
string
`db:"user_id"`
...
...
@@ -39,25 +40,29 @@ type refreshTokenModel struct {
}
// buildToken combines the token ID and token payload to create a new token.
func
buildToken
(
tokenID
int64
,
tokenPayload
string
)
string
{
return
fmt
.
Sprintf
(
"%d%s%s"
,
tokenID
,
refresh
.
TokenDelimer
,
tokenPayload
)
func
buildToken
(
tokenID
int64
,
tokenPayload
[]
byte
)
string
{
return
fmt
.
Sprintf
(
"%d%s%s"
,
tokenID
,
refresh
.
TokenDelimer
,
base64
.
URLEncoding
.
EncodeToString
(
tokenPayload
)
)
}
// parseToken parses a token and returns the token ID and token payload.
func
parseToken
(
token
string
)
(
int64
,
string
,
error
)
{
func
parseToken
(
token
string
)
(
int64
,
[]
byte
,
error
)
{
parts
:=
strings
.
SplitN
(
token
,
refresh
.
TokenDelimer
,
2
)
if
len
(
parts
)
!=
2
{
return
-
1
,
""
,
refresh
.
ErrorInvalidToken
return
-
1
,
nil
,
refresh
.
ErrorInvalidToken
}
id
,
err
:=
strconv
.
ParseInt
(
parts
[
0
],
0
,
64
)
if
err
!=
nil
{
return
-
1
,
""
,
refresh
.
ErrorInvalidToken
return
-
1
,
nil
,
refresh
.
ErrorInvalidToken
}
return
id
,
parts
[
1
],
nil
tokenPayload
,
err
:=
base64
.
URLEncoding
.
DecodeString
(
parts
[
1
])
if
err
!=
nil
{
return
-
1
,
nil
,
refresh
.
ErrorInvalidToken
}
return
id
,
tokenPayload
,
nil
}
func
checkTokenPayload
(
payloadHash
,
payload
string
)
error
{
if
err
:=
bcrypt
.
CompareHashAndPassword
(
[]
byte
(
payloadHash
),
[]
byte
(
payload
)
);
err
!=
nil
{
func
checkTokenPayload
(
payloadHash
,
payload
[]
byte
)
error
{
if
err
:=
bcrypt
.
CompareHashAndPassword
(
payloadHash
,
payload
);
err
!=
nil
{
switch
err
{
case
bcrypt
.
ErrMismatchedHashAndPassword
:
return
refresh
.
ErrorInvalidToken
...
...
@@ -89,13 +94,13 @@ func (r *refreshTokenRepo) Create(userID, clientID string) (string, error) {
return
""
,
err
}
payloadHash
,
err
:=
bcrypt
.
GenerateFromPassword
(
[]
byte
(
tokenPayload
)
,
bcrypt
.
DefaultCost
)
payloadHash
,
err
:=
bcrypt
.
GenerateFromPassword
(
tokenPayload
,
bcrypt
.
DefaultCost
)
if
err
!=
nil
{
return
""
,
err
}
record
:=
&
refreshTokenModel
{
PayloadHash
:
string
(
payloadHash
)
,
PayloadHash
:
payloadHash
,
UserID
:
userID
,
ClientID
:
clientID
,
}
...
...
@@ -109,6 +114,7 @@ func (r *refreshTokenRepo) Create(userID, clientID string) (string, error) {
func
(
r
*
refreshTokenRepo
)
Verify
(
clientID
,
token
string
)
(
string
,
error
)
{
tokenID
,
tokenPayload
,
err
:=
parseToken
(
token
)
if
err
!=
nil
{
return
""
,
err
}
...
...
functional/db_test.go
View file @
e077803e
package
functional
import
(
"encoding/base64"
"fmt"
"net/url"
"os"
...
...
@@ -342,6 +343,12 @@ func TestDBClientIdentityAll(t *testing.T) {
}
}
// buildRefreshToken combines the token ID and token payload to create a new token.
// used in the tests to created a refresh token.
func
buildRefreshToken
(
tokenID
int64
,
tokenPayload
[]
byte
)
string
{
return
fmt
.
Sprintf
(
"%d%s%s"
,
tokenID
,
refresh
.
TokenDelimer
,
base64
.
URLEncoding
.
EncodeToString
(
tokenPayload
))
}
func
TestDBRefreshRepoCreate
(
t
*
testing
.
T
)
{
r
:=
db
.
NewRefreshTokenRepo
(
connect
(
t
))
...
...
@@ -383,6 +390,13 @@ func TestDBRefreshRepoVerify(t *testing.T) {
t
.
Fatalf
(
"Unexpected error: %v"
,
err
)
}
badTokenPayload
,
err
:=
refresh
.
DefaultRefreshTokenGenerator
()
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected error: %v"
,
err
)
}
tokenWithBadID
:=
"404"
+
token
[
1
:
]
tokenWithBadPayload
:=
buildRefreshToken
(
1
,
badTokenPayload
)
tests
:=
[]
struct
{
token
string
creds
oidc
.
ClientCredentials
...
...
@@ -390,7 +404,39 @@ func TestDBRefreshRepoVerify(t *testing.T) {
expected
string
}{
{
"invalid-token-foo"
,
"invalid-token-format"
,
oidc
.
ClientCredentials
{
ID
:
"client-foo"
,
Secret
:
"secret-foo"
},
refresh
.
ErrorInvalidToken
,
""
,
},
{
"b/invalid-base64-encoded-format"
,
oidc
.
ClientCredentials
{
ID
:
"client-foo"
,
Secret
:
"secret-foo"
},
refresh
.
ErrorInvalidToken
,
""
,
},
{
"1/invalid-base64-encoded-format"
,
oidc
.
ClientCredentials
{
ID
:
"client-foo"
,
Secret
:
"secret-foo"
},
refresh
.
ErrorInvalidToken
,
""
,
},
{
token
+
"corrupted-token-payload"
,
oidc
.
ClientCredentials
{
ID
:
"client-foo"
,
Secret
:
"secret-foo"
},
refresh
.
ErrorInvalidToken
,
""
,
},
{
// The token's ID content is invalid.
tokenWithBadID
,
oidc
.
ClientCredentials
{
ID
:
"client-foo"
,
Secret
:
"secret-foo"
},
refresh
.
ErrorInvalidToken
,
""
,
},
{
// The token's payload content is invalid.
tokenWithBadPayload
,
oidc
.
ClientCredentials
{
ID
:
"client-foo"
,
Secret
:
"secret-foo"
},
refresh
.
ErrorInvalidToken
,
""
,
...
...
@@ -428,13 +474,42 @@ func TestDBRefreshRepoRevoke(t *testing.T) {
t
.
Fatalf
(
"Unexpected error: %v"
,
err
)
}
badTokenPayload
,
err
:=
refresh
.
DefaultRefreshTokenGenerator
()
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected error: %v"
,
err
)
}
tokenWithBadID
:=
"404"
+
token
[
1
:
]
tokenWithBadPayload
:=
buildRefreshToken
(
1
,
badTokenPayload
)
tests
:=
[]
struct
{
token
string
userID
string
err
error
}{
{
"invalid-token-foo"
,
"invalid-token-format"
,
"user-foo"
,
refresh
.
ErrorInvalidToken
,
},
{
"1/invalid-base64-encoded-format"
,
"user-foo"
,
refresh
.
ErrorInvalidToken
,
},
{
token
+
"corrupted-token-payload"
,
"user-foo"
,
refresh
.
ErrorInvalidToken
,
},
{
// The token's ID is invalid.
tokenWithBadID
,
"user-foo"
,
refresh
.
ErrorInvalidToken
,
},
{
// The token's payload is invalid.
tokenWithBadPayload
,
"user-foo"
,
refresh
.
ErrorInvalidToken
,
},
...
...
refresh/refreshtest/repo.go
View file @
e077803e
...
...
@@ -10,9 +10,9 @@ import (
// The tokens are in the form { refresh-1, refresh-2 ... refresh-n}.
func
NewTestRefreshTokenRepo
()
(
refresh
.
RefreshTokenRepo
,
error
)
{
var
tokenIdx
int
tokenGenerator
:=
func
()
(
string
,
error
)
{
tokenGenerator
:=
func
()
(
[]
byte
,
error
)
{
tokenIdx
++
return
fmt
.
Sprintf
(
"refresh-%d"
,
tokenIdx
),
nil
return
[]
byte
(
fmt
.
Sprintf
(
"refresh-%d"
,
tokenIdx
)
),
nil
}
return
refresh
.
NewRefreshTokenRepoWithTokenGenerator
(
tokenGenerator
),
nil
}
refresh/repo.go
View file @
e077803e
package
refresh
import
(
"bytes"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"strconv"
...
...
@@ -17,25 +17,26 @@ const (
var
(
ErrorInvalidUserID
=
errors
.
New
(
"invalid user ID"
)
ErrorInvalidClientID
=
errors
.
New
(
"invalid client ID"
)
ErrorInvalidToken
=
errors
.
New
(
"invalid token"
)
)
type
RefreshTokenGenerator
func
()
(
string
,
error
)
type
RefreshTokenGenerator
func
()
(
[]
byte
,
error
)
func
(
g
RefreshTokenGenerator
)
Generate
()
(
string
,
error
)
{
func
(
g
RefreshTokenGenerator
)
Generate
()
(
[]
byte
,
error
)
{
return
g
()
}
func
DefaultRefreshTokenGenerator
()
(
string
,
error
)
{
func
DefaultRefreshTokenGenerator
()
(
[]
byte
,
error
)
{
// TODO(yifan) Remove this duplicated token generate function.
b
:=
make
([]
byte
,
DefaultRefreshTokenPayloadLength
)
n
,
err
:=
rand
.
Read
(
b
)
if
err
!=
nil
{
return
""
,
err
return
nil
,
err
}
else
if
n
!=
DefaultRefreshTokenPayloadLength
{
return
""
,
errors
.
New
(
"unable to read enough random bytes"
)
return
nil
,
errors
.
New
(
"unable to read enough random bytes"
)
}
return
b
ase64
.
URLEncoding
.
EncodeToString
(
b
)
,
nil
return
b
,
nil
}
type
RefreshTokenRepo
interface
{
...
...
@@ -52,7 +53,7 @@ type RefreshTokenRepo interface {
}
type
refreshToken
struct
{
payload
string
payload
[]
byte
userID
string
clientID
string
}
...
...
@@ -63,21 +64,21 @@ type memRefreshTokenRepo struct {
}
// buildToken combines the token ID and token payload to create a new token.
func
buildToken
(
tokenID
int
,
tokenPayload
string
)
string
{
func
buildToken
(
tokenID
int
,
tokenPayload
[]
byte
)
string
{
return
fmt
.
Sprintf
(
"%d%s%s"
,
tokenID
,
TokenDelimer
,
tokenPayload
)
}
// parseToken parses a token and returns the token ID and token payload.
func
parseToken
(
token
string
)
(
int
,
string
,
error
)
{
func
parseToken
(
token
string
)
(
int
,
[]
byte
,
error
)
{
parts
:=
strings
.
SplitN
(
token
,
TokenDelimer
,
2
)
if
len
(
parts
)
!=
2
{
return
-
1
,
""
,
ErrorInvalidToken
return
-
1
,
nil
,
ErrorInvalidToken
}
id
,
err
:=
strconv
.
Atoi
(
parts
[
0
])
if
err
!=
nil
{
return
-
1
,
""
,
ErrorInvalidToken
return
-
1
,
nil
,
ErrorInvalidToken
}
return
id
,
parts
[
1
]
,
nil
return
id
,
[]
byte
(
parts
[
1
])
,
nil
}
// NewRefreshTokenRepo returns an in-memory RefreshTokenRepo useful for development.
...
...
@@ -131,7 +132,7 @@ func (r *memRefreshTokenRepo) Verify(clientID, token string) (string, error) {
return
""
,
ErrorInvalidToken
}
if
record
.
payload
!=
tokenPayload
{
if
!
bytes
.
Equal
(
record
.
payload
,
tokenPayload
)
{
return
""
,
ErrorInvalidToken
}
...
...
@@ -153,7 +154,7 @@ func (r *memRefreshTokenRepo) Revoke(userID, token string) error {
return
ErrorInvalidToken
}
if
record
.
payload
!=
tokenPayload
{
if
!
bytes
.
Equal
(
record
.
payload
,
tokenPayload
)
{
return
ErrorInvalidToken
}
...
...
server/server_test.go
View file @
e077803e
...
...
@@ -397,7 +397,7 @@ func TestServerTokenFail(t *testing.T) {
signer
jose
.
Signer
argCC
oidc
.
ClientCredentials
argKey
string
err
string
err
error
scope
[]
string
refreshToken
string
}{
...
...
@@ -423,7 +423,7 @@ func TestServerTokenFail(t *testing.T) {
signer
:
signerFixture
,
argCC
:
ccFixture
,
argKey
:
"foo"
,
err
:
oauth2
.
ErrorInvalidGrant
,
err
:
oauth2
.
NewError
(
oauth2
.
ErrorInvalidGrant
)
,
scope
:
[]
string
{
"openid"
,
"offline_access"
},
},
...
...
@@ -432,7 +432,7 @@ func TestServerTokenFail(t *testing.T) {
signer
:
signerFixture
,
argCC
:
oidc
.
ClientCredentials
{
ID
:
"YYY"
},
argKey
:
keyFixture
,
err
:
oauth2
.
ErrorInvalidClient
,
err
:
oauth2
.
NewError
(
oauth2
.
ErrorInvalidClient
)
,
scope
:
[]
string
{
"openid"
,
"offline_access"
},
},
...
...
@@ -441,7 +441,7 @@ func TestServerTokenFail(t *testing.T) {
signer
:
&
StaticSigner
{
sig
:
nil
,
err
:
errors
.
New
(
"fail"
)},
argCC
:
ccFixture
,
argKey
:
keyFixture
,
err
:
oauth2
.
ErrorServerError
,
err
:
oauth2
.
NewError
(
oauth2
.
ErrorServerError
)
,
scope
:
[]
string
{
"openid"
,
"offline_access"
},
},
}
...
...
@@ -502,18 +502,14 @@ func TestServerTokenFail(t *testing.T) {
t
.
Fatalf
(
"case %d: expect refresh token %q, got %q"
,
i
,
tt
.
refreshToken
,
token
)
panic
(
""
)
}
if
tt
.
err
==
""
{
if
err
!=
nil
{
t
.
Errorf
(
"case %d: got non-nil error: %v"
,
i
,
err
)
}
else
if
jwt
==
nil
{
t
.
Errorf
(
"case %d: got nil JWT"
,
i
)
if
!
reflect
.
DeepEqual
(
err
,
tt
.
err
)
{
t
.
Errorf
(
"case %d: expect %v, got %v"
,
i
,
tt
.
err
,
err
)
}
}
else
{
if
err
.
Error
()
!=
tt
.
err
{
t
.
Errorf
(
"case %d: want err %q, got %q"
,
i
,
tt
.
err
,
err
.
Error
())
}
else
if
jwt
!=
nil
{
t
.
Errorf
(
"case %d: got non-nil JWT"
,
i
)
if
err
==
nil
&&
jwt
==
nil
{
t
.
Errorf
(
"case %d: got nil JWT"
,
i
)
}
if
err
!=
nil
&&
jwt
!=
nil
{
t
.
Errorf
(
"case %d: got non-nil JWT %v"
,
i
,
jwt
)
}
}
}
...
...
@@ -537,7 +533,7 @@ func TestServerRefreshToken(t *testing.T) {
clientID
string
// The client that associates with the token.
creds
oidc
.
ClientCredentials
signer
jose
.
Signer
err
string
err
error
}{
// Everything is good.
{
...
...
@@ -545,7 +541,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
credXXX
,
signerFixture
,
""
,
nil
,
},
// Invalid refresh token(malformatted).
{
...
...
@@ -553,15 +549,23 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
credXXX
,
signerFixture
,
oauth2
.
ErrorInvalidRequest
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidRequest
)
,
},
// Invalid refresh token.
// Invalid refresh token
(invalid payload content)
.
{
"0/refresh-
1
"
,
"0/refresh-
2
"
,
"XXX"
,
credXXX
,
signerFixture
,
oauth2
.
ErrorInvalidRequest
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidRequest
),
},
// Invalid refresh token(invalid ID content).
{
"1/refresh-2"
,
"XXX"
,
credXXX
,
signerFixture
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidRequest
),
},
// Invalid client(client is not associated with the token).
{
...
...
@@ -569,7 +573,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
credYYY
,
signerFixture
,
oauth2
.
ErrorInvalidClient
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidClient
)
,
},
// Invalid client(no client ID).
{
...
...
@@ -577,7 +581,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
oidc
.
ClientCredentials
{
ID
:
""
,
Secret
:
"aaa"
},
signerFixture
,
oauth2
.
ErrorInvalidClient
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidClient
)
,
},
// Invalid client(no such client).
{
...
...
@@ -585,7 +589,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
oidc
.
ClientCredentials
{
ID
:
"AAA"
,
Secret
:
"aaa"
},
signerFixture
,
oauth2
.
ErrorInvalidClient
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidClient
)
,
},
// Invalid client(no secrets).
{
...
...
@@ -593,7 +597,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
oidc
.
ClientCredentials
{
ID
:
"XXX"
},
signerFixture
,
oauth2
.
ErrorInvalidClient
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidClient
)
,
},
// Invalid client(invalid secret).
{
...
...
@@ -601,7 +605,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
oidc
.
ClientCredentials
{
ID
:
"XXX"
,
Secret
:
"bad-secret"
},
signerFixture
,
oauth2
.
ErrorInvalidClient
,
oauth2
.
NewError
(
oauth2
.
ErrorInvalidClient
)
,
},
// Signing operation fails.
{
...
...
@@ -609,7 +613,7 @@ func TestServerRefreshToken(t *testing.T) {
"XXX"
,
credXXX
,
&
StaticSigner
{
sig
:
nil
,
err
:
errors
.
New
(
"fail"
)},
oauth2
.
ErrorServerError
,
oauth2
.
NewError
(
oauth2
.
ErrorServerError
)
,
},
}
...
...
@@ -646,11 +650,9 @@ func TestServerRefreshToken(t *testing.T) {
}
jwt
,
err
:=
srv
.
RefreshToken
(
tt
.
creds
,
tt
.
token
)
if
err
!=
nil
{
if
err
.
Error
()
!=
tt
.
err
{
if
!
reflect
.
DeepEqual
(
err
,
tt
.
err
)
{
t
.
Errorf
(
"Case %d: expect: %v, got: %v"
,
i
,
tt
.
err
,
err
)
}
}
if
jwt
!=
nil
{
if
string
(
jwt
.
Signature
)
!=
"beer"
{
...
...
@@ -715,7 +717,7 @@ func TestServerRefreshToken(t *testing.T) {
srv
.
UserRepo
=
userRepo
_
,
err
=
srv
.
RefreshToken
(
credXXX
,
"0/refresh-1"
)
if
err
==
nil
||
err
.
Error
()
!=
oauth2
.
ErrorServerError
{
t
.
Errorf
(
"Expect: %v, got: %v"
,
oauth2
.
ErrorServerError
,
err
)
if
!
reflect
.
DeepEqual
(
err
,
oauth2
.
NewError
(
oauth2
.
ErrorServerError
))
{
t
.
Errorf
(
"Expect: %v, got: %v"
,
oauth2
.
NewError
(
oauth2
.
ErrorServerError
)
,
err
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment