Skip to content

Commit

Permalink
fix: support builder service account
Browse files Browse the repository at this point in the history
  • Loading branch information
viet nguyen committed May 17, 2023
1 parent 6489fbb commit 217be20
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 11 deletions.
4 changes: 3 additions & 1 deletion src/auth/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ export const createContext = async ({ req }): Promise<any> => {

const user: AuthUserType = {
roles: [],
uuid: undefined
uuid: undefined,
isBuilder: false
}

const authHeader = String(headers?.authorization ?? '')
if (authHeader.startsWith('Bearer ')) {
const token = authHeader.substring(7, authHeader.length).trim()
const z = await verifyJWT(token)

user.isBuilder = z?.scope.includes('builder:default')
user.roles = z?.['https://tacos.openbeta.io/roles'] ?? []
const uidStr: string | undefined = z?.['https://tacos.openbeta.io/uuid']
user.uuid = uidStr != null ? muid.from(uidStr) : undefined
Expand Down
10 changes: 6 additions & 4 deletions src/auth/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { shield, allow } from 'graphql-shield'
import { isEditor, isUserAdmin } from './rules.js'
import { shield, allow, or } from 'graphql-shield'
import { isEditor, isUserAdmin, isOwner, isBuilderServiceAccount } from './rules.js'

const permissions = shield({
Query: {
'*': allow
'*': allow,
getUserProfile: or(isOwner, isBuilderServiceAccount)
},
Mutation: {
addOrganization: isUserAdmin,
Expand All @@ -12,7 +13,8 @@ const permissions = shield({
addArea: isEditor,
updateArea: isEditor,
updateClimbs: isEditor,
deleteClimbs: isEditor
deleteClimbs: isEditor,
updateUserProfile: isOwner
}
},
{
Expand Down
22 changes: 20 additions & 2 deletions src/auth/rules.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import { rule } from 'graphql-shield'
import muuid from 'uuid-mongodb'

export const isEditor = rule()(async (parent, args, ctx, info) => {
return (ctx.user.uuid != null) && ctx.user.roles.includes('editor')
return _hasUserUuid(ctx) && ctx.user.roles.includes('editor')
})

export const isUserAdmin = rule()(async (parent, args, ctx, info) => {
return (ctx.user.uuid != null) && ctx.user.roles.includes('user_admin')
return _hasUserUuid(ctx) && ctx.user.roles.includes('user_admin')
})

export const isOwner = rule()(async (parent, args, ctx, info) => {
return _hasUserUuid(ctx) && ctx.user.uuid === muuid.from(args.userUuid)
})

export const isBuilderServiceAccount = rule()(async (parent, args, ctx: Context, info) => {
return _hasUserUuid(ctx) && ctx.user.isBuilder
})

interface Context {
user: {
uuid?: string
isBuilder: boolean
}
}

const _hasUserUuid = (ctx: Context): boolean => ctx.user.uuid != null
4 changes: 2 additions & 2 deletions src/graphql/user/UserQueries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import muuid from 'uuid-mongodb'
import { DataSourcesType } from '../../types'
import { DataSourcesType, ContextWithAuth } from '../../types'
import { GetUsernameReturn, User } from '../../db/UserTypes'

const UserQueries = {
Expand All @@ -9,7 +9,7 @@ const UserQueries = {
return await users.getUsername(uuid)
},

getUserProfile: async (_, { userUuid }, { dataSources }): Promise<User | null> => {
getUserProfile: async (_, { userUuid }, { dataSources }: ContextWithAuth): Promise<User | null> => {
const { users }: DataSourcesType = dataSources
const uuid = muuid.from(userUuid)
return await users.getUserProfile(uuid)
Expand Down
4 changes: 2 additions & 2 deletions src/model/UserDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ const regUsernameKeywords = /openbeta|0penbeta|admin/i
* @param username
* @returns true if has valid format
*/
export const isValidUsername = (username: string): boolean => {
const isValidUsername = (username: string): boolean => {
return username != null && username.length <= 30 &&
!regUsernameKeywords.test(username) &&
regUsername.test(username)
Expand All @@ -169,4 +169,4 @@ const isValidUrl = (url: string): boolean => {
} catch (e) {
return false
}
}
}
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface QueryByIdType {
export interface AuthUserType {
roles: string[]
uuid: MUUID | undefined
isBuilder: boolean
}

export interface DataSourcesType {
Expand Down

0 comments on commit 217be20

Please sign in to comment.