feat: auth service logic for purging expired unverified accounts upon registration, new sql queries for this purpose
This commit is contained in:
@@ -11,6 +11,48 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const checkUserRegistrationAvailability = `-- name: CheckUserRegistrationAvailability :one
|
||||
SELECT
|
||||
COUNT(CASE WHEN users.username = $1::text THEN 1 END) > 0 AS username_busy,
|
||||
COUNT(CASE WHEN linfo.email = $2::text THEN 1 END) > 0 AS email_busy
|
||||
FROM users
|
||||
JOIN login_informations AS linfo ON linfo.user_id = users.id
|
||||
WHERE
|
||||
(
|
||||
users.username = $1::text OR
|
||||
linfo.email = $2::text
|
||||
)
|
||||
AND
|
||||
(
|
||||
users.verified IS TRUE OR
|
||||
NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM confirmation_codes AS codes
|
||||
WHERE codes.user_id = users.id
|
||||
AND codes.code_type = 0
|
||||
AND codes.deleted IS FALSE
|
||||
AND codes.expires_at > CURRENT_TIMESTAMP
|
||||
)
|
||||
)
|
||||
`
|
||||
|
||||
type CheckUserRegistrationAvailabilityParams struct {
|
||||
Username string
|
||||
Email string
|
||||
}
|
||||
|
||||
type CheckUserRegistrationAvailabilityRow struct {
|
||||
UsernameBusy bool
|
||||
EmailBusy bool
|
||||
}
|
||||
|
||||
func (q *Queries) CheckUserRegistrationAvailability(ctx context.Context, arg CheckUserRegistrationAvailabilityParams) (CheckUserRegistrationAvailabilityRow, error) {
|
||||
row := q.db.QueryRow(ctx, checkUserRegistrationAvailability, arg.Username, arg.Email)
|
||||
var i CheckUserRegistrationAvailabilityRow
|
||||
err := row.Scan(&i.UsernameBusy, &i.EmailBusy)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createBannedUser = `-- name: CreateBannedUser :one
|
||||
INSERT INTO banned_users(user_id, expires_at, reason, banned_by)
|
||||
VALUES ( $1, $2, $3, $4) RETURNING id, user_id, date, reason, expires_at, banned_by, pardoned, pardoned_by
|
||||
@@ -209,6 +251,35 @@ func (q *Queries) CreateUser(ctx context.Context, username string) (User, error)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteUnverifiedAccountsHavingUsernameOrEmail = `-- name: DeleteUnverifiedAccountsHavingUsernameOrEmail :one
|
||||
WITH deleted_rows AS (
|
||||
DELETE FROM users
|
||||
WHERE
|
||||
(username = $1::text OR
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM login_informations AS linfo
|
||||
WHERE linfo.user_id = users.id
|
||||
AND linfo.email = $2::text
|
||||
))
|
||||
AND verified IS FALSE
|
||||
RETURNING id, username, verified, registration_date, deleted
|
||||
)
|
||||
SELECT COUNT(*) AS deleted_count FROM deleted_rows
|
||||
`
|
||||
|
||||
type DeleteUnverifiedAccountsHavingUsernameOrEmailParams struct {
|
||||
Username string
|
||||
Email string
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteUnverifiedAccountsHavingUsernameOrEmail(ctx context.Context, arg DeleteUnverifiedAccountsHavingUsernameOrEmailParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, deleteUnverifiedAccountsHavingUsernameOrEmail, arg.Username, arg.Email)
|
||||
var deleted_count int64
|
||||
err := row.Scan(&deleted_count)
|
||||
return deleted_count, err
|
||||
}
|
||||
|
||||
const deleteUser = `-- name: DeleteUser :exec
|
||||
DELETE FROM users
|
||||
WHERE id = $1
|
||||
@@ -603,6 +674,69 @@ func (q *Queries) GetValidConfirmationCodeByCode(ctx context.Context, arg GetVal
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getValidConfirmationCodesByUsername = `-- name: GetValidConfirmationCodesByUsername :many
|
||||
SELECT confirmation_codes.id, user_id, code_type, code_hash, expires_at, used, confirmation_codes.deleted, users.id, username, verified, registration_date, users.deleted FROM confirmation_codes
|
||||
JOIN users on users.id = confirmation_codes.user_id
|
||||
WHERE
|
||||
users.username = $1::text AND
|
||||
code_type = $2::integer AND
|
||||
expires_at > CURRENT_TIMESTAMP AND
|
||||
used IS FALSE
|
||||
`
|
||||
|
||||
type GetValidConfirmationCodesByUsernameParams struct {
|
||||
Username string
|
||||
CodeType int32
|
||||
}
|
||||
|
||||
type GetValidConfirmationCodesByUsernameRow struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
CodeType int32
|
||||
CodeHash string
|
||||
ExpiresAt pgtype.Timestamp
|
||||
Used *bool
|
||||
Deleted *bool
|
||||
ID_2 int64
|
||||
Username string
|
||||
Verified *bool
|
||||
RegistrationDate pgtype.Timestamp
|
||||
Deleted_2 *bool
|
||||
}
|
||||
|
||||
func (q *Queries) GetValidConfirmationCodesByUsername(ctx context.Context, arg GetValidConfirmationCodesByUsernameParams) ([]GetValidConfirmationCodesByUsernameRow, error) {
|
||||
rows, err := q.db.Query(ctx, getValidConfirmationCodesByUsername, arg.Username, arg.CodeType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetValidConfirmationCodesByUsernameRow
|
||||
for rows.Next() {
|
||||
var i GetValidConfirmationCodesByUsernameRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.CodeType,
|
||||
&i.CodeHash,
|
||||
&i.ExpiresAt,
|
||||
&i.Used,
|
||||
&i.Deleted,
|
||||
&i.ID_2,
|
||||
&i.Username,
|
||||
&i.Verified,
|
||||
&i.RegistrationDate,
|
||||
&i.Deleted_2,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getValidUserByLoginCredentials = `-- name: GetValidUserByLoginCredentials :one
|
||||
SELECT
|
||||
users.id,
|
||||
|
||||
Reference in New Issue
Block a user