diff --git a/platform/galaxy/src/index.ts b/platform/galaxy/src/index.ts index 4006c5b6f5..b6bbbc9a15 100644 --- a/platform/galaxy/src/index.ts +++ b/platform/galaxy/src/index.ts @@ -25,7 +25,7 @@ const plugins = [ galaxyApiKey: { type: 'apiKey', in: 'header', - name: 'X-GALAXY-API-KEY', + name: 'X-GALAXY-KEY', description: 'Galaxy API Key', }, bearerAuthorization: { diff --git a/platform/galaxy/src/schema/resolvers/authorization.ts b/platform/galaxy/src/schema/resolvers/authorization.ts index 4195c710c2..ca220fcef8 100644 --- a/platform/galaxy/src/schema/resolvers/authorization.ts +++ b/platform/galaxy/src/schema/resolvers/authorization.ts @@ -12,6 +12,13 @@ import { ResolverContext } from './common' import createCoreClient from '@proofzero/platform-clients/core' import { getAuthzHeaderConditionallyFromToken } from '@proofzero/utils' import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace' +import { GraphQLError } from 'graphql/error' +import { AppAPIKeyHeader } from '@proofzero/types/headers' +import { + ApplicationURN, + ApplicationURNSpace, +} from '@proofzero/urns/application' +import * as jose from 'jose' const authorizationResolvers: Resolvers = { Query: { @@ -29,6 +36,53 @@ const authorizationResolvers: Resolvers = { clientId, }) }, + getAuthorizedIdentities: async ( + _parent: any, + { opts }: { opts: { limit: number; offset: number } }, + { env, apiKey, traceSpan }: ResolverContext + ) => { + const coreClient = createCoreClient(env.Core, { + ...generateTraceContextHeaders(traceSpan), + [AppAPIKeyHeader]: apiKey, + }) + const { limit, offset } = opts + + //Check if valid numbers, including value of 0 for offset + if ( + limit == null || + offset == null || + !Number.isInteger(limit) || + !Number.isInteger(offset) || + limit > 50 || + limit < 1 + ) + throw new GraphQLError( + 'Limit and offset numbers need to be provided, with the limit beging between 1 and 50' + ) + + let clientIdFromApiKey + try { + const apiKeyApplicationURN = jose.decodeJwt(apiKey) + .sub as ApplicationURN + clientIdFromApiKey = + ApplicationURNSpace.nss(apiKeyApplicationURN).split('/')[1] + } catch (e) { + console.error('Error parsing clientId', e) + throw new GraphQLError('Could not retrieve clientId from API key.') + } + + const edgeResults = + await coreClient.starbase.getAuthorizedIdentities.query({ + client: clientIdFromApiKey, + opt: { + limit, + offset, + }, + }) + return edgeResults.identities.map(({ identityURN, imageURL, name }) => { + return { identityURN, imageURL, name } + }) + }, }, Mutation: { setExternalAppData: async ( @@ -60,6 +114,12 @@ const AuthorizationResolverComposition = { isAuthorized(), logAnalytics(), ], + 'Query.getAuthorizedIdentities': [ + requestLogging(), + setupContext(), + validateApiKey(), + logAnalytics(), + ], 'Mutation.setExternalAppData': [ requestLogging(), setupContext(), diff --git a/platform/galaxy/src/schema/types/authorization.ts b/platform/galaxy/src/schema/types/authorization.ts index 1b3f613d3b..bc3e4a7838 100644 --- a/platform/galaxy/src/schema/types/authorization.ts +++ b/platform/galaxy/src/schema/types/authorization.ts @@ -1,6 +1,13 @@ export default /* GraphQL */ ` + type AuthorizationIdentity { + identityURN: String + name: String + imageURL: String + } + type Query { getExternalAppData: JSON + getAuthorizedIdentities(opts: Pagination!): [AuthorizationIdentity] } type Mutation { diff --git a/platform/galaxy/src/schema/types/common.ts b/platform/galaxy/src/schema/types/common.ts index 35cad8d77c..92348369fc 100644 --- a/platform/galaxy/src/schema/types/common.ts +++ b/platform/galaxy/src/schema/types/common.ts @@ -1,3 +1,8 @@ export default /* GraphQL */ ` scalar JSON + + input Pagination { + offset: Int! + limit: Int! + } ` diff --git a/platform/starbase/src/jsonrpc/router.ts b/platform/starbase/src/jsonrpc/router.ts index 98b68f5f69..3071a1a63b 100644 --- a/platform/starbase/src/jsonrpc/router.ts +++ b/platform/starbase/src/jsonrpc/router.ts @@ -212,6 +212,7 @@ export const appRouter = t.router({ getAuthorizedIdentities: t.procedure .use(AuthorizationTokenFromHeader) .use(ValidateJWT) + .use(ApiKeyExtractMiddleware) .use(LogUsage) .use(Analytics) .use(OwnAppsMiddleware)