making some progress

This commit is contained in:
2026-04-25 13:31:41 -06:00
parent 27088c2cd8
commit 09f4421f7f
11 changed files with 166 additions and 125 deletions

View File

@@ -1,5 +0,0 @@
package main
func main() {
}

View File

@@ -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")
}

View File

@@ -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]
}

View File

@@ -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 '',

View File

@@ -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"`

View File

@@ -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);

View File

@@ -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
View File

@@ -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
View File

@@ -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=

View File

@@ -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"