Merge pull request #15 from Einlar/main

Fixes for v0.37
This commit is contained in:
David Price
2021-10-19 16:38:41 -07:00
committed by GitHub
5 changed files with 107 additions and 98 deletions

View File

@@ -11,7 +11,9 @@ describe('requireAuth directive', () => {
it('requireAuth has stub implementation. Should not throw when current user', () => { it('requireAuth has stub implementation. Should not throw when current user', () => {
// If you want to set values in context, pass it through e.g. // If you want to set values in context, pass it through e.g.
// mockRedwoodDirective(requireAuth, { context: { currentUser: { id: 1, name: 'Lebron McGretzky' } }}) // 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() expect(mockExecution).not.toThrowError()
}) })

View File

@@ -1,15 +1,13 @@
import { import { parseJWT } from '@redwoodjs/api'
AuthenticationError, import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'
ForbiddenError,
parseJWT,
} from '@redwoodjs/graphql-server'
import { logger } from 'src/lib/logger' import { logger } from 'src/lib/logger'
/** /**
* getCurrentUser returns the user information together with * getCurrentUser returns the user information together with
* an optional collection of roles used by requireAuth() to check * an optional collection of roles used by requireAuth() to check
* if the user is authenticated or has role-based access * 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 { 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 * @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 * such as headers and cookies, and the context information about the invocation such as IP Address
@@ -44,43 +42,46 @@ export const isAuthenticated = () => {
return !!context.currentUser 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) * 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 }) => { export const hasRole = ({ roles }) => {
if (!isAuthenticated()) { if (!isAuthenticated()) {
return false return false
} }
if ( if (roles) {
typeof roles !== 'undefined' && if (Array.isArray(roles)) {
typeof roles === 'string' && return context.currentUser.roles?.some((r) => roles.includes(r))
context.currentUser.roles?.includes(roles)
) {
return true
} }
if ( if (typeof roles === 'string') {
typeof roles !== 'undefined' && return context.currentUser.roles?.includes(roles)
Array.isArray(roles) &&
context.currentUser.roles?.some((r) => roles.includes(r))
) {
return true
} }
// roles not found
return false return false
} }
return true
}
/** /**
* Use requireAuth in your services to check that a user is logged in, * 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 * whether or not they are assigned a role, and optionally raise an
* error if they're not. * 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) * @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 * @see https://github.com/redwoodjs/redwood/tree/main/packages/auth for examples
*/ */
export const requireAuth = ({ roles } = {}) => { export const requireAuth = ({ roles }) => {
if (!isAuthenticated) { if (!isAuthenticated()) {
throw new AuthenticationError("You don't have permission to do that.") throw new AuthenticationError("You don't have permission to do that.")
} }

View File

@@ -17,7 +17,7 @@
"@redwoodjs/forms": "^0.37.4", "@redwoodjs/forms": "^0.37.4",
"@redwoodjs/router": "^0.37.4", "@redwoodjs/router": "^0.37.4",
"@redwoodjs/web": "^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", "prop-types": "^15.7.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2" "react-dom": "^17.0.2"

View File

@@ -6,10 +6,10 @@ import {
FieldError, FieldError,
Label, Label,
FormError, FormError,
useForm,
} from '@redwoodjs/forms' } from '@redwoodjs/forms'
import { useMutation } from '@redwoodjs/web' import { useMutation } from '@redwoodjs/web'
import { toast, Toaster } from '@redwoodjs/web/toast' import { toast, Toaster } from '@redwoodjs/web/toast'
import { useForm } from 'react-hook-form'
const CREATE_CONTACT = gql` const CREATE_CONTACT = gql`
mutation CreateContactMutation($input: CreateContactInput!) { mutation CreateContactMutation($input: CreateContactInput!) {
@@ -34,7 +34,8 @@ const ContactPage = () => {
console.log(data) console.log(data)
} }
return <> return (
<>
<Toaster /> <Toaster />
<Form <Form
onSubmit={onSubmit} onSubmit={onSubmit}
@@ -74,6 +75,10 @@ const ContactPage = () => {
name="email" name="email"
validation={{ validation={{
required: true, required: true,
pattern: {
value: /[^@]+@[^.]+\..+/,
message: 'Please enter a valid email address',
},
}} }}
className="border rounded-sm px-2 py-1" className="border rounded-sm px-2 py-1"
errorClassName="border rounded-sm px-2 py-1 border-red-700 outline-none" errorClassName="border rounded-sm px-2 py-1 border-red-700 outline-none"
@@ -102,7 +107,8 @@ const ContactPage = () => {
Save Save
</Submit> </Submit>
</Form> </Form>
</>; </>
)
} }
export default ContactPage export default ContactPage

View File

@@ -13764,10 +13764,10 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0:
resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61"
integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==
netlify-identity-widget@^1.9.1: netlify-identity-widget@^1.9.2:
version "1.9.1" version "1.9.2"
resolved "https://registry.yarnpkg.com/netlify-identity-widget/-/netlify-identity-widget-1.9.1.tgz#9e716c4b92b9f0cc041074eb86fc962f35295b46" resolved "https://registry.yarnpkg.com/netlify-identity-widget/-/netlify-identity-widget-1.9.2.tgz#4339c9155fc4c2570ae3ddd61825d952b574b02e"
integrity sha512-9oIWjwUSdRk3SkREcZNjZaVuDDx9T/wSIXZNQsQeY4qoXic/FiXVEGgu2RU3IuA4OI3L2652xY1o+PpS03Ugaw== integrity sha512-IbS1JHhs7BflCCvp3C9f6tmNSZqbyBhZ4Gs5+Qxt4IlPybTOVv0PqJ4TAsA7uxh1R+oXOAmk0OOMAkEaPYeCtA==
new-github-issue-url@0.2.1: new-github-issue-url@0.2.1:
version "0.2.1" version "0.2.1"