Skip to content

Commit 5b5fb8c

Browse files
ImTotemclaude
andcommitted
fix(auth): school_email unique constraint + duplicate check
- Add unique constraint on school_email (migration 007) - Register checks both Google email and school_email for duplicates - Add find_by_school_email to PgMemberRepository - Error messages in Korean for user-facing conflict responses Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1e80e3e commit 5b5fb8c

File tree

4 files changed

+32
-4
lines changed

4 files changed

+32
-4
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""add unique constraint on school_email
2+
3+
Revision ID: 007
4+
Revises: 006
5+
"""
6+
7+
from alembic import op
8+
9+
revision = "007"
10+
down_revision = "006"
11+
12+
13+
def upgrade() -> None:
14+
op.create_unique_constraint("uq_members_school_email", "members", ["school_email"])
15+
16+
17+
def downgrade() -> None:
18+
op.drop_constraint("uq_members_school_email", "members")

src/bcsd_api/auth/service.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def register(
4141
settings: Settings, repo: PgMemberRepository, conn: Connection,
4242
) -> tuple[str, str]:
4343
profile = google_auth.verify_token(google_token, settings.google_client_id)
44-
_check_duplicate(profile["email"], repo)
44+
_check_duplicate(profile["email"], school_email, repo)
4545
member_id = generate_id("M")
4646
row = _build_row(
4747
member_id, name, profile["email"],
@@ -60,9 +60,11 @@ def _issue_jwt(payload: dict, settings: Settings) -> str:
6060
)
6161

6262

63-
def _check_duplicate(email: str, repo: PgMemberRepository) -> None:
63+
def _check_duplicate(email: str, school_email: str, repo: PgMemberRepository) -> None:
6464
if repo.find_by_email(email):
65-
raise Conflict("member already registered")
65+
raise Conflict("이미 가입된 Google 계정입니다")
66+
if repo.find_by_school_email(school_email):
67+
raise Conflict("이미 가입된 학교 이메일입니다")
6668

6769

6870
def _now_kst() -> str:

src/bcsd_api/member/pg_repository.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ def find_by_email(self, email: str) -> dict | None:
1616
return None
1717
return row._asdict()
1818

19+
def find_by_school_email(self, school_email: str) -> dict | None:
20+
row = self._conn.execute(
21+
select(members).where(members.c.school_email == school_email),
22+
).first()
23+
if not row:
24+
return None
25+
return row._asdict()
26+
1927
def create(self, row: dict) -> None:
2028
self._conn.execute(insert(members).values(**row))
2129

src/bcsd_api/tables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Column("email", String, nullable=False, unique=True),
1010
Column("department", String),
1111
Column("student_id", String),
12-
Column("school_email", String),
12+
Column("school_email", String, unique=True),
1313
Column("phone", String),
1414
Column("status", String, nullable=False, server_default="Beginner"),
1515
Column("track", String),

0 commit comments

Comments
 (0)