From 3255800eb06ffc0087d8d8027fb6c7fb5a719ec4 Mon Sep 17 00:00:00 2001 From: Aditya Sridhar Date: Fri, 15 Dec 2023 18:51:33 -0500 Subject: [PATCH 1/2] chore: add passage and redwood custom auth --- api/src/functions/graphql.ts | 2 + api/src/lib/auth.ts | 133 +++++++++++++-- package.json | 1 + web/package.json | 2 + web/src/App.tsx | 10 +- web/src/Routes.tsx | 4 +- web/src/auth.ts | 92 ++++++++++ yarn.lock | 313 ++++++++++++++++++++++++++++++++++- 8 files changed, 530 insertions(+), 27 deletions(-) create mode 100644 web/src/auth.ts diff --git a/api/src/functions/graphql.ts b/api/src/functions/graphql.ts index 4cf7e5ca..cb9bbdb3 100644 --- a/api/src/functions/graphql.ts +++ b/api/src/functions/graphql.ts @@ -7,10 +7,12 @@ import directives from 'src/directives/**/*.{js,ts}' import sdls from 'src/graphql/**/*.sdl.{js,ts}' import services from 'src/services/**/*.{js,ts}' +import { getCurrentUser } from 'src/lib/auth' import { db } from 'src/lib/db' import { logger } from 'src/lib/logger' export const handler = createGraphQLHandler({ + getCurrentUser, loggerConfig: { logger, options: { requestId: true, operationName: true } }, directives, sdls, diff --git a/api/src/lib/auth.ts b/api/src/lib/auth.ts index f98fe93a..77708384 100644 --- a/api/src/lib/auth.ts +++ b/api/src/lib/auth.ts @@ -1,25 +1,126 @@ +import { parseJWT, Decoded } from '@redwoodjs/api' +import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server' + +/** + * Represents the user attributes returned by the decoding the + * Authentication provider's JWT together with an optional list of roles. + */ +type RedwoodUser = Record & { roles?: string[] } + /** - * Once you are ready to add authentication to your application - * you'll build out requireAuth() with real functionality. For - * now we just return `true` so that the calls in services - * have something to check against, simulating a logged - * in user that is allowed to access that service. + * getCurrentUser returns the user information together with + * an optional collection of roles used by requireAuth() to check + * if the user is authenticated or has role-based access * - * See https://redwoodjs.com/docs/authentication for more info. + * !! BEWARE !! Anything returned from this function will be available to the + * client--it becomes the content of `currentUser` on the web side (as well as + * `context.currentUser` on the api side). You should carefully add additional + * fields to the return object only once you've decided they are safe to be seen + * if someone were to open the Web Inspector in their browser. + * + * @see https://github.com/redwoodjs/redwood/tree/main/packages/auth for examples + * + * @param decoded - The decoded access token containing user info and JWT + * claims like `sub`. Note, this could be null. + * @param { token, SupportedAuthTypes type } - The access token itself as well + * as the auth provider type + * @param { APIGatewayEvent event, Context context } - An optional object which + * contains information from the invoker such as headers and cookies, and the + * context information about the invocation such as IP Address + * @returns RedwoodUser */ -export const isAuthenticated = () => { - return true +export const getCurrentUser = async ( + decoded: Decoded +): Promise => { + if (!decoded) { + return null + } + + const { roles } = parseJWT({ decoded }) + + if (roles) { + return { ...decoded, roles } + } + + return { ...decoded } } -export const hasRole = ({ roles }) => { - return roles !== undefined +/** + * The user is authenticated if there is a currentUser in the context + * + * @returns {boolean} - If the currentUser is authenticated + */ +export const isAuthenticated = (): boolean => { + return !!context.currentUser } -// This is used by the redwood directive -// in ./api/src/directives/requireAuth +/** + * When checking role membership, roles can be a single value, a list, or none. + * You can use Prisma enums too (if you're using them for roles), just import your enum type from `@prisma/client` + */ +type AllowedRoles = string | string[] | undefined + +/** + * Checks if the currentUser is authenticated (and assigned one of the given roles) + * + * @param roles: {@link AllowedRoles} - Checks if the currentUser is assigned one of these roles + * + * @returns {boolean} - Returns true if the currentUser is logged in and assigned one of the given roles, + * or when no roles are provided to check against. Otherwise returns false. + */ +export const hasRole = (roles: AllowedRoles): boolean => { + if (!isAuthenticated()) { + return false + } + + const currentUserRoles = context.currentUser?.roles + + if (typeof roles === 'string') { + if (typeof currentUserRoles === 'string') { + // roles to check is a string, currentUser.roles is a string + return currentUserRoles === roles + } else if (Array.isArray(currentUserRoles)) { + // roles to check is a string, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + + if (Array.isArray(roles)) { + if (Array.isArray(currentUserRoles)) { + // roles to check is an array, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => + roles.includes(allowedRole) + ) + } else if (typeof currentUserRoles === 'string') { + // roles to check is an array, currentUser.roles is a string + return roles.some((allowedRole) => currentUserRoles === allowedRole) + } + } + + // roles not found + return false +} + +/** + * Use requireAuth in your services to check that a user is logged in, + * whether or not they are assigned a role, and optionally raise an + * error if they're not. + * + * @param roles?: {@link AllowedRoles} - When checking role membership, these roles grant access. + * + * @returns - If the currentUser is authenticated (and assigned one of the given roles) + * + * @throws {@link AuthenticationError} - If the currentUser is not authenticated + * @throws {@link ForbiddenError} - If the currentUser is not allowed due to role permissions + * + * @see https://github.com/redwoodjs/redwood/tree/main/packages/auth for examples + */ +export const requireAuth = ({ roles }: { roles?: AllowedRoles } = {}) => { + if (!isAuthenticated()) { + throw new AuthenticationError("You don't have permission to do that.") + } -// Roles are passed in by the requireAuth directive if you have auth setup -// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -export const requireAuth = ({ roles }) => { - return isAuthenticated() + if (roles && !hasRole(roles)) { + throw new ForbiddenError("You don't have access to do that.") + } } diff --git a/package.json b/package.json index 0950844c..3bb03917 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "devDependencies": { "@netlify/zip-it-and-ship-it": "^9.27.0", + "@redwoodjs/auth-custom-setup": "6.4.2", "@redwoodjs/core": "6.4.2" }, "eslintConfig": { diff --git a/web/package.json b/web/package.json index 27cbc1b6..d39ea1cc 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,8 @@ }, "dependencies": { "@datadog/browser-rum": "^5.4.0", + "@passageidentity/passage-elements": "^1.17.0", + "@redwoodjs/auth": "6.4.2", "@redwoodjs/forms": "6.4.2", "@redwoodjs/router": "6.4.2", "@redwoodjs/web": "6.4.2", diff --git a/web/src/App.tsx b/web/src/App.tsx index 656fe632..133cebcb 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -27,14 +27,18 @@ import { RedwoodApolloProvider } from '@redwoodjs/web/apollo' import FatalErrorPage from 'src/pages/FatalErrorPage' import Routes from 'src/Routes' +import { AuthProvider, useAuth } from './auth' + import './scss/custom.scss' const App = () => ( - - - + + + + + ) diff --git a/web/src/Routes.tsx b/web/src/Routes.tsx index a8ff9821..590b5442 100644 --- a/web/src/Routes.tsx +++ b/web/src/Routes.tsx @@ -11,9 +11,11 @@ import { Set, Router, Route } from '@redwoodjs/router' import ScaffoldLayout from 'src/layouts/ScaffoldLayout' +import { useAuth } from './auth' + const Routes = () => { return ( - + diff --git a/web/src/auth.ts b/web/src/auth.ts new file mode 100644 index 00000000..eff2981b --- /dev/null +++ b/web/src/auth.ts @@ -0,0 +1,92 @@ +import { createAuthentication } from '@redwoodjs/auth' + +// If you're integrating with an auth service provider you should delete this interface. +// Instead you should import the type from their auth client sdk. +export interface AuthClient { + login: () => User + logout: () => void + signup: () => User + getToken: () => string + getUserMetadata: () => User | null +} + +// If you're integrating with an auth service provider you should delete this interface. +// This type should be inferred from the general interface above. +interface User { + // The name of the id variable will vary depending on what auth service + // provider you're integrating with. Another common name is `sub` + id: string + email?: string + username?: string + roles: string[] +} + +// If you're integrating with an auth service provider you should delete this interface +// This type should be inferred from the general interface above +export interface ValidateResetTokenResponse { + error?: string + [key: string]: string | undefined +} + +// Replace this with the auth service provider client sdk +const client = { + login: () => ({ + id: 'unique-user-id', + email: 'email@example.com', + roles: [], + }), + signup: () => ({ + id: 'unique-user-id', + email: 'email@example.com', + roles: [], + }), + logout: () => {}, + getToken: () => 'super-secret-short-lived-token', + getUserMetadata: () => ({ + id: 'unique-user-id', + email: 'email@example.com', + roles: [], + }), +} + +function createAuth() { + const authImplementation = createAuthImplementation(client) + + // You can pass custom provider hooks here if you need to as a second + // argument. See the Redwood framework source code for how that's used + return createAuthentication(authImplementation) +} + +// This is where most of the integration work will take place. You should keep +// the shape of this object (i.e. keep all the key names) but change all the +// values/functions to use methods from the auth service provider client sdk +// you're integrating with +function createAuthImplementation(client: AuthClient) { + return { + type: 'custom-auth', + client, + login: async () => client.login(), + logout: async () => client.logout(), + signup: async () => client.signup(), + getToken: async () => client.getToken(), + /** + * Actual user metadata might look something like this + * { + * "id": "11111111-2222-3333-4444-5555555555555", + * "aud": "authenticated", + * "role": "authenticated", + * "roles": ["admin"], + * "email": "email@example.com", + * "app_metadata": { + * "provider": "email" + * }, + * "user_metadata": null, + * "created_at": "2016-05-15T19:53:12.368652374-07:00", + * "updated_at": "2016-05-15T19:53:12.368652374-07:00" + * } + */ + getUserMetadata: async () => client.getUserMetadata(), + } +} + +export const { AuthProvider, useAuth } = createAuth() diff --git a/yarn.lock b/yarn.lock index 53588613..200969e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1124,7 +1124,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.1.6, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.8, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.16, @babel/parser@npm:^7.22.5, @babel/parser@npm:^7.23.6, @babel/parser@npm:^7.3.2": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.1.6, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.8, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.16, @babel/parser@npm:^7.22.5, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.23.6, @babel/parser@npm:^7.3.2": version: 7.23.6 resolution: "@babel/parser@npm:7.23.6" bin: @@ -4122,6 +4122,33 @@ __metadata: languageName: node linkType: hard +"@intlify/core-base@npm:9.8.0": + version: 9.8.0 + resolution: "@intlify/core-base@npm:9.8.0" + dependencies: + "@intlify/message-compiler": 9.8.0 + "@intlify/shared": 9.8.0 + checksum: 3e34ef70d378d45c8e579b930f57af8f9b55d4c81e1ae9c2626f720930c785905a35f5ef415d70aa3aa0a899270bf27fec880909bf54f2dc3555bcbdc0448c6a + languageName: node + linkType: hard + +"@intlify/message-compiler@npm:9.8.0": + version: 9.8.0 + resolution: "@intlify/message-compiler@npm:9.8.0" + dependencies: + "@intlify/shared": 9.8.0 + source-map-js: ^1.0.2 + checksum: d01763ff78745e0402a028324d249ec0bc420cb2babd0420c3d1efb3e4d4b9a2fe8851950649b27acc8d4a5da615f4ca3ee4e423cacf96d32b5a391e50ffc574 + languageName: node + linkType: hard + +"@intlify/shared@npm:9.8.0": + version: 9.8.0 + resolution: "@intlify/shared@npm:9.8.0" + checksum: d1b061594ece1c429335b92b25a0db1a8ab51dd26ca85dae9f09eb520541244cdf77e4997e6cfded386836b24c061b0dffc315879227d3f72749802e25a81b7e + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -4421,7 +4448,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 @@ -5035,6 +5062,45 @@ __metadata: languageName: node linkType: hard +"@passageidentity/passage-elements@npm:^1.17.0": + version: 1.17.0 + resolution: "@passageidentity/passage-elements@npm:1.17.0" + dependencies: + "@passageidentity/passage-js": 3.11.0 + dayjs: ^1.11.0 + gridstack: 5.0.0 + intl-tel-input: ^17.0.13 + jwt-decode: ^3.1.2 + ua-parser-js: ^1.0.35 + vue: ^3.3.4 + vue-i18n: ^9.3 + vue-inline-svg: ^3.1.0 + checksum: b26e7ee5e60cdbc56360006b3ce2b791255efdf5ae1a62c1bac24b8d84edf7875df3c8daf8811feb36bb879ddaea1e85b8d577fadb57dcec10bdc11c2d2065a0 + languageName: node + linkType: hard + +"@passageidentity/passage-js@npm:3.11.0": + version: 3.11.0 + resolution: "@passageidentity/passage-js@npm:3.11.0" + dependencies: + "@passageidentity/webauthnutils": 1.1.2 + "@types/node": ^17.0.27 + js-cookie: ^3.0.1 + jwt-decode: ^3.1.2 + serialize-error: ^11.0.0 + checksum: 3137dd7e8b72530191574e904c7f7ebce01984381473119f050633c01722f35ffeac348728ee35bdf93bfa06a4f736c8adb5264c3cb5a42d5d70b47b7cb786fe + languageName: node + linkType: hard + +"@passageidentity/webauthnutils@npm:1.1.2": + version: 1.1.2 + resolution: "@passageidentity/webauthnutils@npm:1.1.2" + dependencies: + ua-parser-js: ^1.0.34 + checksum: c0e29e4f320b3ce2cba6a2588782627723afdfc45303193ee24e2ddb1a554a72e6afbc2b9417d12a7216c9d7b323ef0c6480039017dfe96d19adb4fd913f6d43 + languageName: node + linkType: hard + "@peculiar/asn1-schema@npm:^2.3.6": version: 2.3.8 resolution: "@peculiar/asn1-schema@npm:2.3.8" @@ -5457,6 +5523,17 @@ __metadata: languageName: node linkType: hard +"@redwoodjs/auth-custom-setup@npm:6.4.2": + version: 6.4.2 + resolution: "@redwoodjs/auth-custom-setup@npm:6.4.2" + dependencies: + "@babel/runtime-corejs3": 7.23.2 + "@redwoodjs/cli-helpers": 6.4.2 + core-js: 3.33.2 + checksum: dde842111cc5d4b39b1b492d1a9499e473fb355615e2228cd9e3022d3d3e1ac6dd72db578c6db085387897a74c0f7db02f07edf3c1bfdc183963ae5ca4097e00 + languageName: node + linkType: hard + "@redwoodjs/auth@npm:6.4.2": version: 6.4.2 resolution: "@redwoodjs/auth@npm:6.4.2" @@ -7134,6 +7211,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^17.0.27": + version: 17.0.45 + resolution: "@types/node@npm:17.0.45" + checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8 + languageName: node + linkType: hard + "@types/normalize-package-data@npm:^2.4.0": version: 2.4.4 resolution: "@types/normalize-package-data@npm:2.4.4" @@ -7579,6 +7663,125 @@ __metadata: languageName: node linkType: hard +"@vue/compiler-core@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/compiler-core@npm:3.3.11" + dependencies: + "@babel/parser": ^7.23.5 + "@vue/shared": 3.3.11 + estree-walker: ^2.0.2 + source-map-js: ^1.0.2 + checksum: 30bc962fd30fe20082ad935579968acd9d7d32bdfab78a2136061e3d8488dabd6fc838b392758470a6205223f56d0d6f70b1bd025f8f668f7b13d0f9e06981b5 + languageName: node + linkType: hard + +"@vue/compiler-dom@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/compiler-dom@npm:3.3.11" + dependencies: + "@vue/compiler-core": 3.3.11 + "@vue/shared": 3.3.11 + checksum: 0a3b8267f0ff208425e6e8db371935a2948f9c24e436d8d7f52f2c873c729112e8c78cbba7b9aa3568597d306f8dfdc13fdec71736b4bd65ebdcadbc4976b0e1 + languageName: node + linkType: hard + +"@vue/compiler-sfc@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/compiler-sfc@npm:3.3.11" + dependencies: + "@babel/parser": ^7.23.5 + "@vue/compiler-core": 3.3.11 + "@vue/compiler-dom": 3.3.11 + "@vue/compiler-ssr": 3.3.11 + "@vue/reactivity-transform": 3.3.11 + "@vue/shared": 3.3.11 + estree-walker: ^2.0.2 + magic-string: ^0.30.5 + postcss: ^8.4.32 + source-map-js: ^1.0.2 + checksum: 9b588c2de5ee31ccc5ee8d44fe50f2b9c7ecc9d93f45ffd94cf57de3546d8113a5cf822a3d9ad54594385991dce2a7ba6acc288cba10fc56a8b638e679c4b921 + languageName: node + linkType: hard + +"@vue/compiler-ssr@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/compiler-ssr@npm:3.3.11" + dependencies: + "@vue/compiler-dom": 3.3.11 + "@vue/shared": 3.3.11 + checksum: 047c239b873b0670fdfab101d646d2449f5dad96d6a2e724e28c696e33515bf310d806ec7d3147a7e6ad2d9cd648baa7ebaf821a3fb767f5e7d4dfbcc93d2178 + languageName: node + linkType: hard + +"@vue/devtools-api@npm:^6.5.0": + version: 6.5.1 + resolution: "@vue/devtools-api@npm:6.5.1" + checksum: 3de9ff5ec78890c84d22c59910e26bf53140413895ba85b0e2a276609c24d9dde007cf468d9f21ef18389eaef75605fe94e79a761beb30d3bbb7af1ef19bbd4e + languageName: node + linkType: hard + +"@vue/reactivity-transform@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/reactivity-transform@npm:3.3.11" + dependencies: + "@babel/parser": ^7.23.5 + "@vue/compiler-core": 3.3.11 + "@vue/shared": 3.3.11 + estree-walker: ^2.0.2 + magic-string: ^0.30.5 + checksum: bf40f9173b627cca0bac89f15f4760b9ffc6d579fab22cec8828e36943058f8d5b864414a3269f2d8af2c8133daeacbca2b8b509306f6ae607e571a8f09b50a3 + languageName: node + linkType: hard + +"@vue/reactivity@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/reactivity@npm:3.3.11" + dependencies: + "@vue/shared": 3.3.11 + checksum: b3d7db835cfd652add265c54e84c318b5d7beefb343a61a0f198e7c5943b6d3f19e42b93605976b366e853abd502a51d33aafe62809d576f78e850bfecb4a44d + languageName: node + linkType: hard + +"@vue/runtime-core@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/runtime-core@npm:3.3.11" + dependencies: + "@vue/reactivity": 3.3.11 + "@vue/shared": 3.3.11 + checksum: fabf4c314c395c0d88a259113954302df999673e07e2cb9431e9beb74f6eefd41be56b550c1c40c0d696545eef830017db4613408be3b6f8ad02089a5b74abda + languageName: node + linkType: hard + +"@vue/runtime-dom@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/runtime-dom@npm:3.3.11" + dependencies: + "@vue/runtime-core": 3.3.11 + "@vue/shared": 3.3.11 + csstype: ^3.1.2 + checksum: e732b22f3a156aef35f83504e312d2f94811da231e7826f79093d04dcfd852b3295b4ec71d9cc75d1751aea316ec279852277ffe500f5f5153977870610fd95e + languageName: node + linkType: hard + +"@vue/server-renderer@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/server-renderer@npm:3.3.11" + dependencies: + "@vue/compiler-ssr": 3.3.11 + "@vue/shared": 3.3.11 + peerDependencies: + vue: 3.3.11 + checksum: 48ab0b67f36814ddb0b44f8455a6fe0e790159add94297c2d10f8d9661897ce82034a4cf87ce8590b06626864ef8e16157e65114cf2451f133f9e791dba5967d + languageName: node + linkType: hard + +"@vue/shared@npm:3.3.11": + version: 3.3.11 + resolution: "@vue/shared@npm:3.3.11" + checksum: 1b98f5280f6a3fb0dfe6dfa4fc6589633208f1ad84f435ecca2f936bbabce60a21c25b0ff1fc48628dc9bfd9148a798991011d2053cad532c30931728fbeeb69 + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": version: 1.11.6 resolution: "@webassemblyjs/ast@npm:1.11.6" @@ -11034,7 +11237,7 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2": +"csstype@npm:^3.0.2, csstype@npm:^3.1.2": version: 3.1.3 resolution: "csstype@npm:3.1.3" checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 @@ -11089,6 +11292,13 @@ __metadata: languageName: node linkType: hard +"dayjs@npm:^1.11.0": + version: 1.11.10 + resolution: "dayjs@npm:1.11.10" + checksum: a6b5a3813b8884f5cd557e2e6b7fa569f4c5d0c97aca9558e38534af4f2d60daafd3ff8c2000fed3435cfcec9e805bcebd99f90130c6d1c5ef524084ced588c4 + languageName: node + linkType: hard + "dc-polyfill@npm:^0.1.2": version: 0.1.3 resolution: "dc-polyfill@npm:0.1.3" @@ -12770,7 +12980,7 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:2.0.2, estree-walker@npm:^2.0.1": +"estree-walker@npm:2.0.2, estree-walker@npm:^2.0.1, estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" checksum: 6151e6f9828abe2259e57f5fd3761335bb0d2ebd76dc1a01048ccee22fabcfef3c0859300f6d83ff0d1927849368775ec5a6d265dde2f6de5a1be1721cd94efc @@ -14133,6 +14343,13 @@ __metadata: languageName: node linkType: hard +"gridstack@npm:5.0.0": + version: 5.0.0 + resolution: "gridstack@npm:5.0.0" + checksum: 438076867294368c95dbee958d2d3402e6b46ae8e885796acb63420671b828d98d63503dc7935ea3b3662e0c3c0fefa17a270c83f89319935c34f8c5002f38ce + languageName: node + linkType: hard + "gzip-size@npm:^6.0.0": version: 6.0.0 resolution: "gzip-size@npm:6.0.0" @@ -14838,6 +15055,13 @@ __metadata: languageName: node linkType: hard +"intl-tel-input@npm:^17.0.13": + version: 17.0.21 + resolution: "intl-tel-input@npm:17.0.21" + checksum: 834c4b72f6e8e9905544e1959ff5501e3f071d744be3f51187f5544953d829b988641ace5ddf23a417866205737af5d5197056aedcdc830caf424469ad5d521a + languageName: node + linkType: hard + "invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" @@ -16051,6 +16275,13 @@ __metadata: languageName: node linkType: hard +"js-cookie@npm:^3.0.1": + version: 3.0.5 + resolution: "js-cookie@npm:3.0.5" + checksum: 2dbd2809c6180fbcf060c6957cb82dbb47edae0ead6bd71cbeedf448aa6b6923115003b995f7d3e3077bfe2cb76295ea6b584eb7196cca8ba0a09f389f64967a + languageName: node + linkType: hard + "js-levenshtein@npm:^1.1.6": version: 1.1.6 resolution: "js-levenshtein@npm:1.1.6" @@ -16326,6 +16557,13 @@ __metadata: languageName: node linkType: hard +"jwt-decode@npm:^3.1.2": + version: 3.1.2 + resolution: "jwt-decode@npm:3.1.2" + checksum: 20a4b072d44ce3479f42d0d2c8d3dabeb353081ba4982e40b83a779f2459a70be26441be6c160bfc8c3c6eadf9f6380a036fbb06ac5406b5674e35d8c4205eeb + languageName: node + linkType: hard + "keyv@npm:^3.0.0": version: 3.1.0 resolution: "keyv@npm:3.1.0" @@ -16846,6 +17084,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.5": + version: 0.30.5 + resolution: "magic-string@npm:0.30.5" + dependencies: + "@jridgewell/sourcemap-codec": ^1.4.15 + checksum: da10fecff0c0a7d3faf756913ce62bd6d5e7b0402be48c3b27bfd651b90e29677e279069a63b764bcdc1b8ecdcdb898f29a5c5ec510f2323e8d62ee057a6eb18 + languageName: node + linkType: hard + "make-dir@npm:4.0.0, make-dir@npm:^4.0.0": version: 4.0.0 resolution: "make-dir@npm:4.0.0" @@ -19174,7 +19421,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.14, postcss@npm:^8.4.21, postcss@npm:^8.4.23, postcss@npm:^8.4.24, postcss@npm:^8.4.27, postcss@npm:^8.4.31": +"postcss@npm:^8.2.14, postcss@npm:^8.4.21, postcss@npm:^8.4.23, postcss@npm:^8.4.24, postcss@npm:^8.4.27, postcss@npm:^8.4.31, postcss@npm:^8.4.32": version: 8.4.32 resolution: "postcss@npm:8.4.32" dependencies: @@ -20418,6 +20665,7 @@ __metadata: resolution: "root-workspace-0b6124@workspace:." dependencies: "@netlify/zip-it-and-ship-it": ^9.27.0 + "@redwoodjs/auth-custom-setup": 6.4.2 "@redwoodjs/core": 6.4.2 fsevents: ^2.3.3 languageName: unknown @@ -20738,6 +20986,15 @@ __metadata: languageName: node linkType: hard +"serialize-error@npm:^11.0.0": + version: 11.0.3 + resolution: "serialize-error@npm:11.0.3" + dependencies: + type-fest: ^2.12.2 + checksum: 09d1aee6186fd5ff8acc074ee8641116cdd07b12df1e95682c43d8b5d1ef657deecc2efede7f1a08f5ff3ef3d65fb60ab9c8b4b2fdde65867ad3e6d4feed34a9 + languageName: node + linkType: hard + "serialize-javascript@npm:^4.0.0": version: 4.0.0 resolution: "serialize-javascript@npm:4.0.0" @@ -22352,7 +22609,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^2.19.0": +"type-fest@npm:^2.12.2, type-fest@npm:^2.19.0": version: 2.19.0 resolution: "type-fest@npm:2.19.0" checksum: a4ef07ece297c9fba78fc1bd6d85dff4472fe043ede98bd4710d2615d15776902b595abf62bd78339ed6278f021235fb28a96361f8be86ed754f778973a0d278 @@ -22470,7 +22727,7 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^1.0.35": +"ua-parser-js@npm:^1.0.34, ua-parser-js@npm:^1.0.35": version: 1.0.37 resolution: "ua-parser-js@npm:1.0.37" checksum: 4d481c720d523366d7762dc8a46a1b58967d979aacf786f9ceceb1cd767de069f64a4bdffb63956294f1c0696eb465ddb950f28ba90571709e33521b4bd75e07 @@ -23009,6 +23266,46 @@ __metadata: languageName: node linkType: hard +"vue-i18n@npm:^9.3": + version: 9.8.0 + resolution: "vue-i18n@npm:9.8.0" + dependencies: + "@intlify/core-base": 9.8.0 + "@intlify/shared": 9.8.0 + "@vue/devtools-api": ^6.5.0 + peerDependencies: + vue: ^3.0.0 + checksum: 507d683268ac6a2a11640065c9e7fbec66f15e514f6ae412b65f3bea9ae1b65afc43e9c1832f2c7a5ac14b23117415de4849f3a2ea0b79cbcfa6a5871c8793cf + languageName: node + linkType: hard + +"vue-inline-svg@npm:^3.1.0": + version: 3.1.2 + resolution: "vue-inline-svg@npm:3.1.2" + peerDependencies: + vue: ^3 + checksum: 3699193cd0219fa62022e276936949bbf2cbfca8adeb11f24f414c4e35107e32c46be07dd32ad65afd13a5bef9ad72b35c992800ca63158a8c6e8acc6726e9e4 + languageName: node + linkType: hard + +"vue@npm:^3.3.4": + version: 3.3.11 + resolution: "vue@npm:3.3.11" + dependencies: + "@vue/compiler-dom": 3.3.11 + "@vue/compiler-sfc": 3.3.11 + "@vue/runtime-dom": 3.3.11 + "@vue/server-renderer": 3.3.11 + "@vue/shared": 3.3.11 + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 724709b543e74426a271e65d952f2e37682f39a99e67e43cae69fd1867455fa5edc7b4d4ee703aad037e1b03dea8e3743c36738b6c1a9fd1834d7acf912c1f2b + languageName: node + linkType: hard + "w3c-xmlserializer@npm:^4.0.0": version: 4.0.0 resolution: "w3c-xmlserializer@npm:4.0.0" @@ -23115,6 +23412,8 @@ __metadata: resolution: "web@workspace:web" dependencies: "@datadog/browser-rum": ^5.4.0 + "@passageidentity/passage-elements": ^1.17.0 + "@redwoodjs/auth": 6.4.2 "@redwoodjs/forms": 6.4.2 "@redwoodjs/router": 6.4.2 "@redwoodjs/vite": 6.4.2 From e89d8f43270762a67581e05c0c89d3443c860a20 Mon Sep 17 00:00:00 2001 From: Aditya Sridhar Date: Fri, 15 Dec 2023 19:16:41 -0500 Subject: [PATCH 2/2] fix: test --- api/src/directives/requireAuth/requireAuth.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/directives/requireAuth/requireAuth.test.ts b/api/src/directives/requireAuth/requireAuth.test.ts index 0f01aa36..88bbf88b 100644 --- a/api/src/directives/requireAuth/requireAuth.test.ts +++ b/api/src/directives/requireAuth/requireAuth.test.ts @@ -9,9 +9,9 @@ describe('requireAuth directive', () => { }) it('requireAuth has stub implementation. Should not throw when current user', () => { - // If you want to set values in context, pass it through e.g. - // mockRedwoodDirective(requireAuth, { context: { currentUser: { id: 1, name: 'Lebron McGretzky' } }}) - const mockExecution = mockRedwoodDirective(requireAuth, { context: {} }) + const mockExecution = mockRedwoodDirective(requireAuth, { + context: { currentUser: { id: 1, name: 'Some User' } }, + }) expect(mockExecution).not.toThrowError() })