feat: add admin user management features and update user repository methods
- Implemented updateRoles, updateSanctions, and deleteUser methods in both in-memory and PostgreSQL user repositories. - Enhanced UserSanctions and UserServerRestriction interfaces to include additional properties. - Added AdminView component for admin functionalities including user lookup, role management, sanctions application, and profile management. - Integrated admin token handling in TRPC client for secure API requests. - Updated routing to include admin dashboard and linked it in the default layout.
This commit is contained in:
@@ -81,5 +81,38 @@ export const createInMemoryUserRepository = (
|
||||
}
|
||||
throw new Error('User not found.');
|
||||
},
|
||||
async updateRoles(userId: string, roles: string[]): Promise<void> {
|
||||
for (const user of usersByName.values()) {
|
||||
if (user.id === userId) {
|
||||
user.roles = [...roles];
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error('User not found.');
|
||||
},
|
||||
async updateSanctions(userId: string, sanctions: UserRecord['sanctions']): Promise<void> {
|
||||
for (const user of usersByName.values()) {
|
||||
if (user.id === userId) {
|
||||
user.sanctions = { ...sanctions };
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error('User not found.');
|
||||
},
|
||||
async deleteUser(userId: string): Promise<void> {
|
||||
for (const [username, user] of usersByName.entries()) {
|
||||
if (user.id === userId) {
|
||||
usersByName.delete(username);
|
||||
if (user.oauthType === 'KAKAO' && user.oauthId) {
|
||||
usersByOauthId.delete(`${user.oauthType}:${user.oauthId}`);
|
||||
}
|
||||
if (user.email) {
|
||||
usersByEmail.delete(user.email.toLowerCase());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error('User not found.');
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -129,5 +129,26 @@ export const createPostgresUserRepository = (
|
||||
},
|
||||
});
|
||||
},
|
||||
async updateRoles(userId: string, roles: string[]): Promise<void> {
|
||||
await prisma.appUser.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
roles: roles as GatewayPrisma.JsonArray,
|
||||
},
|
||||
});
|
||||
},
|
||||
async updateSanctions(userId: string, sanctions: UserSanctions): Promise<void> {
|
||||
await prisma.appUser.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
sanctions: sanctions as GatewayPrisma.JsonObject,
|
||||
},
|
||||
});
|
||||
},
|
||||
async deleteUser(userId: string): Promise<void> {
|
||||
await prisma.appUser.delete({
|
||||
where: { id: userId },
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -28,6 +28,15 @@ export interface UserSanctions {
|
||||
warningCount?: number;
|
||||
flags?: string[];
|
||||
notes?: string;
|
||||
profileIconResetAt?: string;
|
||||
serverRestrictions?: Record<string, UserServerRestriction>;
|
||||
}
|
||||
|
||||
export interface UserServerRestriction {
|
||||
blockedFeatures?: string[];
|
||||
until?: string;
|
||||
reason?: string;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export const toPublicUser = (user: UserRecord): PublicUser => ({
|
||||
@@ -59,6 +68,9 @@ export interface UserRepository {
|
||||
verifyPassword(user: UserRecord, password: string): Promise<boolean>;
|
||||
updatePassword(userId: string, password: string): Promise<void>;
|
||||
updateOAuthInfo(userId: string, oauthInfo: UserOAuthInfo): Promise<void>;
|
||||
updateRoles(userId: string, roles: string[]): Promise<void>;
|
||||
updateSanctions(userId: string, sanctions: UserSanctions): Promise<void>;
|
||||
deleteUser(userId: string): Promise<void>;
|
||||
}
|
||||
|
||||
export interface UserOAuthInfo {
|
||||
|
||||
Reference in New Issue
Block a user