Skip to content

Commit

Permalink
feat(auth): fix graphql failing queries for allTeams query
Browse files Browse the repository at this point in the history
  • Loading branch information
bahdcoder committed Aug 3, 2021
1 parent b197066 commit c769374
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 156 deletions.
45 changes: 31 additions & 14 deletions packages/auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
export * from './config'

import { setup } from './setup'
import { Request } from 'express'
import { request, Request } from 'express'
import { Teams } from './teams/Teams'
import { permission, PermissionContract } from './teams/Permission'

Expand Down Expand Up @@ -166,7 +166,11 @@ export class Auth implements AuthContract {
restAPiPlugin.config.extra?.path !== 'api'
) {
this.config.apiPath = restAPiPlugin.config.extra?.path

return restAPiPlugin.config.extra?.path
}

return this.config.apiPath
}

public setup(fn: AuthSetupFn) {
Expand Down Expand Up @@ -777,7 +781,10 @@ export class Auth implements AuthContract {
async (resolve, parent, args, context, info) => {
await this.getAuthUserFromContext(context)

await this.getCurrentTeamFromContext(context)
await this.getCurrentTeamFromContext(
context,
currentCtx().plugins
)

await this.setAuthUserForPublicRoutes(context)

Expand Down Expand Up @@ -846,7 +853,10 @@ export class Auth implements AuthContract {
async (request, response, next) => {
await this.getAuthUserFromContext(request as any)

await this.getCurrentTeamFromContext(request as any)
await this.getCurrentTeamFromContext(
request as any,
currentCtx().plugins
)

await this.setAuthUserForPublicRoutes(request as any)

Expand Down Expand Up @@ -937,14 +947,6 @@ export class Auth implements AuthContract {
})
}

private getRegistrationFieldsDocs() {
const properties: any = {}

// TODO: Calculate and push new registration fields to be exposed to API

return properties
}

private extendRoutes() {
const name = this.__resources.user.data.slugSingular

Expand Down Expand Up @@ -2322,7 +2324,10 @@ export class Auth implements AuthContract {
return this.__resources.permission.data.camelCaseNamePlural
}

public getCurrentTeamFromContext = async (ctx: ApiContext) => {
public getCurrentTeamFromContext = async (
ctx: ApiContext,
plugins: PluginContract[]
) => {
if (!this.config.teams) {
return
}
Expand All @@ -2331,14 +2336,26 @@ export class Auth implements AuthContract {

const { headers, params } = req

const currentTeamId =
let currentTeamId =
(headers['x-current-team'] as any) || params.team || body.teamId

if (
!currentTeamId &&
req.originalUrl.startsWith(
`/${this.resolveApiPath(plugins)}/${
this.__resources.team.data.slugPlural
}`
) &&
['GET', 'PATCH', 'PUT', 'DELETE'].includes(req.method)
) {
currentTeamId = params.id
}

if (!currentTeamId) {
return
}

const team = await ctx.repositories.teams.findOne({
const team = await ctx.repositories.teams().findOne({
id: currentTeamId
})

Expand Down
35 changes: 19 additions & 16 deletions packages/auth/src/teams/Teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import {
array,
route,
Utils,
PluginSetupConfig,
graphQlQuery,
ResourceContract,
GraphQlMiddleware
} from '@tensei/common'
import { validateAll, validations } from 'indicative/validator'

const findTeamMiddleware: RequestHandler = (request, response, next) => {
export const findTeamMiddleware: RequestHandler = (request, response, next) => {
const { team, params } = request

if (!team) {
Expand All @@ -27,7 +26,7 @@ const findTeamMiddleware: RequestHandler = (request, response, next) => {
next()
}

const isTeamOwnerMiddleware: RequestHandler = async (
export const isTeamOwnerMiddleware: RequestHandler = async (
request,
response,
next
Expand All @@ -41,7 +40,7 @@ const isTeamOwnerMiddleware: RequestHandler = async (
next()
}

const findTeamQueryMiddleware: GraphQlMiddleware = (
export const findTeamQueryMiddleware: GraphQlMiddleware = (
resolve,
parent,
args,
Expand Down Expand Up @@ -110,7 +109,7 @@ const handleInviteTeamMember = (auth: AuthContract) => async (

const invitedUser = await repositories[
auth.__resources.user.data.camelCaseNamePlural
].findOne({
]().findOne({
email: payload.email
})

Expand All @@ -122,8 +121,8 @@ const handleInviteTeamMember = (auth: AuthContract) => async (
return
}

await repositories.memberships.persistAndFlush(
repositories.memberships.create({
await repositories.memberships().persistAndFlush(
repositories.memberships().create({
team,
[auth.__resources.user.data.camelCaseName]: invitedUser,
permissions: payload.permissions
Expand Down Expand Up @@ -240,7 +239,6 @@ export class Teams {
graphQlQuery('All teams for a user')
.path('allTeams')
.authorize(({ user }) => !!user)
.authorize(async ({ user, team }) => await user.belongsToTeam(team))
.handle(async (_, args, ctx, info) => {
const { user } = ctx

Expand Down Expand Up @@ -285,6 +283,10 @@ export class Teams {
const self = this

userResource.method('ownsTeam', function (this: any, team: any) {
if (!team) {
return false
}

return (
team.owner.toString() === this.id.toString() ||
team.owner?.id.toString() === this.id.toString()
Expand All @@ -294,7 +296,7 @@ export class Teams {
userResource.method(
'teamMembership',
async function (this: any, team: any) {
const membership = await this.ctx.repositories.memberships.findOne({
const membership = await this.ctx.repositories.memberships().findOne({
team,
[self.auth.__resources.user.data.camelCaseName]: this
})
Expand Down Expand Up @@ -351,19 +353,20 @@ export class Teams {

userResource.method('allTeams', async function (this: any) {
const [ownedTeams, memberships] = await Promise.all([
this.ctx.orm.em.find(
self.auth.__resources.team.data.pascalCaseName,
this.repositories.teams().find(
{ owner: this },
{
populate: [
`memberships.${self.auth.__resources.user.data.camelCaseName}`
`memberships.${self.auth.__resources.user.data.camelCaseName}`,
'owner'
]
}
),
this.ctx.orm.em.find(
self.auth.__resources.membership.data.pascalCaseName,
this.repositories.memberships().find(
{ [self.auth.__resources.user.data.camelCaseName]: this.id },
{ populate: ['team.owner'] }
{
populate: [`${self.auth.__resources.team.data.camelCaseName}.owner`]
}
)
])

Expand Down Expand Up @@ -404,7 +407,7 @@ export class Teams {
.path(this.auth.__getApiPath('teams/:team/memberships'))
.handle(async ({ repositories, team }, { formatter: { ok } }) => {
return ok(
await repositories.memberships.find(
await repositories.memberships().find(
{
team
},
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/resources/Resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export class Resource implements ResourceContract {

public repositoryMethod<Fn = ResourceMethod>(name: string, fn: Fn) {
this.data.repositoryMethods = [
...this.data.methods,
...this.data.repositoryMethods,
{
name,
fn
Expand Down
8 changes: 5 additions & 3 deletions packages/common/typings/resources.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
declare module '@tensei/common/resources' {
import { Request } from 'express'
import { Request, RequestHandler } from 'express'
import { FilterContract } from '@tensei/common/filters'
import { SerializedField, FieldContract } from '@tensei/common/fields'
import { SerializedAction, ActionContract } from '@tensei/common/actions'
Expand All @@ -12,7 +12,8 @@ declare module '@tensei/common/resources' {
DatabaseRepositoryInterface,
User,
DataPayload,
ResourceHelpers
ResourceHelpers,
GraphQlMiddleware
} from '@tensei/common/config'
import { ActionResponse } from '@tensei/common/actions'
export interface ValidationMessages {
Expand Down Expand Up @@ -129,9 +130,10 @@ declare module '@tensei/common/resources' {
extend(extend: ResourceExtendContract): this
filters(filters: FilterContract[]): this
permissions(permissions: Permission[]): this
canFetchRelation(authorizeFunction: AuthorizeFunction): this
canShow(authorizeFunction: AuthorizeFunction): this

canFetch(authorizeFunction: AuthorizeFunction): this
canFetchRelation(authorizeFunction: AuthorizeFunction): this
canInsert(authorizeFunction: AuthorizeFunction): this
canUpdate(authorizeFunction: AuthorizeFunction): this
canDelete(authorizeFunction: AuthorizeFunction): this
Expand Down
6 changes: 3 additions & 3 deletions packages/core/Tensei.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,15 @@ export class Tensei implements TenseiContract {
.handle(() => {
const table = new Table({
head: ['METHOD', 'URI', 'MIDDLEWARE', 'NAME', 'DESCRIPTION'],
colWidths: [10, 45, 15, 25, 42]
colWidths: [10, 45, 15, 25, 25, 42]
})

table.push(
...this.ctx.routes.map(route => [
route.config.type,
route.config.path,
route.config.middleware.length,
route.config.id,
route.config.name,
route.config.description
])
Expand Down Expand Up @@ -628,8 +629,7 @@ export class Tensei implements TenseiContract {
request.storage = this.ctx.storage
request.emitter = this.ctx.emitter
request.indicative = indicative
request.db = this.ctx.db
request.repositories = this.ctx.db
request.repositories = this.ctx.repositories

// @ts-ignore
this.ctx.request = request
Expand Down
1 change: 1 addition & 0 deletions packages/core/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class Database {
resource.data.methods.forEach(method => {
entityClass.prototype[method.name] = function (...fnArgs: any) {
this.ctx = config // Set the config on the value of this
this.ctx.manager = config.orm?.em.fork()
this.repositories = config.repositories // Set the repositories on the value of this
const fn = method.fn.bind(this)

Expand Down
41 changes: 27 additions & 14 deletions packages/orm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,41 @@ import { resolveFieldTypescriptType } from './helpers'
export class Orm {
constructor(public ctx: Config) {}

private cachedRepositories: any = {}

public generate() {
const repositories: any = {}

const self = this

this.ctx.resources.forEach(resource => {
repositories[
resource.data.camelCaseNamePlural
] = this.ctx.orm?.em.getRepository(resource.data.pascalCaseName)
repositories[resource.data.camelCaseNamePlural] = function () {
if (self.cachedRepositories[resource.data.camelCaseNamePlural]) {
return self.cachedRepositories[resource.data.camelCaseNamePlural]
}

resource.data.repositoryMethods.forEach(method => {
const methodName = method.name.replace(/\s+/g, '')
const repository = (
self.ctx.request?.manager || self.ctx.orm!.em
).getRepository(resource.data.pascalCaseName)

const ctx = this.ctx
resource.data.repositoryMethods.forEach(method => {
const methodName = method.name.replace(/\s+/g, '')

// Set ctx property on repository instance
repositories[resource.data.camelCaseNamePlural]['ctx'] = ctx
repositories[resource.data.camelCaseNamePlural]['repositories'] =
ctx.repositories
;(repository as any)[methodName] = method.fn.bind(repository)
})

repositories[resource.data.camelCaseNamePlural][
methodName
] = method.fn.bind(repositories[resource.data.camelCaseNamePlural])
})
self.cachedRepositories[resource.data.camelCaseNamePlural] = repository

return repository
}

Object.defineProperty(
repositories[resource.data.camelCaseNamePlural],
'name',
{
value: `${resource.data.pascalCaseName}Repository`
}
)
})

return repositories
Expand Down
Loading

0 comments on commit c769374

Please sign in to comment.