making some progress
This commit is contained in:
@@ -1,5 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"git.nmcnew.com/nmcnew/bracketeer/db"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrAuthFailed = errors.New("auth values don't match")
|
|
||||||
)
|
|
||||||
|
|
||||||
type AuthService interface {
|
|
||||||
Login(ctx context.Context, username string, authValue string, authType string) (*db.User, error)
|
|
||||||
}
|
|
||||||
type authService struct {
|
|
||||||
q *db.Queries
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAuthService(q *db.Queries) AuthService {
|
|
||||||
return &authService{
|
|
||||||
q: q,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *authService) Login(ctx context.Context, username, authValue, authType string) (*db.User, error) {
|
|
||||||
dbValue, err := s.q.GetUserAuthValue(ctx, db.GetUserAuthValueParams{
|
|
||||||
Name: username,
|
|
||||||
Type: db.AuthTypeFromString(authType),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch authType {
|
|
||||||
case "password":
|
|
||||||
err = bcrypt.CompareHashAndPassword([]byte(dbValue.AuthValue), []byte(authValue))
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrAuthFailed
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if authValue != dbValue.AuthValue {
|
|
||||||
return nil, ErrAuthFailed
|
|
||||||
}
|
|
||||||
user, err := s.q.GetUserFromId(ctx, dbValue.UserID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &user, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, ErrAuthFailed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *authService) Register(ctx context.Context, username, email, bio, profileURL, authValue, authType string) (*db.User, error) {
|
|
||||||
panic("unimplemented")
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
var authMap = map[string]AuthType{
|
|
||||||
string(AuthTypePassword): AuthTypePassword,
|
|
||||||
string(AuthTypeDiscord): AuthTypeDiscord,
|
|
||||||
string(AuthTypeGoogle): AuthTypeGoogle,
|
|
||||||
}
|
|
||||||
|
|
||||||
func AuthTypeFromString(input string) AuthType {
|
|
||||||
return authMap[input]
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
-- +goose Up
|
-- +goose Up
|
||||||
-- create initial schema
|
-- create initial schema
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id UUID PRIMARY KEY ,
|
id UUID PRIMARY KEY DEFAULT uuidv7(),
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
email TEXT NOT NULL,
|
email TEXT NOT NULL,
|
||||||
bio TEXT NOT NULL default '',
|
bio TEXT NOT NULL default '',
|
||||||
|
|||||||
39
db/models.go
39
db/models.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -97,8 +98,8 @@ func (ns NullEntrantType) Value() (driver.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AuthMethod struct {
|
type AuthMethod struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
UserID pgtype.UUID `json:"user_id"`
|
UserID uuid.UUID `json:"user_id"`
|
||||||
Type AuthType `json:"type"`
|
Type AuthType `json:"type"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
@@ -106,63 +107,63 @@ type AuthMethod struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Bracket struct {
|
type Bracket struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
EventID pgtype.UUID `json:"event_id"`
|
EventID uuid.UUID `json:"event_id"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BracketEntrant struct {
|
type BracketEntrant struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
SeedOrder int32 `json:"seed_order"`
|
SeedOrder int32 `json:"seed_order"`
|
||||||
EntrantID pgtype.UUID `json:"entrant_id"`
|
EntrantID uuid.UUID `json:"entrant_id"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entrant struct {
|
type Entrant struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
EventID pgtype.UUID `json:"event_id"`
|
EventID uuid.UUID `json:"event_id"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Match struct {
|
type Match struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Player1 pgtype.UUID `json:"player1"`
|
Player1 uuid.UUID `json:"player1"`
|
||||||
Player2 pgtype.UUID `json:"player2"`
|
Player2 uuid.UUID `json:"player2"`
|
||||||
Player1From pgtype.UUID `json:"player1_from"`
|
Player1From uuid.UUID `json:"player1_from"`
|
||||||
Player2From pgtype.UUID `json:"player2_from"`
|
Player2From uuid.UUID `json:"player2_from"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Team struct {
|
type Team struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TeamEntrant struct {
|
type TeamEntrant struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
TeamID pgtype.UUID `json:"team_id"`
|
TeamID uuid.UUID `json:"team_id"`
|
||||||
EntrantID pgtype.UUID `json:"entrant_id"`
|
EntrantID uuid.UUID `json:"entrant_id"`
|
||||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID pgtype.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Bio string `json:"bio"`
|
Bio string `json:"bio"`
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
-- name: GetUserFromId :one
|
-- name: GetUserById :one
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM users u
|
FROM users u
|
||||||
WHERE u.id = $1;
|
WHERE u.id = @user_id::uuid;
|
||||||
|
|
||||||
-- name: GetUserAuthValue :one
|
-- name: GetUserAuthValue :one
|
||||||
SELECT u.ID as user_id, a.value as auth_value
|
SELECT u.ID as user_id, a.value as auth_value
|
||||||
@@ -9,5 +9,20 @@ FROM users u
|
|||||||
JOIN auth_method a
|
JOIN auth_method a
|
||||||
ON a.user_id = u.id
|
ON a.user_id = u.id
|
||||||
WHERE
|
WHERE
|
||||||
(u.name = $1 OR u.email = $1)
|
(u.name = @auth_value::text OR u.email = @auth_value)
|
||||||
AND a.type = $2;
|
AND a.type = @auth_type::auth_type;
|
||||||
|
|
||||||
|
-- name: CreateUser :one
|
||||||
|
INSERT INTO users (name, email, bio, profile_photo)
|
||||||
|
VALUES($1, $2, $3, $4)
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: UpdateUser :one
|
||||||
|
UPDATE users
|
||||||
|
SET name = @name::text, email = @email::text, bio = @bio::text, profile_photo = @photo::text
|
||||||
|
WHERE id = @id::uuid
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: CreateAuthMethod :exec
|
||||||
|
INSERT INTO auth_method (user_id, type, value)
|
||||||
|
VALUES ($1, $2, $3);
|
||||||
|
|||||||
140
db/users.sql.go
140
db/users.sql.go
@@ -8,44 +8,130 @@ package db
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
const getUserAuthValue = `-- name: GetUserAuthValue :one
|
const createAuthMethod = `-- name: CreateAuthMethod :exec
|
||||||
SELECT u.ID as user_id, a.value as auth_value
|
INSERT INTO auth_method (user_id, type, value)
|
||||||
FROM users u
|
VALUES ($1, $2, $3)
|
||||||
JOIN auth_method a
|
|
||||||
ON a.user_id = u.id
|
|
||||||
WHERE
|
|
||||||
(u.name = $1 OR u.email = $1)
|
|
||||||
AND a.type = $2
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetUserAuthValueParams struct {
|
type CreateAuthMethodParams struct {
|
||||||
Name string `json:"name"`
|
UserID uuid.UUID `json:"user_id"`
|
||||||
Type AuthType `json:"type"`
|
Type AuthType `json:"type"`
|
||||||
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetUserAuthValueRow struct {
|
func (q *Queries) CreateAuthMethod(ctx context.Context, arg CreateAuthMethodParams) error {
|
||||||
UserID pgtype.UUID `json:"user_id"`
|
_, err := q.db.Exec(ctx, createAuthMethod, arg.UserID, arg.Type, arg.Value)
|
||||||
AuthValue string `json:"auth_value"`
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetUserAuthValue(ctx context.Context, arg GetUserAuthValueParams) (GetUserAuthValueRow, error) {
|
const createUser = `-- name: CreateUser :one
|
||||||
row := q.db.QueryRow(ctx, getUserAuthValue, arg.Name, arg.Type)
|
INSERT INTO users (name, email, bio, profile_photo)
|
||||||
var i GetUserAuthValueRow
|
VALUES($1, $2, $3, $4)
|
||||||
err := row.Scan(&i.UserID, &i.AuthValue)
|
RETURNING id, name, email, bio, profile_photo, updated_at, created_at
|
||||||
return i, err
|
|
||||||
}
|
|
||||||
|
|
||||||
const getUserFromId = `-- name: GetUserFromId :one
|
|
||||||
SELECT id, name, email, bio, profile_photo, updated_at, created_at
|
|
||||||
FROM users u
|
|
||||||
WHERE u.id = $1
|
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) GetUserFromId(ctx context.Context, id pgtype.UUID) (User, error) {
|
type CreateUserParams struct {
|
||||||
row := q.db.QueryRow(ctx, getUserFromId, id)
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Bio string `json:"bio"`
|
||||||
|
ProfilePhoto pgtype.Text `json:"profile_photo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
|
||||||
|
row := q.db.QueryRow(ctx, createUser,
|
||||||
|
arg.Name,
|
||||||
|
arg.Email,
|
||||||
|
arg.Bio,
|
||||||
|
arg.ProfilePhoto,
|
||||||
|
)
|
||||||
|
var i User
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.Email,
|
||||||
|
&i.Bio,
|
||||||
|
&i.ProfilePhoto,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
&i.CreatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserAuthValue = `-- name: GetUserAuthValue :one
|
||||||
|
SELECT u.ID as user_id, a.value as auth_value
|
||||||
|
FROM users u
|
||||||
|
JOIN auth_method a
|
||||||
|
ON a.user_id = u.id
|
||||||
|
WHERE
|
||||||
|
(u.name = $1::text OR u.email = $1)
|
||||||
|
AND a.type = $2::auth_type
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetUserAuthValueParams struct {
|
||||||
|
AuthValue string `json:"auth_value"`
|
||||||
|
AuthType AuthType `json:"auth_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetUserAuthValueRow struct {
|
||||||
|
UserID uuid.UUID `json:"user_id"`
|
||||||
|
AuthValue string `json:"auth_value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetUserAuthValue(ctx context.Context, arg GetUserAuthValueParams) (GetUserAuthValueRow, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getUserAuthValue, arg.AuthValue, arg.AuthType)
|
||||||
|
var i GetUserAuthValueRow
|
||||||
|
err := row.Scan(&i.UserID, &i.AuthValue)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserById = `-- name: GetUserById :one
|
||||||
|
SELECT id, name, email, bio, profile_photo, updated_at, created_at
|
||||||
|
FROM users u
|
||||||
|
WHERE u.id = $1::uuid
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetUserById(ctx context.Context, userID uuid.UUID) (User, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getUserById, userID)
|
||||||
|
var i User
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.Email,
|
||||||
|
&i.Bio,
|
||||||
|
&i.ProfilePhoto,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
&i.CreatedAt,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateUser = `-- name: UpdateUser :one
|
||||||
|
UPDATE users
|
||||||
|
SET name = $1::text, email = $2::text, bio = $3::text, profile_photo = $4::text
|
||||||
|
WHERE id = $5::uuid
|
||||||
|
RETURNING id, name, email, bio, profile_photo, updated_at, created_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateUserParams struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Bio string `json:"bio"`
|
||||||
|
Photo string `json:"photo"`
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error) {
|
||||||
|
row := q.db.QueryRow(ctx, updateUser,
|
||||||
|
arg.Name,
|
||||||
|
arg.Email,
|
||||||
|
arg.Bio,
|
||||||
|
arg.Photo,
|
||||||
|
arg.ID,
|
||||||
|
)
|
||||||
var i User
|
var i User
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -15,6 +15,7 @@ require (
|
|||||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/goccy/go-yaml v1.9.5 // indirect
|
github.com/goccy/go-yaml v1.9.5 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/graphql-go/graphql v0.8.0 // indirect
|
github.com/graphql-go/graphql v0.8.0 // indirect
|
||||||
github.com/graphql-go/handler v0.2.3 // indirect
|
github.com/graphql-go/handler v0.2.3 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -214,6 +214,8 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||||
|
|||||||
10
sqlc.yaml
10
sqlc.yaml
@@ -9,3 +9,13 @@ sql:
|
|||||||
out: "db"
|
out: "db"
|
||||||
sql_package: "pgx/v5"
|
sql_package: "pgx/v5"
|
||||||
emit_json_tags: true
|
emit_json_tags: true
|
||||||
|
overrides:
|
||||||
|
- db_type: "uuid"
|
||||||
|
go_type:
|
||||||
|
import: "github.com/google/uuid"
|
||||||
|
type: "UUID"
|
||||||
|
- db_type: "uuid"
|
||||||
|
nullable: true
|
||||||
|
go_type:
|
||||||
|
import: "github.com/google/uuid"
|
||||||
|
type: "UUID"
|
||||||
|
|||||||
Reference in New Issue
Block a user