Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions packages/wabe/src/database/DatabaseController.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { selectFieldsWithoutPrivateFields } from 'src/utils/helper'
import type { WabeTypes } from '../..'
import { OperationType, initializeHook } from '../hooks'
import type { SchemaInterface } from '../schema'
Expand Down Expand Up @@ -57,7 +58,9 @@ export class DatabaseController<T extends WabeTypes> {
realClass.fields[fieldName]?.type === 'Relation',
)

return Object.entries(select).reduce(
return Object.entries(
context.isRoot ? select : selectFieldsWithoutPrivateFields(select),
).reduce(
(acc, [fieldName, value]) => {
// If not pointer or relation
if (!pointerOrRelationFields.includes(fieldName))
Expand Down Expand Up @@ -644,12 +647,8 @@ export class DatabaseController<T extends WabeTypes> {

return this.getObject({
className,
context: {
...context,
// @ts-expect-error
user: className === 'User' ? res : context.user,
},
select,
context: contextWithRoot(context),
select: selectFieldsWithoutPrivateFields(select),
id: res.id,
})
}
Expand Down
55 changes: 55 additions & 0 deletions packages/wabe/src/database/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { Wabe } from '../server'
import {
type DevWabeTypes,
getAdminUserClient,
getAnonymousClient,
getGraphqlClient,
} from '../utils/helper'
import { setupTests, closeTests } from '../utils/testHelper'
Expand Down Expand Up @@ -134,6 +135,60 @@ describe('Database', () => {
spyGetObjects.mockClear()
})

it('should allow to signUp with anonymous user and read his own data', async () => {
const setup = await setupTests([
{
name: 'User',
fields: {},
searchableFields: ['email', 'firstName', 'lastName'],
permissions: {
read: {
authorizedRoles: ['Admin', 'Client'],
requireAuthentication: true,
},
update: {
authorizedRoles: ['Admin', 'Client'],
requireAuthentication: true,
},
delete: {
authorizedRoles: ['Admin', 'Client'],
requireAuthentication: true,
},
},
},
])

const client = getAnonymousClient(setup.port)

const res = await client.request<any>(
gql`
mutation signUpWith($input: SignUpWithInput!) {
signUpWith(input: $input) {
id
accessToken
refreshToken
csrfToken
}
}
`,
{
input: {
authentication: {
emailPassword: {
email: 'test@example.com',
password: 'password',
},
},
},
},
)

expect(res.signUpWith.id).toBeDefined()
expect(res.signUpWith.accessToken).toBeDefined()
expect(res.signUpWith.refreshToken).toBeDefined()
expect(res.signUpWith.csrfToken).toBeDefined()
})

it('should return id of a relation if set to true in select on getObject', async () => {
const rootClient = getGraphqlClient(wabe.config.port)

Expand Down
24 changes: 12 additions & 12 deletions packages/wabe/src/hooks/permissions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('Permissions', () => {
select: {},
})

expect(_checkCLP(obj, OperationType.BeforeRead)).rejects.toThrow(
expect(() => _checkCLP(obj, OperationType.BeforeRead)).toThrow(
'Permission denied to read class TestClass4',
)
})
Expand Down Expand Up @@ -141,13 +141,13 @@ describe('Permissions', () => {
select: {},
})

expect(_checkCLP(obj, OperationType.BeforeRead)).rejects.toThrow(
expect(() => _checkCLP(obj, OperationType.BeforeRead)).toThrow(
'Permission denied to read class TestClass5',
)
})

it('should get the permission for a given className', async () => {
const permission = await _getPermissionPropertiesOfAClass({
it('should get the permission for a given className', () => {
const permission = _getPermissionPropertiesOfAClass({
className: 'TestClass',
operation: 'read',
context,
Expand All @@ -158,7 +158,7 @@ describe('Permissions', () => {
authorizedRoles: [RoleEnum.Admin],
})

const permission2 = await _getPermissionPropertiesOfAClass({
const permission2 = _getPermissionPropertiesOfAClass({
className: 'TestClass2',
operation: 'read',
context,
Expand All @@ -185,7 +185,7 @@ describe('Permissions', () => {
select: {},
})

expect(_checkCLP(obj, OperationType.BeforeRead)).rejects.toThrow(
expect(() => _checkCLP(obj, OperationType.BeforeRead)).toThrow(
'Permission denied to read class TestClass',
)
})
Expand Down Expand Up @@ -251,7 +251,7 @@ describe('Permissions', () => {
select: {},
})

expect(_checkCLP(obj, OperationType.BeforeRead)).rejects.toThrow(
expect(() => _checkCLP(obj, OperationType.BeforeRead)).toThrow(
'Permission denied to read class TestClass3',
)
})
Expand Down Expand Up @@ -288,7 +288,7 @@ describe('Permissions', () => {
select: {},
})

expect(_checkCLP(obj, OperationType.BeforeRead)).rejects.toThrow(
expect(() => _checkCLP(obj, OperationType.BeforeRead)).toThrow(
'Permission denied to read class TestClass',
)
})
Expand Down Expand Up @@ -351,7 +351,7 @@ describe('Permissions', () => {
const spyBeforeRead = spyOn(
permissions,
'defaultCheckPermissionOnRead',
).mockResolvedValue()
).mockReturnValue()

permissions.defaultCheckPermissionOnRead({} as never)

Expand All @@ -365,7 +365,7 @@ describe('Permissions', () => {
const spyBeforeCreate = spyOn(
permissions,
'defaultCheckPermissionOnCreate',
).mockResolvedValue()
).mockReturnValue()

permissions.defaultCheckPermissionOnCreate({
sessionId: 'sessionId',
Expand All @@ -385,7 +385,7 @@ describe('Permissions', () => {
const spyBeforeUpdate = spyOn(
permissions,
'defaultCheckPermissionOnUpdate',
).mockResolvedValue()
).mockReturnValue()

permissions.defaultCheckPermissionOnUpdate({
sessionId: 'sessionId',
Expand All @@ -405,7 +405,7 @@ describe('Permissions', () => {
const spyBeforeDelete = spyOn(
permissions,
'defaultCheckPermissionOnDelete',
).mockResolvedValue()
).mockReturnValue()

permissions.defaultCheckPermissionOnDelete({
sessionId: 'sessionId',
Expand Down
10 changes: 6 additions & 4 deletions packages/wabe/src/hooks/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const _getPermissionPropertiesOfAClass = ({
return permission
}

export const _checkCLP = async (
export const _checkCLP = (
object: HookObject<any, any>,
operationType: OperationType,
) => {
Expand All @@ -48,7 +48,7 @@ export const _checkCLP = async (

if (!permissionOperation) throw new Error('Bad operation type provided')

const permissionProperties = await _getPermissionPropertiesOfAClass({
const permissionProperties = _getPermissionPropertiesOfAClass({
className: object.className,
operation: permissionOperation,
context: object.context,
Expand All @@ -69,10 +69,11 @@ export const _checkCLP = async (
return

// User is not corrected but requireAuthentication is on true
if (!sessionId || !object.getUser())
if (!sessionId || !object.getUser()) {
throw new Error(
`Permission denied to ${permissionOperation} class ${object.className}`,
)
}

if (permissionProperties.authorizedRoles?.includes('everyone')) return

Expand All @@ -88,10 +89,11 @@ export const _checkCLP = async (
const roleName = object.context.user?.role?.name

// No role name found
if (!roleName)
if (!roleName) {
throw new Error(
`Permission denied to ${permissionOperation} class ${object.className}`,
)
}

// The role of the user is not included in the authorizedRoles
if (!permissionProperties.authorizedRoles?.includes(roleName))
Expand Down
71 changes: 51 additions & 20 deletions packages/wabe/src/hooks/setupAcl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ describe('setupAcl', () => {
rootClient,
})

const res = await userClient.request<any>(gql`
const setupResult = await userClient.request<any>(gql`
mutation createSetupACL8 {
createSetupACL8(input: {fields: {test: "test"}}) {
setupACL8 {
Expand All @@ -370,20 +370,37 @@ describe('setupAcl', () => {
}
`)

const res = await rootClient.request<any>(gql`
query setupACL8 {
setupACL8(id: "${setupResult.createSetupACL8.setupACL8.id}") {
id
acl {
users {
userId
read
write
}
roles {
roleId
read
write
}
}
}
}
`)

// User
expect(res.createSetupACL8.setupACL8.acl.users[0].userId).toEqual(userId)
expect(res.createSetupACL8.setupACL8.acl.users[0].read).toEqual(true)
expect(res.createSetupACL8.setupACL8.acl.users[0].write).toEqual(true)
expect(res.setupACL8.acl.users[0].userId).toEqual(userId)
expect(res.setupACL8.acl.users[0].read).toEqual(true)
expect(res.setupACL8.acl.users[0].write).toEqual(true)

// Role
expect(
await getRoleNameFromId(
res.createSetupACL8.setupACL8.acl.roles[0].roleId,
rootClient,
),
await getRoleNameFromId(res.setupACL8.acl.roles[0].roleId, rootClient),
).toEqual('Client')
expect(res.createSetupACL8.setupACL8.acl.roles[0].read).toEqual(true)
expect(res.createSetupACL8.setupACL8.acl.roles[0].write).toEqual(true)
expect(res.setupACL8.acl.roles[0].read).toEqual(true)
expect(res.setupACL8.acl.roles[0].write).toEqual(true)
})

it('should not update acl object if the acl function is not present in permissions in the class', async () => {
Expand Down Expand Up @@ -469,7 +486,7 @@ describe('setupAcl', () => {
})

it('should get different role id for read and write if roles are different', async () => {
const res = await rootClient.request<any>(gql`
const setupResult = await rootClient.request<any>(gql`
mutation createSetupACL5 {
createSetupACL5(input: {fields: {test: "test"}}) {
setupACL5 {
Expand All @@ -491,21 +508,35 @@ describe('setupAcl', () => {
}
`)

expect(res.createSetupACL5.setupACL5.acl.users).toHaveLength(0)
const res = await rootClient.request<any>(gql`
query setupACL5 {
setupACL5(id: "${setupResult.createSetupACL5.setupACL5.id}") {
id
acl {
users {
userId
read
write
}
roles {
roleId
read
write
}
}
}
}
`)

expect(res.setupACL5.acl.users).toHaveLength(0)

// Role
expect(
await getRoleNameFromId(
res.createSetupACL5.setupACL5.acl.roles[0].roleId,
rootClient,
),
await getRoleNameFromId(res.setupACL5.acl.roles[0].roleId, rootClient),
).toEqual('Client')

expect(
await getRoleNameFromId(
res.createSetupACL5.setupACL5.acl.roles[1].roleId,
rootClient,
),
await getRoleNameFromId(res.setupACL5.acl.roles[1].roleId, rootClient),
).toEqual('Client2')
})

Expand Down
2 changes: 2 additions & 0 deletions packages/wabe/src/schema/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type { HookObject } from '../hooks/HookObject'
import { signUpWithResolver } from '../authentication/resolvers/signUpWithResolver'
import { signInWithResolver } from '../authentication/resolvers/signInWithResolver'

export const defaultPrivateFields = ['acl']

export type WabePrimaryTypes =
| 'String'
| 'Int'
Expand Down
Loading