음성 재생과 운영 배포 정리
This commit is contained in:
parent
8ed185ce6c
commit
ac7db95542
1020 changed files with 46863 additions and 2175 deletions
|
|
@ -7,9 +7,10 @@ import {
|
|||
useState,
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import { api, authApi, type MeResponse } from "./api";
|
||||
import { api, apiUrl, authApi, type MeResponse } from "./api";
|
||||
|
||||
export type Role = "learner" | "teacher" | "admin";
|
||||
export type AccountStatus = "pending" | "approved" | "suspended";
|
||||
export type DesignRole = "learner" | "instructor" | "admin";
|
||||
|
||||
export interface AuthUser {
|
||||
|
|
@ -17,8 +18,16 @@ export interface AuthUser {
|
|||
email: string;
|
||||
name: string;
|
||||
role: Role;
|
||||
adminAccess: boolean;
|
||||
superAdmin: boolean;
|
||||
accountStatus: AccountStatus;
|
||||
approvalRequired: boolean;
|
||||
cohortIds: string[];
|
||||
consentAt: number | null;
|
||||
onboardingCompletedAt: number | null;
|
||||
nickname: string;
|
||||
selfIntroduction: string;
|
||||
avatarUrl: string;
|
||||
}
|
||||
|
||||
export interface AuthContextValue {
|
||||
|
|
@ -27,6 +36,7 @@ export interface AuthContextValue {
|
|||
loading: boolean;
|
||||
login: (role: Role, opts?: { email?: string; displayName?: string }) => Promise<AuthUser>;
|
||||
logout: () => Promise<void>;
|
||||
refresh: () => Promise<AuthUser | null>;
|
||||
acceptConsent: () => Promise<void>;
|
||||
withdrawConsent: () => Promise<void>;
|
||||
}
|
||||
|
|
@ -57,6 +67,12 @@ export function roleHomePath(role: Role): string {
|
|||
}
|
||||
}
|
||||
|
||||
export function canAccessRole(user: AuthUser, role: Role): boolean {
|
||||
if (user.role === role) return true;
|
||||
if (user.superAdmin) return true;
|
||||
return role === "admin" && user.adminAccess;
|
||||
}
|
||||
|
||||
const DEV_EMAIL_BY_ROLE: Record<Role, string> = {
|
||||
learner: "learner@hs.ac.kr",
|
||||
teacher: "teacher@hs.ac.kr",
|
||||
|
|
@ -72,13 +88,24 @@ const DEV_NAME_BY_ROLE: Record<Role, string> = {
|
|||
const AuthContext = createContext<AuthContextValue | null>(null);
|
||||
|
||||
function userFromMe(me: MeResponse): AuthUser {
|
||||
const onboarding = me as MeResponse & { onboarding_completed_at?: number | null };
|
||||
const nickname = (me.nickname ?? "").trim();
|
||||
const avatarUrl = (me.avatar_url ?? "").trim();
|
||||
return {
|
||||
userId: me.user_id,
|
||||
email: me.email,
|
||||
name: me.display_name || me.email || me.user_id,
|
||||
name: nickname || me.display_name || me.email || me.user_id,
|
||||
role: (me.role as Role) ?? "learner",
|
||||
adminAccess: Boolean(me.admin_access),
|
||||
superAdmin: Boolean(me.super_admin),
|
||||
accountStatus: (me.account_status as AccountStatus | undefined) ?? "approved",
|
||||
approvalRequired: me.approval_required ?? false,
|
||||
cohortIds: me.cohort_ids ?? [],
|
||||
consentAt: me.consent_at ?? null,
|
||||
onboardingCompletedAt: onboarding.onboarding_completed_at ?? null,
|
||||
nickname,
|
||||
selfIntroduction: (me.self_introduction ?? "").trim(),
|
||||
avatarUrl: avatarUrl ? apiUrl(avatarUrl) : "",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +147,18 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||
return next;
|
||||
}, []);
|
||||
|
||||
const refresh = useCallback<AuthContextValue["refresh"]>(async () => {
|
||||
try {
|
||||
const me = await api.get<MeResponse>("/auth/me");
|
||||
const next = userFromMe(me);
|
||||
setUser(next);
|
||||
return next;
|
||||
} catch {
|
||||
setUser(null);
|
||||
return null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const logout = useCallback<AuthContextValue["logout"]>(async () => {
|
||||
try {
|
||||
await api.post("/auth/logout");
|
||||
|
|
@ -141,8 +180,17 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||
}, []);
|
||||
|
||||
const value = useMemo<AuthContextValue>(
|
||||
() => ({ user, role: user?.role ?? null, loading, login, logout, acceptConsent, withdrawConsent }),
|
||||
[user, loading, login, logout, acceptConsent, withdrawConsent],
|
||||
() => ({
|
||||
user,
|
||||
role: user?.role ?? null,
|
||||
loading,
|
||||
login,
|
||||
logout,
|
||||
refresh,
|
||||
acceptConsent,
|
||||
withdrawConsent,
|
||||
}),
|
||||
[user, loading, login, logout, refresh, acceptConsent, withdrawConsent],
|
||||
);
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue