Skip to content

Commit

Permalink
그룹 멤버 목록 API에 정보 추가 (#245)
Browse files Browse the repository at this point in the history
* 그룹 멤버 목록 API에 정보 추가

* dprint fmt
  • Loading branch information
tirr-c authored Sep 21, 2023
1 parent ef7df6a commit 12e6fa7
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 55 deletions.
34 changes: 18 additions & 16 deletions src/api/handlers/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ export function listMembers(model: Model): IMiddleware {

let owner = false;
let users: Array<User> = [];
let studentNumberMap: Map<number, Array<string>>;
try {
await model.pgDo(async tr => {
owner = await model.groups.checkOwner(tr, gid, ctx.state.userIdx);

if (owner) {
users = await model.users.getAllMembershipUsers(tr, gid, pagination);
const indices = users.map(u => u.idx);
studentNumberMap = await model.users.getStudentNumbersByUserIdxBulk(tr, indices);
}
});
} catch (e) {
Expand All @@ -66,14 +69,12 @@ export function listMembers(model: Model): IMiddleware {
}

ctx.status = 200;
users.forEach((u: any) => {
u.uid = u.idx;
delete u.idx;
delete u.username;
delete u.shell;
delete u.preferredLanguage;
});
ctx.body = users;
ctx.body = users.map(u => ({
uid: u.idx,
username: u.username,
name: u.name,
studentNumbers: studentNumberMap?.get(u.idx) ?? [],
}));
} else {
ctx.status = 401;
return;
Expand All @@ -89,12 +90,15 @@ export function listPending(model: Model): IMiddleware {

let owner = false;
let users: Array<User> = [];
let studentNumberMap: Map<number, Array<string>>;
try {
await model.pgDo(async tr => {
owner = await model.groups.checkOwner(tr, gid, ctx.state.userIdx);

if (owner) {
users = await model.users.getAllPendingMembershipUsers(tr, gid);
const indices = users.map(u => u.idx);
studentNumberMap = await model.users.getStudentNumbersByUserIdxBulk(tr, indices);
}
});
} catch (e) {
Expand All @@ -108,14 +112,12 @@ export function listPending(model: Model): IMiddleware {
}

ctx.status = 200;
users.forEach((u: any) => {
u.uid = u.idx;
delete u.idx;
delete u.username;
delete u.shell;
delete u.preferredLanguage;
});
ctx.body = users;
ctx.body = users.map(u => ({
uid: u.idx,
username: u.username,
name: u.name,
studentNumbers: studentNumberMap?.get(u.idx) ?? [],
}));
} else {
ctx.status = 401;
return;
Expand Down
17 changes: 0 additions & 17 deletions src/model/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,23 +225,6 @@ export default class Groups {
return result.rows.map(row => row.idx);
}

private rowToUser(row: any): User {
const user: User = {
idx: row.idx,
username: row.username,
name: row.name,
uid: row.uid,
shell: row.shell,
preferredLanguage: row.preferred_language,
};

if (row.student_number) {
user.studentNumber = row.student_number;
}

return user;
}

private rowToGroup(row: any): Group {
return {
idx: row.idx,
Expand Down
47 changes: 25 additions & 22 deletions src/model/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export interface User {
uid: number;
shell: string;
preferredLanguage: Language;
studentNumber?: string;
}

export interface UserMembership {
Expand Down Expand Up @@ -348,8 +347,8 @@ export default class Users {
groupIdx: number,
pagination?: { start: number; count: number },
): Promise<Array<User>> {
let query = 'SELECT u.*, sn.student_number FROM user_memberships AS um INNER JOIN users AS u '
+ 'ON um.user_idx = u.idx INNER JOIN student_numbers AS sn ON sn.owner_idx = u.idx '
let query = 'SELECT u.* FROM user_memberships AS um '
+ 'INNER JOIN users AS u ON um.user_idx = u.idx '
+ 'WHERE um.group_idx = $1 ORDER BY um.idx';
const params = [groupIdx];
if (pagination != null) {
Expand Down Expand Up @@ -446,9 +445,8 @@ export default class Users {
tr: Transaction,
groupIdx: number,
): Promise<Array<User>> {
const query =
'SELECT u.*, sn.student_number FROM pending_user_memberships AS pum INNER JOIN users AS u '
+ 'ON pum.user_idx = u.idx INNER JOIN student_numbers AS sn ON sn.owner_idx = u.idx '
const query = 'SELECT u.* FROM pending_user_memberships AS pum '
+ 'INNER JOIN users AS u ON pum.user_idx = u.idx '
+ 'WHERE pum.group_idx = $1 ORDER BY pum.idx';
const result = await tr.query(query, [groupIdx]);
return result.rows.map(row => this.rowToUser(row));
Expand Down Expand Up @@ -491,6 +489,26 @@ export default class Users {
return result.rows.map(row => row.student_number);
}

public async getStudentNumbersByUserIdxBulk(
tr: Transaction,
userIndices: Array<number>,
): Promise<Map<number, Array<string>>> {
const query = 'SELECT u.idx, sn.student_number FROM users u '
+ 'LEFT OUTER JOIN student_numbers AS sn ON sn.owner_idx = u.idx '
+ 'WHERE u.idx = ANY($1)';
const result = await tr.query(query, [userIndices]);
const map = new Map<number, Array<string>>();
for (const row of result.rows) {
const idx = row.idx;
const studentNumber = row.student_number;
if (!map.has(idx)) {
map.set(idx, []);
}
map.get(idx)!.push(studentNumber);
}
return map;
}

public async addStudentNumber(
tr: Transaction,
userIdx: number,
Expand All @@ -503,20 +521,14 @@ export default class Users {
}

private rowToUser(row: any): User {
const user: User = {
return {
idx: row.idx,
username: row.username,
name: row.name,
uid: row.uid,
shell: row.shell,
preferredLanguage: row.preferred_language,
};

if (row.student_number) {
user.studentNumber = row.student_number;
}

return user;
}

private rowToUserMembership(row: any): UserMembership {
Expand All @@ -528,15 +540,6 @@ export default class Users {
};
}

private rowToPendingUserMembership(row: any): UserMembership {
return {
idx: row.idx,
userIdx: row.user_idx,
groupIdx: row.group_idx,
pending: true,
};
}

private asyncRandomBytes(n: number): Promise<Buffer> {
return new Promise((resolve, reject) => {
crypto.randomBytes(n, (err, buf) => {
Expand Down

0 comments on commit 12e6fa7

Please sign in to comment.