mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Add authentication and personal user endpoint (#29)
* feat: Add authentication and personal user endpoint This contribution adds a lot of scaffolding for the database fake and testability of coderd. A new endpoint "/user" is added to return the currently authenticated user to the requester. * Use TestMain to catch leak instead * Add userpassword package * Add WIP * Add user auth * Fix test * Add comments * Fix login response * Fix order * Fix generated code * Update httpapi/httpapi.go Co-authored-by: Bryan <bryan@coder.com> Co-authored-by: Bryan <bryan@coder.com>
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package databasefake
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/coder/coder/database"
|
||||
)
|
||||
|
||||
// New returns an in-memory fake of the database.
|
||||
func New() database.Store {
|
||||
return &fakeQuerier{
|
||||
apiKeys: make([]database.APIKey, 0),
|
||||
users: make([]database.User, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// fakeQuerier replicates database functionality to enable quick testing.
|
||||
type fakeQuerier struct {
|
||||
apiKeys []database.APIKey
|
||||
users []database.User
|
||||
}
|
||||
|
||||
// InTx doesn't rollback data properly for in-memory yet.
|
||||
func (q *fakeQuerier) InTx(ctx context.Context, fn func(database.Store) error) error {
|
||||
return fn(q)
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetAPIKeyByID(ctx context.Context, id string) (database.APIKey, error) {
|
||||
for _, apiKey := range q.apiKeys {
|
||||
if apiKey.ID == id {
|
||||
return apiKey, nil
|
||||
}
|
||||
}
|
||||
return database.APIKey{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetUserByEmailOrUsername(ctx context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) {
|
||||
for _, user := range q.users {
|
||||
if user.Email == arg.Email || user.Username == arg.Username {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
return database.User{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetUserByID(ctx context.Context, id string) (database.User, error) {
|
||||
for _, user := range q.users {
|
||||
if user.ID == id {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
return database.User{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetUserCount(ctx context.Context) (int64, error) {
|
||||
return int64(len(q.users)), nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) InsertAPIKey(ctx context.Context, arg database.InsertAPIKeyParams) (database.APIKey, error) {
|
||||
key := database.APIKey{
|
||||
ID: arg.ID,
|
||||
HashedSecret: arg.HashedSecret,
|
||||
UserID: arg.UserID,
|
||||
Application: arg.Application,
|
||||
Name: arg.Name,
|
||||
LastUsed: arg.LastUsed,
|
||||
ExpiresAt: arg.ExpiresAt,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
LoginType: arg.LoginType,
|
||||
OIDCAccessToken: arg.OIDCAccessToken,
|
||||
OIDCRefreshToken: arg.OIDCRefreshToken,
|
||||
OIDCIDToken: arg.OIDCIDToken,
|
||||
OIDCExpiry: arg.OIDCExpiry,
|
||||
DevurlToken: arg.DevurlToken,
|
||||
}
|
||||
q.apiKeys = append(q.apiKeys, key)
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) InsertUser(ctx context.Context, arg database.InsertUserParams) (database.User, error) {
|
||||
user := database.User{
|
||||
ID: arg.ID,
|
||||
Email: arg.Email,
|
||||
Name: arg.Name,
|
||||
LoginType: arg.LoginType,
|
||||
HashedPassword: arg.HashedPassword,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
UpdatedAt: arg.UpdatedAt,
|
||||
Username: arg.Username,
|
||||
}
|
||||
q.users = append(q.users, user)
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateAPIKeyByID(ctx context.Context, arg database.UpdateAPIKeyByIDParams) error {
|
||||
for index, apiKey := range q.apiKeys {
|
||||
if apiKey.ID != arg.ID {
|
||||
continue
|
||||
}
|
||||
apiKey.LastUsed = arg.LastUsed
|
||||
apiKey.ExpiresAt = arg.ExpiresAt
|
||||
apiKey.OIDCAccessToken = arg.OIDCAccessToken
|
||||
apiKey.OIDCRefreshToken = arg.OIDCRefreshToken
|
||||
apiKey.OIDCExpiry = arg.OIDCExpiry
|
||||
q.apiKeys[index] = apiKey
|
||||
return nil
|
||||
}
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package database
|
||||
|
||||
import "context"
|
||||
|
||||
// NewInMemory returns an in-memory store of the database.
|
||||
func NewInMemory() Store {
|
||||
return &memoryQuerier{}
|
||||
}
|
||||
|
||||
type memoryQuerier struct{}
|
||||
|
||||
// InTx doesn't rollback data properly for in-memory yet.
|
||||
func (q *memoryQuerier) InTx(ctx context.Context, fn func(Store) error) error {
|
||||
return fn(q)
|
||||
}
|
||||
|
||||
func (q *memoryQuerier) ExampleQuery(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
+6
-6
@@ -13,7 +13,7 @@ type LoginType string
|
||||
const (
|
||||
LoginTypeBuiltIn LoginType = "built-in"
|
||||
LoginTypeSaml LoginType = "saml"
|
||||
LoginTypeOidc LoginType = "oidc"
|
||||
LoginTypeOIDC LoginType = "oidc"
|
||||
)
|
||||
|
||||
func (e *LoginType) Scan(src interface{}) error {
|
||||
@@ -48,7 +48,7 @@ func (e *UserStatus) Scan(src interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ApiKey struct {
|
||||
type APIKey struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
@@ -59,10 +59,10 @@ type ApiKey struct {
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
OidcAccessToken string `db:"oidc_access_token" json:"oidc_access_token"`
|
||||
OidcRefreshToken string `db:"oidc_refresh_token" json:"oidc_refresh_token"`
|
||||
OidcIDToken string `db:"oidc_id_token" json:"oidc_id_token"`
|
||||
OidcExpiry time.Time `db:"oidc_expiry" json:"oidc_expiry"`
|
||||
OIDCAccessToken string `db:"oidc_access_token" json:"oidc_access_token"`
|
||||
OIDCRefreshToken string `db:"oidc_refresh_token" json:"oidc_refresh_token"`
|
||||
OIDCIDToken string `db:"oidc_id_token" json:"oidc_id_token"`
|
||||
OIDCExpiry time.Time `db:"oidc_expiry" json:"oidc_expiry"`
|
||||
DevurlToken bool `db:"devurl_token" json:"devurl_token"`
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -7,7 +7,13 @@ import (
|
||||
)
|
||||
|
||||
type querier interface {
|
||||
ExampleQuery(ctx context.Context) error
|
||||
GetAPIKeyByID(ctx context.Context, id string) (APIKey, error)
|
||||
GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error)
|
||||
GetUserByID(ctx context.Context, id string) (User, error)
|
||||
GetUserCount(ctx context.Context) (int64, error)
|
||||
InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error)
|
||||
InsertUser(ctx context.Context, arg InsertUserParams) (User, error)
|
||||
UpdateAPIKeyByID(ctx context.Context, arg UpdateAPIKeyByIDParams) error
|
||||
}
|
||||
|
||||
var _ querier = (*sqlQuerier)(nil)
|
||||
|
||||
+107
-2
@@ -1,2 +1,107 @@
|
||||
-- name: ExampleQuery :exec
|
||||
SELECT 'example query';
|
||||
-- Database queries are generated using sqlc. See:
|
||||
-- https://docs.sqlc.dev/en/latest/tutorials/getting-started-postgresql.html
|
||||
--
|
||||
-- Run "make gen" to generate models and query functions.
|
||||
;
|
||||
|
||||
-- name: GetAPIKeyByID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
api_keys
|
||||
WHERE
|
||||
id = $1
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetUserByID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
id = $1
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetUserByEmailOrUsername :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
username = $1
|
||||
OR email = $2
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetUserCount :one
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
users;
|
||||
|
||||
-- name: InsertAPIKey :one
|
||||
INSERT INTO
|
||||
api_keys (
|
||||
id,
|
||||
hashed_secret,
|
||||
user_id,
|
||||
application,
|
||||
name,
|
||||
last_used,
|
||||
expires_at,
|
||||
created_at,
|
||||
updated_at,
|
||||
login_type,
|
||||
oidc_access_token,
|
||||
oidc_refresh_token,
|
||||
oidc_id_token,
|
||||
oidc_expiry,
|
||||
devurl_token
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$13,
|
||||
$14,
|
||||
$15
|
||||
) RETURNING *;
|
||||
|
||||
-- name: InsertUser :one
|
||||
INSERT INTO
|
||||
users (
|
||||
id,
|
||||
email,
|
||||
name,
|
||||
login_type,
|
||||
hashed_password,
|
||||
created_at,
|
||||
updated_at,
|
||||
username
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
|
||||
|
||||
-- name: UpdateAPIKeyByID :exec
|
||||
UPDATE
|
||||
api_keys
|
||||
SET
|
||||
last_used = $2,
|
||||
expires_at = $3,
|
||||
oidc_access_token = $4,
|
||||
oidc_refresh_token = $5,
|
||||
oidc_expiry = $6
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
+321
-4
@@ -5,13 +5,330 @@ package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
const exampleQuery = `-- name: ExampleQuery :exec
|
||||
SELECT 'example query'
|
||||
const getAPIKeyByID = `-- name: GetAPIKeyByID :one
|
||||
SELECT
|
||||
id, hashed_secret, user_id, application, name, last_used, expires_at, created_at, updated_at, login_type, oidc_access_token, oidc_refresh_token, oidc_id_token, oidc_expiry, devurl_token
|
||||
FROM
|
||||
api_keys
|
||||
WHERE
|
||||
id = $1
|
||||
LIMIT
|
||||
1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) ExampleQuery(ctx context.Context) error {
|
||||
_, err := q.db.ExecContext(ctx, exampleQuery)
|
||||
func (q *sqlQuerier) GetAPIKeyByID(ctx context.Context, id string) (APIKey, error) {
|
||||
row := q.db.QueryRowContext(ctx, getAPIKeyByID, id)
|
||||
var i APIKey
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.HashedSecret,
|
||||
&i.UserID,
|
||||
&i.Application,
|
||||
&i.Name,
|
||||
&i.LastUsed,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LoginType,
|
||||
&i.OIDCAccessToken,
|
||||
&i.OIDCRefreshToken,
|
||||
&i.OIDCIDToken,
|
||||
&i.OIDCExpiry,
|
||||
&i.DevurlToken,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one
|
||||
SELECT
|
||||
id, email, name, revoked, login_type, hashed_password, created_at, updated_at, temporary_password, avatar_hash, ssh_key_regenerated_at, username, dotfiles_git_uri, roles, status, relatime, gpg_key_regenerated_at, _decomissioned, shell
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
username = $1
|
||||
OR email = $2
|
||||
LIMIT
|
||||
1
|
||||
`
|
||||
|
||||
type GetUserByEmailOrUsernameParams struct {
|
||||
Username string `db:"username" json:"username"`
|
||||
Email string `db:"email" json:"email"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserByEmailOrUsername, arg.Username, arg.Email)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Email,
|
||||
&i.Name,
|
||||
&i.Revoked,
|
||||
&i.LoginType,
|
||||
&i.HashedPassword,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.TemporaryPassword,
|
||||
&i.AvatarHash,
|
||||
&i.SshKeyRegeneratedAt,
|
||||
&i.Username,
|
||||
&i.DotfilesGitUri,
|
||||
pq.Array(&i.Roles),
|
||||
&i.Status,
|
||||
&i.Relatime,
|
||||
&i.GpgKeyRegeneratedAt,
|
||||
&i.Decomissioned,
|
||||
&i.Shell,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserByID = `-- name: GetUserByID :one
|
||||
SELECT
|
||||
id, email, name, revoked, login_type, hashed_password, created_at, updated_at, temporary_password, avatar_hash, ssh_key_regenerated_at, username, dotfiles_git_uri, roles, status, relatime, gpg_key_regenerated_at, _decomissioned, shell
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
id = $1
|
||||
LIMIT
|
||||
1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetUserByID(ctx context.Context, id string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserByID, id)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Email,
|
||||
&i.Name,
|
||||
&i.Revoked,
|
||||
&i.LoginType,
|
||||
&i.HashedPassword,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.TemporaryPassword,
|
||||
&i.AvatarHash,
|
||||
&i.SshKeyRegeneratedAt,
|
||||
&i.Username,
|
||||
&i.DotfilesGitUri,
|
||||
pq.Array(&i.Roles),
|
||||
&i.Status,
|
||||
&i.Relatime,
|
||||
&i.GpgKeyRegeneratedAt,
|
||||
&i.Decomissioned,
|
||||
&i.Shell,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserCount = `-- name: GetUserCount :one
|
||||
SELECT
|
||||
COUNT(*)
|
||||
FROM
|
||||
users
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetUserCount(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserCount)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const insertAPIKey = `-- name: InsertAPIKey :one
|
||||
INSERT INTO
|
||||
api_keys (
|
||||
id,
|
||||
hashed_secret,
|
||||
user_id,
|
||||
application,
|
||||
name,
|
||||
last_used,
|
||||
expires_at,
|
||||
created_at,
|
||||
updated_at,
|
||||
login_type,
|
||||
oidc_access_token,
|
||||
oidc_refresh_token,
|
||||
oidc_id_token,
|
||||
oidc_expiry,
|
||||
devurl_token
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$13,
|
||||
$14,
|
||||
$15
|
||||
) RETURNING id, hashed_secret, user_id, application, name, last_used, expires_at, created_at, updated_at, login_type, oidc_access_token, oidc_refresh_token, oidc_id_token, oidc_expiry, devurl_token
|
||||
`
|
||||
|
||||
type InsertAPIKeyParams struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
Application bool `db:"application" json:"application"`
|
||||
Name string `db:"name" json:"name"`
|
||||
LastUsed time.Time `db:"last_used" json:"last_used"`
|
||||
ExpiresAt time.Time `db:"expires_at" json:"expires_at"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
OIDCAccessToken string `db:"oidc_access_token" json:"oidc_access_token"`
|
||||
OIDCRefreshToken string `db:"oidc_refresh_token" json:"oidc_refresh_token"`
|
||||
OIDCIDToken string `db:"oidc_id_token" json:"oidc_id_token"`
|
||||
OIDCExpiry time.Time `db:"oidc_expiry" json:"oidc_expiry"`
|
||||
DevurlToken bool `db:"devurl_token" json:"devurl_token"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertAPIKey,
|
||||
arg.ID,
|
||||
arg.HashedSecret,
|
||||
arg.UserID,
|
||||
arg.Application,
|
||||
arg.Name,
|
||||
arg.LastUsed,
|
||||
arg.ExpiresAt,
|
||||
arg.CreatedAt,
|
||||
arg.UpdatedAt,
|
||||
arg.LoginType,
|
||||
arg.OIDCAccessToken,
|
||||
arg.OIDCRefreshToken,
|
||||
arg.OIDCIDToken,
|
||||
arg.OIDCExpiry,
|
||||
arg.DevurlToken,
|
||||
)
|
||||
var i APIKey
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.HashedSecret,
|
||||
&i.UserID,
|
||||
&i.Application,
|
||||
&i.Name,
|
||||
&i.LastUsed,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.LoginType,
|
||||
&i.OIDCAccessToken,
|
||||
&i.OIDCRefreshToken,
|
||||
&i.OIDCIDToken,
|
||||
&i.OIDCExpiry,
|
||||
&i.DevurlToken,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertUser = `-- name: InsertUser :one
|
||||
INSERT INTO
|
||||
users (
|
||||
id,
|
||||
email,
|
||||
name,
|
||||
login_type,
|
||||
hashed_password,
|
||||
created_at,
|
||||
updated_at,
|
||||
username
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id, email, name, revoked, login_type, hashed_password, created_at, updated_at, temporary_password, avatar_hash, ssh_key_regenerated_at, username, dotfiles_git_uri, roles, status, relatime, gpg_key_regenerated_at, _decomissioned, shell
|
||||
`
|
||||
|
||||
type InsertUserParams struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Name string `db:"name" json:"name"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
HashedPassword []byte `db:"hashed_password" json:"hashed_password"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Username string `db:"username" json:"username"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertUser(ctx context.Context, arg InsertUserParams) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertUser,
|
||||
arg.ID,
|
||||
arg.Email,
|
||||
arg.Name,
|
||||
arg.LoginType,
|
||||
arg.HashedPassword,
|
||||
arg.CreatedAt,
|
||||
arg.UpdatedAt,
|
||||
arg.Username,
|
||||
)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Email,
|
||||
&i.Name,
|
||||
&i.Revoked,
|
||||
&i.LoginType,
|
||||
&i.HashedPassword,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.TemporaryPassword,
|
||||
&i.AvatarHash,
|
||||
&i.SshKeyRegeneratedAt,
|
||||
&i.Username,
|
||||
&i.DotfilesGitUri,
|
||||
pq.Array(&i.Roles),
|
||||
&i.Status,
|
||||
&i.Relatime,
|
||||
&i.GpgKeyRegeneratedAt,
|
||||
&i.Decomissioned,
|
||||
&i.Shell,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateAPIKeyByID = `-- name: UpdateAPIKeyByID :exec
|
||||
UPDATE
|
||||
api_keys
|
||||
SET
|
||||
last_used = $2,
|
||||
expires_at = $3,
|
||||
oidc_access_token = $4,
|
||||
oidc_refresh_token = $5,
|
||||
oidc_expiry = $6
|
||||
WHERE
|
||||
id = $1
|
||||
`
|
||||
|
||||
type UpdateAPIKeyByIDParams struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
LastUsed time.Time `db:"last_used" json:"last_used"`
|
||||
ExpiresAt time.Time `db:"expires_at" json:"expires_at"`
|
||||
OIDCAccessToken string `db:"oidc_access_token" json:"oidc_access_token"`
|
||||
OIDCRefreshToken string `db:"oidc_refresh_token" json:"oidc_refresh_token"`
|
||||
OIDCExpiry time.Time `db:"oidc_expiry" json:"oidc_expiry"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateAPIKeyByID(ctx context.Context, arg UpdateAPIKeyByIDParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateAPIKeyByID,
|
||||
arg.ID,
|
||||
arg.LastUsed,
|
||||
arg.ExpiresAt,
|
||||
arg.OIDCAccessToken,
|
||||
arg.OIDCRefreshToken,
|
||||
arg.OIDCExpiry,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,4 +19,10 @@ overrides:
|
||||
- db_type: citext
|
||||
go_type: string
|
||||
rename:
|
||||
api_key: APIKey
|
||||
login_type_oidc: LoginTypeOIDC
|
||||
oidc_access_token: OIDCAccessToken
|
||||
oidc_expiry: OIDCExpiry
|
||||
oidc_id_token: OIDCIDToken
|
||||
oidc_refresh_token: OIDCRefreshToken
|
||||
userstatus: UserStatus
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package database
|
||||
|
||||
import "time"
|
||||
|
||||
// Now returns a standardized timezone used for database resources.
|
||||
func Now() time.Time {
|
||||
return time.Now().UTC()
|
||||
}
|
||||
Reference in New Issue
Block a user