Kurt/rw 37 upgrade (#566)
* Update readme * Upgrade redwood to 0.37.x
This commit was merged in pull request #566.
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@redwoodjs/api": "^0.36.4",
|
||||
"@redwoodjs/api": "^0.37.5",
|
||||
"@redwoodjs/graphql-server": "^0.37.5",
|
||||
"@sentry/node": "^6.5.1",
|
||||
"axios": "^0.21.1",
|
||||
"cloudinary": "^1.23.0",
|
||||
|
||||
18
app/api/src/directives/requireAuth/requireAuth.test.ts
Normal file
18
app/api/src/directives/requireAuth/requireAuth.test.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { mockRedwoodDirective, getDirectiveName } from '@redwoodjs/testing/api'
|
||||
|
||||
import requireAuth from './requireAuth'
|
||||
|
||||
describe('requireAuth directive', () => {
|
||||
it('declares the directive sdl as schema, with the correct name', () => {
|
||||
expect(requireAuth.schema).toBeTruthy()
|
||||
expect(getDirectiveName(requireAuth.schema)).toBe('requireAuth')
|
||||
})
|
||||
|
||||
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: {} })
|
||||
|
||||
expect(mockExecution).not.toThrowError()
|
||||
})
|
||||
})
|
||||
22
app/api/src/directives/requireAuth/requireAuth.ts
Normal file
22
app/api/src/directives/requireAuth/requireAuth.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
import { createValidatorDirective } from '@redwoodjs/graphql-server'
|
||||
|
||||
import { requireAuth as applicationRequireAuth } from 'src/lib/auth'
|
||||
|
||||
export const schema = gql`
|
||||
"""
|
||||
Use to check whether or not a user is authenticated and is associated
|
||||
with an optional set of roles.
|
||||
"""
|
||||
directive @requireAuth(roles: [String]) on FIELD_DEFINITION
|
||||
`
|
||||
|
||||
const validate = ({ directiveArgs }) => {
|
||||
const { roles } = directiveArgs
|
||||
applicationRequireAuth({ roles })
|
||||
}
|
||||
|
||||
const requireAuth = createValidatorDirective(schema, validate)
|
||||
|
||||
export default requireAuth
|
||||
10
app/api/src/directives/skipAuth/skipAuth.test.ts
Normal file
10
app/api/src/directives/skipAuth/skipAuth.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { getDirectiveName } from '@redwoodjs/testing/api'
|
||||
|
||||
import skipAuth from './skipAuth'
|
||||
|
||||
describe('skipAuth directive', () => {
|
||||
it('declares the directive sdl as schema, with the correct name', () => {
|
||||
expect(skipAuth.schema).toBeTruthy()
|
||||
expect(getDirectiveName(skipAuth.schema)).toBe('skipAuth')
|
||||
})
|
||||
})
|
||||
16
app/api/src/directives/skipAuth/skipAuth.ts
Normal file
16
app/api/src/directives/skipAuth/skipAuth.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
import { createValidatorDirective } from '@redwoodjs/graphql-server'
|
||||
|
||||
export const schema = gql`
|
||||
"""
|
||||
Use to skip authentication checks and allow public access.
|
||||
"""
|
||||
directive @skipAuth on FIELD_DEFINITION
|
||||
`
|
||||
|
||||
const skipAuth = createValidatorDirective(schema, () => {
|
||||
return
|
||||
})
|
||||
|
||||
export default skipAuth
|
||||
@@ -15,7 +15,7 @@ You'll need to have Docker installed
|
||||
Because of the way the docker containers to be deployed as lambdas on aws are somewhat specialised for the purpose we're using `docker-compose` to spin one up for each function/endpoint. So we've added a aws-emulation layer
|
||||
|
||||
|
||||
The docker build relies on a git ignored file, the aws-lambda-rie. [Download it](https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/download/v1.0/aws-lambda-rie), then put it into `app/api/src/docker/common/`. alternatively you can put this download into the DockerFiles by reading the instructions at around line 29 of the DockerFiles (`app/api/src/docker/openscad/Dockerfile` & `app/api/src/docker/cadquery/Dockerfile`). However this will mean slower build times as it will need download this 14mb file every build.
|
||||
The docker build relies on a git ignored file, the aws-lambda-rie. [Download it](https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/download/v1.0/aws-lambda-rie), then put it into `app/api/src/docker/common/`. Alternatively you can put this download into the DockerFiles by reading the instructions at around line 29 of the DockerFiles (`app/api/src/docker/openscad/Dockerfile` & `app/api/src/docker/cadquery/Dockerfile`). However this will mean slower build times as it will need download this 14mb file every build.
|
||||
|
||||
|
||||
Run
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import {
|
||||
createGraphQLHandler,
|
||||
makeMergedSchema,
|
||||
makeServices,
|
||||
} from '@redwoodjs/api'
|
||||
import { createGraphQLHandler } from '@redwoodjs/graphql-server'
|
||||
import { createSentryApolloPlugin } from 'src/lib/sentry'
|
||||
import { logger } from 'src/lib/logger'
|
||||
|
||||
import schemas from 'src/graphql/**/*.{js,ts}'
|
||||
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'
|
||||
@@ -15,11 +12,11 @@ import { db } from 'src/lib/db'
|
||||
export const handler = createGraphQLHandler({
|
||||
loggerConfig: { logger, options: {} },
|
||||
getCurrentUser,
|
||||
schema: makeMergedSchema({
|
||||
schemas,
|
||||
services: makeServices({ services }),
|
||||
}),
|
||||
directives,
|
||||
sdls,
|
||||
services,
|
||||
plugins: [createSentryApolloPlugin()],
|
||||
|
||||
onException: () => {
|
||||
// Disconnect from your database with an unhandled exception.
|
||||
db.$disconnect()
|
||||
|
||||
@@ -11,9 +11,10 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Query {
|
||||
projectReactions: [ProjectReaction!]!
|
||||
projectReaction(id: String!): ProjectReaction
|
||||
projectReactions: [ProjectReaction!]! @skipAuth
|
||||
projectReaction(id: String!): ProjectReaction @skipAuth
|
||||
projectReactionsByProjectId(projectId: String!): [ProjectReaction!]!
|
||||
@skipAuth
|
||||
}
|
||||
|
||||
input ToggleProjectReactionInput {
|
||||
@@ -30,10 +31,11 @@ export const schema = gql`
|
||||
|
||||
type Mutation {
|
||||
toggleProjectReaction(input: ToggleProjectReactionInput!): ProjectReaction!
|
||||
@requireAuth
|
||||
updateProjectReaction(
|
||||
id: String!
|
||||
input: UpdateProjectReactionInput!
|
||||
): ProjectReaction!
|
||||
deleteProjectReaction(id: String!): ProjectReaction!
|
||||
): ProjectReaction! @requireAuth
|
||||
deleteProjectReaction(id: String!): ProjectReaction! @requireAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -11,8 +11,8 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Query {
|
||||
comments: [Comment!]!
|
||||
comment(id: String!): Comment
|
||||
comments: [Comment!]! @skipAuth
|
||||
comment(id: String!): Comment @skipAuth
|
||||
}
|
||||
|
||||
input CreateCommentInput {
|
||||
@@ -28,8 +28,9 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createComment(input: CreateCommentInput!): Comment!
|
||||
createComment(input: CreateCommentInput!): Comment! @requireAuth
|
||||
updateComment(id: String!, input: UpdateCommentInput!): Comment!
|
||||
deleteComment(id: String!): Comment!
|
||||
@requireAuth
|
||||
deleteComment(id: String!): Comment! @requireAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -15,6 +15,6 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
sendAllUsersEmail(input: Email!): EmailResponse!
|
||||
sendAllUsersEmail(input: Email!): EmailResponse! @requireAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -26,9 +26,10 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Query {
|
||||
projects(userName: String): [Project!]!
|
||||
project(id: String!): Project
|
||||
projects(userName: String): [Project!]! @skipAuth
|
||||
project(id: String!): Project @skipAuth
|
||||
projectByUserAndTitle(userName: String!, projectTitle: String!): Project
|
||||
@skipAuth
|
||||
}
|
||||
|
||||
input CreateProjectInput {
|
||||
@@ -55,14 +56,15 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createProject(input: CreateProjectInput!): Project!
|
||||
forkProject(input: ForkProjectInput!): Project!
|
||||
createProject(input: CreateProjectInput!): Project! @requireAuth
|
||||
forkProject(input: ForkProjectInput!): Project! @requireAuth
|
||||
updateProject(id: String!, input: UpdateProjectInput!): Project!
|
||||
@requireAuth
|
||||
updateProjectImages(
|
||||
id: String!
|
||||
mainImage64: String
|
||||
socialCard64: String
|
||||
): Project!
|
||||
deleteProject(id: String!): Project!
|
||||
): Project! @requireAuth
|
||||
deleteProject(id: String!): Project! @requireAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -10,7 +10,7 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Query {
|
||||
socialCards: [SocialCard!]!
|
||||
socialCard(id: String!): SocialCard
|
||||
socialCards: [SocialCard!]! @skipAuth
|
||||
socialCard(id: String!): SocialCard @skipAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -10,8 +10,8 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Query {
|
||||
subjectAccessRequests: [SubjectAccessRequest!]!
|
||||
subjectAccessRequest(id: String!): SubjectAccessRequest
|
||||
subjectAccessRequests: [SubjectAccessRequest!]! @requireAuth
|
||||
subjectAccessRequest(id: String!): SubjectAccessRequest @requireAuth
|
||||
}
|
||||
|
||||
input CreateSubjectAccessRequestInput {
|
||||
@@ -29,11 +29,11 @@ export const schema = gql`
|
||||
type Mutation {
|
||||
createSubjectAccessRequest(
|
||||
input: CreateSubjectAccessRequestInput!
|
||||
): SubjectAccessRequest!
|
||||
): SubjectAccessRequest! @requireAuth
|
||||
updateSubjectAccessRequest(
|
||||
id: String!
|
||||
input: UpdateSubjectAccessRequestInput!
|
||||
): SubjectAccessRequest!
|
||||
deleteSubjectAccessRequest(id: String!): SubjectAccessRequest!
|
||||
): SubjectAccessRequest! @requireAuth
|
||||
deleteSubjectAccessRequest(id: String!): SubjectAccessRequest! @requireAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -16,9 +16,9 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Query {
|
||||
users: [User!]!
|
||||
user(id: String!): User
|
||||
userName(userName: String!): User
|
||||
users: [User!]! @requireAuth
|
||||
user(id: String!): User @skipAuth
|
||||
userName(userName: String!): User @skipAuth
|
||||
}
|
||||
|
||||
input CreateUserInput {
|
||||
@@ -38,9 +38,10 @@ export const schema = gql`
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createUser(input: CreateUserInput!): User!
|
||||
updateUser(id: String!, input: UpdateUserInput!): User!
|
||||
createUser(input: CreateUserInput!): User! @requireAuth
|
||||
updateUser(id: String!, input: UpdateUserInput!): User! @requireAuth
|
||||
updateUserByUserName(userName: String!, input: UpdateUserInput!): User!
|
||||
deleteUser(id: String!): User!
|
||||
@requireAuth
|
||||
deleteUser(id: String!): User! @requireAuth
|
||||
}
|
||||
`
|
||||
|
||||
@@ -1,61 +1,5 @@
|
||||
// Define what you want `currentUser` to return throughout your app. For example,
|
||||
// to return a real user from your database, you could do something like:
|
||||
//
|
||||
// export const getCurrentUser = async ({ email }) => {
|
||||
// return await db.user.findUnique({ where: { email } })
|
||||
// }
|
||||
//
|
||||
// If you want to enforce role-based access ...
|
||||
//
|
||||
// You'll need to set the currentUser's roles attributes to the
|
||||
// collection of roles as defined by your app.
|
||||
//
|
||||
// This allows requireAuth() on the api side and hasRole() in the useAuth() hook on the web side
|
||||
// to check if the user is assigned a given role or not.
|
||||
//
|
||||
// How you set the currentUser's roles depends on your auth provider and its implementation.
|
||||
//
|
||||
// For example, your decoded JWT may store `roles` in it namespaced `app_metadata`:
|
||||
//
|
||||
// {
|
||||
// 'https://example.com/app_metadata': { authorization: { roles: ['admin'] } },
|
||||
// 'https://example.com/user_metadata': {},
|
||||
// iss: 'https://app.us.auth0.com/',
|
||||
// sub: 'email|1234',
|
||||
// aud: [
|
||||
// 'https://example.com',
|
||||
// 'https://app.us.auth0.com/userinfo'
|
||||
// ],
|
||||
// iat: 1596481520,
|
||||
// exp: 1596567920,
|
||||
// azp: '1l0w6JXXXXL880T',
|
||||
// scope: 'openid profile email'
|
||||
// }
|
||||
//
|
||||
// The parseJWT utility will extract the roles from decoded token.
|
||||
//
|
||||
// The app_medata claim may or may not be namespaced based on the auth provider.
|
||||
// Note: Auth0 requires namespacing custom JWT claims
|
||||
//
|
||||
// Some providers, such as with Auth0, will set roles an authorization
|
||||
// attribute in app_metadata (namespaced or not):
|
||||
//
|
||||
// 'app_metadata': { authorization: { roles: ['publisher'] } }
|
||||
// 'https://example.com/app_metadata': { authorization: { roles: ['publisher'] } }
|
||||
//
|
||||
// Other providers may include roles simply within app_metadata:
|
||||
//
|
||||
// 'app_metadata': { roles: ['author'] }
|
||||
// 'https://example.com/app_metadata': { roles: ['author'] }
|
||||
//
|
||||
// And yet other may define roles as a custom claim at the root of the decoded token:
|
||||
//
|
||||
// roles: ['admin']
|
||||
//
|
||||
// The function `getCurrentUser` should return the user information
|
||||
// together with a collection of roles to check for role assignment:
|
||||
|
||||
import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api'
|
||||
import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'
|
||||
import { parseJWT } from '@redwoodjs/api'
|
||||
|
||||
/**
|
||||
* Use requireAuth in your services to check that a user is logged in,
|
||||
@@ -97,8 +41,24 @@ import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api'
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export const getCurrentUser = async (decoded, { _token, _type }) => {
|
||||
return { ...decoded, roles: parseJWT({ decoded }).roles }
|
||||
export const getCurrentUser = async (
|
||||
decoded,
|
||||
{ _token, _type },
|
||||
{ _event, _context }
|
||||
) => {
|
||||
if (!decoded) {
|
||||
// if no decoded, then never set currentUser
|
||||
return null
|
||||
}
|
||||
|
||||
const { roles } = parseJWT({ decoded }) // extract and check roles separately
|
||||
|
||||
if (roles) {
|
||||
return { ...decoded, roles }
|
||||
}
|
||||
|
||||
return { ...decoded } // only return when certain you have
|
||||
// the currentUser properties
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AuthenticationError, ForbiddenError } from '@redwoodjs/api'
|
||||
import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'
|
||||
import type { Project } from '@prisma/client'
|
||||
import { db } from 'src/lib/db'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Config, ApolloError } from '@redwoodjs/graphql-server'
|
||||
import * as Sentry from '@sentry/node'
|
||||
import { Config, ApolloError } from '@redwoodjs/api'
|
||||
|
||||
let sentryInitialized = false
|
||||
if (process.env.SENTRY_DSN && !sentryInitialized) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UserInputError } from '@redwoodjs/api'
|
||||
import { UserInputError } from '@redwoodjs/graphql-server'
|
||||
|
||||
import { requireAuth } from 'src/lib/auth'
|
||||
import { requireOwnership } from 'src/lib/owner'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ResolverArgs } from '@redwoodjs/graphql-server'
|
||||
import type { Prisma, Project as ProjectType } from '@prisma/client'
|
||||
import type { ResolverArgs } from '@redwoodjs/api'
|
||||
import { uploadImage, makeSocialPublicIdServer } from 'src/lib/cloudinary'
|
||||
|
||||
import { db } from 'src/lib/db'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ResolverArgs, BeforeResolverSpecType } from '@redwoodjs/graphql-server'
|
||||
import type { Prisma } from '@prisma/client'
|
||||
import type { ResolverArgs, BeforeResolverSpecType } from '@redwoodjs/api'
|
||||
|
||||
import { db } from 'src/lib/db'
|
||||
import { requireAuth } from 'src/lib/auth'
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { UserInputError, ForbiddenError } from '@redwoodjs/graphql-server'
|
||||
import { db } from 'src/lib/db'
|
||||
import { requireAuth } from 'src/lib/auth'
|
||||
import { requireOwnership } from 'src/lib/owner'
|
||||
import { UserInputError } from '@redwoodjs/api'
|
||||
import { enforceAlphaNumeric, destroyImage } from 'src/services/helpers'
|
||||
import type { Prisma } from '@prisma/client'
|
||||
import { ForbiddenError } from '@redwoodjs/api'
|
||||
|
||||
function userNameVerification(userName: string): string {
|
||||
if (userName.length < 5) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"aws-emulate": "nodemon ./api/src/docker/aws-emulator.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redwoodjs/core": "^0.36.4"
|
||||
"@redwoodjs/core": "^0.37.5"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@redwoodjs/eslint-config",
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
"@react-three/drei": "^7.3.1",
|
||||
"@react-three/fiber": "^7.0.5",
|
||||
"@react-three/postprocessing": "^2.0.5",
|
||||
"@redwoodjs/auth": "^0.36.4",
|
||||
"@redwoodjs/forms": "^0.36.4",
|
||||
"@redwoodjs/router": "^0.36.4",
|
||||
"@redwoodjs/web": "^0.36.4",
|
||||
"@redwoodjs/auth": "^0.37.5",
|
||||
"@redwoodjs/forms": "^0.37.5",
|
||||
"@redwoodjs/router": "^0.37.5",
|
||||
"@redwoodjs/web": "^0.37.5",
|
||||
"@sentry/browser": "^6.5.1",
|
||||
"@tailwindcss/aspect-ratio": "0.2.1",
|
||||
"axios": "^0.21.1",
|
||||
@@ -62,4 +62,4 @@
|
||||
"raw-loader": "^4.0.2",
|
||||
"tailwindcss": "^2.2.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
10439
app/yarn.lock
10439
app/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user