feat: overhaul the nakama user management, leaderboard, prep for 2.1
This commit is contained in:
@@ -25,6 +25,8 @@ function InitModule(
|
||||
initializer.registerRpc("admin_get_player_list", rpcAdminGetPlayerList);
|
||||
initializer.registerRpc("admin_end_match", rpcAdminEndMatch);
|
||||
initializer.registerRpc("admin_set_user_role", rpcAdminSetUserRole);
|
||||
initializer.registerRpc("admin_list_users", rpcAdminListUsers);
|
||||
initializer.registerRpc("admin_delete_users", rpcAdminDeleteUsers);
|
||||
|
||||
// User management RPCs
|
||||
initializer.registerRpc("get_user_profile", rpcGetUserProfile);
|
||||
@@ -597,6 +599,94 @@ function rpcGetLeaderboardStats(
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Admin User Management RPCs
|
||||
// =============================================================================
|
||||
|
||||
function rpcAdminListUsers(
|
||||
ctx: nkruntime.Context,
|
||||
logger: nkruntime.Logger,
|
||||
nk: nkruntime.Nakama,
|
||||
payload: string
|
||||
): string {
|
||||
requireAdmin(ctx, nk);
|
||||
|
||||
try {
|
||||
const users: any[] = [];
|
||||
let cursor = "";
|
||||
for (let page = 0; page < 10; page++) {
|
||||
const result = nk.usersList("", "", 100, cursor);
|
||||
if (!result || !result.users || result.users.length === 0) break;
|
||||
for (const u of result.users) {
|
||||
let metadata: UserMetadata = {};
|
||||
try { metadata = JSON.parse(u.metadata || "{}"); } catch(e) {}
|
||||
users.push({
|
||||
user_id: u.id,
|
||||
username: u.username || "",
|
||||
display_name: u.displayName || u.username || "",
|
||||
create_time: u.createTime,
|
||||
role: metadata.role || "player",
|
||||
banned: metadata.banned || false,
|
||||
ban_reason: metadata.ban_reason || ""
|
||||
});
|
||||
}
|
||||
if (!result.cursor) break;
|
||||
cursor = result.cursor;
|
||||
}
|
||||
return JSON.stringify({ users, count: users.length });
|
||||
} catch (e) {
|
||||
logger.error(`Failed to list users: ${e}`);
|
||||
throw new Error(`Failed to list users: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
interface DeleteUsersRequest {
|
||||
user_ids: string[];
|
||||
}
|
||||
|
||||
function rpcAdminDeleteUsers(
|
||||
ctx: nkruntime.Context,
|
||||
logger: nkruntime.Logger,
|
||||
nk: nkruntime.Nakama,
|
||||
payload: string
|
||||
): string {
|
||||
requireAdmin(ctx, nk);
|
||||
|
||||
const request = JSON.parse(payload) as DeleteUsersRequest;
|
||||
const userIds = request.user_ids || [];
|
||||
|
||||
if (userIds.length === 0) {
|
||||
throw new Error("No user IDs provided");
|
||||
}
|
||||
|
||||
for (const uid of userIds) {
|
||||
if (uid === ctx.userId) {
|
||||
throw new Error("Cannot delete your own account");
|
||||
}
|
||||
}
|
||||
|
||||
const deleted: string[] = [];
|
||||
const failed: { user_id: string; reason: string }[] = [];
|
||||
|
||||
for (const uid of userIds) {
|
||||
try {
|
||||
const account = nk.accountGetId(uid);
|
||||
const meta = JSON.parse(account.user.metadata || "{}") as UserMetadata;
|
||||
if (ADMIN_ROLES.includes(meta.role || "")) {
|
||||
failed.push({ user_id: uid, reason: "Cannot delete admin account" });
|
||||
continue;
|
||||
}
|
||||
nk.accountDeleteId(uid, false);
|
||||
deleted.push(uid);
|
||||
logger.warn(`User ${uid} deleted by ${ctx.userId}`);
|
||||
} catch (e) {
|
||||
failed.push({ user_id: uid, reason: `${e}` });
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify({ success: true, deleted, failed });
|
||||
}
|
||||
|
||||
// Before login hook to check ban status
|
||||
function beforeAuthenticateEmail(
|
||||
ctx: nkruntime.Context,
|
||||
|
||||
Reference in New Issue
Block a user