From e6315cf9060a781fd006d8a559853d410a670095 Mon Sep 17 00:00:00 2001 From: j285he Date: Mon, 22 Nov 2021 12:47:00 -0500 Subject: [PATCH] Generate members list (#354) #301 https://csclub.uwaterloo.ca/~a3thakra/csc/j285he-ldap/about/members/ Co-authored-by: Jared He <66887902+jaredjhe@users.noreply.github.com> Co-authored-by: Jared He Reviewed-on: https://git.csclub.uwaterloo.ca/www/www-new/pulls/354 Reviewed-by: n3parikh Co-authored-by: j285he Co-committed-by: j285he --- .drone.yml | 2 +- components/Navbar.tsx | 4 + deploy.sh | 2 + lib/members.ts | 61 ++++++++++++++ package-lock.json | 147 +++++++++++++++++++++++++++++++-- package.json | 1 + pages/about/members.module.css | 6 ++ pages/about/members.tsx | 65 +++++++++++++++ 8 files changed, 280 insertions(+), 8 deletions(-) create mode 100644 lib/members.ts create mode 100644 pages/about/members.module.css create mode 100644 pages/about/members.tsx diff --git a/.drone.yml b/.drone.yml index ddced624..e24c796b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -42,7 +42,7 @@ steps: depends_on: - optimize-images commands: - - npm run build:web + - USE_LDAP=true npm run build:web - name: export image: node:16 diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 73f13bcc..6fecceea 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -32,6 +32,10 @@ const menu: Menu = [ name: "Meet the Team", route: "/about/team", }, + { + name: "Members", + route: "/about/members", + }, { name: "Constitution", route: "/about/constitution", diff --git a/deploy.sh b/deploy.sh index 530eb69b..f07dfeb2 100755 --- a/deploy.sh +++ b/deploy.sh @@ -4,6 +4,8 @@ set -ex ulimit -u 512 DIR=$(mktemp --directory) +# set USE_LDAP to true to generate member list using LDAP database +export USE_LDAP=true pushd $DIR diff --git a/lib/members.ts b/lib/members.ts new file mode 100644 index 00000000..7cce6ca2 --- /dev/null +++ b/lib/members.ts @@ -0,0 +1,61 @@ +import { Client } from "ldapts"; + +export interface Member { + name: string; + id: string; + program: string; +} + +export async function getMembers( + year: string, + term: string +): Promise { + if (term !== "winter" && term !== "spring" && term !== "fall") { + throw new Error(`[getMembers] Not a valid term: "${term}"`); + } + + if (process.env.USE_LDAP?.toLowerCase() !== "true") { + return dummyMembers; + } + + let members: Member[] = []; + + const url = "ldap://ldap1.csclub.uwaterloo.ca"; + const searchDN = "ou=People,dc=csclub,dc=uwaterloo,dc=ca"; + const client = new Client({ url }); + + try { + await client.bind("", ""); + const { searchEntries } = await client.search(searchDN, { + scope: "sub", + filter: `(&(objectClass=member)(term=${term.slice(0, 1)}${year}))`, + }); + + members = searchEntries + .map((item) => { + return { + name: item.cn as string, + id: item.uid as string, + program: item.program === undefined ? "" : (item.program as string), + }; + }) + .sort((item1: Member, item2: Member) => item1.id.localeCompare(item2.id)); + } finally { + await client.unbind(); + } + + return members; +} + +const dummyMembers: Member[] = [ + { + name: "John Smith", + id: "j12smith", + program: "MAT/Mathematics Computer Science", + }, + { + name: "Jane Smith", + id: "j34smith", + program: "MAT/Mathematics Computer Science", + }, +]; diff --git a/package-lock.json b/package-lock.json index f9cf0838..18cc2255 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "website", + "name": "www-new", "version": "0.1.0", "lockfileVersion": 2, "requires": true, @@ -15,6 +15,7 @@ "date-fns-tz": "^1.1.6", "fs-extra": "^10.0.0", "image-size": "^1.0.0", + "ldapts": "^3.1.0", "next": "11.0.1", "next-mdx-remote": "3.0.4", "prettier": "^2.3.0", @@ -1030,6 +1031,14 @@ "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", "dev": true }, + "node_modules/@types/asn1": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.0.tgz", + "integrity": "sha512-5TMxIpYbIA9c1J0hYQjQDX3wr+rTgQEAXaW2BI8ECM8FO53wSW4HFZplTalrKSHuZUc76NtXcePRhwuOHqGD5g==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -1071,9 +1080,9 @@ } }, "node_modules/@types/node": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", - "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==" }, "node_modules/@types/parse5": { "version": "5.0.3", @@ -1108,6 +1117,11 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" }, + "node_modules/@types/uuid": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "4.28.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.4.tgz", @@ -1555,6 +1569,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -4620,6 +4642,44 @@ "node": ">=0.10.0" } }, + "node_modules/ldapts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/ldapts/-/ldapts-3.1.1.tgz", + "integrity": "sha512-RNxTlfiPS4fTN0b7oY0OE4d+E/uVg1nNlK1ZLPFyVsp4Gr8qSclJUWjdJ5W7PUtuiWh7kEEdNq1YAA+abERZZA==", + "dependencies": { + "@types/asn1": "~0.2.0", + "@types/node": "^16.11.6", + "@types/uuid": "~8.3.1", + "asn1": "~0.2.4", + "debug": "~4.3.2", + "strict-event-emitter-types": "~2.0.0", + "uuid": "~8.3.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ldapts/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ldapts/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -8398,6 +8458,11 @@ "debug": "2" } }, + "node_modules/strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -9097,6 +9162,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/uuid-random": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/uuid-random/-/uuid-random-1.3.2.tgz", @@ -10155,6 +10228,14 @@ "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", "dev": true }, + "@types/asn1": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.0.tgz", + "integrity": "sha512-5TMxIpYbIA9c1J0hYQjQDX3wr+rTgQEAXaW2BI8ECM8FO53wSW4HFZplTalrKSHuZUc76NtXcePRhwuOHqGD5g==", + "requires": { + "@types/node": "*" + } + }, "@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -10196,9 +10277,9 @@ } }, "@types/node": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", - "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==" }, "@types/parse5": { "version": "5.0.3", @@ -10233,6 +10314,11 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" }, + "@types/uuid": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==" + }, "@typescript-eslint/eslint-plugin": { "version": "4.28.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.4.tgz", @@ -10521,6 +10607,14 @@ "function-bind": "^1.1.1" } }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -12773,6 +12867,35 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, + "ldapts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/ldapts/-/ldapts-3.1.1.tgz", + "integrity": "sha512-RNxTlfiPS4fTN0b7oY0OE4d+E/uVg1nNlK1ZLPFyVsp4Gr8qSclJUWjdJ5W7PUtuiWh7kEEdNq1YAA+abERZZA==", + "requires": { + "@types/asn1": "~0.2.0", + "@types/node": "^16.11.6", + "@types/uuid": "~8.3.1", + "asn1": "~0.2.4", + "debug": "~4.3.2", + "strict-event-emitter-types": "~2.0.0", + "uuid": "~8.3.2" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -15640,6 +15763,11 @@ "debug": "2" } }, + "strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -16156,6 +16284,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "uuid-random": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/uuid-random/-/uuid-random-1.3.2.tgz", diff --git a/package.json b/package.json index dbe82c23..e824f4c2 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@squoosh/lib": "^0.4.0", "date-fns": "^2.11.1", "date-fns-tz": "^1.1.6", + "ldapts": "^3.1.0", "fs-extra": "^10.0.0", "image-size": "^1.0.0", "next": "11.0.1", diff --git a/pages/about/members.module.css b/pages/about/members.module.css new file mode 100644 index 00000000..c7b721d4 --- /dev/null +++ b/pages/about/members.module.css @@ -0,0 +1,6 @@ +.table { + display: table; + width: 100%; + margin-top: calc(20rem / 16); + margin-bottom: calc(60rem / 16); +} diff --git a/pages/about/members.tsx b/pages/about/members.tsx new file mode 100644 index 00000000..7f8f4b0b --- /dev/null +++ b/pages/about/members.tsx @@ -0,0 +1,65 @@ +import { GetStaticProps } from "next"; +import React from "react"; + +import { Link } from "@/components/Link"; +import { Table } from "@/components/Table"; +import { getCurrentTerm } from "@/lib/events"; +import { getMembers, Member } from "@/lib/members"; +import { capitalize } from "@/utils"; + +import styles from "./members.module.css"; + +interface Props { + members: Member[]; + year: string; + term: string; +} + +export default function Members(props: Props) { + return ( + <> +

Members

+

+ {`The members for ${capitalize(props.term)} ${ + props.year + } are listed here. We currently + have ${props.members.length} members. Use of this list for solicitation + of any form is prohibited, if you wish to get in touch with the + membership as a whole please contact the Executive.`} +

+ + + + + + + + + + {props.members.map((member) => ( + + + + + + ))} + +
Name / WebpageProgramUserid
+ + {member.name} + + {member.program}{member.id}
+ + ); +} + +export const getStaticProps: GetStaticProps = async () => { + const curTerm = getCurrentTerm(); + return { + props: { + year: curTerm.year, + term: curTerm.term, + members: await getMembers(curTerm.year, curTerm.term), + }, + }; +};