Use LDAP API to fetch executive members' name (Closes #376) (#396)
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
Co-authored-by: Rebecca-Chou <beihaozhou@gmail.com> Reviewed-on: #396 Reviewed-by: n3parikh <n3parikh@csclub.uwaterloo.ca>pull/412/head
parent
dd911c12ea
commit
bb073136b0
123
lib/team.ts
123
lib/team.ts
|
@ -1,11 +1,32 @@
|
|||
import { readFile, readdir, access } from "fs/promises";
|
||||
import { readFile, access } from "fs/promises";
|
||||
import path from "path";
|
||||
|
||||
import matter from "gray-matter";
|
||||
import { Client } from "ldapts";
|
||||
import { serialize } from "next-mdx-remote/serialize";
|
||||
|
||||
import { getCurrentTerm } from "@/lib/events";
|
||||
import { capitalize } from "@/utils";
|
||||
|
||||
const EXECS_PATH = path.join("content", "team", "execs");
|
||||
const fileType = ".md";
|
||||
const FILETYPE = ".md";
|
||||
const { year, term } = getCurrentTerm();
|
||||
|
||||
const execPositions: { [position: string]: string } = {
|
||||
president: "President",
|
||||
"vice-president": "Vice President",
|
||||
secretary: "Assistant Vice President",
|
||||
treasurer: "Treasurer",
|
||||
sysadmin: "System Administrator",
|
||||
};
|
||||
|
||||
const orderedExecPositions: string[] = [
|
||||
"president",
|
||||
"vice-president",
|
||||
"secretary",
|
||||
"treasurer",
|
||||
"sysadmin",
|
||||
];
|
||||
|
||||
export interface Metadata {
|
||||
name: string;
|
||||
|
@ -13,23 +34,93 @@ export interface Metadata {
|
|||
image: string;
|
||||
}
|
||||
|
||||
export async function getExecNames() {
|
||||
return (await readdir(EXECS_PATH))
|
||||
.filter((name) => name.endsWith(fileType))
|
||||
.map((name) => name.slice(0, -1 * fileType.length));
|
||||
export async function getExecNamePosPairs() {
|
||||
if (process.env.USE_LDAP?.toLowerCase() !== "true") {
|
||||
return [["codey", "mascot"]];
|
||||
}
|
||||
|
||||
const url = "ldap://ldap1.csclub.uwaterloo.ca";
|
||||
const searchDN = "ou=People,dc=csclub,dc=uwaterloo,dc=ca";
|
||||
const client = new Client({ url });
|
||||
|
||||
// position: name
|
||||
const execMembers: { [position: string]: string } = {};
|
||||
let formattedExec: [string, string][] = [];
|
||||
|
||||
try {
|
||||
await client.bind("", "");
|
||||
const { searchEntries } = await client.search(searchDN, {
|
||||
scope: "sub",
|
||||
filter: `(&(objectClass=member)(term=${(term as string).slice(
|
||||
0,
|
||||
1
|
||||
)}${year}))`,
|
||||
});
|
||||
|
||||
// item.position might be an array if the member has more than one position
|
||||
searchEntries.forEach((item) => {
|
||||
if (typeof item.position === "string" && item.position in execPositions) {
|
||||
execMembers[item.position] = item.cn as string;
|
||||
} else if (item.position instanceof Array) {
|
||||
item.position.forEach((p) => {
|
||||
if ((p as string) in execPositions) {
|
||||
execMembers[p as string] = item.cn as string;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
formattedExec = orderedExecPositions.map((position) => {
|
||||
return [
|
||||
`${execMembers[position].split(" ")[0].toLowerCase()}-${execMembers[
|
||||
position
|
||||
]
|
||||
.split(" ")[1]
|
||||
.toLowerCase()}`,
|
||||
position,
|
||||
];
|
||||
});
|
||||
|
||||
formattedExec = [...formattedExec, ["codey", "mascot"]];
|
||||
} finally {
|
||||
await client.unbind();
|
||||
}
|
||||
|
||||
return formattedExec;
|
||||
}
|
||||
|
||||
export async function getExec(fileName: string, convert = true) {
|
||||
const raw = await readFile(path.join(EXECS_PATH, `${fileName}${fileType}`));
|
||||
const { content, data: metadata } = matter(raw);
|
||||
const image =
|
||||
(metadata.image as string | undefined) ??
|
||||
(await getMemberImagePath(metadata.name));
|
||||
export async function getExec(name: string, pos: string, convert = true) {
|
||||
let content, metadata;
|
||||
|
||||
return {
|
||||
content: convert ? await serialize(content) : content,
|
||||
metadata: { ...metadata, image } as Metadata,
|
||||
};
|
||||
try {
|
||||
const raw = await readFile(path.join(EXECS_PATH, `${name}${FILETYPE}`));
|
||||
({ content, data: metadata } = matter(raw));
|
||||
|
||||
const image = await getMemberImagePath(metadata.name);
|
||||
|
||||
return {
|
||||
content: convert ? await serialize(content) : content,
|
||||
metadata: { ...metadata, image } as Metadata,
|
||||
};
|
||||
} catch (err) {
|
||||
// Capitalize the first letter of the first name and last name
|
||||
const firstName = capitalize(name.split("-")[0]);
|
||||
const lastName = capitalize(name.split("-")[1]);
|
||||
|
||||
const posName = execPositions[pos];
|
||||
content = "Coming Soon!";
|
||||
metadata = {
|
||||
name: `${firstName} ${lastName}`,
|
||||
role: `${posName}`,
|
||||
};
|
||||
|
||||
const image = await getMemberImagePath(metadata.name);
|
||||
|
||||
return {
|
||||
content: convert ? await serialize(content) : content,
|
||||
metadata: { ...metadata, image } as Metadata,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function getImage(imgPath: string) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import { TeamMemberCard } from "@/components/TeamMemberCard";
|
|||
import { Title } from "@/components/Title";
|
||||
import {
|
||||
getExec,
|
||||
getExecNames,
|
||||
getExecNamePosPairs,
|
||||
Metadata,
|
||||
getMemberImagePath,
|
||||
} from "@/lib/team";
|
||||
|
@ -208,10 +208,12 @@ async function getTeamWithImages(team: TeamMember[]) {
|
|||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async () => {
|
||||
const execNames = await getExecNames();
|
||||
const execNamePosPairs = await getExecNamePosPairs();
|
||||
|
||||
const execs = (await Promise.all(
|
||||
execNames.map((name) => getExec(name))
|
||||
execNamePosPairs.map((namePosPair) =>
|
||||
getExec(namePosPair[0], namePosPair[1])
|
||||
)
|
||||
)) as SerializedExec[];
|
||||
|
||||
const [
|
||||
|
|
Loading…
Reference in New Issue