Skip to content

Commit

Permalink
feat(docs): add API responses support to rest api docs
Browse files Browse the repository at this point in the history
- Add authentication to documentation
  • Loading branch information
Frantz Kati committed Nov 25, 2020
1 parent 1219f30 commit d048993
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 153 deletions.
161 changes: 72 additions & 89 deletions packages/auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,18 +386,12 @@ class Auth {
.hideFromNavigation()
.fields([
belongsTo(this.config.userResource).nullable(),
textarea('Access Token')
.hidden()
.hideFromApi()
.hideOnUpdate()
.hideOnIndex()
.hideOnDetail()
.hideOnCreate(),
text('Email'),
textarea('Access Token').hidden().hideFromApi(),
text('Email').hidden(),
textarea('Temporal Token').nullable().hidden(),
json('Payload').hidden().hideFromApi(),
text('Provider').rules('required'),
text('Provider User ID')
text('Provider User ID').hidden()
])
}

Expand Down Expand Up @@ -562,7 +556,7 @@ class Auth {
return {}
})
.afterCoreRoutesSetup(
async ({ graphQlQueries, routes, apiPath }) => {
async ({ graphQlQueries, routes, apiPath, app }) => {
graphQlQueries.forEach(query => {
if (query.config.resource) {
const { path, internal } = query.config
Expand Down Expand Up @@ -623,7 +617,40 @@ class Auth {
}
})

app.use(async (request, response, next) => {
await this.getAuthUserFromContext(request as any)

return next()
})

app.use(async (request, response, next) => {
await this.setAuthUserForPublicRoutes(request as any)

return next()
})

routes.forEach(route => {
route.middleware([
async (request, response, next) => {
const authorizers = await Promise.all(
route.config.authorize.map(fn =>
fn(request as any)
)
)

if (
authorizers.filter(authorized => authorized)
.length !==
route.config.authorize.length
) {
return response.status(401).json({
message: `Unauthorized.`
})
}

next()
}
])
if (route.config.resource) {
const {
resource,
Expand All @@ -634,6 +661,18 @@ class Auth {

const { slugSingular, slugPlural } = resource.data

route.extend({
...route.config.extend,
docs: {
...route.config.extend?.docs,
security: [
{
Bearer: []
}
]
}
})

if (
path === `/${apiPath}/${slugPlural}` &&
type === 'POST' &&
Expand Down Expand Up @@ -700,42 +739,6 @@ class Auth {
)
}
}

route.middleware([
async (request, response, next) => {
await this.getAuthUserFromContext(
request as any
)

return next()
},
async (request, response, next) => {
await this.setAuthUserForPublicRoutes(
request as any
)

return next()
},
async (request, response, next) => {
const authorizers = await Promise.all(
route.config.authorize.map(fn =>
fn(request as any)
)
)

if (
authorizers.filter(authorized => authorized)
.length !==
route.config.authorize.length
) {
return response.status(401).json({
message: `Unauthorized.`
})
}

next()
}
])
})
}
)
Expand Down Expand Up @@ -793,15 +796,13 @@ class Auth {
}
}
})
.handle(async (request, { formatter: { ok, unprocess } }) =>
{
try {
return ok(await this.login(request as any))
} catch (error) {
return unprocess(error)
}
.handle(async (request, { formatter: { ok, unprocess } }) => {
try {
return ok(await this.login(request as any))
} catch (error) {
return unprocess(error)
}
),
}),
route(`Register ${name}`)
.path(this.getApiPath('register'))
.post()
Expand Down Expand Up @@ -934,6 +935,7 @@ class Auth {
summary: `Enable two factor authentication for an existing ${name}.`
}
})
.authorize(({ user }) => user && !user.public)
.handle(async (request, response) =>
response.formatter.ok(
await this.enableTwoFactorAuth(request as any)
Expand All @@ -949,6 +951,7 @@ class Auth {
description: `This endpoint confirms enabling 2fa for an account. A previous call to /${this.config.apiPath}/two-factor/enable is required to generate a 2fa secret for the ${name}'s account.`
}
})
.authorize(({ user }) => user && !user.public)
.handle(async (request, response) =>
response.formatter.ok(
await this.enableTwoFactorAuth(request as any)
Expand All @@ -957,12 +960,14 @@ class Auth {
route(`Disable Two Factor Auth`)
.path(this.getApiPath('two-factor/disable'))
.post()
.authorize(({ user }) => user && !user.public)
.extend({
docs: {
...extend,
summary: `Disable two factor authentication for an existing ${name}.`
}
})
.authorize(({ user }) => !!user)
.handle(async (request, response) =>
response.formatter.ok(
await this.disableTwoFactorAuth(request as any)
Expand All @@ -971,22 +976,26 @@ class Auth {
route(`Get authenticated ${name}`)
.path(this.getApiPath('me'))
.get()
.authorize(({ user }) => user && !user.public)
.extend({
docs: {
...extend,
summary: `Get the authenticated ${name} from a valid JWT.`
summary: `Get the authenticated ${name} from a valid JWT.`,
security: [
{
Bearer: []
}
]
}
})
.handle(async ({ user }, { formatter: { ok, unauthorized } }) =>
user && !user.public
? ok(user)
: unauthorized({
message: 'Unauthorized.'
})
.handle(
async ({ user }, { formatter: { ok, unauthorized } }) =>
user
),
route(`Resend Verification email`)
.path(this.getApiPath('verification/resend'))
.post()
.authorize(({ user }) => user && !user.public)
.extend({
docs: {
...extend,
Expand Down Expand Up @@ -1031,6 +1040,7 @@ class Auth {
route('Refresh Token')
.path(this.getApiPath('refresh-token'))
.post()
.authorize(({ user }) => user && !user.public)
.extend({
docs: {
...extend,
Expand Down Expand Up @@ -1062,6 +1072,7 @@ class Auth {
route('Remove refresh Token')
.path(this.getApiPath('refresh-token'))
.delete()
.authorize(({ user }) => user && !user.public)
.extend({
docs: {
...extend,
Expand Down Expand Up @@ -1607,34 +1618,6 @@ class Auth {
return this.getUserPayload(ctx)
}

public authMiddleware = async (
request: Request,
response: Response,
next: NextFunction
) => {
if (!request.user) {
return response.status(401).json({
message: 'Unauthenticated.'
})
}

next()
}

public verifiedMiddleware = async (
request: Request,
response: Response,
next: NextFunction
) => {
if (!request.user?.email_verified_at) {
return response.status(400).json({
message: 'Unverified.'
})
}

next()
}

public authorizeResolver = async (
ctx: GraphQLPluginContext,
query: GraphQlQueryContract
Expand Down
2 changes: 1 addition & 1 deletion packages/common/typings/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ declare module '@tensei/common/config' {

type EndpointTypes = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'

interface RouteExtendContract extends any {}
interface RouteExtendContract extends Record<string, any> {}

interface RouteContract {
config: RouteConfig & {
Expand Down
1 change: 1 addition & 0 deletions packages/docs/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare module '@tensei/common' {
description?: string
parameters?: any[]
definitions?: any
responses?: any
}
}

Expand Down
Loading

0 comments on commit d048993

Please sign in to comment.