Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
360 changes: 345 additions & 15 deletions schema/schema.graphql

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/features/account/components/create-admin-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const FIELDS: {
name: 'username',
label: '아이디',
autoComplete: 'off',
help: '4~80자의 영문 소문자, 숫자, 마침표(.), 밑줄(_), 하이픈(-)을 쓸 수 있습니다.',
help: '4~80자의 영문, 숫자, 마침표(.), 밑줄(_), 하이픈(-)을 쓸 수 있습니다. 로그인할 때 대소문자는 구분하지 않습니다.',
},
{
name: 'password',
Expand Down
2 changes: 2 additions & 0 deletions src/features/account/create-admin-schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ describe('createAdminSchema', () => {
it.each([
[{}, true],
[{ username: 'Ops' }, false],
[{ username: 'Ops.Admin_1' }, true],
[{ username: 'ops@admin' }, false],
[{ email: 'nope' }, false],
[{ email: 'a@b.co', name: '운영' }, true],
])('%j → %s', (patch, ok) => {
Expand Down
6 changes: 3 additions & 3 deletions src/features/account/create-admin-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { z } from 'zod';

import { initialPasswordSchema } from '@/shared/lib/initial-password';

/** BE AdminCreateAdminInput 규칙: 아이디 4~80 소문자·숫자·._-, 초기 비밀번호 8~64자. */
/** BE AdminCreateAdminInput 규칙: 아이디 4~80 영문·숫자·._-, 초기 비밀번호 8~64자. */
export const createAdminSchema = z.object({
username: z
.string()
.trim()
.regex(
/^[a-z0-9._-]{4,80}$/,
'아이디는 4~80자의 영문 소문자, 숫자, 마침표(.), 밑줄(_), 하이픈(-)으로 입력해 주세요.',
/^[A-Za-z0-9._-]{4,80}$/,
'아이디는 4~80자의 영문, 숫자, 마침표(.), 밑줄(_), 하이픈(-)으로 입력해 주세요.',
),
password: initialPasswordSchema,
email: z.string().trim().email('이메일 형식이 아닙니다.').or(z.literal('')),
Expand Down
2 changes: 1 addition & 1 deletion src/features/account/pages/admins.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('관리자 계정', () => {
await userEvent.click(within(dialog).getByRole('button', { name: '추가' }));
expect(
await within(dialog).findByText(
'아이디는 4~80자의 영문 소문자, 숫자, 마침표(.), 밑줄(_), 하이픈(-)으로 입력해 주세요.',
'아이디는 4~80자의 영문, 숫자, 마침표(.), 밑줄(_), 하이픈(-)으로 입력해 주세요.',
),
).toBeInTheDocument();
await userEvent.type(within(dialog).getByLabelText('아이디'), 'new.admin');
Expand Down
2 changes: 1 addition & 1 deletion src/features/sellers/components/create-seller-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const TEXT: {
label: '아이디',
required: true,
autoComplete: 'off',
help: '4~80자의 영문 소문자, 숫자, 마침표(.), 밑줄(_), 하이픈(-)을 쓸 수 있습니다.',
help: '4~80자의 영문, 숫자, 마침표(.), 밑줄(_), 하이픈(-)을 쓸 수 있습니다. 로그인할 때 대소문자는 구분하지 않습니다.',
},
{
name: 'password',
Expand Down
7 changes: 6 additions & 1 deletion src/features/sellers/create-seller-schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('createSellerSchema', () => {
});

it.each([
['username', 'Lumi'], // 대문자
['username', 'lumi@shop'], // 허용 외 문자
['username', 'ab'], // 짧음
['password', '1234567'], // 7자
['password', 'a'.repeat(65)],
Expand All @@ -63,6 +63,11 @@ describe('createSellerSchema', () => {
expect(createSellerSchema.safeParse({ ...base, [key]: value }).success).toBe(false);
});

it('아이디에 영문 대문자를 받고 입력 그대로 보낸다', () => {
const parsed = createSellerSchema.parse({ ...base, username: 'Lumi.Cake' });
expect(toCreateSellerInput(parsed).username).toBe('Lumi.Cake');
});

// BE 상한: auth-admin.constants(name·email), store-field-limits(나머지)
it.each([
['name', 100],
Expand Down
4 changes: 2 additions & 2 deletions src/features/sellers/create-seller-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { z } from 'zod';
import { refineCoordPair, storeLocationShape } from '@/features/stores';
import { initialPasswordSchema } from '@/shared/lib/initial-password';

const USERNAME = /^[a-z0-9._-]{4,80}$/;
const USERNAME = /^[A-Za-z0-9._-]{4,80}$/;

/** BE 상한(auth-admin.constants·store-field-limits). BE는 trim 뒤 코드 포인트로 센다. */
const SELLER_FIELD_MAX = {
Expand Down Expand Up @@ -32,7 +32,7 @@ const sellerFields = z.object({
.trim()
.regex(
USERNAME,
'아이디는 4~80자의 영문 소문자, 숫자, 마침표(.), 밑줄(_), 하이픈(-)으로 입력해 주세요.',
'아이디는 4~80자의 영문, 숫자, 마침표(.), 밑줄(_), 하이픈(-)으로 입력해 주세요.',
),
password: initialPasswordSchema,
email: maxChars(SELLER_FIELD_MAX.email)
Expand Down
4 changes: 2 additions & 2 deletions src/graphql/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export type AdminCreateAdminInput = {
name?: string | null | undefined;
/** 초기 비밀번호. 8~64자(공백만으로는 불가). 최초 로그인 시 변경이 강제되므로 조합 규칙은 없다. */
password: string;
/** 로그인 username. 4~80자, 소문자·숫자·`.`·`_`·`-`만 허용. 이미 쓰이고 있으면 BAD_USER_INPUT. */
/** 로그인 username. 4~80자, 영문 대소문자·숫자·`.`·`_`·`-`만 허용. 이미 쓰이고 있으면(대소문자만 달라도) BAD_USER_INPUT. */
username: string;
};

Expand Down Expand Up @@ -169,7 +169,7 @@ export type AdminCreateSellerInput = {
password: string;
/** 매장 기본 정보. */
store: AdminCreateSellerStoreInput;
/** 로그인 username. 4~80자, 소문자·숫자·`.`·`_`·`-`만 허용. 이미 쓰이고 있으면 BAD_USER_INPUT. */
/** 로그인 username. 4~80자, 영문 대소문자·숫자·`.`·`_`·`-`만 허용. 이미 쓰이고 있으면(대소문자만 달라도) BAD_USER_INPUT. */
username: string;
/** 홈페이지·SNS URL. 선택. */
websiteUrl?: string | null | undefined;
Expand Down
Loading