diff --git a/api/src/directives/requireAuth/requireAuth.test.js b/api/src/directives/requireAuth/requireAuth.test.js
index 0f01aa3..75453ef 100644
--- a/api/src/directives/requireAuth/requireAuth.test.js
+++ b/api/src/directives/requireAuth/requireAuth.test.js
@@ -11,7 +11,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: 'Bob McBobFace' } },
+ })
expect(mockExecution).not.toThrowError()
})
diff --git a/api/src/lib/auth.js b/api/src/lib/auth.js
index d0ba80d..2b35523 100644
--- a/api/src/lib/auth.js
+++ b/api/src/lib/auth.js
@@ -1,15 +1,13 @@
-import {
- AuthenticationError,
- ForbiddenError,
- parseJWT,
-} from '@redwoodjs/graphql-server'
+import { parseJWT } from '@redwoodjs/api'
+import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'
import { logger } from 'src/lib/logger'
+
/**
* 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
*
- * @param decoded - The decoded access token containing user info and JWT claims like `sub`
+ * @param decoded - The decoded access token containing user info and JWT claims like `sub`. Note could be null.
* @param { token, SupportedAuthTypes type } - The access token itself as well as the auth provider type
* @param { APIGatewayEvent event, Context context } - An object which contains information from the invoker
* such as headers and cookies, and the context information about the invocation such as IP Address
@@ -44,35 +42,38 @@ export const isAuthenticated = () => {
return !!context.currentUser
}
+/**
+ * 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`
+ */
+
/**
* Checks if the currentUser is authenticated (and assigned one of the given roles)
*
- * @param {string= | string[]=} roles - A single role or list of roles to check if the user belongs to
+ * @param roles: AllowedRoles - Checks if the currentUser is assigned one of these roles
*
- * @returns {boolean} - Returns true if the currentUser is authenticated (and assigned one of the given 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 }) => {
if (!isAuthenticated()) {
return false
}
- if (
- typeof roles !== 'undefined' &&
- typeof roles === 'string' &&
- context.currentUser.roles?.includes(roles)
- ) {
- return true
+ if (roles) {
+ if (Array.isArray(roles)) {
+ return context.currentUser.roles?.some((r) => roles.includes(r))
+ }
+
+ if (typeof roles === 'string') {
+ return context.currentUser.roles?.includes(roles)
+ }
+
+ // roles not found
+ return false
}
- if (
- typeof roles !== 'undefined' &&
- Array.isArray(roles) &&
- context.currentUser.roles?.some((r) => roles.includes(r))
- ) {
- return true
- }
-
- return false
+ return true
}
/**
@@ -80,7 +81,7 @@ export const hasRole = ({ roles }) => {
* whether or not they are assigned a role, and optionally raise an
* error if they're not.
*
- * @param {string= | string[]=} roles - A single role or list of roles to check if the user belongs to
+ * @param roles: AllowedRoles - When checking role membership, these roles grant access.
*
* @returns - If the currentUser is authenticated (and assigned one of the given roles)
*
@@ -89,8 +90,8 @@ export const hasRole = ({ roles }) => {
*
* @see https://github.com/redwoodjs/redwood/tree/main/packages/auth for examples
*/
-export const requireAuth = ({ roles } = {}) => {
- if (!isAuthenticated) {
+export const requireAuth = ({ roles }) => {
+ if (!isAuthenticated()) {
throw new AuthenticationError("You don't have permission to do that.")
}
diff --git a/web/package.json b/web/package.json
index 0dddd0f..ed1e9a4 100644
--- a/web/package.json
+++ b/web/package.json
@@ -17,7 +17,7 @@
"@redwoodjs/forms": "^0.37.4",
"@redwoodjs/router": "^0.37.4",
"@redwoodjs/web": "^0.37.4",
- "netlify-identity-widget": "^1.9.1",
+ "netlify-identity-widget": "^1.9.2",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2"
@@ -28,4 +28,4 @@
"postcss-loader": "^6.1.1",
"tailwindcss": "^2.2.7"
}
-}
\ No newline at end of file
+}
diff --git a/web/src/pages/ContactPage/ContactPage.js b/web/src/pages/ContactPage/ContactPage.js
index 65a066e..f91cded 100644
--- a/web/src/pages/ContactPage/ContactPage.js
+++ b/web/src/pages/ContactPage/ContactPage.js
@@ -6,10 +6,10 @@ import {
FieldError,
Label,
FormError,
+ useForm,
} from '@redwoodjs/forms'
import { useMutation } from '@redwoodjs/web'
import { toast, Toaster } from '@redwoodjs/web/toast'
-import { useForm } from 'react-hook-form'
const CREATE_CONTACT = gql`
mutation CreateContactMutation($input: CreateContactInput!) {
@@ -34,75 +34,81 @@ const ContactPage = () => {
console.log(data)
}
- return <>
-