Merge branch 'feat-sql' into ml2

This commit is contained in:
2025-08-04 21:26:40 +03:00
5 changed files with 400 additions and 53 deletions

View File

@@ -15,7 +15,7 @@ type BannedUser struct {
Reason *string
ExpiresAt pgtype.Timestamp
BannedBy *string
Pardoned *bool
Pardoned bool
PardonedBy *string
}
@@ -25,8 +25,8 @@ type ConfirmationCode struct {
CodeType int32
CodeHash string
ExpiresAt pgtype.Timestamp
Used *bool
Deleted *bool
Used bool
Deleted bool
}
type LoginInformation struct {
@@ -78,8 +78,34 @@ type Session struct {
type User struct {
ID int64
Username string
Verified *bool
Verified bool
RegistrationDate pgtype.Timestamp
Role int32
Deleted *bool
}
type Wish struct {
ID int64
Guid pgtype.UUID
WishListID int64
Name string
Description string
PictureUrl string
Stars int16
CreationDate pgtype.Timestamp
Fulfilled bool
FulfilledDate pgtype.Timestamp
Deleted bool
}
type WishList struct {
ID int64
Guid pgtype.UUID
ProfileID int64
Hidden bool
Name string
IconName *string
Color *string
ColorGrad *string
Deleted bool
}

View File

@@ -253,6 +253,54 @@ func (q *Queries) CreateUser(ctx context.Context, username string) (User, error)
return i, err
}
const createWishList = `-- name: CreateWishList :one
INSERT INTO wish_lists(profile_id, hidden, name, icon_name, color, color_grad)
VALUES (
(SELECT p.id FROM profiles AS p
JOIN users AS u ON u.id = p.user_id
WHERE u.username = $1::text),
$2::boolean,
$3::text,
$4::text,
$5::text,
$6::boolean
)
RETURNING id, guid, profile_id, hidden, name, icon_name, color, color_grad, deleted
`
type CreateWishListParams struct {
Username string
Hidden bool
Name string
IconName string
Color string
ColorGrad bool
}
func (q *Queries) CreateWishList(ctx context.Context, arg CreateWishListParams) (WishList, error) {
row := q.db.QueryRow(ctx, createWishList,
arg.Username,
arg.Hidden,
arg.Name,
arg.IconName,
arg.Color,
arg.ColorGrad,
)
var i WishList
err := row.Scan(
&i.ID,
&i.Guid,
&i.ProfileID,
&i.Hidden,
&i.Name,
&i.IconName,
&i.Color,
&i.ColorGrad,
&i.Deleted,
)
return i, err
}
const deleteUnverifiedAccountsHavingUsernameOrEmail = `-- name: DeleteUnverifiedAccountsHavingUsernameOrEmail :one
WITH deleted_rows AS (
DELETE FROM users
@@ -369,7 +417,9 @@ WHERE
AND NOT EXISTS (
SELECT 1
FROM banned_users
WHERE user_id = u.id
WHERE user_id = u.id AND
pardoned IS FALSE AND
(expires_at IS NULL OR expires_at < CURRENT_TIMESTAMP)
)
)
`
@@ -726,11 +776,11 @@ type GetValidConfirmationCodesByUsernameRow struct {
CodeType int32
CodeHash string
ExpiresAt pgtype.Timestamp
Used *bool
Deleted *bool
Used bool
Deleted bool
ID_2 int64
Username string
Verified *bool
Verified bool
RegistrationDate pgtype.Timestamp
Role int32
Deleted_2 *bool
@@ -777,12 +827,17 @@ SELECT
linfo.totp_encrypted
FROM users
JOIN login_informations AS linfo ON users.id = linfo.user_id
LEFT JOIN banned_users AS banned ON users.id = banned.user_id
WHERE
users.username = $1 AND
users.verified IS TRUE AND -- Verified
users.deleted IS FALSE AND -- Not deleted
banned.user_id IS NULL AND -- Not banned
NOT EXISTS (
SELECT 1
FROM banned_users
WHERE user_id = users.id AND
pardoned IS FALSE AND
(expires_at IS NULL OR expires_at < CURRENT_TIMESTAMP)
) AND -- Not banned
linfo.password_hash = crypt($2::text, linfo.password_hash)
`
@@ -794,7 +849,7 @@ type GetValidUserByLoginCredentialsParams struct {
type GetValidUserByLoginCredentialsRow struct {
ID int64
Username string
Verified *bool
Verified bool
RegistrationDate pgtype.Timestamp
Role int32
Deleted *bool
@@ -856,6 +911,108 @@ func (q *Queries) GetValidUserSessions(ctx context.Context, userID int64) ([]Ses
return items, nil
}
const getWishlistByGuid = `-- name: GetWishlistByGuid :one
SELECT id, guid, profile_id, hidden, name, icon_name, color, color_grad, deleted FROM wish_lists wl
WHERE wl.guid = ($1::text)::uuid
`
func (q *Queries) GetWishlistByGuid(ctx context.Context, guid string) (WishList, error) {
row := q.db.QueryRow(ctx, getWishlistByGuid, guid)
var i WishList
err := row.Scan(
&i.ID,
&i.Guid,
&i.ProfileID,
&i.Hidden,
&i.Name,
&i.IconName,
&i.Color,
&i.ColorGrad,
&i.Deleted,
)
return i, err
}
const getWishlistsByUsernameWithPrivacy = `-- name: GetWishlistsByUsernameWithPrivacy :many
SELECT
wl.id, wl.guid, wl.profile_id, wl.hidden, wl.name, wl.icon_name, wl.color, wl.color_grad, wl.deleted,
CASE
WHEN (ps.hide_profile_details OR ps.hide_for_unauthenticated) THEN FALSE
ELSE TRUE
END AS access_allowed
FROM
wish_lists wl
JOIN
profiles AS p ON wl.profile_id = p.id
JOIN
profile_settings AS ps ON ps.profile_id = p.id
JOIN
users AS u ON p.user_id = u.id
WHERE
wl.deleted IS FALSE AND
u.username = $1::text AND
(
u.username = $2::text OR
(u.verified IS TRUE AND
NOT EXISTS (
SELECT 1
FROM banned_users
WHERE user_id = u.id AND
pardoned IS FALSE AND
(expires_at IS NULL OR expires_at < CURRENT_TIMESTAMP)
))
)
`
type GetWishlistsByUsernameWithPrivacyParams struct {
Username string
Requester string
}
type GetWishlistsByUsernameWithPrivacyRow struct {
ID int64
Guid pgtype.UUID
ProfileID int64
Hidden bool
Name string
IconName *string
Color *string
ColorGrad *string
Deleted bool
AccessAllowed bool
}
func (q *Queries) GetWishlistsByUsernameWithPrivacy(ctx context.Context, arg GetWishlistsByUsernameWithPrivacyParams) ([]GetWishlistsByUsernameWithPrivacyRow, error) {
rows, err := q.db.Query(ctx, getWishlistsByUsernameWithPrivacy, arg.Username, arg.Requester)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetWishlistsByUsernameWithPrivacyRow
for rows.Next() {
var i GetWishlistsByUsernameWithPrivacyRow
if err := rows.Scan(
&i.ID,
&i.Guid,
&i.ProfileID,
&i.Hidden,
&i.Name,
&i.IconName,
&i.Color,
&i.ColorGrad,
&i.Deleted,
&i.AccessAllowed,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const pruneExpiredConfirmationCodes = `-- name: PruneExpiredConfirmationCodes :exec
DELETE FROM confirmation_codes
WHERE expires_at < CURRENT_TIMESTAMP
@@ -920,7 +1077,7 @@ type UpdateBannedUserParams struct {
Reason *string
ExpiresAt pgtype.Timestamp
BannedBy *string
Pardoned *bool
Pardoned bool
PardonedBy *string
}
@@ -946,8 +1103,8 @@ WHERE id = $1
type UpdateConfirmationCodeParams struct {
ID int64
Used *bool
Deleted *bool
Used bool
Deleted bool
}
func (q *Queries) UpdateConfirmationCode(ctx context.Context, arg UpdateConfirmationCodeParams) error {
@@ -1112,7 +1269,7 @@ WHERE id = $1
type UpdateUserParams struct {
ID int64
Verified *bool
Verified bool
Deleted *bool
}
@@ -1129,7 +1286,7 @@ WHERE username = $1
type UpdateUserByUsernameParams struct {
Username string
Verified *bool
Verified bool
Deleted *bool
}
@@ -1137,3 +1294,76 @@ func (q *Queries) UpdateUserByUsername(ctx context.Context, arg UpdateUserByUser
_, err := q.db.Exec(ctx, updateUserByUsername, arg.Username, arg.Verified, arg.Deleted)
return err
}
const updateWishByGuid = `-- name: UpdateWishByGuid :exec
UPDATE wishes w
SET
name = COALESCE($1::text, w.name),
description = COALESCE($2::text, w.description),
picture_url = COALESCE($3::text, w.picture_url),
stars = COALESCE($4::smallint, w.stars),
fulfilled = COALESCE($5::boolean, w.fulfilled),
fulfilled_date = COALESCE($6::timestamp, w.fulfilled_date),
deleted = COALESCE($7::boolean, w.deleted)
WHERE w.guid = ($8::text)::uuid
`
type UpdateWishByGuidParams struct {
Name string
Description string
PictureUrl string
Stars int16
Fulfilled bool
FulfilledDate pgtype.Timestamp
Deleted bool
Guid string
}
func (q *Queries) UpdateWishByGuid(ctx context.Context, arg UpdateWishByGuidParams) error {
_, err := q.db.Exec(ctx, updateWishByGuid,
arg.Name,
arg.Description,
arg.PictureUrl,
arg.Stars,
arg.Fulfilled,
arg.FulfilledDate,
arg.Deleted,
arg.Guid,
)
return err
}
const updateWishListByGuid = `-- name: UpdateWishListByGuid :exec
UPDATE wish_lists wl
SET
hidden = COALESCE($1::boolean, wl.hidden),
name = COALESCE($2::text, wl.name),
icon_name = COALESCE($3::text, wl.icon_name),
color = COALESCE($4::text, wl.color),
color_grad = COALESCE($5::text, wl.color_grad),
deleted = COALESCE($6::boolean, wl.deleted)
WHERE wl.guid = ($7::text)::uuid
`
type UpdateWishListByGuidParams struct {
Hidden bool
Name string
IconName string
Color string
ColorGrad string
Deleted bool
Guid string
}
func (q *Queries) UpdateWishListByGuid(ctx context.Context, arg UpdateWishListByGuidParams) error {
_, err := q.db.Exec(ctx, updateWishListByGuid,
arg.Hidden,
arg.Name,
arg.IconName,
arg.Color,
arg.ColorGrad,
arg.Deleted,
arg.Guid,
)
return err
}

View File

@@ -422,7 +422,7 @@ func (a *authServiceImpl) RegistrationComplete(cinfo dto.ClientInfo, request mod
err = db.TXQueries.UpdateConfirmationCode(db.CTX, database.UpdateConfirmationCodeParams{
ID: confirmationCode.ID,
Used: utils.NewPointer(true),
Used: true,
})
if err != nil {
@@ -436,7 +436,7 @@ func (a *authServiceImpl) RegistrationComplete(cinfo dto.ClientInfo, request mod
err = db.TXQueries.UpdateUser(db.CTX, database.UpdateUserParams{
ID: user.ID,
Verified: utils.NewPointer(true),
Verified: true,
})
if err != nil {
@@ -880,7 +880,7 @@ func (a *authServiceImpl) PasswordResetComplete(request models.PasswordResetComp
if err = db.TXQueries.UpdateConfirmationCode(db.CTX, database.UpdateConfirmationCodeParams{
ID: resetCode.ID,
Used: utils.NewPointer(true),
Used: true,
}); err != nil {
a.log.Error(
"Failed to invalidate password reset code upon use",