data seed and authorization fixes

This commit is contained in:
Yared Yemane 2026-01-14 02:27:26 -08:00
parent 87e57ca548
commit 513927f48f
23 changed files with 787 additions and 831 deletions

View File

@ -5,7 +5,7 @@ INSERT INTO users (
id, id,
first_name, first_name,
last_name, last_name,
user_name, -- user_name,
email, email,
phone_number, phone_number,
role, role,
@ -22,7 +22,7 @@ VALUES
10, 10,
'Demo', 'Demo',
'Student', 'Student',
'demo_student', -- 'demo_student',
'student10@yimaru.com', 'student10@yimaru.com',
NULL, NULL,
'USER', 'USER',
@ -38,7 +38,7 @@ VALUES
11, 11,
'System', 'System',
'Admin', 'Admin',
'sys_admin', -- 'sys_admin',
'admin@yimaru.com', 'admin@yimaru.com',
'0911001100', '0911001100',
'ADMIN', 'ADMIN',
@ -54,7 +54,7 @@ VALUES
12, 12,
'Support', 'Support',
'Agent', 'Agent',
'support_agent', -- 'support_agent',
'support@yimaru.com', 'support@yimaru.com',
'0911223344', '0911223344',
'SUPPORT', 'SUPPORT',

View File

@ -1,64 +1,80 @@
-- ====================================================== -- ======================================================
-- Reset sequences for LMS tables -- Reset sequences for LMS tables (PostgreSQL)
-- ====================================================== -- ======================================================
-- users.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('users', 'id'), pg_get_serial_sequence('users', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM users), 1),
) true
FROM users; );
-- assessment_questions.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('courses', 'id'), pg_get_serial_sequence('assessment_questions', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM assessment_questions), 1),
) true
FROM courses; );
-- assessment_question_options.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('course_modules', 'id'), pg_get_serial_sequence('assessment_question_options', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM assessment_question_options), 1),
) true
FROM course_modules; );
-- assessment_short_answers.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('lessons', 'id'), pg_get_serial_sequence('assessment_short_answers', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM assessment_short_answers), 1),
) true
FROM lessons; );
-- assessment_attempts.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('enrollments', 'id'), pg_get_serial_sequence('assessment_attempts', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM assessment_attempts), 1),
) true
FROM enrollments; );
-- assessment_attempt_questions.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('assessments', 'id'), pg_get_serial_sequence('assessment_attempt_questions', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM assessment_attempt_questions), 1),
) true
FROM assessments; );
-- assessment_attempt_answers.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('assessment_submissions', 'id'), pg_get_serial_sequence('assessment_attempt_answers', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM assessment_attempt_answers), 1),
) true
FROM assessment_submissions; );
-- refresh_tokens.id (BIGSERIAL)
SELECT setval(
pg_get_serial_sequence('refresh_tokens', 'id'),
COALESCE((SELECT MAX(id) FROM refresh_tokens), 1),
true
);
-- otps.id (BIGSERIAL)
SELECT setval(
pg_get_serial_sequence('otps', 'id'),
COALESCE((SELECT MAX(id) FROM otps), 1),
true
);
-- notifications.id (BIGSERIAL)
SELECT setval( SELECT setval(
pg_get_serial_sequence('notifications', 'id'), pg_get_serial_sequence('notifications', 'id'),
COALESCE(MAX(id), 1) COALESCE((SELECT MAX(id) FROM notifications), 1),
) true
FROM notifications; );
-- SELECT setval( -- reported_issues.id (BIGSERIAL)
-- pg_get_serial_sequence('referral_codes', 'id'), SELECT setval(
-- COALESCE(MAX(id), 1) pg_get_serial_sequence('reported_issues', 'id'),
-- ) COALESCE((SELECT MAX(id) FROM reported_issues), 1),
-- FROM referral_codes; true
);
-- SELECT setval(
-- pg_get_serial_sequence('user_referrals', 'id'),
-- COALESCE(MAX(id), 1)
-- )
-- FROM user_referrals;

View File

