From 21d44321eed91900a332a1ae46950aaf99c7fc69 Mon Sep 17 00:00:00 2001 From: RewanshChoudhary Date: Sat, 7 Feb 2026 17:10:25 +0530 Subject: [PATCH 1/7] phone no duplication, team name limit from 5 to 50 and update regno function addition --- database/queries/users.sql | 15 +++++++-- pkg/controllers/teams.go | 13 ++++--- pkg/controllers/user.go | 20 +++++++++++ pkg/db/sqlc/teams.sql.go | 19 ++++++----- pkg/db/sqlc/users.sql.go | 69 ++++++++++++++++++++++++++++---------- 5 files changed, 104 insertions(+), 32 deletions(-) diff --git a/database/queries/users.sql b/database/queries/users.sql index ed3a394..dba8cf5 100644 --- a/database/queries/users.sql +++ b/database/queries/users.sql @@ -149,7 +149,10 @@ SET is_leader = FALSE, updated_at = now() WHERE id = $1::uuid; - +-- name: GetUserByPhoneNo :one + SELECT * +FROM users +WHERE phone_no = $1; -- name: GetTeamIDByUID :one SELECT team_id @@ -189,4 +192,12 @@ updated AS ( AND EXISTS (SELECT 1 FROM new_leader) RETURNING * ) -SELECT * FROM updated; \ No newline at end of file + +SELECT * FROM updated; +-- name: UpdateRegNo :exec +UPDATE users +SET + reg_no = $2, + updated_at = now() +WHERE email = $1; + diff --git a/pkg/controllers/teams.go b/pkg/controllers/teams.go index f46d42b..0b79f5d 100644 --- a/pkg/controllers/teams.go +++ b/pkg/controllers/teams.go @@ -3,6 +3,7 @@ package controllers import ( "fmt" "net/http" + "strings" "time" "github.com/CodeChefVIT/devsoc-backend-26/pkg/db" @@ -49,6 +50,13 @@ func CreateTeam(c echo.Context) error { team sqlc.Team err error ) + if len(strings.TrimSpace(req.Name)) < 5 || len(req.Name) > 50 { + return c.JSON(http.StatusBadRequest, &models.Response{ + Success: false, + Message: "team name should be in between 5 to 50 characters", + }) + } + ctx := c.Request().Context() exists, err := db.Queries.NameExists(ctx, req.Name) if err != nil { @@ -63,7 +71,7 @@ func CreateTeam(c echo.Context) error { Message: "team name already taken TwT", }) } - for attempts := 0; attempts < 5; attempts++ { + for range 5 { code, genErr := utils.GenerateTeamCode(6) if genErr != nil { return c.JSON(http.StatusInternalServerError, &models.Response{ @@ -242,7 +250,6 @@ func UpdateTeam(c echo.Context) error { ID: id, Name: name, }) - if err != nil { return c.JSON(http.StatusInternalServerError, &models.Response{ Success: false, @@ -285,7 +292,6 @@ func ToggleTeamBan(c echo.Context) error { IsBanned: newBanStatus, TotalScore: existing.TotalScore, }) - if err != nil { return c.JSON(http.StatusInternalServerError, &models.Response{ Success: false, @@ -339,7 +345,6 @@ func JoinTeam(c echo.Context) error { teamKeyStr, 30*time.Minute, ).Result() - if err != nil { fmt.Printf("Rediserror: %v\n", err) return c.JSON(http.StatusInternalServerError, &models.Response{ diff --git a/pkg/controllers/user.go b/pkg/controllers/user.go index 13ffc06..dac3c8f 100644 --- a/pkg/controllers/user.go +++ b/pkg/controllers/user.go @@ -131,6 +131,16 @@ func CompleteProfile(c echo.Context) error { }) } + if req.PhoneNo != "" { + existingPhone, err := db.Queries.GetUserByPhoneNo(ctx, &req.PhoneNo) + if err == nil && existingPhone.ID != user.ID { + return c.JSON(http.StatusConflict, models.Response{ + Success: false, + Message: "Phone number already in use", + }) + } + } + phone := req.PhoneNo gender := req.Gender ghub := req.GithubProfile @@ -241,6 +251,16 @@ func UpdateProfile(c echo.Context) error { }) } + if req.PhoneNo != "" { + existingPhone, err := db.Queries.GetUserByPhoneNo(ctx, &req.PhoneNo) + if err == nil && existingPhone.ID != user.ID { + return c.JSON(http.StatusConflict, models.Response{ + Success: false, + Message: "Phone number already in use", + }) + } + } + phone := req.PhoneNo gender := req.Gender ghub := req.GithubProfile diff --git a/pkg/db/sqlc/teams.sql.go b/pkg/db/sqlc/teams.sql.go index 090618a..f5d8f85 100644 --- a/pkg/db/sqlc/teams.sql.go +++ b/pkg/db/sqlc/teams.sql.go @@ -69,6 +69,16 @@ func (q *Queries) DecrementSize(ctx context.Context, id pgtype.UUID) error { return err } +const deleteTeam = `-- name: DeleteTeam :exec +DELETE FROM teams +WHERE id = $1 +` + +func (q *Queries) DeleteTeam(ctx context.Context, id pgtype.UUID) error { + _, err := q.db.Exec(ctx, deleteTeam, id) + return err +} + const getAllTeams = `-- name: GetAllTeams :many SELECT id, name, team_size, round_qualified, code, is_banned, total_score FROM teams @@ -366,12 +376,3 @@ func (q *Queries) UpdateTeamName(ctx context.Context, arg UpdateTeamNameParams) _, err := q.db.Exec(ctx, updateTeamName, arg.Name, arg.ID) return err } -const deleteTeam = `-- name: DeleteTeam :exec -DELETE FROM teams -WHERE id = $1 -` - -func (q *Queries) DeleteTeam(ctx context.Context, id pgtype.UUID) error { - _, err := q.db.Exec(ctx, deleteTeam, id) - return err -} \ No newline at end of file diff --git a/pkg/db/sqlc/users.sql.go b/pkg/db/sqlc/users.sql.go index 697c78c..e6dfd34 100644 --- a/pkg/db/sqlc/users.sql.go +++ b/pkg/db/sqlc/users.sql.go @@ -112,23 +112,6 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) error { return err } -const updateRegNo = `UPDATE users -SET - reg_no = $2, - updated_at = now() -WHERE email = $1 -` - -type UpdateRegNoParams struct { - Email string - RegNo *string -} - -func (q *Queries) UpdateRegNo(ctx context.Context, arg UpdateRegNoParams) error { - _, err := q.db.Exec(ctx, updateRegNo, arg.Email, arg.RegNo) - return err -} - const getAllUsers = `-- name: GetAllUsers :many SELECT u.id, @@ -333,6 +316,39 @@ func (q *Queries) GetUserByEmail(ctx context.Context, email string) (User, error return i, err } +const getUserByPhoneNo = `-- name: GetUserByPhoneNo :one + SELECT id, team_id, name, email, phone_no, reg_no, gender, hostel_block, room_no, github_profile, residency, role, is_leader, is_banned, is_profile_complete, google_id, google_profile_pic, created_at, updated_at +FROM users +WHERE phone_no = $1 +` + +func (q *Queries) GetUserByPhoneNo(ctx context.Context, phoneNo *string) (User, error) { + row := q.db.QueryRow(ctx, getUserByPhoneNo, phoneNo) + var i User + err := row.Scan( + &i.ID, + &i.TeamID, + &i.Name, + &i.Email, + &i.PhoneNo, + &i.RegNo, + &i.Gender, + &i.HostelBlock, + &i.RoomNo, + &i.GithubProfile, + &i.Residency, + &i.Role, + &i.IsLeader, + &i.IsBanned, + &i.IsProfileComplete, + &i.GoogleID, + &i.GoogleProfilePic, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + const getUserByRegNo = `-- name: GetUserByRegNo :one SELECT id, team_id, name, email, phone_no, reg_no, gender, hostel_block, room_no, github_profile, residency, role, is_leader, is_banned, is_profile_complete, google_id, google_profile_pic, created_at, updated_at FROM users @@ -537,6 +553,7 @@ updated AS ( AND EXISTS (SELECT 1 FROM new_leader) RETURNING id, team_id, name, email, phone_no, reg_no, gender, hostel_block, room_no, github_profile, residency, role, is_leader, is_banned, is_profile_complete, google_id, google_profile_pic, created_at, updated_at ) + SELECT id, team_id, name, email, phone_no, reg_no, gender, hostel_block, room_no, github_profile, residency, role, is_leader, is_banned, is_profile_complete, google_id, google_profile_pic, created_at, updated_at FROM updated ` @@ -600,6 +617,24 @@ func (q *Queries) UnbanUser(ctx context.Context, email string) error { return err } +const updateRegNo = `-- name: UpdateRegNo :exec +UPDATE users +SET + reg_no = $2, + updated_at = now() +WHERE email = $1 +` + +type UpdateRegNoParams struct { + Email string + RegNo *string +} + +func (q *Queries) UpdateRegNo(ctx context.Context, arg UpdateRegNoParams) error { + _, err := q.db.Exec(ctx, updateRegNo, arg.Email, arg.RegNo) + return err +} + const updateTeamByEmail = `-- name: UpdateTeamByEmail :exec UPDATE users SET team_id = $1 From deb7d8d8d56e9964c53727b3f57c0741f2861c9e Mon Sep 17 00:00:00 2001 From: RewanshChoudhary Date: Sat, 7 Feb 2026 17:45:41 +0530 Subject: [PATCH 2/7] A user can't join a team that has no members --- docker-compose.dev.yml | 81 ++++++++++++++++++++++++++++++++++++++++ pkg/controllers/teams.go | 14 +++++++ 2 files changed, 95 insertions(+) create mode 100644 docker-compose.dev.yml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..ab302b6 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,81 @@ +services: + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:9.2.3 + container_name: elastic + env_file: + - .env + ports: + - 127.0.0.1:9200:9200 + volumes: + - ./elasticsearch/certs:/usr/share/elasticsearch/config/certs:ro + - elastic_data:/usr/share/elasticsearch/data + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + healthcheck: + test: + ["CMD-SHELL", "curl http://localhost:9200/_cluster/health || exit 1"] + interval: 5s + timeout: 2s + retries: 20 + environment: + - discovery.type=single-node + - xpack.security.enabled=false + - bootstrap.memory_lock=true + + + postgres: + image: postgres:16 + container_name: devsoc_postgres + env_file: + - .env + ports: + - "127.0.0.1:5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + + redis: + image: redis:latest + container_name: devsoc_redis + ports: + - "127.0.0.1:6379:6379" + env_file: + - .env + volumes: + - redis_data:/data + + api: + build: + context: ./ + dockerfile: Dockerfile.dev + container_name: devsoc_api + ports: + - "127.0.0.1:8080:8080" + volumes: + - .:/app + env_file: + - .env + environment: + - GOFLAGS=-buildvcs=false + restart: on-failure + depends_on: + elasticsearch: + condition: service_healthy + postgres: + condition: service_started + redis: + condition: service_started + command: > + sh -c " + goose -dir database/schema up && + air -c .air.toml + " + +volumes: + postgres_data: + redis_data: + elastic_data: diff --git a/pkg/controllers/teams.go b/pkg/controllers/teams.go index 0b79f5d..f93af84 100644 --- a/pkg/controllers/teams.go +++ b/pkg/controllers/teams.go @@ -337,6 +337,20 @@ func JoinTeam(c echo.Context) error { }) } + teamSize, err := db.Queries.GetTeamSizeByID(ctx, teamKey) + if err != nil { + return c.JSON(http.StatusInternalServerError, &models.Response{ + Success: false, + Message: "failed to verify team", + }) + } + if teamSize == 0 { + return c.JSON(http.StatusBadRequest, &models.Response{ + Success: false, + Message: "cannot join a team that has no members", + }) + } + teamKeyStr := teamKey.String() ok, err = redis.RequestManager.SetNX( From 4cbb3c04d4cad6c3c1a91aa4cbac0b707e047dc6 Mon Sep 17 00:00:00 2001 From: RewanshChoudhary Date: Sat, 7 Feb 2026 17:46:42 +0530 Subject: [PATCH 3/7] .. --- docker-compose.dev.yml | 81 ------------------------------------------ 1 file changed, 81 deletions(-) delete mode 100644 docker-compose.dev.yml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml deleted file mode 100644 index ab302b6..0000000 --- a/docker-compose.dev.yml +++ /dev/null @@ -1,81 +0,0 @@ -services: - elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:9.2.3 - container_name: elastic - env_file: - - .env - ports: - - 127.0.0.1:9200:9200 - volumes: - - ./elasticsearch/certs:/usr/share/elasticsearch/config/certs:ro - - elastic_data:/usr/share/elasticsearch/data - ulimits: - memlock: - soft: -1 - hard: -1 - nofile: - soft: 65536 - hard: 65536 - healthcheck: - test: - ["CMD-SHELL", "curl http://localhost:9200/_cluster/health || exit 1"] - interval: 5s - timeout: 2s - retries: 20 - environment: - - discovery.type=single-node - - xpack.security.enabled=false - - bootstrap.memory_lock=true - - - postgres: - image: postgres:16 - container_name: devsoc_postgres - env_file: - - .env - ports: - - "127.0.0.1:5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - - redis: - image: redis:latest - container_name: devsoc_redis - ports: - - "127.0.0.1:6379:6379" - env_file: - - .env - volumes: - - redis_data:/data - - api: - build: - context: ./ - dockerfile: Dockerfile.dev - container_name: devsoc_api - ports: - - "127.0.0.1:8080:8080" - volumes: - - .:/app - env_file: - - .env - environment: - - GOFLAGS=-buildvcs=false - restart: on-failure - depends_on: - elasticsearch: - condition: service_healthy - postgres: - condition: service_started - redis: - condition: service_started - command: > - sh -c " - goose -dir database/schema up && - air -c .air.toml - " - -volumes: - postgres_data: - redis_data: - elastic_data: From 69177b68aaf2f9a50cae0ee256c694d3833d611b Mon Sep 17 00:00:00 2001 From: Rewansh Choudhary Date: Sat, 7 Feb 2026 18:40:55 +0530 Subject: [PATCH 4/7] Redundant operation --- pkg/controllers/teams.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pkg/controllers/teams.go b/pkg/controllers/teams.go index f93af84..c353b0e 100644 --- a/pkg/controllers/teams.go +++ b/pkg/controllers/teams.go @@ -337,19 +337,6 @@ func JoinTeam(c echo.Context) error { }) } - teamSize, err := db.Queries.GetTeamSizeByID(ctx, teamKey) - if err != nil { - return c.JSON(http.StatusInternalServerError, &models.Response{ - Success: false, - Message: "failed to verify team", - }) - } - if teamSize == 0 { - return c.JSON(http.StatusBadRequest, &models.Response{ - Success: false, - Message: "cannot join a team that has no members", - }) - } teamKeyStr := teamKey.String() From 6486440ac1fa96d5d608bcf64456faecae770081 Mon Sep 17 00:00:00 2001 From: Rewansh Choudhary Date: Sat, 7 Feb 2026 20:28:55 +0530 Subject: [PATCH 5/7] Change team name length validation limits Update team name length validation to be between 5 and 12 characters. --- pkg/controllers/teams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/teams.go b/pkg/controllers/teams.go index c353b0e..5920999 100644 --- a/pkg/controllers/teams.go +++ b/pkg/controllers/teams.go @@ -50,7 +50,7 @@ func CreateTeam(c echo.Context) error { team sqlc.Team err error ) - if len(strings.TrimSpace(req.Name)) < 5 || len(req.Name) > 50 { + if len(strings.TrimSpace(req.Name)) < 5 || len(req.Name) > 12 { return c.JSON(http.StatusBadRequest, &models.Response{ Success: false, Message: "team name should be in between 5 to 50 characters", From 2f2b5409c26749d0ea1b551d966e559921c4f296 Mon Sep 17 00:00:00 2001 From: RewanshChoudhary Date: Sun, 8 Feb 2026 02:26:13 +0530 Subject: [PATCH 6/7] Added the mandatory field for github --- database/queries/users.sql | 5 +---- pkg/controllers/submission.go | 3 --- pkg/utils/validators.go | 15 ++++++++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/database/queries/users.sql b/database/queries/users.sql index 54340a4..cf3e142 100644 --- a/database/queries/users.sql +++ b/database/queries/users.sql @@ -149,10 +149,7 @@ SET is_leader = FALSE, updated_at = now() WHERE id = $1::uuid; --- name: GetUserByPhoneNo :one - SELECT * -FROM users -WHERE phone_no = $1; + -- name: GetTeamIDByUID :one SELECT team_id diff --git a/pkg/controllers/submission.go b/pkg/controllers/submission.go index c9851b9..1d6ea3e 100644 --- a/pkg/controllers/submission.go +++ b/pkg/controllers/submission.go @@ -33,7 +33,6 @@ func CreateSubmission(c echo.Context) error { Success: false, Message: "Invalid request payload", }) - } if errors := utils.ValSub( @@ -55,7 +54,6 @@ func CreateSubmission(c echo.Context) error { Success: false, Message: "User or team not found", }) - } exists, err := db.Queries.Submission(ctx, teamID) @@ -180,7 +178,6 @@ func GetSubmission(c echo.Context) error { Success: false, Message: "Submission not found", }) - } log.Println("Error while getting submission from db: ", err) return c.JSON(http.StatusInternalServerError, &models.Response{ diff --git a/pkg/utils/validators.go b/pkg/utils/validators.go index 1c4c570..b510e3d 100644 --- a/pkg/utils/validators.go +++ b/pkg/utils/validators.go @@ -77,6 +77,11 @@ func FormatValidationErrors(err error) []string { } func ValSub(t, d, g, f, o string) string { + chk := func(v string) bool { + u, err := url.ParseRequestURI(v) + return err == nil && (u.Scheme == "http" || u.Scheme == "https") + } + t = strings.TrimSpace(t) if t == "" { return "title is required" @@ -93,14 +98,14 @@ func ValSub(t, d, g, f, o string) string { return "description too long" } - chk := func(v string) bool { - u, err := url.ParseRequestURI(v) - return err == nil && (u.Scheme == "http" || u.Scheme == "https") + g = strings.TrimSpace(g) + if g == "" { + return "github link is required" } - - if strings.TrimSpace(g) != "" && !chk(g) { + if !chk(g) { return "invalid github url" } + if strings.TrimSpace(f) != "" && !chk(f) { return "invalid figma url" } From 20f2fc3174696bb852b3dcb715e483af73d2b87e Mon Sep 17 00:00:00 2001 From: Rewansh Choudhary Date: Sun, 8 Feb 2026 02:33:57 +0530 Subject: [PATCH 7/7] Fix team name length validation message --- pkg/controllers/teams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/teams.go b/pkg/controllers/teams.go index 5920999..e69ec48 100644 --- a/pkg/controllers/teams.go +++ b/pkg/controllers/teams.go @@ -53,7 +53,7 @@ func CreateTeam(c echo.Context) error { if len(strings.TrimSpace(req.Name)) < 5 || len(req.Name) > 12 { return c.JSON(http.StatusBadRequest, &models.Response{ Success: false, - Message: "team name should be in between 5 to 50 characters", + Message: "team name should be in between 5 to 12 characters", }) }