From 713798b2b1e83b3318b2d0998854cece42898db1 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Sat, 15 Feb 2025 20:50:51 -0500 Subject: [PATCH 01/11] Add Request Management Page --- web/components/HOC/PageAccess.tsx | 2 + web/components/Navbar.tsx | 21 +++++++++ web/pages/request.tsx | 73 +++++++++++++++++++++++++++++++ web/utils/consts.ts | 1 + web/utils/visibility.ts | 1 + 5 files changed, 98 insertions(+) create mode 100644 web/pages/request.tsx diff --git a/web/components/HOC/PageAccess.tsx b/web/components/HOC/PageAccess.tsx index 0c6a8710..0d09d3f3 100644 --- a/web/components/HOC/PageAccess.tsx +++ b/web/components/HOC/PageAccess.tsx @@ -13,6 +13,7 @@ const restricted = new Set([Role.Admin]); const pageAccess: Record> = { [Pages.ONBOARDING]: unrestricted, [Pages.ACCESS_MANAGEMENT]: restricted, + [Pages.REQUEST_MANAGEMENT]: restricted, [Pages.PROFILE]: unrestricted, [Pages.FEED]: unrestricted, [Pages.RESOURCES]: unrestricted, @@ -23,6 +24,7 @@ const pageAccess: Record> = { const pageTitles: Record = { [Pages.ONBOARDING]: "Onboarding", [Pages.ACCESS_MANAGEMENT]: "Access Management", + [Pages.REQUEST_MANAGEMENT]: "Request Management", [Pages.PROFILE]: "Profile", [Pages.FEED]: "Feed", [Pages.RESOURCES]: "Resources", diff --git a/web/components/Navbar.tsx b/web/components/Navbar.tsx index caee21a3..5776d688 100644 --- a/web/components/Navbar.tsx +++ b/web/components/Navbar.tsx @@ -216,6 +216,27 @@ export default function Navbar() { Access Management + + + Request Management + + (false); + const [search, setSearch] = useState(""); + const [searchQuery, isUpdating] = useDebounce(search, 400); + const selectedAccounts = useRef>(new Set([])); + const accounts = trpc.account.search.useQuery({ searchSubject: searchQuery }); + + return ( + + + + + Add New Account + + + + + + + + + + + + ); +} + +export default pageAccessHOC(Request); diff --git a/web/utils/consts.ts b/web/utils/consts.ts index 2b030115..badc8a27 100644 --- a/web/utils/consts.ts +++ b/web/utils/consts.ts @@ -1,6 +1,7 @@ enum Pages { FEED = "/", ACCESS_MANAGEMENT = "/access", + REQUEST_MANAGEMENT = "/request", ONBOARDING = "/onboarding", PROFILE = "/profile", RESOURCES = "/resources", diff --git a/web/utils/visibility.ts b/web/utils/visibility.ts index 49bc0479..908f5d3b 100644 --- a/web/utils/visibility.ts +++ b/web/utils/visibility.ts @@ -4,6 +4,7 @@ export const navbarVisiblity = { [Pages.FEED]: true, [Pages.ONBOARDING]: false, [Pages.ACCESS_MANAGEMENT]: true, + [Pages.REQUEST_MANAGEMENT]: true, [Pages.PROFILE]: true, [Pages.RESOURCES]: true, [Pages.USERS]: true, From 97217dccdb650b8f9a8315263323ca2b5b436e63 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Sun, 16 Feb 2025 04:05:22 -0500 Subject: [PATCH 02/11] Modify user model with new VerifiedByAdmin field --- web/db/models/User.ts | 5 +++++ web/server/routers/auth.ts | 23 ++++++++++++++++++----- web/server/routers/user.ts | 1 + web/utils/types/user.ts | 1 + 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/web/db/models/User.ts b/web/db/models/User.ts index 72c6b6ac..aec742ae 100644 --- a/web/db/models/User.ts +++ b/web/db/models/User.ts @@ -11,6 +11,7 @@ import { Size, } from "../../utils/types/post"; import { IUser } from "../../utils/types/user"; +import { boolean } from "zod"; const { Schema } = mongoose; const userSchema = new Schema({ @@ -43,6 +44,10 @@ const userSchema = new Schema({ unique: true, index: true, }, + verifiedByAdmin: { + type: Boolean, + required: true, + }, role: { type: String, required: true, diff --git a/web/server/routers/auth.ts b/web/server/routers/auth.ts index 98c1e403..b9fb3a03 100644 --- a/web/server/routers/auth.ts +++ b/web/server/routers/auth.ts @@ -7,6 +7,7 @@ import { } from "../../db/actions/User"; import { router, procedure } from "../trpc"; import { logUserCreateEvent } from "../../utils/analytics-logger"; +import { Role } from "../../utils/types/account"; const FACEBOOK_SIGN_IN_PROVIDER = "facebook.com" as const; @@ -48,20 +49,21 @@ export const authRouter = router({ hasCompletedOnboarding: document!.hasCompletedOnboarding, }; } else if (user && !account) { - // Subsequent sign-in, unauthorized account + // Subsequent sign-in, unauthorized account (approval request workflow) await updateUserByUid(ctx.session.uid, { disabled: true, }); throw new TRPCError({ code: "UNAUTHORIZED", message: - "You are not permitted to log into this site. Ensure that the account you are logging in with has been given access to the tool.", + "You are not permitted to log into this site. Please try again after your request for access has been approved.", }); } else if (!user && account) { - // First-time sign-in, authorized account + // First-time sign-in, authorized account (invitation workflow) const document = await createUser({ uid: ctx.session.uid, email: ctx.session.email, + verifiedByAdmin: true, role: account.role, hasCompletedOnboarding: false, disabled: false, @@ -75,11 +77,22 @@ export const authRouter = router({ hasCompletedOnboarding: false, }; } else { - // First-time sign-in, unauthorized + // First-time sign-in, unauthorized account (approval request workflow) + const document = await createUser({ + uid: ctx.session.uid, + email: ctx.session.email, + verifiedByAdmin: false, + role: Role.Volunteer, + hasCompletedOnboarding: false, + disabled: true, + name: ctx.session.name, + picture: ctx.session.picture, + }); + // TODO: send email to manager throw new TRPCError({ code: "UNAUTHORIZED", message: - "You are not permitted to log into this site. Ensure that the account you are logging in with has the correct email address.", + "You are not permitted to log into this site. Please try again after your request for access has been approved.", }); } } catch (e) { diff --git a/web/server/routers/user.ts b/web/server/routers/user.ts index a8206db6..39782b94 100644 --- a/web/server/routers/user.ts +++ b/web/server/routers/user.ts @@ -50,6 +50,7 @@ export const userRouter = router({ if (!user) { await createUser({ ...input, + verifiedByAdmin: false, disabled: false, hasCompletedOnboarding: false, }); diff --git a/web/utils/types/user.ts b/web/utils/types/user.ts index 2e409a33..26934821 100644 --- a/web/utils/types/user.ts +++ b/web/utils/types/user.ts @@ -18,6 +18,7 @@ export interface IUser { preferredEmail?: string; name?: string; uid: string; + verifiedByAdmin: boolean; role: Role; disabled: boolean; hasCompletedOnboarding: boolean; From 3147854f113c0d3584b2bb6755b1531c72ea45a4 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Sun, 16 Feb 2025 23:42:34 -0500 Subject: [PATCH 03/11] Implement request management and approve/decline endpoints --- .../RequestManagement/ApproveSelector.tsx | 95 +++++++++++++++++++ .../RequestManagement/RequestTable.tsx | 63 ++++++++++++ .../RequestManagement/RequestedUserCard.tsx | 52 ++++++++++ web/db/actions/User.ts | 17 ++++ web/pages/request.tsx | 49 ++-------- web/server/routers/user.ts | 85 +++++++++++++++++ 6 files changed, 318 insertions(+), 43 deletions(-) create mode 100644 web/components/RequestManagement/ApproveSelector.tsx create mode 100644 web/components/RequestManagement/RequestTable.tsx create mode 100644 web/components/RequestManagement/RequestedUserCard.tsx diff --git a/web/components/RequestManagement/ApproveSelector.tsx b/web/components/RequestManagement/ApproveSelector.tsx new file mode 100644 index 00000000..0532e938 --- /dev/null +++ b/web/components/RequestManagement/ApproveSelector.tsx @@ -0,0 +1,95 @@ +import { roleLabels } from "../../utils/types/account"; +import { Role } from "../../utils/types/account"; +import { trpc } from "../../utils/trpc"; +import { IUser } from "../../utils/types/user"; + +import { + Popover, + PopoverTrigger, + PopoverContent, + Box, + Flex, + Text, + useDisclosure, +} from "@chakra-ui/react"; +import { ChevronDownIcon, ChevronUpIcon } from "@chakra-ui/icons"; + +interface PropertyType { + requestedUser: IUser; +} + +function ApproveSelector(props: PropertyType) { + const { requestedUser } = props; + const { isOpen, onOpen, onClose } = useDisclosure(); + + const mutation = trpc.user.approveUser.useMutation(); + const utils = trpc.useUtils(); + + const options = Object.entries(roleLabels).map(([k, v]) => ({ + key: k as Role, + label: v, + })); + + const handleApprove = (requestedUser: IUser, newRole: Role) => { + mutation.mutate( + { email: requestedUser.email, role: newRole }, + { + onSuccess() { + utils.user.invalidate(); + utils.account.invalidate(); + }, + } + ); + }; + + return ( + + + + Approve + {isOpen ? : } + + + + + {options.map((option) => { + return ( + handleApprove(requestedUser, option.key)} + as="button" + bgColor="tag-primary-bg" + paddingX={2} + borderRadius={8} + w="fit-content" + > + {option.label} + + ); + })} + + + + ); +} +export default ApproveSelector; diff --git a/web/components/RequestManagement/RequestTable.tsx b/web/components/RequestManagement/RequestTable.tsx new file mode 100644 index 00000000..03921005 --- /dev/null +++ b/web/components/RequestManagement/RequestTable.tsx @@ -0,0 +1,63 @@ +import RequestedUserCard from "./RequestedUserCard"; +import { Grid, GridItem, Spinner, Text, Center, Box } from "@chakra-ui/react"; +import { IUser } from "../../utils/types/user"; + +interface PropertyType { + requestedUserList: IUser[] | undefined; + isLoading: boolean; +} + +function RequestTable(props: PropertyType) { + const { requestedUserList, isLoading } = props; + + if (isLoading) { + return ( +
+ +
+ ); + } + + if (requestedUserList && requestedUserList.length > 0) { + return ( + + + {requestedUserList.map((requestedUser) => { + return ( + + + + ); + })} + + + ); + } + + return ( +
+ No results found. +
+ ); +} + +export default RequestTable; diff --git a/web/components/RequestManagement/RequestedUserCard.tsx b/web/components/RequestManagement/RequestedUserCard.tsx new file mode 100644 index 00000000..a18b303b --- /dev/null +++ b/web/components/RequestManagement/RequestedUserCard.tsx @@ -0,0 +1,52 @@ +import { IUser } from "../../utils/types/user"; +import { Box, Flex, Text } from "@chakra-ui/react"; +import ApproveSelector from "./ApproveSelector"; +import { trpc } from "../../utils/trpc"; + +interface PropertyType { + user: IUser; +} + +function RequestedUserCard(props: PropertyType) { + const { user } = props; + + const mutation = trpc.user.delete.useMutation(); + const utils = trpc.useUtils(); + + const handleDecline = (requestedUser: IUser) => { + mutation.mutate(requestedUser.uid, { + onSuccess() { + utils.user.invalidate(); + }, + }); + }; + + return ( + + + + {user.email} + + + + handleDecline(user)} + > + Decline + + + ); +} + +export default RequestedUserCard; diff --git a/web/db/actions/User.ts b/web/db/actions/User.ts index 9bc19c8e..006c03c0 100644 --- a/web/db/actions/User.ts +++ b/web/db/actions/User.ts @@ -57,6 +57,21 @@ async function findUserByEmail( ); } +async function findUnverifiedUsers(session?: ClientSession): Promise { + return await User.find( + { verifiedByAdmin: false }, + { _id: 0, __v: 0 }, + { session } + ).exec(); +} + +async function deleteUser( + uid: string, + session?: ClientSession +): Promise { + return await User.findOneAndDelete({ uid: uid }, { session }).exec(); +} + async function updateUserByEmail( email: string, update: UpdateQuery, @@ -141,6 +156,8 @@ export { createUser, findUserByUid, findUserByEmail, + findUnverifiedUsers, + deleteUser, updateAllUsers, updateUserByEmail, updateUserByUid, diff --git a/web/pages/request.tsx b/web/pages/request.tsx index f17f4d73..c25cc4e2 100644 --- a/web/pages/request.tsx +++ b/web/pages/request.tsx @@ -1,18 +1,10 @@ -import CreateAccountForm from "../components/AccessManagement/CreateAccountForm"; -import AccountTable from "../components/AccessManagement/AccountTable"; -import { useRef, useState } from "react"; -import { Text, Flex, Box } from "@chakra-ui/react"; +import { Flex } from "@chakra-ui/react"; import { trpc } from "../utils/trpc"; import pageAccessHOC from "../components/HOC/PageAccess"; -import useDebounce from "../hooks/useDebounce"; -import TableHeader from "../components/AccessManagement/TableHeader"; +import RequestTable from "../components/RequestManagement/RequestTable"; function Request() { - const [isSelecting, setIsSelecting] = useState(false); - const [search, setSearch] = useState(""); - const [searchQuery, isUpdating] = useDebounce(search, 400); - const selectedAccounts = useRef>(new Set([])); - const accounts = trpc.account.search.useQuery({ searchSubject: searchQuery }); + const requestedUsers = trpc.user.getUnverifiedUsers.useQuery(); return ( - - - Add New Account - - - - - - - diff --git a/web/server/routers/user.ts b/web/server/routers/user.ts index 39782b94..7afdfa31 100644 --- a/web/server/routers/user.ts +++ b/web/server/routers/user.ts @@ -5,6 +5,9 @@ import { findUserByUid, updateUserByUid, searchUsers, + findUnverifiedUsers, + deleteUser, + updateUserByEmail, } from "../../db/actions/User"; import { TRPCError } from "@trpc/server"; import { Role } from "../../utils/types/account"; @@ -19,6 +22,8 @@ import { Behavioral, } from "../../utils/types/post"; import { IUser } from "../../utils/types/user"; +import { addAccount } from "../../db/actions/Account"; +import Account from "../../db/models/Account"; const userPreferencesSchema = z.object({ preferredEmail: z.string().email().optional(), @@ -83,6 +88,20 @@ export const userRouter = router({ }); } }), + delete: procedure.input(z.string()).mutation(async ({ ctx, input }) => { + try { + const deletedUser = await deleteUser(input); + return { success: true }; + } catch (e) { + if (e instanceof TRPCError) throw e; + else + throw new TRPCError({ + message: "Internal Server Error", + code: "INTERNAL_SERVER_ERROR", + cause: e, + }); + } + }), disableStatus: procedure .input( z.object({ @@ -175,4 +194,70 @@ export const userRouter = router({ }); } }), + getUnverifiedUsers: procedure.query(async () => { + try { + const res = await findUnverifiedUsers(); + return res as IUser[]; + } catch (e) { + if (e instanceof TRPCError) throw e; + else + throw new TRPCError({ + message: "Internal Server Error", + code: "INTERNAL_SERVER_ERROR", + cause: e, + }); + } + }), + approveUser: procedure + .input( + z.object({ + email: z.string().email(), + role: z.nativeEnum(Role), + }) + ) + .mutation(async ({ ctx, input }) => { + if (ctx.session?.email?.toLowerCase() === input.email.toLowerCase()) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "User cannot add themselves", + }); + } + + const session = await Account.startSession(); + session.startTransaction(); + + try { + const inputData: { email: string; role: Role } = { + email: input.email, + role: input.role, + }; + + if ((await addAccount(inputData, session)) === null) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Account already exists", + }); + } + + await updateUserByEmail( + input.email, + { verifiedByAdmin: true, role: input.role, disabled: false }, + session + ); + + session.commitTransaction(); + return { success: true }; + } catch (e) { + session.abortTransaction(); + if (e instanceof TRPCError) { + throw e; + } else { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "An unexpected error occurred", + cause: e, + }); + } + } + }), }); From 3f5ee0c5883a07b510af32f383d11f9076e94899 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Sun, 16 Feb 2025 23:43:41 -0500 Subject: [PATCH 04/11] Implement sending emails when new user sign-up --- web/package.json | 1 + web/server/routers/auth.ts | 28 ++++ web/yarn.lock | 256 +++++++++++++++++++++++++++++++++++-- 3 files changed, 277 insertions(+), 8 deletions(-) diff --git a/web/package.json b/web/package.json index f51213fd..2673086e 100644 --- a/web/package.json +++ b/web/package.json @@ -56,6 +56,7 @@ "jest": "^29.6.2", "jest-environment-jsdom": "^29.6.2", "jsonwebtoken": "^9.0.0", + "juno-sdk": "^0.0.5", "mongoose": "^6.8.3", "next": "13.1.1", "next-query-params": "^4.3.0", diff --git a/web/server/routers/auth.ts b/web/server/routers/auth.ts index b9fb3a03..adea4267 100644 --- a/web/server/routers/auth.ts +++ b/web/server/routers/auth.ts @@ -1,5 +1,6 @@ import { TRPCError } from "@trpc/server"; import { findAccount } from "../../db/actions/Account"; +import juno from "juno-sdk"; import { createUser, findUserByEmail, @@ -10,6 +11,15 @@ import { logUserCreateEvent } from "../../utils/analytics-logger"; import { Role } from "../../utils/types/account"; const FACEBOOK_SIGN_IN_PROVIDER = "facebook.com" as const; +const JUNO_API_KEY = process.env.JUNO_API_KEY as string; +const JUNO_BASE_URL = process.env.JUNO_BASE_URL as string; +const JUNO_SENDER_EMAIL = process.env.JUNO_SENDER_EMAIL as string; +const JUNO_SENDER_NAME = process.env.JUNO_SENDER_NAME as string; + +juno.init({ + apiKey: JUNO_API_KEY as string, + baseURL: JUNO_BASE_URL as string, +}); export const authRouter = router({ signIn: procedure @@ -89,6 +99,24 @@ export const authRouter = router({ picture: ctx.session.picture, }); // TODO: send email to manager + const emailContent = `A new user signed up: ${ctx.session.email}, please go to admin request management portal to approve/decline their request.`; + await juno.email.sendEmail({ + recipients: [ + { + email: "josephshenq@gmail.com", + name: "Bits of Good Engineering", + }, + ], + bcc: [], + cc: [], + sender: { + email: JUNO_SENDER_EMAIL as string, + name: JUNO_SENDER_NAME as string, + }, + subject: "Angels Among Us New User Sign-in Request", + contents: [{ type: "text/html", value: emailContent }], + }); + throw new TRPCError({ code: "UNAUTHORIZED", message: diff --git a/web/yarn.lock b/web/yarn.lock index 2a42e60a..b1493d7f 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1780,6 +1780,11 @@ resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@bitauth/libauth@^1.17.1": + version "1.19.1" + resolved "https://registry.yarnpkg.com/@bitauth/libauth/-/libauth-1.19.1.tgz#713751bbc09815b667f8fe00a1cc5b0f3bf45dd1" + integrity sha512-R524tD5VwOt3QRHr7N518nqTVR/HKgfWL4LypekcGuNQN8R4PWScvuRcRzrY39A28kLztMv+TJdiKuMNbkU1ug== + "@bitwarden/cli@^2023.1.0": version "2023.9.1" resolved "https://registry.npmjs.org/@bitwarden/cli/-/cli-2023.9.1.tgz" @@ -7250,7 +7255,7 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -7638,6 +7643,18 @@ ascii-table@0.0.9: resolved "https://registry.npmjs.org/ascii-table/-/ascii-table-0.0.9.tgz" integrity sha1-BqZgTWpV1L9BqaR9mHLXp42jHnM= +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" @@ -7735,6 +7752,16 @@ avvio@^8.2.0: debug "^4.0.0" fastq "^1.6.1" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" + integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== + axe-core@^4.6.2: version "4.8.2" resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz" @@ -7907,6 +7934,13 @@ batch@^0.6.1: resolved "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + before-after-hook@^2.2.0: version "2.2.2" resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz" @@ -8312,6 +8346,11 @@ caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001538: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz" integrity sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw== +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + catharsis@^0.9.0: version "0.9.0" resolved "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz" @@ -8720,7 +8759,7 @@ colorspace@1.1.x: color "^3.1.3" text-hex "1.0.x" -combined-stream@^1.0.8: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -9045,6 +9084,11 @@ core-js-compat@^3.31.0: dependencies: browserslist "^4.21.10" +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + core-util-is@^1.0.3, core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" @@ -9315,6 +9359,13 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + data-uri-to-buffer@3: version "3.0.1" resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz" @@ -9874,6 +9925,14 @@ eastasianwidth@^0.2.0: resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" @@ -10748,7 +10807,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -10797,6 +10856,16 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fast-content-type-parse@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.0.0.tgz" @@ -11290,6 +11359,11 @@ for-in@^1.0.2: resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + form-data-encoder@^2.1.2: version "2.1.4" resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz" @@ -11304,6 +11378,15 @@ form-data@4.0.0, form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz" @@ -11632,6 +11715,13 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + gh-release-fetch@4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/gh-release-fetch/-/gh-release-fetch-4.0.3.tgz" @@ -11906,6 +11996,19 @@ gtoken@^6.1.0: google-p12-pem "^4.0.0" jws "^4.0.0" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" @@ -12190,6 +12293,15 @@ http-proxy@1.18.1, http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + http2-wrapper@^1.0.0-beta.5.2: version "1.0.3" resolved "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz" @@ -12900,7 +13012,7 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: dependencies: which-typed-array "^1.1.11" -is-typedarray@^1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -13013,6 +13125,11 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" @@ -13542,6 +13659,11 @@ js2xmlparser@^4.0.2: dependencies: xmlcreate "^2.0.4" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + jsdoc@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz" @@ -13661,12 +13783,17 @@ json-schema-traverse@^1.0.0: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@5: +json-stringify-safe@5, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -13742,6 +13869,16 @@ jsonwebtoken@^9.0.0, jsonwebtoken@^9.0.2: ms "^2.1.1" semver "^7.5.4" +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: version "3.3.5" resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz" @@ -13767,6 +13904,14 @@ junk@^4.0.0: resolved "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz" integrity sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ== +juno-sdk@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/juno-sdk/-/juno-sdk-0.0.5.tgz#7bca2a273f62d6707c2ca6f875a3b9b69ea096b8" + integrity sha512-JJayvnYeuF8sjRV4HFtpMslZIwsWvCPcW3WxY1TXr4IM+tUpMc4sEhW02haBQJ5YEKCG/1HjLcPP9FjufpyZ4g== + dependencies: + "@bitauth/libauth" "^1.17.1" + request "^2.88.2" + jwa@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz" @@ -14708,7 +14853,7 @@ mime-db@^1.28.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -15520,6 +15665,11 @@ nwsapi@^2.2.2, nwsapi@^2.2.4: resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz" integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" @@ -16147,6 +16297,11 @@ pend@~1.2.0: resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + pick-util@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/pick-util/-/pick-util-1.1.5.tgz" @@ -16535,6 +16690,13 @@ pseudomap@^1.0.1: resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +psl@^1.1.28: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + psl@^1.1.33: version "1.9.0" resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" @@ -16561,6 +16723,11 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pupa@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz" @@ -16587,6 +16754,11 @@ qs@^6.11.0, qs@^6.5.2, qs@^6.9.6: dependencies: side-channel "^1.0.4" +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + querystringify@^2.1.1: version "2.2.0" resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" @@ -17061,6 +17233,32 @@ repeat-string@^1.6.1: resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" @@ -17302,7 +17500,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -17340,7 +17538,7 @@ safe-stable-stringify@^2.3.1: resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz" integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -17789,6 +17987,21 @@ sprintf-js@~1.0.2: resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + stack-generator@^2.0.3: version "2.0.10" resolved "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz" @@ -18621,6 +18834,14 @@ tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" @@ -18725,6 +18946,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" @@ -19136,6 +19362,11 @@ uuid@9.0.0: resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + uuid@^8.0.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" @@ -19180,6 +19411,15 @@ vary@^1, vary@^1.1.2, vary@~1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vm2@^3.9.17: version "3.9.19" resolved "https://registry.npmjs.org/vm2/-/vm2-3.9.19.tgz" From 4be6205e39f9a02f37f106cb0389653276cd2263 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Sun, 16 Feb 2025 23:58:43 -0500 Subject: [PATCH 05/11] Refactor approval endpoints and debug remove accounts --- .../RequestManagement/ApproveSelector.tsx | 2 +- web/server/routers/account.ts | 8 ++- web/server/routers/user.ts | 52 ------------------- 3 files changed, 7 insertions(+), 55 deletions(-) diff --git a/web/components/RequestManagement/ApproveSelector.tsx b/web/components/RequestManagement/ApproveSelector.tsx index 0532e938..766cd8e9 100644 --- a/web/components/RequestManagement/ApproveSelector.tsx +++ b/web/components/RequestManagement/ApproveSelector.tsx @@ -22,7 +22,7 @@ function ApproveSelector(props: PropertyType) { const { requestedUser } = props; const { isOpen, onOpen, onClose } = useDisclosure(); - const mutation = trpc.user.approveUser.useMutation(); + const mutation = trpc.account.add.useMutation(); const utils = trpc.useUtils(); const options = Object.entries(roleLabels).map(([k, v]) => ({ diff --git a/web/server/routers/account.ts b/web/server/routers/account.ts index 652e28c8..c9f698a2 100644 --- a/web/server/routers/account.ts +++ b/web/server/routers/account.ts @@ -94,7 +94,11 @@ export const accountRouter = router({ try { await removeAllAccounts(input, session); - await updateAllUsers(input, { disabled: true }, session); + await updateAllUsers( + input, + { verifiedByAdmin: false, disabled: true }, + session + ); session.commitTransaction(); return { success: true }; @@ -142,7 +146,7 @@ export const accountRouter = router({ await updateUserByEmail( input.email, - { role: input.role, disabled: false }, + { verifiedByAdmin: true, role: input.role, disabled: false }, session ); diff --git a/web/server/routers/user.ts b/web/server/routers/user.ts index 7afdfa31..c2052fed 100644 --- a/web/server/routers/user.ts +++ b/web/server/routers/user.ts @@ -208,56 +208,4 @@ export const userRouter = router({ }); } }), - approveUser: procedure - .input( - z.object({ - email: z.string().email(), - role: z.nativeEnum(Role), - }) - ) - .mutation(async ({ ctx, input }) => { - if (ctx.session?.email?.toLowerCase() === input.email.toLowerCase()) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "User cannot add themselves", - }); - } - - const session = await Account.startSession(); - session.startTransaction(); - - try { - const inputData: { email: string; role: Role } = { - email: input.email, - role: input.role, - }; - - if ((await addAccount(inputData, session)) === null) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Account already exists", - }); - } - - await updateUserByEmail( - input.email, - { verifiedByAdmin: true, role: input.role, disabled: false }, - session - ); - - session.commitTransaction(); - return { success: true }; - } catch (e) { - session.abortTransaction(); - if (e instanceof TRPCError) { - throw e; - } else { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: "An unexpected error occurred", - cause: e, - }); - } - } - }), }); From 2c260f88c15dc24dac50bf8958c002018034b083 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Mon, 17 Feb 2025 00:02:25 -0500 Subject: [PATCH 06/11] change email recipient to bog email --- web/server/routers/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/server/routers/auth.ts b/web/server/routers/auth.ts index adea4267..e6f9efb4 100644 --- a/web/server/routers/auth.ts +++ b/web/server/routers/auth.ts @@ -103,7 +103,7 @@ export const authRouter = router({ await juno.email.sendEmail({ recipients: [ { - email: "josephshenq@gmail.com", + email: "gt.engineering@hack4impact.org", name: "Bits of Good Engineering", }, ], From 95ef148cfcd9889beada3d47d333c55538eff75a Mon Sep 17 00:00:00 2001 From: Samrat Sahoo Date: Mon, 17 Feb 2025 06:11:47 -0500 Subject: [PATCH 07/11] minor clean up --- .../RequestManagement/RequestedUserCard.tsx | 2 +- web/server/juno.ts | 33 +++++++++++++++++++ web/server/routers/auth.ts | 32 +++++------------- 3 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 web/server/juno.ts diff --git a/web/components/RequestManagement/RequestedUserCard.tsx b/web/components/RequestManagement/RequestedUserCard.tsx index a18b303b..3bfe2a6c 100644 --- a/web/components/RequestManagement/RequestedUserCard.tsx +++ b/web/components/RequestManagement/RequestedUserCard.tsx @@ -43,7 +43,7 @@ function RequestedUserCard(props: PropertyType) { justifyContent="center" onClick={() => handleDecline(user)} > - Decline + Delete User ); diff --git a/web/server/juno.ts b/web/server/juno.ts new file mode 100644 index 00000000..18a0e774 --- /dev/null +++ b/web/server/juno.ts @@ -0,0 +1,33 @@ +import juno from 'juno-sdk'; +import { EmailRecipient } from 'juno-sdk/build/main/internal/api'; + +const JUNO_API_KEY = process.env.JUNO_API_KEY as string; +const JUNO_BASE_URL = process.env.JUNO_BASE_URL as string; +const JUNO_SENDER_EMAIL = process.env.JUNO_SENDER_EMAIL as string; +const JUNO_SENDER_NAME = process.env.JUNO_SENDER_NAME as string; + +juno.init({ + apiKey: JUNO_API_KEY as string, + baseURL: JUNO_BASE_URL as string, +}); + +export const sendJunoEmail = async (emailContent: string, emailSubject: string, emailRecipient: EmailRecipient[], throwError?: boolean) => { + try { + await juno.email.sendEmail({ + recipients: emailRecipient, + bcc: [], + cc: [], + sender: { + email: JUNO_SENDER_EMAIL as string, + name: JUNO_SENDER_NAME as string, + }, + subject: emailSubject, + contents: [{ type: "text/html", value: emailContent }], + }); + } catch (e) { + if (throwError) { + throw e; + } + } + +} \ No newline at end of file diff --git a/web/server/routers/auth.ts b/web/server/routers/auth.ts index e6f9efb4..466b8203 100644 --- a/web/server/routers/auth.ts +++ b/web/server/routers/auth.ts @@ -9,17 +9,11 @@ import { import { router, procedure } from "../trpc"; import { logUserCreateEvent } from "../../utils/analytics-logger"; import { Role } from "../../utils/types/account"; +import { sendJunoEmail } from "../juno"; const FACEBOOK_SIGN_IN_PROVIDER = "facebook.com" as const; -const JUNO_API_KEY = process.env.JUNO_API_KEY as string; -const JUNO_BASE_URL = process.env.JUNO_BASE_URL as string; -const JUNO_SENDER_EMAIL = process.env.JUNO_SENDER_EMAIL as string; -const JUNO_SENDER_NAME = process.env.JUNO_SENDER_NAME as string; -juno.init({ - apiKey: JUNO_API_KEY as string, - baseURL: JUNO_BASE_URL as string, -}); + export const authRouter = router({ signIn: procedure @@ -98,25 +92,17 @@ export const authRouter = router({ name: ctx.session.name, picture: ctx.session.picture, }); + console.log("HERE 3"); // TODO: send email to manager const emailContent = `A new user signed up: ${ctx.session.email}, please go to admin request management portal to approve/decline their request.`; - await juno.email.sendEmail({ - recipients: [ - { + + if (process.env.NEXT_PUBLIC_CONTEXT !== "production") { + await sendJunoEmail(emailContent, "Angels Among Us New User Sign-in Request", + [{ email: "gt.engineering@hack4impact.org", name: "Bits of Good Engineering", - }, - ], - bcc: [], - cc: [], - sender: { - email: JUNO_SENDER_EMAIL as string, - name: JUNO_SENDER_NAME as string, - }, - subject: "Angels Among Us New User Sign-in Request", - contents: [{ type: "text/html", value: emailContent }], - }); - + }], false); + } throw new TRPCError({ code: "UNAUTHORIZED", message: From b0bb0a24167992d8f491d224ce4b07416fab7bbf Mon Sep 17 00:00:00 2001 From: Samrat Sahoo Date: Mon, 17 Feb 2025 06:21:42 -0500 Subject: [PATCH 08/11] improve padding --- web/components/RequestManagement/ApproveSelector.tsx | 5 +++-- web/components/RequestManagement/RequestedUserCard.tsx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/web/components/RequestManagement/ApproveSelector.tsx b/web/components/RequestManagement/ApproveSelector.tsx index 766cd8e9..565574d4 100644 --- a/web/components/RequestManagement/ApproveSelector.tsx +++ b/web/components/RequestManagement/ApproveSelector.tsx @@ -53,10 +53,11 @@ function ApproveSelector(props: PropertyType) { handleDecline(user)} From fe05e6b7fbfac415ec88f7d2732c48f8fa9df5a8 Mon Sep 17 00:00:00 2001 From: Samrat Sahoo Date: Mon, 17 Feb 2025 06:25:32 -0500 Subject: [PATCH 09/11] delete firebase user functionality --- web/server/routers/user.ts | 2 ++ web/utils/firebase/firebaseAdmin.ts | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/web/server/routers/user.ts b/web/server/routers/user.ts index c2052fed..f184f570 100644 --- a/web/server/routers/user.ts +++ b/web/server/routers/user.ts @@ -24,6 +24,7 @@ import { import { IUser } from "../../utils/types/user"; import { addAccount } from "../../db/actions/Account"; import Account from "../../db/models/Account"; +import { deleteFirebaseUser } from "../../utils/firebase/firebaseAdmin"; const userPreferencesSchema = z.object({ preferredEmail: z.string().email().optional(), @@ -91,6 +92,7 @@ export const userRouter = router({ delete: procedure.input(z.string()).mutation(async ({ ctx, input }) => { try { const deletedUser = await deleteUser(input); + await deleteFirebaseUser(input); return { success: true }; } catch (e) { if (e instanceof TRPCError) throw e; diff --git a/web/utils/firebase/firebaseAdmin.ts b/web/utils/firebase/firebaseAdmin.ts index e2cd1825..2af77147 100644 --- a/web/utils/firebase/firebaseAdmin.ts +++ b/web/utils/firebase/firebaseAdmin.ts @@ -14,4 +14,15 @@ if (!firebaseAdmin.apps.length) { }); } +export const deleteFirebaseUser = async (uid: string) => { + try { + const user = await firebaseAdmin.auth().getUser(uid); + if (user) { + await firebaseAdmin.auth().deleteUser(uid); + } + } catch (error) { + console.error("Error deleting user:", error); + } +} + export { firebaseAdmin }; From 256a0450319664e947a931d768e76ea634897628 Mon Sep 17 00:00:00 2001 From: josephshenq Date: Fri, 21 Feb 2025 21:30:49 -0500 Subject: [PATCH 10/11] Add modal for unverified user --- web/components/HOC/PageAccess.tsx | 45 +++++++- web/components/Navbar.tsx | 165 ++++++++++++++++++------------ web/context/auth.tsx | 7 +- web/server/routers/account.ts | 2 +- web/server/routers/auth.ts | 40 ++++---- 5 files changed, 170 insertions(+), 89 deletions(-) diff --git a/web/components/HOC/PageAccess.tsx b/web/components/HOC/PageAccess.tsx index 0d09d3f3..958f1a09 100644 --- a/web/components/HOC/PageAccess.tsx +++ b/web/components/HOC/PageAccess.tsx @@ -2,10 +2,11 @@ import { useAuth } from "../../context/auth"; import { Pages } from "../../utils/consts"; import { Role } from "../../utils/types/account"; import React from "react"; -import { Center, Spinner } from "@chakra-ui/react"; +import { Box, Text, Center, Flex, Spinner } from "@chakra-ui/react"; import { useRouter } from "next/router"; import PageNotFoundError from "../404"; import Head from "next/head"; +import Navbar from "../Navbar"; const unrestricted = new Set([Role.Volunteer, Role.ContentCreator, Role.Admin]); const restricted = new Set([Role.Admin]); @@ -58,10 +59,44 @@ const pageAccessHOC =

(Component: React.FC

) => { if (!authorized) { return ( <> - - Page Not Found - - + + + + + + Sorry! + + + + + + Your request to join our platform has been received, and + admins have been notified of the request. Once your request + has been approved, please visit our website again! + + + + + ); } diff --git a/web/components/Navbar.tsx b/web/components/Navbar.tsx index 5776d688..98530797 100644 --- a/web/components/Navbar.tsx +++ b/web/components/Navbar.tsx @@ -35,8 +35,9 @@ import { auth } from "../utils/firebase/firebaseClient"; interface AvatarProps { user: typeof auth.currentUser | null; onMenuClose: () => void; + authorized: boolean; } -function Avatar({ user, onMenuClose }: AvatarProps) { +function Avatar({ user, onMenuClose, authorized }: AvatarProps) { const { userData } = useAuth(); const router = useRouter(); const isMd = useBreakpointValue({ @@ -54,7 +55,9 @@ function Avatar({ user, onMenuClose }: AvatarProps) { p={{ base: 0, md: 4 }} _hover={{ bgColor: "white" }} _active={{ bgColor: "white" }} - borderLeft={{ md: "1px solid black" }} + borderLeft={ + authorized ? { md: "1px solid black" } : { md: "0px solid black" } + } borderRadius={0} onClick={isOpen ? onClose : onMenuClose} rightIcon={isMd ? : undefined} @@ -84,15 +87,17 @@ function Avatar({ user, onMenuClose }: AvatarProps) { {user?.email} - - }> - Profile - - + {authorized && ( + + }> + Profile + + + )} } @@ -123,11 +128,17 @@ export default function Navbar() { const visible = navbarVisiblity[router.pathname as Pages] ?? false; - if (!loading && visible && userData && !userData.hasCompletedOnboarding) { + if ( + !loading && + visible && + userData && + authorized && + !userData.hasCompletedOnboarding + ) { return <>; } - if (loading || !authorized || !visible) { + if (!user || loading || !visible) { return <>; } @@ -178,21 +189,25 @@ export default function Navbar() { alignItems="center" spacing={10} > - - - Feed - - + + Feed + + + )} {role === Role.Admin && ( <> )} - - - Resources - - - + {authorized && ( + <> + + + Resources + + + + )} + - + {isMenuOpen ? ( - - - Feed - - + {authorized && ( + + + Feed + + + )} {role === Role.Admin && ( <> )} - - - Resources - - + {authorized && ( + + + Resources + + + )} ) : null} diff --git a/web/context/auth.tsx b/web/context/auth.tsx index ebfcdab9..fafd8c67 100644 --- a/web/context/auth.tsx +++ b/web/context/auth.tsx @@ -83,7 +83,12 @@ export function AuthProvider({ children }: PropsWithChildren) { if (newSignIn.isError) { // Not authorized await signOut(auth); - } else if (!newSignIn.data!.hasCompletedOnboarding) { + } else if (!newSignIn.data!.authorized) { + router.replace(Pages.REQUEST_MANAGEMENT); + } else if ( + newSignIn.data!.authorized && + !newSignIn.data!.hasCompletedOnboarding + ) { router.replace(Pages.ONBOARDING); } setLoading(false); diff --git a/web/server/routers/account.ts b/web/server/routers/account.ts index c9f698a2..5442dc88 100644 --- a/web/server/routers/account.ts +++ b/web/server/routers/account.ts @@ -96,7 +96,7 @@ export const accountRouter = router({ await removeAllAccounts(input, session); await updateAllUsers( input, - { verifiedByAdmin: false, disabled: true }, + { verifiedByAdmin: false, disabled: true, role: Role.Volunteer }, session ); session.commitTransaction(); diff --git a/web/server/routers/auth.ts b/web/server/routers/auth.ts index 466b8203..ee361a0a 100644 --- a/web/server/routers/auth.ts +++ b/web/server/routers/auth.ts @@ -13,8 +13,6 @@ import { sendJunoEmail } from "../juno"; const FACEBOOK_SIGN_IN_PROVIDER = "facebook.com" as const; - - export const authRouter = router({ signIn: procedure // Firebase displayName needed to populate first-time sign in User @@ -54,14 +52,14 @@ export const authRouter = router({ }; } else if (user && !account) { // Subsequent sign-in, unauthorized account (approval request workflow) - await updateUserByUid(ctx.session.uid, { + const document = await updateUserByUid(ctx.session.uid, { disabled: true, }); - throw new TRPCError({ - code: "UNAUTHORIZED", - message: - "You are not permitted to log into this site. Please try again after your request for access has been approved.", - }); + return { + user: document, + authorized: false, + hasCompletedOnboarding: false, + }; } else if (!user && account) { // First-time sign-in, authorized account (invitation workflow) const document = await createUser({ @@ -97,17 +95,23 @@ export const authRouter = router({ const emailContent = `A new user signed up: ${ctx.session.email}, please go to admin request management portal to approve/decline their request.`; if (process.env.NEXT_PUBLIC_CONTEXT !== "production") { - await sendJunoEmail(emailContent, "Angels Among Us New User Sign-in Request", - [{ - email: "gt.engineering@hack4impact.org", - name: "Bits of Good Engineering", - }], false); + await sendJunoEmail( + emailContent, + "Angels Among Us New User Sign-in Request", + [ + { + email: "gt.engineering@hack4impact.org", + name: "Bits of Good Engineering", + }, + ], + false + ); } - throw new TRPCError({ - code: "UNAUTHORIZED", - message: - "You are not permitted to log into this site. Please try again after your request for access has been approved.", - }); + return { + user: document, + authorized: false, + hasCompletedOnboarding: false, + }; } } catch (e) { if (e instanceof TRPCError) throw e; From bfe4478e48ef9d3288df66a3760ab0ff8a9bc536 Mon Sep 17 00:00:00 2001 From: Samrat Sahoo Date: Sat, 22 Feb 2025 05:47:51 -0500 Subject: [PATCH 11/11] remove console statements --- web/server/routers/auth.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/server/routers/auth.ts b/web/server/routers/auth.ts index ee361a0a..1f5d33ba 100644 --- a/web/server/routers/auth.ts +++ b/web/server/routers/auth.ts @@ -1,6 +1,5 @@ import { TRPCError } from "@trpc/server"; import { findAccount } from "../../db/actions/Account"; -import juno from "juno-sdk"; import { createUser, findUserByEmail, @@ -35,7 +34,6 @@ export const authRouter = router({ } const user = await findUserByEmail(ctx.session.email); const account = await findAccount(ctx.session.email); - if (user && account) { // Subsequent sign-in, authorized account const document = await updateUserByUid(ctx.session.uid, { @@ -90,7 +88,7 @@ export const authRouter = router({ name: ctx.session.name, picture: ctx.session.picture, }); - console.log("HERE 3"); + // TODO: send email to manager const emailContent = `A new user signed up: ${ctx.session.email}, please go to admin request management portal to approve/decline their request.`;