From 10e095656f0c08e553b5b4e94eb9da8936f30745 Mon Sep 17 00:00:00 2001 From: Katalina Okano Date: Wed, 30 Jun 2021 08:02:25 -0400 Subject: [PATCH] chore: update codestyle due to prettier/rule updates --- hack/dockerfiles/bot.Dockerfile | 4 +- packages/api/handlers/clear-guild-cache.ts | 65 +++++----- packages/api/handlers/get-picker-data.ts | 93 +++++++------- packages/api/handlers/sync-from-legacy.ts | 99 +++++++------- packages/api/handlers/update-roles.ts | 121 +++++++++--------- packages/api/utils/api-tools.ts | 96 +++++++------- packages/api/utils/config.ts | 2 +- packages/api/utils/kv.ts | 8 +- packages/api/utils/rate-limiting.ts | 22 ++-- packages/design-system/.storybook/preview.js | 2 +- .../atoms/branding/DynamicBranding.tsx | 14 +- .../editor-category/EditorCategory.tsx | 16 +-- .../featureFlags/react/storyDecorator.tsx | 17 ++- .../misc-utils/withContext/withContext.tsx | 19 +-- .../src/contexts/session/SessionContext.tsx | 5 +- packages/web/src/pages/picker.tsx | 7 +- 16 files changed, 298 insertions(+), 292 deletions(-) diff --git a/hack/dockerfiles/bot.Dockerfile b/hack/dockerfiles/bot.Dockerfile index 4fe9a6b..a735a08 100644 --- a/hack/dockerfiles/bot.Dockerfile +++ b/hack/dockerfiles/bot.Dockerfile @@ -3,8 +3,8 @@ FROM node:14 AS builder # Create the user and group files that will be used in the running container to # run the process as an unprivileged user. RUN mkdir /user \ - && echo 'nobody:x:65534:65534:nobody:/:' >/user/passwd \ - && echo 'nobody:x:65534:' >/user/group + && echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd \ + && echo 'nobody:x:65534:' > /user/group # Set the working directory outside $GOPATH to enable the support for modules. WORKDIR /src diff --git a/packages/api/handlers/clear-guild-cache.ts b/packages/api/handlers/clear-guild-cache.ts index c1e05c8..0649b87 100644 --- a/packages/api/handlers/clear-guild-cache.ts +++ b/packages/api/handlers/clear-guild-cache.ts @@ -10,41 +10,42 @@ import { } from '../utils/responses'; export const ClearGuildCache = withSession( - (session) => async (request: Request): Promise => { - const url = new URL(request.url); - const [, , guildID] = url.pathname.split('/'); - if (!guildID) { - return missingParameters(); - } + (session) => + async (request: Request): Promise => { + const url = new URL(request.url); + const [, , guildID] = url.pathname.split('/'); + if (!guildID) { + return missingParameters(); + } - const rateLimit = useGuildRateLimiter( - guildID, - GuildRateLimiterKey.cacheClear, - 60 * 5 - ); // 5 minute RL TTL, 288 times per day. + const rateLimit = useGuildRateLimiter( + guildID, + GuildRateLimiterKey.cacheClear, + 60 * 5 + ); // 5 minute RL TTL, 288 times per day. - if (!isRoot(session.user.id)) { - const guild = session.guilds.find((guild) => guild.id === guildID); - if (!guild) { + if (!isRoot(session.user.id)) { + const guild = session.guilds.find((guild) => guild.id === guildID); + if (!guild) { + return notFound(); + } + + if ( + guild?.permissionLevel !== UserGuildPermissions.Manager && + guild?.permissionLevel !== UserGuildPermissions.Admin + ) { + return lowPermissions(); + } + + if (await rateLimit()) { + return rateLimited(); + } + } + + const result = await getGuild(guildID, { skipCachePull: true }); + if (!result) { return notFound(); } - - if ( - guild?.permissionLevel !== UserGuildPermissions.Manager && - guild?.permissionLevel !== UserGuildPermissions.Admin - ) { - return lowPermissions(); - } - - if (await rateLimit()) { - return rateLimited(); - } + return ok(); } - - const result = await getGuild(guildID, { skipCachePull: true }); - if (!result) { - return notFound(); - } - return ok(); - } ); diff --git a/packages/api/handlers/get-picker-data.ts b/packages/api/handlers/get-picker-data.ts index e8fcf2f..333db0b 100644 --- a/packages/api/handlers/get-picker-data.ts +++ b/packages/api/handlers/get-picker-data.ts @@ -5,52 +5,53 @@ import { getGuild, getGuildData, getGuildMemberRoles } from '../utils/guild'; const fail = () => respond({ error: 'guild not found' }, { status: 404 }); export const GetPickerData = withSession( - (session: SessionData) => async (request: Request): Promise => { - const url = new URL(request.url); - const [, , guildID] = url.pathname.split('/'); + (session: SessionData) => + async (request: Request): Promise => { + const url = new URL(request.url); + const [, , guildID] = url.pathname.split('/'); - if (!guildID) { - return respond({ error: 'missing guild id' }, { status: 400 }); + if (!guildID) { + return respond({ error: 'missing guild id' }, { status: 400 }); + } + + const { id: userID } = session.user as DiscordUser; + const guilds = session.guilds as GuildSlug[]; + + // Save a Discord API request by checking if this user is a member by session first + const checkGuild = guilds.find((guild) => guild.id === guildID); + if (!checkGuild) { + return fail(); + } + + const guild = await getGuild(guildID, { + skipCachePull: url.searchParams.has('__no_cache'), + }); + if (!guild) { + return fail(); + } + + const memberRolesP = getGuildMemberRoles({ + serverID: guildID, + userID, + }); + + const guildDataP = getGuildData(guildID); + + const [guildData, memberRoles] = await Promise.all([guildDataP, memberRolesP]); + if (!memberRoles) { + return fail(); + } + + const presentableGuild: PresentableGuild = { + id: guildID, + guild: checkGuild, + roles: guild.roles, + member: { + roles: memberRoles, + }, + data: guildData, + }; + + return respond(presentableGuild); } - - const { id: userID } = session.user as DiscordUser; - const guilds = session.guilds as GuildSlug[]; - - // Save a Discord API request by checking if this user is a member by session first - const checkGuild = guilds.find((guild) => guild.id === guildID); - if (!checkGuild) { - return fail(); - } - - const guild = await getGuild(guildID, { - skipCachePull: url.searchParams.has('__no_cache'), - }); - if (!guild) { - return fail(); - } - - const memberRolesP = getGuildMemberRoles({ - serverID: guildID, - userID, - }); - - const guildDataP = getGuildData(guildID); - - const [guildData, memberRoles] = await Promise.all([guildDataP, memberRolesP]); - if (!memberRoles) { - return fail(); - } - - const presentableGuild: PresentableGuild = { - id: guildID, - guild: checkGuild, - roles: guild.roles, - member: { - roles: memberRoles, - }, - data: guildData, - }; - - return respond(presentableGuild); - } ); diff --git a/packages/api/handlers/sync-from-legacy.ts b/packages/api/handlers/sync-from-legacy.ts index a174389..3752e3f 100644 --- a/packages/api/handlers/sync-from-legacy.ts +++ b/packages/api/handlers/sync-from-legacy.ts @@ -17,60 +17,61 @@ import { } from '../utils/responses'; export const SyncFromLegacy = withSession( - (session) => async (request: Request): Promise => { - const url = new URL(request.url); - const [, , guildID] = url.pathname.split('/'); - if (!guildID) { - return missingParameters(); - } + (session) => + async (request: Request): Promise => { + const url = new URL(request.url); + const [, , guildID] = url.pathname.split('/'); + if (!guildID) { + return missingParameters(); + } - const rateLimit = useGuildRateLimiter( - guildID, - GuildRateLimiterKey.legacyImport, - 60 * 20 - ); // 20 minute RL TTL, 72 times per day. + const rateLimit = useGuildRateLimiter( + guildID, + GuildRateLimiterKey.legacyImport, + 60 * 20 + ); // 20 minute RL TTL, 72 times per day. - // Allow root users to trigger this too, just in case. - if (!isRoot(session.user.id)) { - const guild = session.guilds.find((guild) => guild.id === guildID); - if (!guild) { + // Allow root users to trigger this too, just in case. + if (!isRoot(session.user.id)) { + const guild = session.guilds.find((guild) => guild.id === guildID); + if (!guild) { + return notFound(); + } + + if ( + guild?.permissionLevel !== UserGuildPermissions.Manager && + guild?.permissionLevel !== UserGuildPermissions.Admin + ) { + return lowPermissions(); + } + + if (await rateLimit()) { + return rateLimited(); + } + } + + const shouldForce = url.searchParams.get('force') === 'yes'; + + // Not using getGuildData as we want null feedback, not a zeroed out object. + const checkGuild = await GuildData.get(guildID); + // Don't force, and guild exists in our side, but LegacyGuild flag is set, + // fail this request. + if ( + !shouldForce && + checkGuild && + (checkGuild.features & Features.LegacyGuild) === Features.LegacyGuild + ) { + return conflict(); + } + + const legacyGuild = await fetchLegacyServer(guildID); + if (!legacyGuild) { return notFound(); } - if ( - guild?.permissionLevel !== UserGuildPermissions.Manager && - guild?.permissionLevel !== UserGuildPermissions.Admin - ) { - return lowPermissions(); - } + const newGuildData = transformLegacyGuild(legacyGuild); + await GuildData.put(guildID, newGuildData); - if (await rateLimit()) { - return rateLimited(); - } + return ok(); } - - const shouldForce = url.searchParams.get('force') === 'yes'; - - // Not using getGuildData as we want null feedback, not a zeroed out object. - const checkGuild = await GuildData.get(guildID); - // Don't force, and guild exists in our side, but LegacyGuild flag is set, - // fail this request. - if ( - !shouldForce && - checkGuild && - (checkGuild.features & Features.LegacyGuild) === Features.LegacyGuild - ) { - return conflict(); - } - - const legacyGuild = await fetchLegacyServer(guildID); - if (!legacyGuild) { - return notFound(); - } - - const newGuildData = transformLegacyGuild(legacyGuild); - await GuildData.put(guildID, newGuildData); - - return ok(); - } ); diff --git a/packages/api/handlers/update-roles.ts b/packages/api/handlers/update-roles.ts index c85b0eb..b51b29d 100644 --- a/packages/api/handlers/update-roles.ts +++ b/packages/api/handlers/update-roles.ts @@ -21,70 +21,71 @@ import { const notFound = () => respond({ error: 'guild not found' }, { status: 404 }); export const UpdateRoles = withSession( - ({ guilds, user: { id: userID } }: SessionData) => async (request: Request) => { - const updateRequest = (await request.json()) as RoleUpdate; - const [, , guildID] = new URL(request.url).pathname.split('/'); + ({ guilds, user: { id: userID } }: SessionData) => + async (request: Request) => { + const updateRequest = (await request.json()) as RoleUpdate; + const [, , guildID] = new URL(request.url).pathname.split('/'); - if (!guildID) { - return respond({ error: 'guild ID missing from URL' }, { status: 400 }); - } - - if (updateRequest.transactions.length === 0) { - return respond({ error: 'must have as least one transaction' }, { status: 400 }); - } - - const guildCheck = guilds.find((guild) => guild.id === guildID); - if (!guildCheck) { - return notFound(); - } - - const guild = await getGuild(guildID); - if (!guild) { - return notFound(); - } - - const guildMemberRoles = await getGuildMemberRoles( - { serverID: guildID, userID }, - { skipCachePull: true } - ); - if (!guildMemberRoles) { - return notFound(); - } - - const newRoles = calculateNewRoles({ - currentRoles: guildMemberRoles, - guildRoles: guild.roles, - guildData: await getGuildData(guildID), - updateRequest, - }); - - const patchMemberRoles = await discordFetch( - `/guilds/${guildID}/members/${userID}`, - botToken, - AuthType.Bot, - { - method: 'PATCH', - headers: { - 'content-type': 'application/json', - }, - body: JSON.stringify({ - roles: newRoles, - }), + if (!guildID) { + return respond({ error: 'guild ID missing from URL' }, { status: 400 }); } - ); - if (!patchMemberRoles) { - return respond({ error: 'discord rejected the request' }, { status: 500 }); + if (updateRequest.transactions.length === 0) { + return respond({ error: 'must have as least one transaction' }, { status: 400 }); + } + + const guildCheck = guilds.find((guild) => guild.id === guildID); + if (!guildCheck) { + return notFound(); + } + + const guild = await getGuild(guildID); + if (!guild) { + return notFound(); + } + + const guildMemberRoles = await getGuildMemberRoles( + { serverID: guildID, userID }, + { skipCachePull: true } + ); + if (!guildMemberRoles) { + return notFound(); + } + + const newRoles = calculateNewRoles({ + currentRoles: guildMemberRoles, + guildRoles: guild.roles, + guildData: await getGuildData(guildID), + updateRequest, + }); + + const patchMemberRoles = await discordFetch( + `/guilds/${guildID}/members/${userID}`, + botToken, + AuthType.Bot, + { + method: 'PATCH', + headers: { + 'content-type': 'application/json', + }, + body: JSON.stringify({ + roles: newRoles, + }), + } + ); + + if (!patchMemberRoles) { + return respond({ error: 'discord rejected the request' }, { status: 500 }); + } + + const updatedMember: Member = { + roles: patchMemberRoles.roles, + }; + + await updateGuildMemberRoles({ serverID: guildID, userID }, patchMemberRoles.roles); + + return respond(updatedMember); } - - const updatedMember: Member = { - roles: patchMemberRoles.roles, - }; - - await updateGuildMemberRoles({ serverID: guildID, userID }, patchMemberRoles.roles); - - return respond(updatedMember); - } ); const calculateNewRoles = ({ diff --git a/packages/api/utils/api-tools.ts b/packages/api/utils/api-tools.ts index d86d862..f6ab639 100644 --- a/packages/api/utils/api-tools.ts +++ b/packages/api/utils/api-tools.ts @@ -27,17 +27,19 @@ export const addCORS = (init: ResponseInit = {}) => ({ export const respond = (obj: Record, init: ResponseInit = {}) => new Response(JSON.stringify(obj), addCORS(init)); -export const resolveFailures = ( - handleWith: () => Response, - handler: (request: Request) => Promise | Response -) => async (request: Request): Promise => { - try { - return handler(request); - } catch (e) { - console.error(e); - return handleWith() || respond({ error: 'internal server error' }, { status: 500 }); - } -}; +export const resolveFailures = + ( + handleWith: () => Response, + handler: (request: Request) => Promise | Response + ) => + async (request: Request): Promise => { + try { + return handler(request); + } catch (e) { + console.error(e); + return handleWith() || respond({ error: 'internal server error' }, { status: 500 }); + } + }; export const parsePermissions = ( permissions: bigint, @@ -106,33 +108,35 @@ export const discordFetch = async ( } }; -export const cacheLayer = ( - kv: WrappedKVNamespace, - keyFactory: (identity: Identity) => string, - missHandler: (identity: Identity) => Promise, - ttlSeconds?: number -) => async ( - identity: Identity, - options: { skipCachePull?: boolean } = {} -): Promise => { - const key = keyFactory(identity); +export const cacheLayer = + ( + kv: WrappedKVNamespace, + keyFactory: (identity: Identity) => string, + missHandler: (identity: Identity) => Promise, + ttlSeconds?: number + ) => + async ( + identity: Identity, + options: { skipCachePull?: boolean } = {} + ): Promise => { + const key = keyFactory(identity); - if (!options.skipCachePull) { - const value = await kv.get(key); - if (value) { - return value; + if (!options.skipCachePull) { + const value = await kv.get(key); + if (value) { + return value; + } } - } - const fallbackValue = await missHandler(identity); - if (!fallbackValue) { - return null; - } + const fallbackValue = await missHandler(identity); + if (!fallbackValue) { + return null; + } - await kv.put(key, fallbackValue, ttlSeconds); + await kv.put(key, fallbackValue, ttlSeconds); - return fallbackValue; -}; + return fallbackValue; + }; const NotAuthenticated = (extra?: string) => respond( @@ -142,21 +146,21 @@ const NotAuthenticated = (extra?: string) => { status: 403 } ); -export const withSession = ( - wrappedHandler: (session: SessionData) => Handler -): Handler => async (request: Request): Promise => { - const sessionID = getSessionID(request); - if (!sessionID) { - return NotAuthenticated('missing authentication'); - } +export const withSession = + (wrappedHandler: (session: SessionData) => Handler): Handler => + async (request: Request): Promise => { + const sessionID = getSessionID(request); + if (!sessionID) { + return NotAuthenticated('missing authentication'); + } - const session = await Sessions.get(sessionID.id); - if (!session) { - return NotAuthenticated('authentication expired or not found'); - } + const session = await Sessions.get(sessionID.id); + if (!session) { + return NotAuthenticated('authentication expired or not found'); + } - return await wrappedHandler(session)(request); -}; + return await wrappedHandler(session)(request); + }; export const setupStateSession = async (data: T): Promise => { const stateID = (await KSUID.random()).string; diff --git a/packages/api/utils/config.ts b/packages/api/utils/config.ts index e04fae8..935bebd 100644 --- a/packages/api/utils/config.ts +++ b/packages/api/utils/config.ts @@ -1,4 +1,4 @@ -const self = (global as any) as Record; +const self = global as any as Record; const env = (key: string) => self[key] ?? ''; diff --git a/packages/api/utils/kv.ts b/packages/api/utils/kv.ts index e25b62a..db18ef5 100644 --- a/packages/api/utils/kv.ts +++ b/packages/api/utils/kv.ts @@ -53,11 +53,7 @@ class EmulatedKV implements KVNamespace { this.data.delete(key); } - async list(options?: { - prefix?: string; - limit?: number; - cursor?: string; - }): Promise<{ + async list(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<{ keys: { name: string; expiration?: number; metadata?: unknown }[]; list_complete: boolean; cursor: string; @@ -83,7 +79,7 @@ class EmulatedKV implements KVNamespace { const kvOrLocal = (namespace: KVNamespace | null): KVNamespace => namespace || new EmulatedKV(); -const self = (global as any) as Record; +const self = global as any as Record; export const Sessions = new WrappedKVNamespace(kvOrLocal(self.KV_SESSIONS ?? null)); export const GuildData = new WrappedKVNamespace(kvOrLocal(self.KV_GUILD_DATA ?? null)); diff --git a/packages/api/utils/rate-limiting.ts b/packages/api/utils/rate-limiting.ts index f3282ee..372cfb5 100644 --- a/packages/api/utils/rate-limiting.ts +++ b/packages/api/utils/rate-limiting.ts @@ -1,15 +1,13 @@ import { WrappedKVNamespace } from './kv'; -export const useRateLimiter = ( - kv: WrappedKVNamespace, - key: string, - timeoutSeconds: number -) => async (): Promise => { - const value = await kv.get(key); - if (value) { - return true; - } +export const useRateLimiter = + (kv: WrappedKVNamespace, key: string, timeoutSeconds: number) => + async (): Promise => { + const value = await kv.get(key); + if (value) { + return true; + } - await kv.put(key, true, timeoutSeconds); - return false; -}; + await kv.put(key, true, timeoutSeconds); + return false; + }; diff --git a/packages/design-system/.storybook/preview.js b/packages/design-system/.storybook/preview.js index 0bf478f..7708e82 100644 --- a/packages/design-system/.storybook/preview.js +++ b/packages/design-system/.storybook/preview.js @@ -1,5 +1,5 @@ -import { roleypolyTheme } from './theme'; import { mdxComponents } from '../atoms/typography/mdx'; +import { roleypolyTheme } from './theme'; export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, diff --git a/packages/design-system/atoms/branding/DynamicBranding.tsx b/packages/design-system/atoms/branding/DynamicBranding.tsx index 1f94d09..61a3598 100644 --- a/packages/design-system/atoms/branding/DynamicBranding.tsx +++ b/packages/design-system/atoms/branding/DynamicBranding.tsx @@ -10,9 +10,10 @@ type DynamicLogoProps = LogoFlagProps & { }; export const DynamicLogomark = (props: Partial) => { - const variant = React.useMemo(() => getRelevantVariant(props.currentDate), [ - props.currentDate, - ]); + const variant = React.useMemo( + () => getRelevantVariant(props.currentDate), + [props.currentDate] + ); if (!variant) { return ; @@ -35,9 +36,10 @@ export const DynamicLogomark = (props: Partial) => { }; export const DynamicLogotype = (props: Partial) => { - const variant = React.useMemo(() => getRelevantVariant(props.currentDate), [ - props.currentDate, - ]); + const variant = React.useMemo( + () => getRelevantVariant(props.currentDate), + [props.currentDate] + ); if (!variant) { return ; diff --git a/packages/design-system/molecules/editor-category/EditorCategory.tsx b/packages/design-system/molecules/editor-category/EditorCategory.tsx index 12daf3f..e31d5f2 100644 --- a/packages/design-system/molecules/editor-category/EditorCategory.tsx +++ b/packages/design-system/molecules/editor-category/EditorCategory.tsx @@ -38,14 +38,14 @@ export const EditorCategory = (props: Props) => { const [roleSearchPopoverActive, setRoleSearchPopoverActive] = React.useState(false); const [roleSearchTerm, updateSearchTerm] = React.useState(''); - const onUpdate = (key: keyof typeof props.category, pred?: (newValue: any) => any) => ( - newValue: any - ) => { - props.onChange({ - ...props.category, - [key]: pred ? pred(newValue) : newValue, - }); - }; + const onUpdate = + (key: keyof typeof props.category, pred?: (newValue: any) => any) => + (newValue: any) => { + props.onChange({ + ...props.category, + [key]: pred ? pred(newValue) : newValue, + }); + }; const handleRoleSelect = (role: RoleType) => { setRoleSearchPopoverActive(false); diff --git a/packages/misc-utils/featureFlags/react/storyDecorator.tsx b/packages/misc-utils/featureFlags/react/storyDecorator.tsx index cc8fac7..bcd470f 100644 --- a/packages/misc-utils/featureFlags/react/storyDecorator.tsx +++ b/packages/misc-utils/featureFlags/react/storyDecorator.tsx @@ -1,12 +1,11 @@ import * as React from 'react'; import { FeatureFlag, FeatureFlagProvider, FeatureFlagsContext } from './FeatureFlags'; -export const FeatureFlagDecorator = (flags: FeatureFlag[]) => ( - storyFn: () => React.ReactNode -) => { - return ( - - {storyFn()} - - ); -}; +export const FeatureFlagDecorator = + (flags: FeatureFlag[]) => (storyFn: () => React.ReactNode) => { + return ( + + {storyFn()} + + ); + }; diff --git a/packages/misc-utils/withContext/withContext.tsx b/packages/misc-utils/withContext/withContext.tsx index 0fc5310..8c9dfe4 100644 --- a/packages/misc-utils/withContext/withContext.tsx +++ b/packages/misc-utils/withContext/withContext.tsx @@ -1,10 +1,13 @@ import * as React from 'react'; -export const withContext = ( - Context: React.Context, - Component: React.ComponentType -): React.FunctionComponent => (props) => ( - - {(context) => } - -); +export const withContext = + ( + Context: React.Context, + Component: React.ComponentType + ): React.FunctionComponent => + (props) => + ( + + {(context) => } + + ); diff --git a/packages/web/src/contexts/session/SessionContext.tsx b/packages/web/src/contexts/session/SessionContext.tsx index 9fff7ed..94ed941 100644 --- a/packages/web/src/contexts/session/SessionContext.tsx +++ b/packages/web/src/contexts/session/SessionContext.tsx @@ -47,9 +47,8 @@ export const useSessionContext = () => React.useContext(SessionContext); export const SessionContextProvider = (props: { children: React.ReactNode }) => { const { fetch } = useApiContext(); - const [sessionID, setSessionID] = React.useState( - undefined - ); + const [sessionID, setSessionID] = + React.useState(undefined); const [sessionState, setSessionState] = React.useState( SessionState.NoAuth ); diff --git a/packages/web/src/pages/picker.tsx b/packages/web/src/pages/picker.tsx index 93a10ec..c9c577e 100644 --- a/packages/web/src/pages/picker.tsx +++ b/packages/web/src/pages/picker.tsx @@ -41,9 +41,10 @@ const Picker = (props: PickerProps) => { fetchPickerData(); }, [props.serverID, authedFetch, pushRecentGuild]); - React.useCallback((serverID) => pushRecentGuild(serverID), [pushRecentGuild])( - props.serverID - ); + React.useCallback( + (serverID) => pushRecentGuild(serverID), + [pushRecentGuild] + )(props.serverID); if (!isAuthenticated) { return ;