@ -1,10 +1,13 @@
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
first_name VARCHAR(255) NOT NULL, first_name VARCHAR(255),
last_name VARCHAR(255) NOT NULL, last_name VARCHAR(255),
user_name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE, gender VARCHAR(255),
phone_number VARCHAR(20) UNIQUE, birth_day DATE,
email VARCHAR(255),
phone_number VARCHAR(20),
role VARCHAR(50) NOT NULL, -- SUPER_ADMIN, INSTRUCTOR, STUDENT, SUPPORT role VARCHAR(50) NOT NULL, -- SUPER_ADMIN, INSTRUCTOR, STUDENT, SUPPORT
password BYTEA NOT NULL, password BYTEA NOT NULL,
@ -19,20 +22,22 @@ CREATE TABLE IF NOT EXISTS users (
learning_goal TEXT, learning_goal TEXT,
language_goal TEXT, language_goal TEXT,
language_challange TEXT, language_challange TEXT,
favoutite_topic TEXT, favourite_topic TEXT,
initial_assessment_completed BOOLEAN NOT NULL DEFAULT FALSE, initial_assessment_completed BOOLEAN NOT NULL DEFAULT FALSE,
email_verified BOOLEAN NOT NULL DEFAULT FALSE, email_verified BOOLEAN NOT NULL DEFAULT FALSE,
phone_verified BOOLEAN NOT NULL DEFAULT FALSE, phone_verified BOOLEAN NOT NULL DEFAULT FALSE,
status VARCHAR(50) NOT NULL, -- PENDING, ACTIVE, SUSPENDED, DEACTIVATED status VARCHAR(50) NOT NULL, -- PENDING, ACTIVE, SUSPENDED, DEACTIVATED
last_login TIMESTAMPTZ, last_login TIMESTAMPTZ,
profile_completed BOOLEAN NOT NULL DEFAULT FALSE, profile_completed BOOLEAN,
profile_picture_url TEXT, profile_picture_url TEXT,
preferred_language VARCHAR(50), preferred_language VARCHAR(50),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ, updated_at TIMESTAMPTZ,
-- Enforce: at least one contact method must be provided
CONSTRAINT users_email_or_phone_required
CHECK (email IS NOT NULL OR phone_number IS NOT NULL) CHECK (email IS NOT NULL OR phone_number IS NOT NULL)
); );
@ -167,7 +172,7 @@ CREATE TABLE refresh_tokens (
CREATE TABLE otps ( CREATE TABLE otps (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
user_name VARCHAR(100) NOT NULL, user_id BIGSERIAL NOT NULL,
sent_to VARCHAR(255) NOT NULL, sent_to VARCHAR(255) NOT NULL,
medium VARCHAR(50) NOT NULL, -- email, sms medium VARCHAR(50) NOT NULL, -- email, sms
otp_for VARCHAR(50) NOT NULL, -- register, reset otp_for VARCHAR(50) NOT NULL, -- register, reset

View File

@ -5,11 +5,11 @@ SET
used = FALSE, used = FALSE,
used_at = NULL, used_at = NULL,
expires_at = $3 expires_at = $3
WHERE user_name = $1; WHERE user_id = $1;
-- name: CreateOtp :exec -- name: CreateOtp :exec
INSERT INTO otps ( INSERT INTO otps (
user_name, user_id,
sent_to, sent_to,
medium, medium,
otp_for, otp_for,
@ -19,9 +19,9 @@ INSERT INTO otps (
VALUES ($1, $2, $3, $4, $5, $6); VALUES ($1, $2, $3, $4, $5, $6);
-- name: GetOtp :one -- name: GetOtp :one
SELECT id, user_name, sent_to, medium, otp_for, otp, used, used_at, created_at, expires_at SELECT id, user_id, sent_to, medium, otp_for, otp, used, used_at, created_at, expires_at
FROM otps FROM otps
WHERE user_name = $1 WHERE user_id = $1
ORDER BY created_at DESC LIMIT 1; ORDER BY created_at DESC LIMIT 1;
-- name: MarkOtpAsUsed :exec -- name: MarkOtpAsUsed :exec

View File

@ -2,7 +2,7 @@
SELECT SELECT
CASE WHEN status = 'PENDING' THEN true ELSE false END AS is_pending CASE WHEN status = 'PENDING' THEN true ELSE false END AS is_pending
FROM users FROM users
WHERE user_name = $1 WHERE id = $1
LIMIT 1; LIMIT 1;
-- name: IsProfileCompleted :one -- name: IsProfileCompleted :one
@ -16,14 +16,15 @@ LIMIT 1;
SELECT SELECT
CASE WHEN COUNT(*) = 0 THEN true ELSE false END AS is_unique CASE WHEN COUNT(*) = 0 THEN true ELSE false END AS is_unique
FROM users FROM users
WHERE user_name = $1; WHERE id = $1;
-- name: CreateUser :one -- name: CreateUser :one
INSERT INTO users ( INSERT INTO users (
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -38,7 +39,7 @@ INSERT INTO users (
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
email_verified, email_verified,
@ -52,37 +53,39 @@ INSERT INTO users (
VALUES ( VALUES (
$1, -- first_name $1, -- first_name
$2, -- last_name $2, -- last_name
$3, -- user_name $3, -- gender
$4, -- email $4, -- birth_day
$5, -- phone_number $5, -- email
$6, -- role $6, -- phone_number
$7, -- password $7, -- role
$8, -- age $8, -- password
$9, -- education_level $9, -- age
$10, -- country $10, -- education_level
$11, -- region $11, -- country
$12, -- region
$12, -- nick_name $13, -- nick_name
$13, -- occupation $14, -- occupation
$14, -- learning_goal $15, -- learning_goal
$15, -- language_goal $16, -- language_goal
$16, -- language_challange $17, -- language_challange
$17, -- favoutite_topic $18, -- favourite_topic
$18, -- initial_assessment_completed $19, -- initial_assessment_completed
$19, -- email_verified $20, -- email_verified
$20, -- phone_verified $21, -- phone_verified
$21, -- status $22, -- status
$22, -- profile_completed $23, -- profile_completed
$23, -- profile_picture_url $24, -- profile_picture_url
$24, -- preferred_language $25, -- preferred_language
CURRENT_TIMESTAMP CURRENT_TIMESTAMP
) )
RETURNING RETURNING
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -96,7 +99,7 @@ RETURNING
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
email_verified, email_verified,
@ -119,7 +122,8 @@ SELECT
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -132,7 +136,7 @@ SELECT
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
profile_picture_url, profile_picture_url,
preferred_language, preferred_language,
@ -163,7 +167,8 @@ SELECT
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -177,7 +182,7 @@ SELECT
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
profile_picture_url, profile_picture_url,
@ -205,27 +210,32 @@ UPDATE users
SET SET
first_name = COALESCE($1, first_name), first_name = COALESCE($1, first_name),
last_name = COALESCE($2, last_name), last_name = COALESCE($2, last_name),
user_name = COALESCE($3, user_name),
knowledge_level = COALESCE($4, knowledge_level), -- email = COALESCE($3, email),
age = COALESCE($5, age), -- phone_number = COALESCE($4, phone_number),
education_level = COALESCE($6, education_level),
country = COALESCE($7, country), knowledge_level = COALESCE($3, knowledge_level),
region = COALESCE($8, region), age = COALESCE($4, age),
nick_name = COALESCE($9, nick_name), education_level = COALESCE($5, education_level),
occupation = COALESCE($10, occupation), country = COALESCE($6, country),
learning_goal = COALESCE($11, learning_goal), region = COALESCE($7, region),
language_goal = COALESCE($12, language_goal), nick_name = COALESCE($8, nick_name),
language_challange = COALESCE($13, language_challange), occupation = COALESCE($9, occupation),
favoutite_topic = COALESCE($14, favoutite_topic), learning_goal = COALESCE($10, learning_goal),
initial_assessment_completed = COALESCE($15, initial_assessment_completed), language_goal = COALESCE($11, language_goal),
email_verified = COALESCE($16, email_verified), language_challange = COALESCE($12, language_challange),
phone_verified = COALESCE($17, phone_verified), favourite_topic = COALESCE($13, favourite_topic),
status = COALESCE($18, status), initial_assessment_completed = COALESCE($14, initial_assessment_completed),
profile_completed = COALESCE($19, profile_completed), -- email_verified = COALESCE($15, email_verified),
profile_picture_url = COALESCE($20, profile_picture_url), -- phone_verified = COALESCE($16, phone_verified),
preferred_language = COALESCE($21, preferred_language), -- status = COALESCE($19, status),
profile_completed = COALESCE($15, profile_completed),
profile_picture_url = COALESCE($16, profile_picture_url),
preferred_language = COALESCE($17, preferred_language),
gender = COALESCE($18, gender),
birth_day = COALESCE($19, gender),
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE id = $22; WHERE id = $20;
-- name: DeleteUser :exec -- name: DeleteUser :exec
DELETE FROM users DELETE FROM users
@ -240,47 +250,47 @@ SELECT
SELECT 1 FROM users u2 WHERE u2.email = $2 SELECT 1 FROM users u2 WHERE u2.email = $2
) AS email_exists; ) AS email_exists;
-- name: GetUserByUserName :one -- -- name: GetUserByUserName :one
SELECT -- SELECT
id, -- id,
first_name, -- first_name,
last_name, -- last_name,
user_name, -- email,
email, -- phone_number,
phone_number, -- role,
role, -- password,
password, -- age,
age, -- education_level,
education_level, -- country,
country, -- region,
region,
nick_name, -- nick_name,
occupation, -- occupation,
learning_goal, -- learning_goal,
language_goal, -- language_goal,
language_challange, -- language_challange,
favoutite_topic, -- favourite_topic,
email_verified, -- email_verified,
phone_verified, -- phone_verified,
status, -- status,
profile_completed, -- profile_completed,
last_login, -- last_login,
profile_picture_url, -- profile_picture_url,
preferred_language, -- preferred_language,
created_at, -- created_at,
updated_at -- updated_at
FROM users -- FROM users
WHERE user_name = $1 AND $1 IS NOT NULL -- WHERE user_name = $1 AND $1 IS NOT NULL
LIMIT 1; -- LIMIT 1;
-- name: GetUserByEmailPhone :one -- name: GetUserByEmailPhone :one
SELECT SELECT
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -295,7 +305,7 @@ SELECT
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
email_verified, email_verified,
phone_verified, phone_verified,
@ -316,7 +326,7 @@ UPDATE users
SET SET
password = $1, password = $1,
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE user_name = $2; WHERE id = $2;
-- name: UpdateUserStatus :exec -- name: UpdateUserStatus :exec
UPDATE users UPDATE users

View File

@ -146,7 +146,7 @@ type Notification struct {
type Otp struct { type Otp struct {
ID int64 `json:"id"` ID int64 `json:"id"`
UserName string `json:"user_name"` UserID int64 `json:"user_id"`
SentTo string `json:"sent_to"` SentTo string `json:"sent_to"`
Medium string `json:"medium"` Medium string `json:"medium"`
OtpFor string `json:"otp_for"` OtpFor string `json:"otp_for"`
@ -213,9 +213,10 @@ type ReportedIssue struct {
type User struct { type User struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"` Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
@ -230,13 +231,13 @@ type User struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"` InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"` Status string `json:"status"`
LastLogin pgtype.Timestamptz `json:"last_login"` LastLogin pgtype.Timestamptz `json:"last_login"`
ProfileCompleted bool `json:"profile_completed"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
CreatedAt pgtype.Timestamptz `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`

View File

@ -13,7 +13,7 @@ import (
const CreateOtp = `-- name: CreateOtp :exec const CreateOtp = `-- name: CreateOtp :exec
INSERT INTO otps ( INSERT INTO otps (
user_name, user_id,
sent_to, sent_to,
medium, medium,
otp_for, otp_for,
@ -24,7 +24,7 @@ VALUES ($1, $2, $3, $4, $5, $6)
` `
type CreateOtpParams struct { type CreateOtpParams struct {
UserName string `json:"user_name"` UserID int64 `json:"user_id"`
SentTo string `json:"sent_to"` SentTo string `json:"sent_to"`
Medium string `json:"medium"` Medium string `json:"medium"`
OtpFor string `json:"otp_for"` OtpFor string `json:"otp_for"`
@ -34,7 +34,7 @@ type CreateOtpParams struct {
func (q *Queries) CreateOtp(ctx context.Context, arg CreateOtpParams) error { func (q *Queries) CreateOtp(ctx context.Context, arg CreateOtpParams) error {
_, err := q.db.Exec(ctx, CreateOtp, _, err := q.db.Exec(ctx, CreateOtp,
arg.UserName, arg.UserID,
arg.SentTo, arg.SentTo,
arg.Medium, arg.Medium,
arg.OtpFor, arg.OtpFor,
@ -45,15 +45,15 @@ func (q *Queries) CreateOtp(ctx context.Context, arg CreateOtpParams) error {
} }
const GetOtp = `-- name: GetOtp :one const GetOtp = `-- name: GetOtp :one
SELECT id, user_name, sent_to, medium, otp_for, otp, used, used_at, created_at, expires_at SELECT id, user_id, sent_to, medium, otp_for, otp, used, used_at, created_at, expires_at
FROM otps FROM otps
WHERE user_name = $1 WHERE user_id = $1
ORDER BY created_at DESC LIMIT 1 ORDER BY created_at DESC LIMIT 1
` `
type GetOtpRow struct { type GetOtpRow struct {
ID int64 `json:"id"` ID int64 `json:"id"`
UserName string `json:"user_name"` UserID int64 `json:"user_id"`
SentTo string `json:"sent_to"` SentTo string `json:"sent_to"`
Medium string `json:"medium"` Medium string `json:"medium"`
OtpFor string `json:"otp_for"` OtpFor string `json:"otp_for"`
@ -64,12 +64,12 @@ type GetOtpRow struct {
ExpiresAt pgtype.Timestamptz `json:"expires_at"` ExpiresAt pgtype.Timestamptz `json:"expires_at"`
} }
func (q *Queries) GetOtp(ctx context.Context, userName string) (GetOtpRow, error) { func (q *Queries) GetOtp(ctx context.Context, userID int64) (GetOtpRow, error) {
row := q.db.QueryRow(ctx, GetOtp, userName) row := q.db.QueryRow(ctx, GetOtp, userID)
var i GetOtpRow var i GetOtpRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.UserName, &i.UserID,
&i.SentTo, &i.SentTo,
&i.Medium, &i.Medium,
&i.OtpFor, &i.OtpFor,
@ -105,16 +105,16 @@ SET
used = FALSE, used = FALSE,
used_at = NULL, used_at = NULL,
expires_at = $3 expires_at = $3
WHERE user_name = $1 WHERE user_id = $1
` `
type UpdateExpiredOtpParams struct { type UpdateExpiredOtpParams struct {
UserName string `json:"user_name"` UserID int64 `json:"user_id"`
Otp string `json:"otp"` Otp string `json:"otp"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"` ExpiresAt pgtype.Timestamptz `json:"expires_at"`
} }
func (q *Queries) UpdateExpiredOtp(ctx context.Context, arg UpdateExpiredOtpParams) error { func (q *Queries) UpdateExpiredOtp(ctx context.Context, arg UpdateExpiredOtpParams) error {
_, err := q.db.Exec(ctx, UpdateExpiredOtp, arg.UserName, arg.Otp, arg.ExpiresAt) _, err := q.db.Exec(ctx, UpdateExpiredOtp, arg.UserID, arg.Otp, arg.ExpiresAt)
return err return err
} }

View File

@ -42,7 +42,8 @@ const CreateUser = `-- name: CreateUser :one
INSERT INTO users ( INSERT INTO users (
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -57,7 +58,7 @@ INSERT INTO users (
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
email_verified, email_verified,
@ -71,37 +72,39 @@ INSERT INTO users (
VALUES ( VALUES (
$1, -- first_name $1, -- first_name
$2, -- last_name $2, -- last_name
$3, -- user_name $3, -- gender
$4, -- email $4, -- birth_day
$5, -- phone_number $5, -- email
$6, -- role $6, -- phone_number
$7, -- password $7, -- role
$8, -- age $8, -- password
$9, -- education_level $9, -- age
$10, -- country $10, -- education_level
$11, -- region $11, -- country
$12, -- region
$12, -- nick_name $13, -- nick_name
$13, -- occupation $14, -- occupation
$14, -- learning_goal $15, -- learning_goal
$15, -- language_goal $16, -- language_goal
$16, -- language_challange $17, -- language_challange
$17, -- favoutite_topic $18, -- favourite_topic
$18, -- initial_assessment_completed $19, -- initial_assessment_completed
$19, -- email_verified $20, -- email_verified
$20, -- phone_verified $21, -- phone_verified
$21, -- status $22, -- status
$22, -- profile_completed $23, -- profile_completed
$23, -- profile_picture_url $24, -- profile_picture_url
$24, -- preferred_language $25, -- preferred_language
CURRENT_TIMESTAMP CURRENT_TIMESTAMP
) )
RETURNING RETURNING
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -115,7 +118,7 @@ RETURNING
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
email_verified, email_verified,
@ -129,9 +132,10 @@ RETURNING
` `
type CreateUserParams struct { type CreateUserParams struct {
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"` Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
@ -145,21 +149,22 @@ type CreateUserParams struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"` InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"` Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
} }
type CreateUserRow struct { type CreateUserRow struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"` Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
@ -172,12 +177,12 @@ type CreateUserRow struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"` InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"` Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
CreatedAt pgtype.Timestamptz `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
@ -188,7 +193,8 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateU
row := q.db.QueryRow(ctx, CreateUser, row := q.db.QueryRow(ctx, CreateUser,
arg.FirstName, arg.FirstName,
arg.LastName, arg.LastName,
arg.UserName, arg.Gender,
arg.BirthDay,
arg.Email, arg.Email,
arg.PhoneNumber, arg.PhoneNumber,
arg.Role, arg.Role,
@ -202,7 +208,7 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateU
arg.LearningGoal, arg.LearningGoal,
arg.LanguageGoal, arg.LanguageGoal,
arg.LanguageChallange, arg.LanguageChallange,
arg.FavoutiteTopic, arg.FavouriteTopic,
arg.InitialAssessmentCompleted, arg.InitialAssessmentCompleted,
arg.EmailVerified, arg.EmailVerified,
arg.PhoneVerified, arg.PhoneVerified,
@ -216,7 +222,8 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateU
&i.ID, &i.ID,
&i.FirstName, &i.FirstName,
&i.LastName, &i.LastName,
&i.UserName, &i.Gender,
&i.BirthDay,
&i.Email, &i.Email,
&i.PhoneNumber, &i.PhoneNumber,
&i.Role, &i.Role,
@ -229,7 +236,7 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateU
&i.LearningGoal, &i.LearningGoal,
&i.LanguageGoal, &i.LanguageGoal,
&i.LanguageChallange, &i.LanguageChallange,
&i.FavoutiteTopic, &i.FavouriteTopic,
&i.InitialAssessmentCompleted, &i.InitialAssessmentCompleted,
&i.EmailVerified, &i.EmailVerified,
&i.PhoneVerified, &i.PhoneVerified,
@ -259,7 +266,8 @@ SELECT
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -272,7 +280,7 @@ SELECT
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
profile_picture_url, profile_picture_url,
preferred_language, preferred_language,
@ -306,9 +314,10 @@ type GetAllUsersParams struct {
type GetAllUsersRow struct { type GetAllUsersRow struct {
TotalCount int64 `json:"total_count"` TotalCount int64 `json:"total_count"`
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"` Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
@ -321,14 +330,14 @@ type GetAllUsersRow struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"` InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"` Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
CreatedAt pgtype.Timestamptz `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
} }
@ -354,7 +363,8 @@ func (q *Queries) GetAllUsers(ctx context.Context, arg GetAllUsersParams) ([]Get
&i.ID, &i.ID,
&i.FirstName, &i.FirstName,
&i.LastName, &i.LastName,
&i.UserName, &i.Gender,
&i.BirthDay,
&i.Email, &i.Email,
&i.PhoneNumber, &i.PhoneNumber,
&i.Role, &i.Role,
@ -367,7 +377,7 @@ func (q *Queries) GetAllUsers(ctx context.Context, arg GetAllUsersParams) ([]Get
&i.LearningGoal, &i.LearningGoal,
&i.LanguageGoal, &i.LanguageGoal,
&i.LanguageChallange, &i.LanguageChallange,
&i.FavoutiteTopic, &i.FavouriteTopic,
&i.InitialAssessmentCompleted, &i.InitialAssessmentCompleted,
&i.ProfilePictureUrl, &i.ProfilePictureUrl,
&i.PreferredLanguage, &i.PreferredLanguage,
@ -402,11 +412,15 @@ func (q *Queries) GetTotalUsers(ctx context.Context, role string) (int64, error)
} }
const GetUserByEmailPhone = `-- name: GetUserByEmailPhone :one const GetUserByEmailPhone = `-- name: GetUserByEmailPhone :one
SELECT SELECT
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -421,7 +435,7 @@ SELECT
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
email_verified, email_verified,
phone_verified, phone_verified,
@ -445,9 +459,10 @@ type GetUserByEmailPhoneParams struct {
type GetUserByEmailPhoneRow struct { type GetUserByEmailPhoneRow struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"` Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
@ -461,11 +476,11 @@ type GetUserByEmailPhoneRow struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"` Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
LastLogin pgtype.Timestamptz `json:"last_login"` LastLogin pgtype.Timestamptz `json:"last_login"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
@ -473,6 +488,39 @@ type GetUserByEmailPhoneRow struct {
UpdatedAt pgtype.Timestamptz `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
} }
// -- name: GetUserByUserName :one
// SELECT
//
// id,
// first_name,
// last_name,
// email,
// phone_number,
// role,
// password,
// age,
// education_level,
// country,
// region,
// nick_name,
// occupation,
// learning_goal,
// language_goal,
// language_challange,
// favourite_topic,
// email_verified,
// phone_verified,
// status,
// profile_completed,
// last_login,
// profile_picture_url,
// preferred_language,
// created_at,
// updated_at
//
// FROM users
// WHERE user_name = $1 AND $1 IS NOT NULL
// LIMIT 1;
func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPhoneParams) (GetUserByEmailPhoneRow, error) { func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPhoneParams) (GetUserByEmailPhoneRow, error) {
row := q.db.QueryRow(ctx, GetUserByEmailPhone, arg.Email, arg.PhoneNumber) row := q.db.QueryRow(ctx, GetUserByEmailPhone, arg.Email, arg.PhoneNumber)
var i GetUserByEmailPhoneRow var i GetUserByEmailPhoneRow
@ -480,7 +528,8 @@ func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPho
&i.ID, &i.ID,
&i.FirstName, &i.FirstName,
&i.LastName, &i.LastName,
&i.UserName, &i.Gender,
&i.BirthDay,
&i.Email, &i.Email,
&i.PhoneNumber, &i.PhoneNumber,
&i.Role, &i.Role,
@ -494,7 +543,7 @@ func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPho
&i.LearningGoal, &i.LearningGoal,
&i.LanguageGoal, &i.LanguageGoal,
&i.LanguageChallange, &i.LanguageChallange,
&i.FavoutiteTopic, &i.FavouriteTopic,
&i.EmailVerified, &i.EmailVerified,
&i.PhoneVerified, &i.PhoneVerified,
&i.Status, &i.Status,
@ -509,7 +558,7 @@ func (q *Queries) GetUserByEmailPhone(ctx context.Context, arg GetUserByEmailPho
} }
const GetUserByID = `-- name: GetUserByID :one const GetUserByID = `-- name: GetUserByID :one
SELECT id, first_name, last_name, user_name, email, phone_number, role, password, age, education_level, country, region, knowledge_level, nick_name, occupation, learning_goal, language_goal, language_challange, favoutite_topic, initial_assessment_completed, email_verified, phone_verified, status, last_login, profile_completed, profile_picture_url, preferred_language, created_at, updated_at SELECT id, first_name, last_name, gender, birth_day, email, phone_number, role, password, age, education_level, country, region, knowledge_level, nick_name, occupation, learning_goal, language_goal, language_challange, favourite_topic, initial_assessment_completed, email_verified, phone_verified, status, last_login, profile_completed, profile_picture_url, preferred_language, created_at, updated_at
FROM users FROM users
WHERE id = $1 WHERE id = $1
` `
@ -521,7 +570,8 @@ func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
&i.ID, &i.ID,
&i.FirstName, &i.FirstName,
&i.LastName, &i.LastName,
&i.UserName, &i.Gender,
&i.BirthDay,
&i.Email, &i.Email,
&i.PhoneNumber, &i.PhoneNumber,
&i.Role, &i.Role,
@ -536,7 +586,7 @@ func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
&i.LearningGoal, &i.LearningGoal,
&i.LanguageGoal, &i.LanguageGoal,
&i.LanguageChallange, &i.LanguageChallange,
&i.FavoutiteTopic, &i.FavouriteTopic,
&i.InitialAssessmentCompleted, &i.InitialAssessmentCompleted,
&i.EmailVerified, &i.EmailVerified,
&i.PhoneVerified, &i.PhoneVerified,
@ -551,107 +601,6 @@ func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
return i, err return i, err
} }
const GetUserByUserName = `-- name: GetUserByUserName :one
SELECT
id,
first_name,
last_name,
user_name,
email,
phone_number,
role,
password,
age,
education_level,
country,
region,
nick_name,
occupation,
learning_goal,
language_goal,
language_challange,
favoutite_topic,
email_verified,
phone_verified,
status,
profile_completed,
last_login,
profile_picture_url,
preferred_language,
created_at,
updated_at
FROM users
WHERE user_name = $1 AND $1 IS NOT NULL
LIMIT 1
`
type GetUserByUserNameRow struct {
ID int64 `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
UserName string `json:"user_name"`
Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"`
Password []byte `json:"password"`
Age pgtype.Int4 `json:"age"`
EducationLevel pgtype.Text `json:"education_level"`
Country pgtype.Text `json:"country"`
Region pgtype.Text `json:"region"`
NickName pgtype.Text `json:"nick_name"`
Occupation pgtype.Text `json:"occupation"`
LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"`
EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"`
LastLogin pgtype.Timestamptz `json:"last_login"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
func (q *Queries) GetUserByUserName(ctx context.Context, userName string) (GetUserByUserNameRow, error) {
row := q.db.QueryRow(ctx, GetUserByUserName, userName)
var i GetUserByUserNameRow
err := row.Scan(
&i.ID,
&i.FirstName,
&i.LastName,
&i.UserName,
&i.Email,
&i.PhoneNumber,
&i.Role,
&i.Password,
&i.Age,
&i.EducationLevel,
&i.Country,
&i.Region,
&i.NickName,
&i.Occupation,
&i.LearningGoal,
&i.LanguageGoal,
&i.LanguageChallange,
&i.FavoutiteTopic,
&i.EmailVerified,
&i.PhoneVerified,
&i.Status,
&i.ProfileCompleted,
&i.LastLogin,
&i.ProfilePictureUrl,
&i.PreferredLanguage,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const IsProfileCompleted = `-- name: IsProfileCompleted :one const IsProfileCompleted = `-- name: IsProfileCompleted :one
SELECT SELECT
CASE WHEN profile_completed = true THEN true ELSE false END AS is_pending CASE WHEN profile_completed = true THEN true ELSE false END AS is_pending
@ -671,11 +620,11 @@ const IsUserNameUnique = `-- name: IsUserNameUnique :one
SELECT SELECT
CASE WHEN COUNT(*) = 0 THEN true ELSE false END AS is_unique CASE WHEN COUNT(*) = 0 THEN true ELSE false END AS is_unique
FROM users FROM users
WHERE user_name = $1 WHERE id = $1
` `
func (q *Queries) IsUserNameUnique(ctx context.Context, userName string) (bool, error) { func (q *Queries) IsUserNameUnique(ctx context.Context, id int64) (bool, error) {
row := q.db.QueryRow(ctx, IsUserNameUnique, userName) row := q.db.QueryRow(ctx, IsUserNameUnique, id)
var is_unique bool var is_unique bool
err := row.Scan(&is_unique) err := row.Scan(&is_unique)
return is_unique, err return is_unique, err
@ -685,12 +634,12 @@ const IsUserPending = `-- name: IsUserPending :one
SELECT SELECT
CASE WHEN status = 'PENDING' THEN true ELSE false END AS is_pending CASE WHEN status = 'PENDING' THEN true ELSE false END AS is_pending
FROM users FROM users
WHERE user_name = $1 WHERE id = $1
LIMIT 1 LIMIT 1
` `
func (q *Queries) IsUserPending(ctx context.Context, userName string) (bool, error) { func (q *Queries) IsUserPending(ctx context.Context, id int64) (bool, error) {
row := q.db.QueryRow(ctx, IsUserPending, userName) row := q.db.QueryRow(ctx, IsUserPending, id)
var is_pending bool var is_pending bool
err := row.Scan(&is_pending) err := row.Scan(&is_pending)
return is_pending, err return is_pending, err
@ -701,7 +650,8 @@ SELECT
id, id,
first_name, first_name,
last_name, last_name,
user_name, gender,
birth_day,
email, email,
phone_number, phone_number,
role, role,
@ -715,7 +665,7 @@ SELECT
learning_goal, learning_goal,
language_goal, language_goal,
language_challange, language_challange,
favoutite_topic, favourite_topic,
initial_assessment_completed, initial_assessment_completed,
profile_picture_url, profile_picture_url,
@ -746,9 +696,10 @@ type SearchUserByNameOrPhoneParams struct {
type SearchUserByNameOrPhoneRow struct { type SearchUserByNameOrPhoneRow struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"` Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
Email pgtype.Text `json:"email"` Email pgtype.Text `json:"email"`
PhoneNumber pgtype.Text `json:"phone_number"` PhoneNumber pgtype.Text `json:"phone_number"`
Role string `json:"role"` Role string `json:"role"`
@ -761,14 +712,14 @@ type SearchUserByNameOrPhoneRow struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"` InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"` Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
CreatedAt pgtype.Timestamptz `json:"created_at"` CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"`
} }
@ -786,7 +737,8 @@ func (q *Queries) SearchUserByNameOrPhone(ctx context.Context, arg SearchUserByN
&i.ID, &i.ID,
&i.FirstName, &i.FirstName,
&i.LastName, &i.LastName,
&i.UserName, &i.Gender,
&i.BirthDay,
&i.Email, &i.Email,
&i.PhoneNumber, &i.PhoneNumber,
&i.Role, &i.Role,
@ -799,7 +751,7 @@ func (q *Queries) SearchUserByNameOrPhone(ctx context.Context, arg SearchUserByN
&i.LearningGoal, &i.LearningGoal,
&i.LanguageGoal, &i.LanguageGoal,
&i.LanguageChallange, &i.LanguageChallange,
&i.FavoutiteTopic, &i.FavouriteTopic,
&i.InitialAssessmentCompleted, &i.InitialAssessmentCompleted,
&i.ProfilePictureUrl, &i.ProfilePictureUrl,
&i.PreferredLanguage, &i.PreferredLanguage,
@ -825,16 +777,16 @@ UPDATE users
SET SET
password = $1, password = $1,
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE user_name = $2 WHERE id = $2
` `
type UpdatePasswordParams struct { type UpdatePasswordParams struct {
Password []byte `json:"password"` Password []byte `json:"password"`
UserName string `json:"user_name"` ID int64 `json:"id"`
} }
func (q *Queries) UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error { func (q *Queries) UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error {
_, err := q.db.Exec(ctx, UpdatePassword, arg.Password, arg.UserName) _, err := q.db.Exec(ctx, UpdatePassword, arg.Password, arg.ID)
return err return err
} }
@ -843,33 +795,37 @@ UPDATE users
SET SET
first_name = COALESCE($1, first_name), first_name = COALESCE($1, first_name),
last_name = COALESCE($2, last_name), last_name = COALESCE($2, last_name),
user_name = COALESCE($3, user_name),
knowledge_level = COALESCE($4, knowledge_level), -- email = COALESCE($3, email),
age = COALESCE($5, age), -- phone_number = COALESCE($4, phone_number),
education_level = COALESCE($6, education_level),
country = COALESCE($7, country), knowledge_level = COALESCE($3, knowledge_level),
region = COALESCE($8, region), age = COALESCE($4, age),
nick_name = COALESCE($9, nick_name), education_level = COALESCE($5, education_level),
occupation = COALESCE($10, occupation), country = COALESCE($6, country),
learning_goal = COALESCE($11, learning_goal), region = COALESCE($7, region),
language_goal = COALESCE($12, language_goal), nick_name = COALESCE($8, nick_name),
language_challange = COALESCE($13, language_challange), occupation = COALESCE($9, occupation),
favoutite_topic = COALESCE($14, favoutite_topic), learning_goal = COALESCE($10, learning_goal),
initial_assessment_completed = COALESCE($15, initial_assessment_completed), language_goal = COALESCE($11, language_goal),
email_verified = COALESCE($16, email_verified), language_challange = COALESCE($12, language_challange),
phone_verified = COALESCE($17, phone_verified), favourite_topic = COALESCE($13, favourite_topic),
status = COALESCE($18, status), initial_assessment_completed = COALESCE($14, initial_assessment_completed),
profile_completed = COALESCE($19, profile_completed), -- email_verified = COALESCE($15, email_verified),
profile_picture_url = COALESCE($20, profile_picture_url), -- phone_verified = COALESCE($16, phone_verified),
preferred_language = COALESCE($21, preferred_language), -- status = COALESCE($19, status),
profile_completed = COALESCE($15, profile_completed),
profile_picture_url = COALESCE($16, profile_picture_url),
preferred_language = COALESCE($17, preferred_language),
gender = COALESCE($18, gender),
birth_day = COALESCE($19, gender),
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE id = $22 WHERE id = $20
` `
type UpdateUserParams struct { type UpdateUserParams struct {
FirstName string `json:"first_name"` FirstName pgtype.Text `json:"first_name"`
LastName string `json:"last_name"` LastName pgtype.Text `json:"last_name"`
UserName string `json:"user_name"`
KnowledgeLevel pgtype.Text `json:"knowledge_level"` KnowledgeLevel pgtype.Text `json:"knowledge_level"`
Age pgtype.Int4 `json:"age"` Age pgtype.Int4 `json:"age"`
EducationLevel pgtype.Text `json:"education_level"` EducationLevel pgtype.Text `json:"education_level"`
@ -880,14 +836,13 @@ type UpdateUserParams struct {
LearningGoal pgtype.Text `json:"learning_goal"` LearningGoal pgtype.Text `json:"learning_goal"`
LanguageGoal pgtype.Text `json:"language_goal"` LanguageGoal pgtype.Text `json:"language_goal"`
LanguageChallange pgtype.Text `json:"language_challange"` LanguageChallange pgtype.Text `json:"language_challange"`
FavoutiteTopic pgtype.Text `json:"favoutite_topic"` FavouriteTopic pgtype.Text `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"` InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
EmailVerified bool `json:"email_verified"` ProfileCompleted pgtype.Bool `json:"profile_completed"`
PhoneVerified bool `json:"phone_verified"`
Status string `json:"status"`
ProfileCompleted bool `json:"profile_completed"`
ProfilePictureUrl pgtype.Text `json:"profile_picture_url"` ProfilePictureUrl pgtype.Text `json:"profile_picture_url"`
PreferredLanguage pgtype.Text `json:"preferred_language"` PreferredLanguage pgtype.Text `json:"preferred_language"`
Gender pgtype.Text `json:"gender"`
BirthDay pgtype.Date `json:"birth_day"`
ID int64 `json:"id"` ID int64 `json:"id"`
} }
@ -895,7 +850,6 @@ func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) error {
_, err := q.db.Exec(ctx, UpdateUser, _, err := q.db.Exec(ctx, UpdateUser,
arg.FirstName, arg.FirstName,
arg.LastName, arg.LastName,
arg.UserName,
arg.KnowledgeLevel, arg.KnowledgeLevel,
arg.Age, arg.Age,
arg.EducationLevel, arg.EducationLevel,
@ -906,14 +860,13 @@ func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) error {
arg.LearningGoal, arg.LearningGoal,
arg.LanguageGoal, arg.LanguageGoal,
arg.LanguageChallange, arg.LanguageChallange,
arg.FavoutiteTopic, arg.FavouriteTopic,
arg.InitialAssessmentCompleted, arg.InitialAssessmentCompleted,
arg.EmailVerified,
arg.PhoneVerified,
arg.Status,
arg.ProfileCompleted, arg.ProfileCompleted,
arg.ProfilePictureUrl, arg.ProfilePictureUrl,
arg.PreferredLanguage, arg.PreferredLanguage,
arg.Gender,
arg.BirthDay,
arg.ID, arg.ID,
) )
return err return err

View File

@ -28,7 +28,7 @@ const (
type Otp struct { type Otp struct {
ID int64 ID int64
UserName string UserID int64
SentTo string SentTo string
Medium OtpMedium Medium OtpMedium
For OtpFor For OtpFor

View File

@ -34,7 +34,9 @@ type User struct {
ID int64 ID int64
FirstName string FirstName string
LastName string LastName string
UserName string Gender string
BirthDay time.Time `json:"birth_day"`
// UserName string
Email string Email string
PhoneNumber string PhoneNumber string
Password []byte Password []byte
@ -47,13 +49,13 @@ type User struct {
// Profile fields // Profile fields
KnowledgeLevel string KnowledgeLevel string
initial_assessment_completed bool InitialAssessmentCompleted bool
NickName string NickName string
Occupation string Occupation string
LearningGoal string LearningGoal string
LanguageGoal string LanguageGoal string
LanguageChallange string LanguageChallange string
FavoutiteTopic string FavouriteTopic string
EmailVerified bool EmailVerified bool
PhoneVerified bool PhoneVerified bool
@ -72,7 +74,9 @@ type UserProfileResponse struct {
ID int64 `json:"id"` ID int64 `json:"id"`
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
UserName string `json:"user_name,omitempty"` Gender string `json:"gender"`
BirthDay time.Time `json:"birth_day"`
// UserName string `json:"user_name,omitempty"`
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"` PhoneNumber string `json:"phone_number,omitempty"`
Role Role `json:"role"` Role Role `json:"role"`
@ -89,7 +93,7 @@ type UserProfileResponse struct {
LearningGoal string `json:"learning_goal,omitempty"` LearningGoal string `json:"learning_goal,omitempty"`
LanguageGoal string `json:"language_goal,omitempty"` LanguageGoal string `json:"language_goal,omitempty"`
LanguageChallange string `json:"language_challange,omitempty"` LanguageChallange string `json:"language_challange,omitempty"`
FavoutiteTopic string `json:"favoutite_topic,omitempty"` FavouriteTopic string `json:"favoutite_topic,omitempty"`
EmailVerified bool `json:"email_verified"` EmailVerified bool `json:"email_verified"`
PhoneVerified bool `json:"phone_verified"` PhoneVerified bool `json:"phone_verified"`
@ -107,42 +111,26 @@ type UserProfileResponse struct {
type UserFilter struct { type UserFilter struct {
Role string Role string
Page ValidInt Page int64
PageSize ValidInt PageSize int64
Query ValidString Query string
CreatedBefore ValidTime CreatedBefore ValidTime
CreatedAfter ValidTime CreatedAfter ValidTime
} }
type RegisterUserReq struct { type RegisterUserReq struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
UserName string `json:"user_name"`
Email string `json:"email"` Email string `json:"email"`
PhoneNumber string `json:"phone_number"` PhoneNumber string `json:"phone_number"`
Password string `json:"password"` Password string `json:"password"`
Role string `json:"role"` Role string `json:"role"`
OtpMedium OtpMedium `json:"otp_medium"` OtpMedium OtpMedium `json:"otp_medium"`
// NickName string `json:"nick_name,omitempty"`
// Occupation string `json:"occupation,omitempty"`
// LearningGoal string `json:"learning_goal,omitempty"`
// LanguageGoal string `json:"language_goal,omitempty"`
// LanguageChallange string `json:"language_challange,omitempty"`
// FavoutiteTopic string `json:"favoutite_topic,omitempty"`
// Age int `json:"age,omitempty"`
// EducationLevel string `json:"education_level,omitempty"`
// Country string `json:"country,omitempty"`
// Region string `json:"region,omitempty"`
// PreferredLanguage string `json:"preferred_language,omitempty"`
} }
type CreateUserReq struct { type CreateUserReq struct {
FirstName string FirstName string
LastName string LastName string
UserName string Gender string `json:"gender"`
BirthDay time.Time `json:"birth_day"`
Email string Email string
PhoneNumber string PhoneNumber string
Password string Password string
@ -161,40 +149,58 @@ type CreateUserReq struct {
LearningGoal string LearningGoal string
LanguageGoal string LanguageGoal string
LanguageChallange string LanguageChallange string
FavoutiteTopic string FavouriteTopic string
PreferredLanguage string PreferredLanguage string
} }
type ResetPasswordReq struct { type ResetPasswordReq struct {
UserName string UserID int64
Password string Password string
OtpCode string OtpCode string
} }
type UpdateUserReq struct {
type UpdateUserStatusReq struct {
Status string
UserID int64 UserID int64
}
FirstName ValidString
LastName ValidString type UpdateUserReq struct {
UserName ValidString // Identity (enforced from auth context, not request body)
UserID int64 `json:"-"`
Status ValidString
// Basic profile
Age ValidInt FirstName string `json:"first_name"`
EducationLevel ValidString LastName string `json:"last_name"`
Country ValidString
Region ValidString Gender string `json:"gender"`
BirthDay time.Time `json:"birth_day"`
// Profile fields
KnowledgeLevel ValidString // Contact (optional at least one must exist at DB level)
NickName ValidString // Email string `json:"email"`
Occupation ValidString // PhoneNumber string `json:"phone_number"`
LearningGoal ValidString
LanguageGoal ValidString // Personal details
LanguageChallange ValidString Age int64 `json:"age"`
FavoutiteTopic ValidString EducationLevel string `json:"education_level"`
Country string `json:"country"`
ProfileCompleted ValidBool Region string `json:"region"`
ProfilePictureURL ValidString
PreferredLanguage ValidString // Learning / profile
KnowledgeLevel string `json:"knowledge_level"`
NickName string `json:"nick_name"`
Occupation string `json:"occupation"`
LearningGoal string `json:"learning_goal"`
LanguageGoal string `json:"language_goal"`
LanguageChallange string `json:"language_challange"`
FavouriteTopic string `json:"favourite_topic"`
InitialAssessmentCompleted bool `json:"initial_assessment_completed"`
// EmailVerified bool `json:"email_verified"`
// PhoneVerified bool `json:"phone_verified"`
ProfileCompleted bool `json:"profile_completed"`
// Media & preferences
ProfilePictureURL string `json:"profile_picture_url"`
PreferredLanguage string `json:"preferred_language"`
} }

View File

@ -9,7 +9,7 @@ import (
type UserStore interface { type UserStore interface {
IsProfileCompleted(ctx context.Context, userId int64) (bool, error) IsProfileCompleted(ctx context.Context, userId int64) (bool, error)
UpdateUserStatus(ctx context.Context, user domain.UpdateUserReq) error UpdateUserStatus(ctx context.Context, req domain.UpdateUserStatusReq) error
// GetCorrectOptionForQuestion( // GetCorrectOptionForQuestion(
// ctx context.Context, // ctx context.Context,
// questionID int64, // questionID int64,
@ -19,12 +19,12 @@ type UserStore interface {
// userID int64, // userID int64,
// ) (*dbgen.AssessmentAttempt, error) // ) (*dbgen.AssessmentAttempt, error)
UpdateUserKnowledgeLevel(ctx context.Context, userID int64, knowledgeLevel string) error UpdateUserKnowledgeLevel(ctx context.Context, userID int64, knowledgeLevel string) error
IsUserNameUnique(ctx context.Context, userName string) (bool, error) // IsUserNameUnique(ctx context.Context, userName string) (bool, error)
IsUserPending(ctx context.Context, UserName string) (bool, error) IsUserPending(ctx context.Context, userID int64) (bool, error)
GetUserByUserName( // GetUserByUserName(
ctx context.Context, // ctx context.Context,
userName string, // userName string,
) (domain.User, error) // ) (domain.User, error)
CreateUser( CreateUser(
ctx context.Context, ctx context.Context,
user domain.User, user domain.User,
@ -51,7 +51,7 @@ type UserStore interface {
search string, search string,
role *string, role *string,
) ([]domain.User, error) ) ([]domain.User, error)
UpdateUser(ctx context.Context, user domain.User) error UpdateUser(ctx context.Context, req domain.UpdateUserReq) error
DeleteUser(ctx context.Context, userID int64) error DeleteUser(ctx context.Context, userID int64) error
CheckPhoneEmailExist(ctx context.Context, phone, email string) (phoneExists, emailExists bool, err error) CheckPhoneEmailExist(ctx context.Context, phone, email string) (phoneExists, emailExists bool, err error)
GetUserByEmailPhone( GetUserByEmailPhone(
@ -59,7 +59,7 @@ type UserStore interface {
email string, email string,
phone string, phone string,
) (domain.User, error) ) (domain.User, error)
UpdatePassword(ctx context.Context, password, userName string) error UpdatePassword(ctx context.Context, password string, userID int64) error
} }
type SmsGateway interface { type SmsGateway interface {
SendSMSOTP(ctx context.Context, phoneNumber, otp string) error SendSMSOTP(ctx context.Context, phoneNumber, otp string) error
@ -68,8 +68,8 @@ type EmailGateway interface {
SendEmailOTP(ctx context.Context, email string, otp string) error SendEmailOTP(ctx context.Context, email string, otp string) error
} }
type OtpStore interface { type OtpStore interface {
UpdateOtp(ctx context.Context, otp, userName string) error UpdateOtp(ctx context.Context, otp string, userID int64) error
MarkOtpAsUsed(ctx context.Context, otp domain.Otp) error MarkOtpAsUsed(ctx context.Context, otp domain.Otp) error
CreateOtp(ctx context.Context, otp domain.Otp) error CreateOtp(ctx context.Context, otp domain.Otp) error
GetOtp(ctx context.Context, userName string) (domain.Otp, error) GetOtp(ctx context.Context, userID int64) (domain.Otp, error)
} }

View File

@ -118,9 +118,9 @@ func (s *Store) GetUserByEmailOrPhone(
return domain.User{ return domain.User{
ID: u.ID, ID: u.ID,
FirstName: u.FirstName, FirstName: u.FirstName.String,
LastName: u.LastName, LastName: u.LastName.String,
UserName: u.UserName, // UserName: u.UserName,
Email: u.Email.String, Email: u.Email.String,
PhoneNumber: u.PhoneNumber.String, PhoneNumber: u.PhoneNumber.String,
Password: u.Password, Password: u.Password,
@ -136,7 +136,7 @@ func (s *Store) GetUserByEmailOrPhone(
Status: domain.UserStatus(u.Status), Status: domain.UserStatus(u.Status),
LastLogin: lastLogin, LastLogin: lastLogin,
ProfileCompleted: u.ProfileCompleted, ProfileCompleted: u.ProfileCompleted.Bool,
ProfilePictureURL: u.ProfilePictureUrl.String, ProfilePictureURL: u.ProfilePictureUrl.String,
PreferredLanguage: u.PreferredLanguage.String, PreferredLanguage: u.PreferredLanguage.String,

View File

@ -16,9 +16,9 @@ import (
// Interface for creating new otp store // Interface for creating new otp store
func NewOTPStore(s *Store) ports.OtpStore { return s } func NewOTPStore(s *Store) ports.OtpStore { return s }
func (s *Store) UpdateOtp(ctx context.Context, otp, userName string) error { func (s *Store) UpdateOtp(ctx context.Context, otp string, userId int64) error {
return s.queries.UpdateExpiredOtp(ctx, dbgen.UpdateExpiredOtpParams{ return s.queries.UpdateExpiredOtp(ctx, dbgen.UpdateExpiredOtpParams{
UserName: userName, UserID: userId,
Otp: otp, Otp: otp,
ExpiresAt: pgtype.Timestamptz{ ExpiresAt: pgtype.Timestamptz{
Time: time.Now().Add(5 * time.Minute), Time: time.Now().Add(5 * time.Minute),
@ -29,7 +29,7 @@ func (s *Store) UpdateOtp(ctx context.Context, otp, userName string) error {
func (s *Store) CreateOtp(ctx context.Context, otp domain.Otp) error { func (s *Store) CreateOtp(ctx context.Context, otp domain.Otp) error {
return s.queries.CreateOtp(ctx, dbgen.CreateOtpParams{ return s.queries.CreateOtp(ctx, dbgen.CreateOtpParams{
UserName: otp.UserName, UserID: otp.UserID,
SentTo: otp.SentTo, SentTo: otp.SentTo,
Medium: string(otp.Medium), Medium: string(otp.Medium),
OtpFor: string(otp.For), OtpFor: string(otp.For),
@ -41,10 +41,10 @@ func (s *Store) CreateOtp(ctx context.Context, otp domain.Otp) error {
}) })
} }
func (s *Store) GetOtp(ctx context.Context, userName string) (domain.Otp, error) { func (s *Store) GetOtp(ctx context.Context, userID int64) (domain.Otp, error) {
row, err := s.queries.GetOtp(ctx, userName) row, err := s.queries.GetOtp(ctx, userID)
if err != nil { if err != nil {
fmt.Printf("OTP REPO error: %v userName: %v\n", err, userName) fmt.Printf("OTP REPO error: %v userName: %v\n", err, userID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return domain.Otp{}, domain.ErrOtpNotFound return domain.Otp{}, domain.ErrOtpNotFound
} }
@ -52,7 +52,7 @@ func (s *Store) GetOtp(ctx context.Context, userName string) (domain.Otp, error)
} }
return domain.Otp{ return domain.Otp{
ID: row.ID, ID: row.ID,
UserName: row.UserName, UserID: row.UserID,
SentTo: row.SentTo, SentTo: row.SentTo,
Medium: domain.OtpMedium(row.Medium), Medium: domain.OtpMedium(row.Medium),
For: domain.OtpFor(row.OtpFor), For: domain.OtpFor(row.OtpFor),

View File

@ -34,8 +34,8 @@ func (s *Store) UpdateUserKnowledgeLevel(ctx context.Context, userID int64, know
}) })
} }
func (s *Store) IsUserPending(ctx context.Context, UserName string) (bool, error) { func (s *Store) IsUserPending(ctx context.Context, userID int64) (bool, error) {
isPending, err := s.queries.IsUserPending(ctx, UserName) isPending, err := s.queries.IsUserPending(ctx, userID)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return false, authentication.ErrUserNotFound return false, authentication.ErrUserNotFound
@ -45,18 +45,18 @@ func (s *Store) IsUserPending(ctx context.Context, UserName string) (bool, error
return isPending, nil return isPending, nil
} }
func (s *Store) IsUserNameUnique(ctx context.Context, userName string) (bool, error) { func (s *Store) IsUserNameUnique(ctx context.Context, userID int64) (bool, error) {
isUnique, err := s.queries.IsUserNameUnique(ctx, userName) isUnique, err := s.queries.IsUserNameUnique(ctx, userID)
if err != nil { if err != nil {
return false, err return false, err
} }
return isUnique, nil return isUnique, nil
} }
func (s *Store) UpdateUserStatus(ctx context.Context, user domain.UpdateUserReq) error { func (s *Store) UpdateUserStatus(ctx context.Context, req domain.UpdateUserStatusReq) error {
return s.queries.UpdateUserStatus(ctx, dbgen.UpdateUserStatusParams{ return s.queries.UpdateUserStatus(ctx, dbgen.UpdateUserStatusParams{
Status: user.Status.Value, Status: req.Status,
ID: user.UserID, ID: req.UserID,
}) })
} }
@ -66,9 +66,17 @@ func (s *Store) CreateUserWithoutOtp(
) (domain.User, error) { ) (domain.User, error) {
userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{ userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{
FirstName: user.FirstName, FirstName: pgtype.Text{String: user.FirstName},
LastName: user.LastName, LastName: pgtype.Text{String: user.LastName},
UserName: user.UserName, Gender: pgtype.Text{
String: user.Gender,
Valid: user.Gender != "",
},
BirthDay: pgtype.Date{
Time: user.BirthDay,
Valid: true,
},
// UserName: user.UserName,
Email: pgtype.Text{String: user.Email, Valid: user.Email != ""}, Email: pgtype.Text{String: user.Email, Valid: user.Email != ""},
PhoneNumber: pgtype.Text{String: user.PhoneNumber, Valid: user.PhoneNumber != ""}, PhoneNumber: pgtype.Text{String: user.PhoneNumber, Valid: user.PhoneNumber != ""},
@ -101,9 +109,9 @@ func (s *Store) CreateUserWithoutOtp(
String: user.LanguageChallange, String: user.LanguageChallange,
Valid: user.LanguageChallange != "", Valid: user.LanguageChallange != "",
}, },
FavoutiteTopic: pgtype.Text{ FavouriteTopic: pgtype.Text{
String: user.FavoutiteTopic, String: user.FavouriteTopic,
Valid: user.FavoutiteTopic != "", Valid: user.FavouriteTopic != "",
}, },
EmailVerified: user.EmailVerified, EmailVerified: user.EmailVerified,
@ -114,7 +122,10 @@ func (s *Store) CreateUserWithoutOtp(
Valid: user.ProfilePictureURL != "", Valid: user.ProfilePictureURL != "",
}, },
Status: string(user.Status), Status: string(user.Status),
ProfileCompleted: user.ProfileCompleted, ProfileCompleted: pgtype.Bool{
Bool: user.ProfileCompleted,
Valid: true,
},
PreferredLanguage: pgtype.Text{ PreferredLanguage: pgtype.Text{
String: user.PreferredLanguage, String: user.PreferredLanguage,
Valid: user.PreferredLanguage != "", Valid: user.PreferredLanguage != "",
@ -149,9 +160,17 @@ func (s *Store) CreateUser(
} }
userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{ userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{
FirstName: user.FirstName, FirstName: pgtype.Text{String: user.FirstName},
LastName: user.LastName, LastName: pgtype.Text{String: user.LastName},
UserName: user.UserName, Gender: pgtype.Text{
String: user.Gender,
Valid: user.Gender != "",
},
BirthDay: pgtype.Date{
Time: user.BirthDay,
Valid: true,
},
// UserName: user.UserName,
Email: pgtype.Text{String: user.Email, Valid: user.Email != ""}, Email: pgtype.Text{String: user.Email, Valid: user.Email != ""},
PhoneNumber: pgtype.Text{String: user.PhoneNumber, Valid: user.PhoneNumber != ""}, PhoneNumber: pgtype.Text{String: user.PhoneNumber, Valid: user.PhoneNumber != ""},
@ -169,7 +188,7 @@ func (s *Store) CreateUser(
LearningGoal: pgtype.Text{String: user.LearningGoal, Valid: user.LearningGoal != ""}, LearningGoal: pgtype.Text{String: user.LearningGoal, Valid: user.LearningGoal != ""},
LanguageGoal: pgtype.Text{String: user.LanguageGoal, Valid: user.LanguageGoal != ""}, LanguageGoal: pgtype.Text{String: user.LanguageGoal, Valid: user.LanguageGoal != ""},
LanguageChallange: pgtype.Text{String: user.LanguageChallange, Valid: user.LanguageChallange != ""}, LanguageChallange: pgtype.Text{String: user.LanguageChallange, Valid: user.LanguageChallange != ""},
FavoutiteTopic: pgtype.Text{String: user.FavoutiteTopic, Valid: user.FavoutiteTopic != ""}, FavouriteTopic: pgtype.Text{String: user.FavouriteTopic, Valid: user.FavouriteTopic != ""},
EmailVerified: user.EmailVerified, EmailVerified: user.EmailVerified,
PhoneVerified: user.PhoneVerified, PhoneVerified: user.PhoneVerified,
@ -179,7 +198,10 @@ func (s *Store) CreateUser(
Valid: user.ProfilePictureURL != "", Valid: user.ProfilePictureURL != "",
}, },
Status: string(user.Status), Status: string(user.Status),
ProfileCompleted: user.ProfileCompleted, ProfileCompleted: pgtype.Bool{
Bool: user.ProfileCompleted,
Valid: true,
},
PreferredLanguage: pgtype.Text{ PreferredLanguage: pgtype.Text{
String: user.PreferredLanguage, String: user.PreferredLanguage,
Valid: user.PreferredLanguage != "", Valid: user.PreferredLanguage != "",
@ -223,9 +245,11 @@ func (s *Store) GetUserByID(
return domain.User{ return domain.User{
ID: u.ID, ID: u.ID,
FirstName: u.FirstName, FirstName: u.FirstName.String,
LastName: u.LastName, LastName: u.LastName.String,
UserName: u.UserName, Gender: u.Gender.String,
BirthDay: u.BirthDay.Time,
// UserName: u.UserName,
Email: u.Email.String, Email: u.Email.String,
PhoneNumber: u.PhoneNumber.String, PhoneNumber: u.PhoneNumber.String,
Role: domain.Role(u.Role), Role: domain.Role(u.Role),
@ -240,14 +264,14 @@ func (s *Store) GetUserByID(
LearningGoal: u.LearningGoal.String, LearningGoal: u.LearningGoal.String,
LanguageGoal: u.LanguageGoal.String, LanguageGoal: u.LanguageGoal.String,
LanguageChallange: u.LanguageChallange.String, LanguageChallange: u.LanguageChallange.String,
FavoutiteTopic: u.FavoutiteTopic.String, FavouriteTopic: u.FavouriteTopic.String,
EmailVerified: u.EmailVerified, EmailVerified: u.EmailVerified,
PhoneVerified: u.PhoneVerified, PhoneVerified: u.PhoneVerified,
Status: domain.UserStatus(u.Status), Status: domain.UserStatus(u.Status),
LastLogin: lastLogin, LastLogin: lastLogin,
ProfileCompleted: u.ProfileCompleted, ProfileCompleted: u.ProfileCompleted.Bool,
ProfilePictureURL: u.ProfilePictureUrl.String, ProfilePictureURL: u.ProfilePictureUrl.String,
PreferredLanguage: u.PreferredLanguage.String, PreferredLanguage: u.PreferredLanguage.String,
@ -323,9 +347,11 @@ func (s *Store) GetAllUsers(
users = append(users, domain.User{ users = append(users, domain.User{
ID: u.ID, ID: u.ID,
FirstName: u.FirstName, FirstName: u.FirstName.String,
LastName: u.LastName, LastName: u.LastName.String,
UserName: u.UserName, Gender: u.Gender.String,
BirthDay: u.BirthDay.Time,
// UserName: u.UserName,
Email: u.Email.String, Email: u.Email.String,
PhoneNumber: u.PhoneNumber.String, PhoneNumber: u.PhoneNumber.String,
Role: domain.Role(u.Role), Role: domain.Role(u.Role),
@ -340,14 +366,14 @@ func (s *Store) GetAllUsers(
LearningGoal: u.LearningGoal.String, LearningGoal: u.LearningGoal.String,
LanguageGoal: u.LanguageGoal.String, LanguageGoal: u.LanguageGoal.String,
LanguageChallange: u.LanguageChallange.String, LanguageChallange: u.LanguageChallange.String,
FavoutiteTopic: u.FavoutiteTopic.String, FavouriteTopic: u.FavouriteTopic.String,
EmailVerified: u.EmailVerified, EmailVerified: u.EmailVerified,
PhoneVerified: u.PhoneVerified, PhoneVerified: u.PhoneVerified,
Status: domain.UserStatus(u.Status), Status: domain.UserStatus(u.Status),
ProfilePictureURL: u.ProfilePictureUrl.String, ProfilePictureURL: u.ProfilePictureUrl.String,
ProfileCompleted: u.ProfileCompleted, ProfileCompleted: u.ProfileCompleted.Bool,
PreferredLanguage: u.PreferredLanguage.String, PreferredLanguage: u.PreferredLanguage.String,
CreatedAt: u.CreatedAt.Time, CreatedAt: u.CreatedAt.Time,
@ -408,9 +434,11 @@ func (s *Store) SearchUserByNameOrPhone(
users = append(users, domain.User{ users = append(users, domain.User{
ID: u.ID, ID: u.ID,
FirstName: u.FirstName, FirstName: u.FirstName.String,
LastName: u.LastName, LastName: u.LastName.String,
UserName: u.UserName, Gender: u.Gender.String,
BirthDay: u.BirthDay.Time,
// UserName: u.UserName,
Email: u.Email.String, Email: u.Email.String,
PhoneNumber: u.PhoneNumber.String, PhoneNumber: u.PhoneNumber.String,
Role: domain.Role(u.Role), Role: domain.Role(u.Role),
@ -425,13 +453,13 @@ func (s *Store) SearchUserByNameOrPhone(
LearningGoal: u.LearningGoal.String, LearningGoal: u.LearningGoal.String,
LanguageGoal: u.LanguageGoal.String, LanguageGoal: u.LanguageGoal.String,
LanguageChallange: u.LanguageChallange.String, LanguageChallange: u.LanguageChallange.String,
FavoutiteTopic: u.FavoutiteTopic.String, FavouriteTopic: u.FavouriteTopic.String,
EmailVerified: u.EmailVerified, EmailVerified: u.EmailVerified,
PhoneVerified: u.PhoneVerified, PhoneVerified: u.PhoneVerified,
Status: domain.UserStatus(u.Status), Status: domain.UserStatus(u.Status),
ProfileCompleted: u.ProfileCompleted, ProfileCompleted: u.ProfileCompleted.Bool,
ProfilePictureURL: u.ProfilePictureUrl.String, ProfilePictureURL: u.ProfilePictureUrl.String,
PreferredLanguage: u.PreferredLanguage.String, PreferredLanguage: u.PreferredLanguage.String,
@ -446,69 +474,44 @@ func (s *Store) SearchUserByNameOrPhone(
// UpdateUser updates basic user info // UpdateUser updates basic user info
func (s *Store) UpdateUser( func (s *Store) UpdateUser(
ctx context.Context, ctx context.Context,
user domain.User, req domain.UpdateUserReq,
) error { ) error {
return s.queries.UpdateUser(ctx, dbgen.UpdateUserParams{ return s.queries.UpdateUser(ctx, dbgen.UpdateUserParams{
FirstName: user.FirstName, FirstName: pgtype.Text{String: req.FirstName, Valid: req.FirstName != ""},
LastName: user.LastName, LastName: pgtype.Text{String: req.LastName, Valid: req.LastName != ""},
UserName: user.UserName, Gender: pgtype.Text{
String: req.Gender,
Age: pgtype.Int4{ Valid: req.Gender != "",
Int32: int32(user.Age),
Valid: user.Age > 0,
}, },
EducationLevel: pgtype.Text{ BirthDay: pgtype.Date{
String: user.EducationLevel, Time: req.BirthDay,
Valid: user.EducationLevel != "", Valid: true,
},
Country: pgtype.Text{
String: user.Country,
Valid: user.Country != "",
},
Region: pgtype.Text{
String: user.Region,
Valid: user.Region != "",
}, },
NickName: pgtype.Text{ Age: pgtype.Int4{Int32: int32(req.Age), Valid: req.Age > 0},
String: user.NickName, EducationLevel: pgtype.Text{String: req.EducationLevel, Valid: req.EducationLevel != ""},
Valid: user.NickName != "", Country: pgtype.Text{String: req.Country, Valid: req.Country != ""},
}, Region: pgtype.Text{String: req.Region, Valid: req.Region != ""},
Occupation: pgtype.Text{
String: user.Occupation, NickName: pgtype.Text{String: req.NickName, Valid: req.NickName != ""},
Valid: user.Occupation != "", Occupation: pgtype.Text{String: req.Occupation, Valid: req.Occupation != ""},
}, LearningGoal: pgtype.Text{String: req.LearningGoal, Valid: req.LearningGoal != ""},
LearningGoal: pgtype.Text{ LanguageGoal: pgtype.Text{String: req.LanguageGoal, Valid: req.LanguageGoal != ""},
String: user.LearningGoal, LanguageChallange: pgtype.Text{String: req.LanguageChallange, Valid: req.LanguageChallange != ""},
Valid: user.LearningGoal != "", FavouriteTopic: pgtype.Text{String: req.FavouriteTopic, Valid: req.FavouriteTopic != ""},
},
LanguageGoal: pgtype.Text{ ProfileCompleted: pgtype.Bool{
String: user.LanguageGoal, Bool: req.ProfileCompleted,
Valid: user.LanguageGoal != "", Valid: true,
},
LanguageChallange: pgtype.Text{
String: user.LanguageChallange,
Valid: user.LanguageChallange != "",
},
FavoutiteTopic: pgtype.Text{
String: user.FavoutiteTopic,
Valid: user.FavoutiteTopic != "",
}, },
Status: string(user.Status), ProfilePictureUrl: pgtype.Text{String: req.ProfilePictureURL, Valid: req.ProfilePictureURL != ""},
ProfileCompleted: user.ProfileCompleted, PreferredLanguage: pgtype.Text{String: req.PreferredLanguage, Valid: req.PreferredLanguage != ""},
ProfilePictureUrl: pgtype.Text{
String: user.ProfilePictureURL,
Valid: user.ProfilePictureURL != "",
},
PreferredLanguage: pgtype.Text{
String: user.PreferredLanguage,
Valid: user.PreferredLanguage != "",
},
ID: user.ID, ID: req.UserID,
}) })
} }
// DeleteUser removes a user // DeleteUser removes a user
@ -529,64 +532,64 @@ func (s *Store) CheckPhoneEmailExist(ctx context.Context, phone, email string) (
return res.PhoneExists, res.EmailExists, nil return res.PhoneExists, res.EmailExists, nil
} }
func (s *Store) GetUserByUserName( // func (s *Store) GetUserByUserName(
ctx context.Context, // ctx context.Context,
userName string, // userName string,
) (domain.User, error) { // ) (domain.User, error) {
u, err := s.queries.GetUserByUserName(ctx, userName) // u, err := s.queries.GetUserByUserName(ctx, userName)
if err != nil { // if err != nil {
if errors.Is(err, pgx.ErrNoRows) { // if errors.Is(err, pgx.ErrNoRows) {
return domain.User{}, authentication.ErrUserNotFound // return domain.User{}, authentication.ErrUserNotFound
} // }
return domain.User{}, err // return domain.User{}, err
} // }
var lastLogin *time.Time // var lastLogin *time.Time
if u.LastLogin.Valid { // if u.LastLogin.Valid {
lastLogin = &u.LastLogin.Time // lastLogin = &u.LastLogin.Time
} // }
var updatedAt *time.Time // var updatedAt *time.Time
if u.UpdatedAt.Valid { // if u.UpdatedAt.Valid {
updatedAt = &u.UpdatedAt.Time // updatedAt = &u.UpdatedAt.Time
} // }
return domain.User{ // return domain.User{
ID: u.ID, // ID: u.ID,
FirstName: u.FirstName, // FirstName: u.FirstName,
LastName: u.LastName, // LastName: u.LastName,
UserName: u.UserName, // UserName: u.UserName,
Email: u.Email.String, // Email: u.Email.String,
PhoneNumber: u.PhoneNumber.String, // PhoneNumber: u.PhoneNumber.String,
Password: u.Password, // Password: u.Password,
Role: domain.Role(u.Role), // Role: domain.Role(u.Role),
Age: int(u.Age.Int32), // Age: int(u.Age.Int32),
EducationLevel: u.EducationLevel.String, // EducationLevel: u.EducationLevel.String,
Country: u.Country.String, // Country: u.Country.String,
Region: u.Region.String, // Region: u.Region.String,
NickName: u.NickName.String, // NickName: u.NickName.String,
Occupation: u.Occupation.String, // Occupation: u.Occupation.String,
LearningGoal: u.LearningGoal.String, // LearningGoal: u.LearningGoal.String,
LanguageGoal: u.LanguageGoal.String, // LanguageGoal: u.LanguageGoal.String,
LanguageChallange: u.LanguageChallange.String, // LanguageChallange: u.LanguageChallange.String,
FavoutiteTopic: u.FavoutiteTopic.String, // FavouriteTopic: u.FavouriteTopic.String,
EmailVerified: u.EmailVerified, // EmailVerified: u.EmailVerified,
PhoneVerified: u.PhoneVerified, // PhoneVerified: u.PhoneVerified,
Status: domain.UserStatus(u.Status), // Status: domain.UserStatus(u.Status),
LastLogin: lastLogin, // LastLogin: lastLogin,
ProfileCompleted: u.ProfileCompleted, // ProfileCompleted: u.ProfileCompleted,
ProfilePictureURL: u.ProfilePictureUrl.String, // ProfilePictureURL: u.ProfilePictureUrl.String,
PreferredLanguage: u.PreferredLanguage.String, // PreferredLanguage: u.PreferredLanguage.String,
CreatedAt: u.CreatedAt.Time, // CreatedAt: u.CreatedAt.Time,
UpdatedAt: updatedAt, // UpdatedAt: updatedAt,
}, nil // }, nil
} // }
// GetUserByEmail retrieves a user by email and organization // GetUserByEmail retrieves a user by email and organization
func (s *Store) GetUserByEmailPhone( func (s *Store) GetUserByEmailPhone(
@ -624,9 +627,11 @@ func (s *Store) GetUserByEmailPhone(
return domain.User{ return domain.User{
ID: u.ID, ID: u.ID,
FirstName: u.FirstName, FirstName: u.FirstName.String,
LastName: u.LastName, LastName: u.LastName.String,
UserName: u.UserName, Gender: u.Gender.String,
BirthDay: u.BirthDay.Time,
// UserName: u.UserName,
Email: u.Email.String, Email: u.Email.String,
PhoneNumber: u.PhoneNumber.String, PhoneNumber: u.PhoneNumber.String,
Password: u.Password, Password: u.Password,
@ -642,7 +647,7 @@ func (s *Store) GetUserByEmailPhone(
LearningGoal: u.LearningGoal.String, LearningGoal: u.LearningGoal.String,
LanguageGoal: u.LanguageGoal.String, LanguageGoal: u.LanguageGoal.String,
LanguageChallange: u.LanguageChallange.String, LanguageChallange: u.LanguageChallange.String,
FavoutiteTopic: u.FavoutiteTopic.String, FavouriteTopic: u.FavouriteTopic.String,
EmailVerified: u.EmailVerified, EmailVerified: u.EmailVerified,
PhoneVerified: u.PhoneVerified, PhoneVerified: u.PhoneVerified,
@ -650,7 +655,7 @@ func (s *Store) GetUserByEmailPhone(
ProfilePictureURL: u.ProfilePictureUrl.String, ProfilePictureURL: u.ProfilePictureUrl.String,
LastLogin: lastLogin, LastLogin: lastLogin,
ProfileCompleted: u.ProfileCompleted, ProfileCompleted: u.ProfileCompleted.Bool,
PreferredLanguage: u.PreferredLanguage.String, PreferredLanguage: u.PreferredLanguage.String,
CreatedAt: u.CreatedAt.Time, CreatedAt: u.CreatedAt.Time,
@ -659,10 +664,10 @@ func (s *Store) GetUserByEmailPhone(
} }
// UpdatePassword updates a user's password // UpdatePassword updates a user's password
func (s *Store) UpdatePassword(ctx context.Context, password, userName string) error { func (s *Store) UpdatePassword(ctx context.Context, password string, userID int64) error {
return s.queries.UpdatePassword(ctx, dbgen.UpdatePasswordParams{ return s.queries.UpdatePassword(ctx, dbgen.UpdatePasswordParams{
Password: []byte(password), Password: []byte(password),
UserName: userName, ID: userID,
}) })
} }
@ -675,9 +680,11 @@ func mapCreateUserResult(
return domain.User{ return domain.User{
ID: userRes.ID, ID: userRes.ID,
FirstName: userRes.FirstName, FirstName: userRes.FirstName.String,
LastName: userRes.LastName, LastName: userRes.LastName.String,
UserName: userRes.UserName, Gender: userRes.Gender.String,
BirthDay: userRes.BirthDay.Time,
// UserName: userRes.UserName,
Email: userRes.Email.String, Email: userRes.Email.String,
PhoneNumber: userRes.PhoneNumber.String, PhoneNumber: userRes.PhoneNumber.String,
Role: domain.Role(userRes.Role), Role: domain.Role(userRes.Role),
@ -693,13 +700,13 @@ func mapCreateUserResult(
LearningGoal: userRes.LearningGoal.String, LearningGoal: userRes.LearningGoal.String,
LanguageGoal: userRes.LanguageGoal.String, LanguageGoal: userRes.LanguageGoal.String,
LanguageChallange: userRes.LanguageChallange.String, LanguageChallange: userRes.LanguageChallange.String,
FavoutiteTopic: userRes.FavoutiteTopic.String, FavouriteTopic: userRes.FavouriteTopic.String,
EmailVerified: userRes.EmailVerified, EmailVerified: userRes.EmailVerified,
PhoneVerified: userRes.PhoneVerified, PhoneVerified: userRes.PhoneVerified,
Status: domain.UserStatus(userRes.Status), Status: domain.UserStatus(userRes.Status),
ProfileCompleted: userRes.ProfileCompleted, ProfileCompleted: userRes.ProfileCompleted.Bool,
PreferredLanguage: userRes.PreferredLanguage.String, PreferredLanguage: userRes.PreferredLanguage.String,
CreatedAt: userRes.CreatedAt.Time, CreatedAt: userRes.CreatedAt.Time,

View File

@ -17,7 +17,7 @@ func (s *Service) VerifyOtp(ctx context.Context, email, phone, otpCode string) e
return err return err
} }
// 1. Retrieve the OTP from the store // 1. Retrieve the OTP from the store
storedOtp, err := s.otpStore.GetOtp(ctx, user.UserName) storedOtp, err := s.otpStore.GetOtp(ctx, user.ID)
if err != nil { if err != nil {
return err // could be ErrOtpNotFound or other DB errors return err // could be ErrOtpNotFound or other DB errors
} }
@ -50,12 +50,9 @@ func (s *Service) VerifyOtp(ctx context.Context, email, phone, otpCode string) e
// return err // return err
// } // }
newUser := domain.UpdateUserReq{ newUser := domain.UpdateUserStatusReq{
UserID: user.ID, UserID: user.ID,
Status: domain.ValidString{ Status: string(domain.UserStatusActive),
Value: string(domain.UserStatusActive),
Valid: true,
},
} }
s.userStore.UpdateUserStatus(ctx, newUser) s.userStore.UpdateUserStatus(ctx, newUser)
@ -80,7 +77,7 @@ func (s *Service) ResendOtp(
otpCode, otpCode,
) )
otp, err := s.otpStore.GetOtp(ctx, user.UserName) otp, err := s.otpStore.GetOtp(ctx, user.ID)
if err != nil { if err != nil {
return err return err
} }
@ -106,14 +103,14 @@ func (s *Service) ResendOtp(
return fmt.Errorf("invalid otp medium: %s", otp.Medium) return fmt.Errorf("invalid otp medium: %s", otp.Medium)
} }
if err := s.otpStore.UpdateOtp(ctx, otpCode, user.UserName); err != nil { if err := s.otpStore.UpdateOtp(ctx, otpCode, user.ID); err != nil {
return err return err
} }
return nil return nil
} }
func (s *Service) SendOtp(ctx context.Context, userName string, sentTo string, otpFor domain.OtpFor, medium domain.OtpMedium, provider domain.SMSProvider) error { func (s *Service) SendOtp(ctx context.Context, userID int64, sentTo string, otpFor domain.OtpFor, medium domain.OtpMedium, provider domain.SMSProvider) error {
otpCode := helpers.GenerateOTP() otpCode := helpers.GenerateOTP()
message := fmt.Sprintf("Welcome to Yimaru Online Learning Platform, your OTP is %s please don't share with anyone.", otpCode) message := fmt.Sprintf("Welcome to Yimaru Online Learning Platform, your OTP is %s please don't share with anyone.", otpCode)
@ -140,7 +137,7 @@ func (s *Service) SendOtp(ctx context.Context, userName string, sentTo string, o
} }
otp := domain.Otp{ otp := domain.Otp{
UserName: userName, UserID: userID,
SentTo: sentTo, SentTo: sentTo,
Medium: medium, Medium: medium,
For: otpFor, For: otpFor,

View File

@ -25,7 +25,7 @@ func (s *Service) CreateUser(
return s.userStore.CreateUserWithoutOtp(ctx, domain.User{ return s.userStore.CreateUserWithoutOtp(ctx, domain.User{
FirstName: req.FirstName, FirstName: req.FirstName,
LastName: req.LastName, LastName: req.LastName,
UserName: req.UserName, // UserName: req.UserName,
Email: req.Email, Email: req.Email,
PhoneNumber: req.PhoneNumber, PhoneNumber: req.PhoneNumber,
Password: hashedPassword, Password: hashedPassword,
@ -48,7 +48,7 @@ func (s *Service) DeleteUser(ctx context.Context, id int64) error {
func (s *Service) GetAllUsers(ctx context.Context, filter domain.UserFilter) ([]domain.User, int64, error) { func (s *Service) GetAllUsers(ctx context.Context, filter domain.UserFilter) ([]domain.User, int64, error) {
// Get all Users // Get all Users
return s.userStore.GetAllUsers(ctx, &filter.Role, &filter.Query.Value, &filter.CreatedBefore.Value, &filter.CreatedAfter.Value, int32(filter.PageSize.Value), int32(filter.Page.Value)) return s.userStore.GetAllUsers(ctx, &filter.Role, &filter.Query, &filter.CreatedBefore.Value, &filter.CreatedAfter.Value, int32(filter.PageSize), int32(filter.Page))
} }
func (s *Service) GetUserById(ctx context.Context, id int64) (domain.User, error) { func (s *Service) GetUserById(ctx context.Context, id int64) (domain.User, error) {

View File

@ -26,7 +26,7 @@ func (s *Service) SendRegisterCode(ctx context.Context, medium domain.OtpMedium,
} }
// send otp based on the medium // send otp based on the medium
return s.SendOtp(ctx, "", sentTo, domain.OtpRegister, medium, provider) return s.SendOtp(ctx, 0, sentTo, domain.OtpRegister, medium, provider)
} }
func (s *Service) RegisterUser(ctx context.Context, registerReq domain.RegisterUserReq) (domain.User, error) { func (s *Service) RegisterUser(ctx context.Context, registerReq domain.RegisterUserReq) (domain.User, error) {
@ -54,9 +54,9 @@ func (s *Service) RegisterUser(ctx context.Context, registerReq domain.RegisterU
// Prepare the user // Prepare the user
userR := domain.User{ userR := domain.User{
FirstName: registerReq.FirstName, // FirstName: registerReq.FirstName,
LastName: registerReq.LastName, // LastName: registerReq.LastName,
UserName: registerReq.UserName, // UserName: registerReq.UserName,
Email: registerReq.Email, Email: registerReq.Email,
PhoneNumber: registerReq.PhoneNumber, PhoneNumber: registerReq.PhoneNumber,
Password: hashedPassword, Password: hashedPassword,
@ -92,9 +92,6 @@ func (s *Service) RegisterUser(ctx context.Context, registerReq domain.RegisterU
} }
// Send OTP to the user (email/SMS) // Send OTP to the user (email/SMS)
if err := s.SendOtp(ctx, registerReq.UserName, sentTo, domain.OtpRegister, registerReq.OtpMedium, domain.TwilioSms); err != nil {
return domain.User{}, err
}
// Create the user (no OTP validation yet) // Create the user (no OTP validation yet)
user, err := s.userStore.CreateUserWithoutOtp(ctx, userR) user, err := s.userStore.CreateUserWithoutOtp(ctx, userR)
@ -102,5 +99,9 @@ func (s *Service) RegisterUser(ctx context.Context, registerReq domain.RegisterU
return domain.User{}, err return domain.User{}, err
} }
if err := s.SendOtp(ctx, user.ID, sentTo, domain.OtpRegister, registerReq.OtpMedium, domain.TwilioSms); err != nil {
return domain.User{}, err
}
return user, nil return user, nil
} }

View File

@ -7,7 +7,7 @@ import (
"time" "time"
) )
func (s *Service) SendResetCode(ctx context.Context, userName string, medium domain.OtpMedium, sentTo string, provider domain.SMSProvider) error { func (s *Service) SendResetCode(ctx context.Context, userID int64, medium domain.OtpMedium, sentTo string, provider domain.SMSProvider) error {
var err error var err error
// check if user exists // check if user exists
@ -22,13 +22,13 @@ func (s *Service) SendResetCode(ctx context.Context, userName string, medium dom
return err return err
} }
return s.SendOtp(ctx, userName, sentTo, domain.OtpReset, medium, provider) return s.SendOtp(ctx, userID, sentTo, domain.OtpReset, medium, provider)
} }
func (s *Service) ResetPassword(ctx context.Context, resetReq domain.ResetPasswordReq) error { func (s *Service) ResetPassword(ctx context.Context, resetReq domain.ResetPasswordReq) error {
otp, err := s.otpStore.GetOtp(ctx, resetReq.UserName) otp, err := s.otpStore.GetOtp(ctx, resetReq.UserID)
if err != nil { if err != nil {
return err return err
} }
@ -48,7 +48,7 @@ func (s *Service) ResetPassword(ctx context.Context, resetReq domain.ResetPasswo
return domain.ErrInvalidOtp return domain.ErrInvalidOtp
} }
err = s.userStore.UpdatePassword(ctx, resetReq.Password, resetReq.UserName) err = s.userStore.UpdatePassword(ctx, resetReq.Password, resetReq.UserID)
if err != nil { if err != nil {
return err return err
} }

View File

@ -14,24 +14,24 @@ func (s *Service) GetUserByEmailPhone(
return s.userStore.GetUserByEmailPhone(ctx, email, phone) return s.userStore.GetUserByEmailPhone(ctx, email, phone)
} }
func (s *Service) IsUserPending(ctx context.Context, userName string) (bool, error) { func (s *Service) IsUserPending(ctx context.Context, userID int64) (bool, error) {
return s.userStore.IsUserPending(ctx, userName) return s.userStore.IsUserPending(ctx, userID)
} }
func (s *Service) IsProfileCompleted(ctx context.Context, userId int64) (bool, error) { func (s *Service) IsProfileCompleted(ctx context.Context, userId int64) (bool, error) {
return s.userStore.IsProfileCompleted(ctx, userId) return s.userStore.IsProfileCompleted(ctx, userId)
} }
func (s *Service) IsUserNameUnique(ctx context.Context, userName string) (bool, error) { // func (s *Service) IsUserNameUnique(ctx context.Context, userID int64) (bool, error) {
return s.userStore.IsUserNameUnique(ctx, userName) // return s.userStore.IsUserNameUnique(ctx, userID)
} // }
func (s *Service) GetUserByUserName( // func (s *Service) GetUserByUserName(
ctx context.Context, // ctx context.Context,
userName string, // userName string,
) (domain.User, error) { // ) (domain.User, error) {
return s.userStore.GetUserByUserName(ctx, userName) // return s.userStore.GetUserByUserName(ctx, userName)
} // }
func (s *Service) SearchUserByNameOrPhone(ctx context.Context, searchString string, role *int64) ([]domain.User, error) { func (s *Service) SearchUserByNameOrPhone(ctx context.Context, searchString string, role *int64) ([]domain.User, error) {
// Search user // Search user
@ -45,29 +45,8 @@ func (s *Service) SearchUserByNameOrPhone(ctx context.Context, searchString stri
} }
func (s *Service) UpdateUser(ctx context.Context, req domain.UpdateUserReq) error { func (s *Service) UpdateUser(ctx context.Context, req domain.UpdateUserReq) error {
newUser := domain.User{
ID: req.UserID,
FirstName: req.FirstName.Value,
LastName: req.LastName.Value,
KnowledgeLevel: req.KnowledgeLevel.Value,
UserName: req.UserName.Value,
Age: req.Age.Value,
EducationLevel: req.EducationLevel.Value,
Country: req.Country.Value,
Region: req.Region.Value,
Status: domain.UserStatus(req.Status.Value),
NickName: req.NickName.Value,
Occupation: req.Occupation.Value,
LearningGoal: req.LearningGoal.Value,
LanguageGoal: req.LanguageGoal.Value,
LanguageChallange: req.LanguageChallange.Value,
FavoutiteTopic: req.FavoutiteTopic.Value,
PreferredLanguage: req.PreferredLanguage.Value,
ProfilePictureURL: req.ProfilePictureURL.Value,
}
// Update user in the store // Update user in the store
return s.userStore.UpdateUser(ctx, newUser) return s.userStore.UpdateUser(ctx, req)
} }
// func (s *Service) UpdateUserSuspend(ctx context.Context, id int64, status bool) error { // func (s *Service) UpdateUserSuspend(ctx context.Context, id int64, status bool) error {
@ -87,29 +66,29 @@ func (s *Service) GetUserByID(ctx context.Context, id int64) (domain.User, error
// var query *string // var query *string
// if filter.Query.Valid { // if filter.Query.Valid {
// q := filter.Query.Value // q := filter.Query
// query = &q // query = &q
// } // }
// var createdBefore *time.Time // var createdBefore *time.Time
// if filter.CreatedBefore.Valid { // if filter.CreatedBefore.Valid {
// b := filter.CreatedBefore.Value // b := filter.CreatedBefore
// createdBefore = &b // createdBefore = &b
// } // }
// var createdAfter *time.Time // var createdAfter *time.Time
// if filter.CreatedAfter.Valid { // if filter.CreatedAfter.Valid {
// a := filter.CreatedAfter.Value // a := filter.CreatedAfter
// createdAfter = &a // createdAfter = &a
// } // }
// var limit int32 = 10 // var limit int32 = 10
// var offset int32 = 0 // var offset int32 = 0
// if filter.PageSize.Valid { // if filter.PageSize.Valid {
// limit = int32(filter.PageSize.Value) // limit = int32(filter.PageSize)
// } // }
// if filter.Page.Valid && filter.PageSize.Valid { // if filter.Page.Valid && filter.PageSize.Valid {
// offset = int32(filter.Page.Value * filter.PageSize.Value) // offset = int32(filter.Page * filter.PageSize)
// } // }
// return s.userStore.GetAllUsers(ctx, role, query, createdBefore, createdAfter, limit, offset) // return s.userStore.GetAllUsers(ctx, role, query, createdBefore, createdAfter, limit, offset)

View File

@ -163,7 +163,7 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
searchQuery := c.Query("query") searchQuery := c.Query("query")
searchString := domain.ValidString{ searchString := domain.ValidString{
Value: searchQuery, Value: searchQuery,
Valid: searchQuery != "", // Valid: searchQuery != "",
} }
createdBeforeQuery := c.Query("created_before") createdBeforeQuery := c.Query("created_before")
@ -195,15 +195,9 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
// Value: companyID, // Value: companyID,
// Valid: companyID != 0, // Valid: companyID != 0,
// }, // },
Page: domain.ValidInt{ Page: int64(c.QueryInt("page", 1) - 1),
Value: c.QueryInt("page", 1) - 1, PageSize: int64(c.QueryInt("page_size", 10)),
Valid: true, Query: searchString.Value,
},
PageSize: domain.ValidInt{
Value: c.QueryInt("page_size", 10),
Valid: true,
},
Query: searchString,
CreatedBefore: createdBefore, CreatedBefore: createdBefore,
CreatedAfter: createdAfter, CreatedAfter: createdAfter,
} }
@ -262,11 +256,11 @@ func (h *Handler) GetAllAdmins(c *fiber.Ctx) error {
h.mongoLoggerSvc.Info("admins retrieved successfully", h.mongoLoggerSvc.Info("admins retrieved successfully",
zap.Int("status_code", fiber.StatusOK), zap.Int("status_code", fiber.StatusOK),
zap.Int("count", len(result)), zap.Int("count", len(result)),
zap.Int("page", filter.Page.Value+1), zap.Int("page", int(filter.Page+1)),
zap.Time("timestamp", time.Now()), zap.Time("timestamp", time.Now()),
) )
return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page.Value+1, int(total)) return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, int(filter.Page+1), int(total))
} }
// GetAdminByID godoc // GetAdminByID godoc
@ -357,14 +351,8 @@ func (h *Handler) UpdateAdmin(c *fiber.Ctx) error {
err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{ err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
UserID: adminID, UserID: adminID,
FirstName: domain.ValidString{ FirstName: req.FirstName,
Value: req.FirstName, LastName: req.LastName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
// OrganizationID: orgID, // OrganizationID: orgID,
}) })
if err != nil { if err != nil {

View File

@ -403,14 +403,8 @@ func (h *Handler) UpdateTransactionApprover(c *fiber.Ctx) error {
updateReq := domain.UpdateUserReq{ updateReq := domain.UpdateUserReq{
UserID: approverID, UserID: approverID,
FirstName: domain.ValidString{ FirstName: req.FirstName,
Value: req.FirstName, LastName: req.LastName,
Valid: req.FirstName != "",
},
LastName: domain.ValidString{
Value: req.LastName,
Valid: req.LastName != "",
},
} }
err = h.userSvc.UpdateUser(c.Context(), updateReq) err = h.userSvc.UpdateUser(c.Context(), updateReq)
@ -432,4 +426,3 @@ func (h *Handler) UpdateTransactionApprover(c *fiber.Ctx) error {
return response.WriteJSON(c, fiber.StatusOK, "Transaction approver updated successfully", nil, nil) return response.WriteJSON(c, fiber.StatusOK, "Transaction approver updated successfully", nil, nil)
} }

View File

@ -77,10 +77,10 @@ func (h *Handler) CheckProfileCompleted(c *fiber.Ctx) error {
// @Failure 400 {object} domain.ErrorResponse // @Failure 400 {object} domain.ErrorResponse
// @Failure 404 {object} domain.ErrorResponse // @Failure 404 {object} domain.ErrorResponse
// @Failure 500 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/{tenant_slug}/user [put] // @Router /api/v1/user [put]
func (h *Handler) UpdateUser(c *fiber.Ctx) error { func (h *Handler) UpdateUser(c *fiber.Ctx) error {
// Extract user ID from context // Extract user ID from context
userIDStr, ok := c.Locals("user_id").(string) userID, ok := c.Locals("user_id").(int64)
if !ok { if !ok {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user context", Message: "Invalid user context",
@ -88,13 +88,13 @@ func (h *Handler) UpdateUser(c *fiber.Ctx) error {
}) })
} }
userID, err := strconv.ParseInt(userIDStr, 10, 64) // userID, err := strconv.ParseInt(userIDStr, 10, 64)
if err != nil || userID <= 0 { // if err != nil || userID <= 0 {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ // return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user ID", // Message: "Invalid user ID",
Error: "User ID must be a positive integer", // Error: "User ID must be a positive integer",
}) // })
} // }
// Parse request body // Parse request body
var req domain.UpdateUserReq var req domain.UpdateUserReq
@ -152,12 +152,11 @@ func (h *Handler) UpdateUser(c *fiber.Ctx) error {
// @Failure 500 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/{tenant_slug}/user/knowledge-level [put] // @Router /api/v1/{tenant_slug}/user/knowledge-level [put]
func (h *Handler) UpdateUserKnowledgeLevel(c *fiber.Ctx) error { func (h *Handler) UpdateUserKnowledgeLevel(c *fiber.Ctx) error {
userIDStr := c.Locals("user_id").(string) userID, ok := c.Locals("user_id").(int64)
userID, err := strconv.ParseInt(userIDStr, 10, 64) if !ok {
if err != nil || userID <= 0 {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user ID", Message: "Invalid user context",
Error: "User ID must be a positive integer", Error: "User ID not found in request context",
}) })
} }
@ -169,7 +168,7 @@ func (h *Handler) UpdateUserKnowledgeLevel(c *fiber.Ctx) error {
}) })
} }
err = h.userSvc.UpdateUserKnowledgeLevel(c.Context(), userID, req.KnowledgeLevel) err := h.userSvc.UpdateUserKnowledgeLevel(c.Context(), userID, req.KnowledgeLevel)
if err != nil { if err != nil {
if errors.Is(err, authentication.ErrUserNotFound) { if errors.Is(err, authentication.ErrUserNotFound) {
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{ return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
@ -302,30 +301,30 @@ func (h *Handler) ResendOtp(c *fiber.Ctx) error {
// @Failure 400 {object} domain.ErrorResponse // @Failure 400 {object} domain.ErrorResponse
// @Failure 500 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/user/{user_name}/is-unique [get] // @Router /api/v1/user/{user_name}/is-unique [get]
func (h *Handler) CheckUserNameUnique(c *fiber.Ctx) error { // func (h *Handler) CheckUserNameUnique(c *fiber.Ctx) error {
userName := c.Params("user_name") // userName := c.Params("user_name")
if userName == "" { // if userName == "" {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ // return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user name", // Message: "Invalid user name",
Error: "user_name path parameter cannot be empty", // Error: "user_name path parameter cannot be empty",
}) // })
} // }
isUnique, err := h.userSvc.IsUserNameUnique(c.Context(), userName) // isUnique, err := h.userSvc.IsUserNameUnique(c.Context(), userName)
if err != nil { // if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{ // return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
Message: "Failed to check user name uniqueness", // Message: "Failed to check user name uniqueness",
Error: err.Error(), // Error: err.Error(),
}) // })
} // }
return c.Status(fiber.StatusOK).JSON(domain.Response{ // return c.Status(fiber.StatusOK).JSON(domain.Response{
Message: "User name uniqueness checked successfully", // Message: "User name uniqueness checked successfully",
Data: map[string]bool{ // Data: map[string]bool{
"is_unique": isUnique, // "is_unique": isUnique,
}, // },
}) // })
} // }
// CheckUserPending godoc // CheckUserPending godoc
// @Summary Check if user status is pending // @Summary Check if user status is pending
@ -333,22 +332,28 @@ func (h *Handler) CheckUserNameUnique(c *fiber.Ctx) error {
// @Tags user // @Tags user
// @Accept json // @Accept json
// @Produce json // @Produce json
// @Param user_name path string true "User Name" // @Param user_id path string true "User ID"
// @Success 200 {object} domain.Response // @Success 200 {object} domain.Response
// @Failure 400 {object} domain.ErrorResponse // @Failure 400 {object} domain.ErrorResponse
// @Failure 404 {object} domain.ErrorResponse // @Failure 404 {object} domain.ErrorResponse
// @Failure 500 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/{tenant_slug}/user/{user_name}/is-pending [get] // @Router /api/v1/user/{user_id}/is-pending [get]
func (h *Handler) CheckUserPending(c *fiber.Ctx) error { func (h *Handler) CheckUserPending(c *fiber.Ctx) error {
userName := c.Params("user_name") userID, err := strconv.ParseInt(c.Params("user_id"), 10, 64)
if userName == "" { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user name", Message: "Invalid user ID",
Error: "User name cannot be empty", Error: err.Error(),
})
}
if userID == 0 {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user ID",
Error: "User ID cannot be empty",
}) })
} }
isPending, err := h.userSvc.IsUserPending(c.Context(), userName) isPending, err := h.userSvc.IsUserPending(c.Context(), userID)
if err != nil { if err != nil {
if errors.Is(err, authentication.ErrUserNotFound) { if errors.Is(err, authentication.ErrUserNotFound) {
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{ return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
@ -390,7 +395,7 @@ func (h *Handler) GetAllUsers(c *fiber.Ctx) error {
searchQuery := c.Query("query") searchQuery := c.Query("query")
searchString := domain.ValidString{ searchString := domain.ValidString{
Value: searchQuery, Value: searchQuery,
Valid: searchQuery != "", // Valid: searchQuery != "",
} }
createdBeforeQuery := c.Query("created_before") createdBeforeQuery := c.Query("created_before")
@ -417,15 +422,9 @@ func (h *Handler) GetAllUsers(c *fiber.Ctx) error {
filter := domain.UserFilter{ filter := domain.UserFilter{
Role: c.Query("role"), Role: c.Query("role"),
Page: domain.ValidInt{ Page: int64(c.QueryInt("page", 1) - 1),
Value: c.QueryInt("page", 1) - 1, PageSize: int64(c.QueryInt("page_size", 10)),
Valid: true, Query: searchString.Value,
},
PageSize: domain.ValidInt{
Value: c.QueryInt("page_size", 10),
Valid: true,
},
Query: searchString,
CreatedBefore: createdBefore, CreatedBefore: createdBefore,
CreatedAfter: createdAfter, CreatedAfter: createdAfter,
} }
@ -459,7 +458,7 @@ func (h *Handler) GetAllUsers(c *fiber.Ctx) error {
ID: u.ID, ID: u.ID,
FirstName: u.FirstName, FirstName: u.FirstName,
LastName: u.LastName, LastName: u.LastName,
UserName: u.UserName, // UserName: u.UserName,
Email: u.Email, Email: u.Email,
PhoneNumber: u.PhoneNumber, PhoneNumber: u.PhoneNumber,
Role: u.Role, Role: u.Role,
@ -472,7 +471,7 @@ func (h *Handler) GetAllUsers(c *fiber.Ctx) error {
LearningGoal: u.LearningGoal, LearningGoal: u.LearningGoal,
LanguageGoal: u.LanguageGoal, LanguageGoal: u.LanguageGoal,
LanguageChallange: u.LanguageChallange, LanguageChallange: u.LanguageChallange,
FavoutiteTopic: u.FavoutiteTopic, FavouriteTopic: u.FavouriteTopic,
EmailVerified: u.EmailVerified, EmailVerified: u.EmailVerified,
PhoneVerified: u.PhoneVerified, PhoneVerified: u.PhoneVerified,
LastLogin: u.LastLogin, LastLogin: u.LastLogin,
@ -793,9 +792,9 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
} }
user := domain.RegisterUserReq{ user := domain.RegisterUserReq{
FirstName: req.FirstName, // FirstName: req.FirstName,
LastName: req.LastName, // LastName: req.LastName,
UserName: req.UserName, // UserName: req.UserName,
Email: req.Email, Email: req.Email,
PhoneNumber: req.PhoneNumber, PhoneNumber: req.PhoneNumber,
Password: req.Password, Password: req.Password,
@ -812,7 +811,7 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
// LearningGoal: req.LearningGoal, // LearningGoal: req.LearningGoal,
// LanguageGoal: req.LanguageGoal, // LanguageGoal: req.LanguageGoal,
// LanguageChallange: req.LanguageChallange, // LanguageChallange: req.LanguageChallange,
// FavoutiteTopic: req.FavoutiteTopic, // FavouriteTopic: req.FavouriteTopic,
} }
medium, err := getMedium(req.Email, req.PhoneNumber) medium, err := getMedium(req.Email, req.PhoneNumber)
@ -855,9 +854,9 @@ func (h *Handler) RegisterUser(c *fiber.Ctx) error {
func MapRegisterReqToUser(req domain.RegisterUserReq) domain.User { func MapRegisterReqToUser(req domain.RegisterUserReq) domain.User {
return domain.User{ return domain.User{
FirstName: req.FirstName, // FirstName: req.FirstName,
LastName: req.LastName, // LastName: req.LastName,
UserName: req.UserName, // UserName: req.UserName,
Email: req.Email, Email: req.Email,
PhoneNumber: req.PhoneNumber, PhoneNumber: req.PhoneNumber,
Password: []byte(req.Password), // or hashed password Password: []byte(req.Password), // or hashed password
@ -873,7 +872,7 @@ func MapRegisterReqToUser(req domain.RegisterUserReq) domain.User {
// LearningGoal: req.LearningGoal, // LearningGoal: req.LearningGoal,
// LanguageGoal: req.LanguageGoal, // LanguageGoal: req.LanguageGoal,
// LanguageChallange: req.LanguageChallange, // LanguageChallange: req.LanguageChallange,
// FavoutiteTopic: req.FavoutiteTopic, // FavouriteTopic: req.FavouriteTopic,
} }
} }
@ -931,7 +930,7 @@ func (h *Handler) SendResetCode(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided") return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
} }
if err := h.userSvc.SendResetCode(c.Context(), "", medium, sentTo, domain.AfroMessage); err != nil { if err := h.userSvc.SendResetCode(c.Context(), 0, medium, sentTo, domain.AfroMessage); err != nil {
h.mongoLoggerSvc.Error("Failed to send reset code", h.mongoLoggerSvc.Error("Failed to send reset code",
zap.String("medium", string(medium)), zap.String("medium", string(medium)),
zap.String("sentTo", string(sentTo)), zap.String("sentTo", string(sentTo)),
@ -998,7 +997,7 @@ func (h *Handler) SendTenantResetCode(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided") return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
} }
if err := h.userSvc.SendResetCode(c.Context(), "", medium, sentTo, domain.AfroMessage); err != nil { if err := h.userSvc.SendResetCode(c.Context(), 0, medium, sentTo, domain.AfroMessage); err != nil {
h.mongoLoggerSvc.Error("Failed to send reset code", h.mongoLoggerSvc.Error("Failed to send reset code",
zap.String("medium", string(medium)), zap.String("medium", string(medium)),
zap.String("sentTo", string(sentTo)), zap.String("sentTo", string(sentTo)),
@ -1013,7 +1012,7 @@ func (h *Handler) SendTenantResetCode(c *fiber.Ctx) error {
} }
type ResetPasswordReq struct { type ResetPasswordReq struct {
UserName string `json:"user_name" validate:"required" example:"johndoe"` UserID int64 `json:"user_name" validate:"required" example:"johndoe"`
Password string `json:"password" validate:"required,min=8" example:"newpassword123"` Password string `json:"password" validate:"required,min=8" example:"newpassword123"`
Otp string `json:"otp" validate:"required" example:"123456"` Otp string `json:"otp" validate:"required" example:"123456"`
} }
@ -1072,7 +1071,7 @@ func (h *Handler) ResetPassword(c *fiber.Ctx) error {
// } // }
resetReq := domain.ResetPasswordReq{ resetReq := domain.ResetPasswordReq{
UserName: req.UserName, UserID: req.UserID,
Password: req.Password, Password: req.Password,
OtpCode: req.Otp, OtpCode: req.Otp,
} }
@ -1139,7 +1138,7 @@ func (h *Handler) ResetTenantPassword(c *fiber.Ctx) error {
// } // }
resetReq := domain.ResetPasswordReq{ resetReq := domain.ResetPasswordReq{
UserName: req.UserName, UserID: req.UserID,
Password: req.Password, Password: req.Password,
OtpCode: req.Otp, OtpCode: req.Otp,
} }
@ -1210,7 +1209,8 @@ func (h *Handler) GetUserProfile(c *fiber.Ctx) error {
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
UserName: user.UserName, // UserName: user.UserName,
Occupation: user.Occupation,
Email: user.Email, Email: user.Email,
PhoneNumber: user.PhoneNumber, PhoneNumber: user.PhoneNumber,
Role: user.Role, Role: user.Role,
@ -1299,7 +1299,7 @@ func (h *Handler) AdminProfile(c *fiber.Ctx) error {
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
UserName: user.UserName, // UserName: user.UserName,
Email: user.Email, Email: user.Email,
PhoneNumber: user.PhoneNumber, PhoneNumber: user.PhoneNumber,
Role: user.Role, Role: user.Role,
@ -1421,7 +1421,7 @@ func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
UserName: user.UserName, // UserName: user.UserName,
Email: user.Email, Email: user.Email,
PhoneNumber: user.PhoneNumber, PhoneNumber: user.PhoneNumber,
Role: user.Role, Role: user.Role,
@ -1503,7 +1503,7 @@ func (h *Handler) GetUserByID(c *fiber.Ctx) error {
ID: user.ID, ID: user.ID,
FirstName: user.FirstName, FirstName: user.FirstName,
LastName: user.LastName, LastName: user.LastName,
UserName: user.UserName, // UserName: user.UserName,
Email: user.Email, Email: user.Email,
PhoneNumber: user.PhoneNumber, PhoneNumber: user.PhoneNumber,
Role: user.Role, Role: user.Role,

View File

@ -198,7 +198,7 @@ func (a *App) initAppRoutes() {
groupV1.Get("/users", a.authMiddleware, h.GetAllUsers) groupV1.Get("/users", a.authMiddleware, h.GetAllUsers)
groupV1.Put("/user", a.authMiddleware, h.UpdateUser) groupV1.Put("/user", a.authMiddleware, h.UpdateUser)
groupV1.Put("/user/knowledge-level", h.UpdateUserKnowledgeLevel) groupV1.Put("/user/knowledge-level", h.UpdateUserKnowledgeLevel)
groupV1.Get("/user/:user_name/is-unique", h.CheckUserNameUnique) // groupV1.Get("/user/:user_name/is-unique", h.CheckUserNameUnique)
groupV1.Get("/user/:user_name/is-pending", h.CheckUserPending) groupV1.Get("/user/:user_name/is-pending", h.CheckUserPending)
groupV1.Post("/user/resetPassword", h.ResetPassword) groupV1.Post("/user/resetPassword", h.ResetPassword)
groupV1.Post("/user/sendResetCode", h.SendResetCode) groupV1.Post("/user/sendResetCode", h.SendResetCode)