Add test for revoke api key

This commit is contained in:
Hongbo Wu 2022-05-27 18:07:54 +08:00
parent b77b378221
commit b7206457b4
6 changed files with 193 additions and 118 deletions

View file

@ -39,6 +39,7 @@ export type ApiKey = {
createdAt: Scalars['Date'];
expiresAt: Scalars['Date'];
id: Scalars['ID'];
key?: Maybe<Scalars['String']>;
name: Scalars['String'];
scopes?: Maybe<Array<Scalars['String']>>;
usedAt?: Maybe<Scalars['Date']>;
@ -421,24 +422,6 @@ export type CreateReminderSuccess = {
reminder: Reminder;
};
export type DeleteApiKeyError = {
__typename?: 'DeleteApiKeyError';
errorCodes: Array<DeleteApiKeyErrorCode>;
};
export enum DeleteApiKeyErrorCode {
BadRequest = 'BAD_REQUEST',
NotFound = 'NOT_FOUND',
Unauthorized = 'UNAUTHORIZED'
}
export type DeleteApiKeyResult = DeleteApiKeyError | DeleteApiKeySuccess;
export type DeleteApiKeySuccess = {
__typename?: 'DeleteApiKeySuccess';
apiKey: ApiKey;
};
export type DeleteHighlightError = {
__typename?: 'DeleteHighlightError';
errorCodes: Array<DeleteHighlightErrorCode>;
@ -630,7 +613,7 @@ export type GenerateApiKeyResult = GenerateApiKeyError | GenerateApiKeySuccess;
export type GenerateApiKeySuccess = {
__typename?: 'GenerateApiKeySuccess';
apiKey: Scalars['String'];
apiKey: ApiKey;
};
export type GetFollowersError = {
@ -877,7 +860,6 @@ export type Mutation = {
createNewsletterEmail: CreateNewsletterEmailResult;
createReaction: CreateReactionResult;
createReminder: CreateReminderResult;
deleteApiKey: DeleteApiKeyResult;
deleteHighlight: DeleteHighlightResult;
deleteHighlightReply: DeleteHighlightReplyResult;
deleteLabel: DeleteLabelResult;
@ -892,6 +874,7 @@ export type Mutation = {
logOut: LogOutResult;
mergeHighlight: MergeHighlightResult;
reportItem: ReportItemResult;
revokeApiKey: RevokeApiKeyResult;
saveArticleReadingProgress: SaveArticleReadingProgressResult;
saveFile: SaveResult;
savePage: SaveResult;
@ -961,11 +944,6 @@ export type MutationCreateReminderArgs = {
};
export type MutationDeleteApiKeyArgs = {
id: Scalars['ID'];
};
export type MutationDeleteHighlightArgs = {
highlightId: Scalars['ID'];
};
@ -1031,6 +1009,11 @@ export type MutationReportItemArgs = {
};
export type MutationRevokeApiKeyArgs = {
id: Scalars['ID'];
};
export type MutationSaveArticleReadingProgressArgs = {
input: SaveArticleReadingProgressInput;
};
@ -1420,6 +1403,24 @@ export enum ReportType {
Spam = 'SPAM'
}
export type RevokeApiKeyError = {
__typename?: 'RevokeApiKeyError';
errorCodes: Array<RevokeApiKeyErrorCode>;
};
export enum RevokeApiKeyErrorCode {
BadRequest = 'BAD_REQUEST',
NotFound = 'NOT_FOUND',
Unauthorized = 'UNAUTHORIZED'
}
export type RevokeApiKeyResult = RevokeApiKeyError | RevokeApiKeySuccess;
export type RevokeApiKeySuccess = {
__typename?: 'RevokeApiKeySuccess';
apiKey: ApiKey;
};
export type SaveArticleReadingProgressError = {
__typename?: 'SaveArticleReadingProgressError';
errorCodes: Array<SaveArticleReadingProgressErrorCode>;
@ -2394,10 +2395,6 @@ export type ResolversTypes = {
CreateReminderResult: ResolversTypes['CreateReminderError'] | ResolversTypes['CreateReminderSuccess'];
CreateReminderSuccess: ResolverTypeWrapper<CreateReminderSuccess>;
Date: ResolverTypeWrapper<Scalars['Date']>;
DeleteApiKeyError: ResolverTypeWrapper<DeleteApiKeyError>;
DeleteApiKeyErrorCode: DeleteApiKeyErrorCode;
DeleteApiKeyResult: ResolversTypes['DeleteApiKeyError'] | ResolversTypes['DeleteApiKeySuccess'];
DeleteApiKeySuccess: ResolverTypeWrapper<DeleteApiKeySuccess>;
DeleteHighlightError: ResolverTypeWrapper<DeleteHighlightError>;
DeleteHighlightErrorCode: DeleteHighlightErrorCode;
DeleteHighlightReplyError: ResolverTypeWrapper<DeleteHighlightReplyError>;
@ -2506,6 +2503,10 @@ export type ResolversTypes = {
ReportItemInput: ReportItemInput;
ReportItemResult: ResolverTypeWrapper<ReportItemResult>;
ReportType: ReportType;
RevokeApiKeyError: ResolverTypeWrapper<RevokeApiKeyError>;
RevokeApiKeyErrorCode: RevokeApiKeyErrorCode;
RevokeApiKeyResult: ResolversTypes['RevokeApiKeyError'] | ResolversTypes['RevokeApiKeySuccess'];
RevokeApiKeySuccess: ResolverTypeWrapper<RevokeApiKeySuccess>;
SaveArticleReadingProgressError: ResolverTypeWrapper<SaveArticleReadingProgressError>;
SaveArticleReadingProgressErrorCode: SaveArticleReadingProgressErrorCode;
SaveArticleReadingProgressInput: SaveArticleReadingProgressInput;
@ -2724,9 +2725,6 @@ export type ResolversParentTypes = {
CreateReminderResult: ResolversParentTypes['CreateReminderError'] | ResolversParentTypes['CreateReminderSuccess'];
CreateReminderSuccess: CreateReminderSuccess;
Date: Scalars['Date'];
DeleteApiKeyError: DeleteApiKeyError;
DeleteApiKeyResult: ResolversParentTypes['DeleteApiKeyError'] | ResolversParentTypes['DeleteApiKeySuccess'];
DeleteApiKeySuccess: DeleteApiKeySuccess;
DeleteHighlightError: DeleteHighlightError;
DeleteHighlightReplyError: DeleteHighlightReplyError;
DeleteHighlightReplyResult: ResolversParentTypes['DeleteHighlightReplyError'] | ResolversParentTypes['DeleteHighlightReplySuccess'];
@ -2814,6 +2812,9 @@ export type ResolversParentTypes = {
ReminderSuccess: ReminderSuccess;
ReportItemInput: ReportItemInput;
ReportItemResult: ReportItemResult;
RevokeApiKeyError: RevokeApiKeyError;
RevokeApiKeyResult: ResolversParentTypes['RevokeApiKeyError'] | ResolversParentTypes['RevokeApiKeySuccess'];
RevokeApiKeySuccess: RevokeApiKeySuccess;
SaveArticleReadingProgressError: SaveArticleReadingProgressError;
SaveArticleReadingProgressInput: SaveArticleReadingProgressInput;
SaveArticleReadingProgressResult: ResolversParentTypes['SaveArticleReadingProgressError'] | ResolversParentTypes['SaveArticleReadingProgressSuccess'];
@ -2964,6 +2965,7 @@ export type ApiKeyResolvers<ContextType = ResolverContext, ParentType extends Re
createdAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
expiresAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
key?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
scopes?: Resolver<Maybe<Array<ResolversTypes['String']>>, ParentType, ContextType>;
usedAt?: Resolver<Maybe<ResolversTypes['Date']>, ParentType, ContextType>;
@ -3219,20 +3221,6 @@ export interface DateScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes
name: 'Date';
}
export type DeleteApiKeyErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteApiKeyError'] = ResolversParentTypes['DeleteApiKeyError']> = {
errorCodes?: Resolver<Array<ResolversTypes['DeleteApiKeyErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type DeleteApiKeyResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteApiKeyResult'] = ResolversParentTypes['DeleteApiKeyResult']> = {
__resolveType: TypeResolveFn<'DeleteApiKeyError' | 'DeleteApiKeySuccess', ParentType, ContextType>;
};
export type DeleteApiKeySuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteApiKeySuccess'] = ResolversParentTypes['DeleteApiKeySuccess']> = {
apiKey?: Resolver<ResolversTypes['ApiKey'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type DeleteHighlightErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteHighlightError'] = ResolversParentTypes['DeleteHighlightError']> = {
errorCodes?: Resolver<Array<ResolversTypes['DeleteHighlightErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -3383,7 +3371,7 @@ export type GenerateApiKeyResultResolvers<ContextType = ResolverContext, ParentT
};
export type GenerateApiKeySuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['GenerateApiKeySuccess'] = ResolversParentTypes['GenerateApiKeySuccess']> = {
apiKey?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
apiKey?: Resolver<ResolversTypes['ApiKey'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
@ -3575,7 +3563,6 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
createNewsletterEmail?: Resolver<ResolversTypes['CreateNewsletterEmailResult'], ParentType, ContextType>;
createReaction?: Resolver<ResolversTypes['CreateReactionResult'], ParentType, ContextType, RequireFields<MutationCreateReactionArgs, 'input'>>;
createReminder?: Resolver<ResolversTypes['CreateReminderResult'], ParentType, ContextType, RequireFields<MutationCreateReminderArgs, 'input'>>;
deleteApiKey?: Resolver<ResolversTypes['DeleteApiKeyResult'], ParentType, ContextType, RequireFields<MutationDeleteApiKeyArgs, 'id'>>;
deleteHighlight?: Resolver<ResolversTypes['DeleteHighlightResult'], ParentType, ContextType, RequireFields<MutationDeleteHighlightArgs, 'highlightId'>>;
deleteHighlightReply?: Resolver<ResolversTypes['DeleteHighlightReplyResult'], ParentType, ContextType, RequireFields<MutationDeleteHighlightReplyArgs, 'highlightReplyId'>>;
deleteLabel?: Resolver<ResolversTypes['DeleteLabelResult'], ParentType, ContextType, RequireFields<MutationDeleteLabelArgs, 'id'>>;
@ -3590,6 +3577,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
logOut?: Resolver<ResolversTypes['LogOutResult'], ParentType, ContextType>;
mergeHighlight?: Resolver<ResolversTypes['MergeHighlightResult'], ParentType, ContextType, RequireFields<MutationMergeHighlightArgs, 'input'>>;
reportItem?: Resolver<ResolversTypes['ReportItemResult'], ParentType, ContextType, RequireFields<MutationReportItemArgs, 'input'>>;
revokeApiKey?: Resolver<ResolversTypes['RevokeApiKeyResult'], ParentType, ContextType, RequireFields<MutationRevokeApiKeyArgs, 'id'>>;
saveArticleReadingProgress?: Resolver<ResolversTypes['SaveArticleReadingProgressResult'], ParentType, ContextType, RequireFields<MutationSaveArticleReadingProgressArgs, 'input'>>;
saveFile?: Resolver<ResolversTypes['SaveResult'], ParentType, ContextType, RequireFields<MutationSaveFileArgs, 'input'>>;
savePage?: Resolver<ResolversTypes['SaveResult'], ParentType, ContextType, RequireFields<MutationSavePageArgs, 'input'>>;
@ -3742,6 +3730,20 @@ export type ReportItemResultResolvers<ContextType = ResolverContext, ParentType
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type RevokeApiKeyErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['RevokeApiKeyError'] = ResolversParentTypes['RevokeApiKeyError']> = {
errorCodes?: Resolver<Array<ResolversTypes['RevokeApiKeyErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type RevokeApiKeyResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['RevokeApiKeyResult'] = ResolversParentTypes['RevokeApiKeyResult']> = {
__resolveType: TypeResolveFn<'RevokeApiKeyError' | 'RevokeApiKeySuccess', ParentType, ContextType>;
};
export type RevokeApiKeySuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['RevokeApiKeySuccess'] = ResolversParentTypes['RevokeApiKeySuccess']> = {
apiKey?: Resolver<ResolversTypes['ApiKey'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type SaveArticleReadingProgressErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SaveArticleReadingProgressError'] = ResolversParentTypes['SaveArticleReadingProgressError']> = {
errorCodes?: Resolver<Array<ResolversTypes['SaveArticleReadingProgressErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -4316,9 +4318,6 @@ export type Resolvers<ContextType = ResolverContext> = {
CreateReminderResult?: CreateReminderResultResolvers<ContextType>;
CreateReminderSuccess?: CreateReminderSuccessResolvers<ContextType>;
Date?: GraphQLScalarType;
DeleteApiKeyError?: DeleteApiKeyErrorResolvers<ContextType>;
DeleteApiKeyResult?: DeleteApiKeyResultResolvers<ContextType>;
DeleteApiKeySuccess?: DeleteApiKeySuccessResolvers<ContextType>;
DeleteHighlightError?: DeleteHighlightErrorResolvers<ContextType>;
DeleteHighlightReplyError?: DeleteHighlightReplyErrorResolvers<ContextType>;
DeleteHighlightReplyResult?: DeleteHighlightReplyResultResolvers<ContextType>;
@ -4395,6 +4394,9 @@ export type Resolvers<ContextType = ResolverContext> = {
ReminderResult?: ReminderResultResolvers<ContextType>;
ReminderSuccess?: ReminderSuccessResolvers<ContextType>;
ReportItemResult?: ReportItemResultResolvers<ContextType>;
RevokeApiKeyError?: RevokeApiKeyErrorResolvers<ContextType>;
RevokeApiKeyResult?: RevokeApiKeyResultResolvers<ContextType>;
RevokeApiKeySuccess?: RevokeApiKeySuccessResolvers<ContextType>;
SaveArticleReadingProgressError?: SaveArticleReadingProgressErrorResolvers<ContextType>;
SaveArticleReadingProgressResult?: SaveArticleReadingProgressResultResolvers<ContextType>;
SaveArticleReadingProgressSuccess?: SaveArticleReadingProgressSuccessResolvers<ContextType>;

View file

@ -20,6 +20,7 @@ type ApiKey {
createdAt: Date!
expiresAt: Date!
id: ID!
key: String
name: String!
scopes: [String!]
usedAt: Date
@ -368,22 +369,6 @@ type CreateReminderSuccess {
scalar Date
type DeleteApiKeyError {
errorCodes: [DeleteApiKeyErrorCode!]!
}
enum DeleteApiKeyErrorCode {
BAD_REQUEST
NOT_FOUND
UNAUTHORIZED
}
union DeleteApiKeyResult = DeleteApiKeyError | DeleteApiKeySuccess
type DeleteApiKeySuccess {
apiKey: ApiKey!
}
type DeleteHighlightError {
errorCodes: [DeleteHighlightErrorCode!]!
}
@ -554,7 +539,7 @@ input GenerateApiKeyInput {
union GenerateApiKeyResult = GenerateApiKeyError | GenerateApiKeySuccess
type GenerateApiKeySuccess {
apiKey: String!
apiKey: ApiKey!
}
type GetFollowersError {
@ -778,7 +763,6 @@ type Mutation {
createNewsletterEmail: CreateNewsletterEmailResult!
createReaction(input: CreateReactionInput!): CreateReactionResult!
createReminder(input: CreateReminderInput!): CreateReminderResult!
deleteApiKey(id: ID!): DeleteApiKeyResult!
deleteHighlight(highlightId: ID!): DeleteHighlightResult!
deleteHighlightReply(highlightReplyId: ID!): DeleteHighlightReplyResult!
deleteLabel(id: ID!): DeleteLabelResult!
@ -793,6 +777,7 @@ type Mutation {
logOut: LogOutResult!
mergeHighlight(input: MergeHighlightInput!): MergeHighlightResult!
reportItem(input: ReportItemInput!): ReportItemResult!
revokeApiKey(id: ID!): RevokeApiKeyResult!
saveArticleReadingProgress(input: SaveArticleReadingProgressInput!): SaveArticleReadingProgressResult!
saveFile(input: SaveFileInput!): SaveResult!
savePage(input: SavePageInput!): SaveResult!
@ -989,6 +974,22 @@ enum ReportType {
SPAM
}
type RevokeApiKeyError {
errorCodes: [RevokeApiKeyErrorCode!]!
}
enum RevokeApiKeyErrorCode {
BAD_REQUEST
NOT_FOUND
UNAUTHORIZED
}
union RevokeApiKeyResult = RevokeApiKeyError | RevokeApiKeySuccess
type RevokeApiKeySuccess {
apiKey: ApiKey!
}
type SaveArticleReadingProgressError {
errorCodes: [SaveArticleReadingProgressErrorCode!]!
}

View file

@ -2,14 +2,14 @@ import {
ApiKeysError,
ApiKeysErrorCode,
ApiKeysSuccess,
DeleteApiKeyError,
DeleteApiKeyErrorCode,
DeleteApiKeySuccess,
GenerateApiKeyError,
GenerateApiKeyErrorCode,
GenerateApiKeySuccess,
MutationDeleteApiKeyArgs,
MutationGenerateApiKeyArgs,
MutationRevokeApiKeyArgs,
RevokeApiKeyError,
RevokeApiKeyErrorCode,
RevokeApiKeySuccess,
} from '../../generated/graphql'
import { analytics } from '../../utils/analytics'
import { env } from '../../env'
@ -32,6 +32,7 @@ export const apiKeysResolver = authorized<ApiKeysSuccess, ApiKeysError>(
}
const apiKeys = await getRepository(ApiKey).find({
select: ['id', 'name', 'scopes', 'expiresAt', 'createdAt', 'usedAt'],
where: { user: { id: uid } },
order: { usedAt: 'DESC', createdAt: 'DESC' },
})
@ -75,7 +76,7 @@ export const generateApiKeyResolver = authorized<
const exp = new Date(expiresAt)
const apiKey = generateApiKey()
await getRepository(ApiKey).save({
const apiKeyData = await getRepository(ApiKey).save({
user: { id: uid },
name,
key: hashApiKey(apiKey),
@ -92,7 +93,12 @@ export const generateApiKeyResolver = authorized<
},
})
return { apiKey }
return {
apiKey: {
...apiKeyData,
key: apiKey,
},
}
} catch (error) {
console.error(error)
@ -100,18 +106,18 @@ export const generateApiKeyResolver = authorized<
}
})
export const deleteApiKeyResolver = authorized<
DeleteApiKeySuccess,
DeleteApiKeyError,
MutationDeleteApiKeyArgs
export const revokeApiKeyResolver = authorized<
RevokeApiKeySuccess,
RevokeApiKeyError,
MutationRevokeApiKeyArgs
>(async (_, { id }, { claims: { uid }, log }) => {
log.info('deleteApiKeyResolver')
log.info('RevokeApiKeyResolver')
try {
const user = await getRepository(User).findOneBy({ id: uid })
if (!user) {
return {
errorCodes: [DeleteApiKeyErrorCode.Unauthorized],
errorCodes: [RevokeApiKeyErrorCode.Unauthorized],
}
}
@ -121,27 +127,30 @@ export const deleteApiKeyResolver = authorized<
})
if (!apiKey) {
return {
errorCodes: [DeleteApiKeyErrorCode.NotFound],
errorCodes: [RevokeApiKeyErrorCode.NotFound],
}
}
if (apiKey.user.id !== uid) {
return {
errorCodes: [DeleteApiKeyErrorCode.Unauthorized],
errorCodes: [RevokeApiKeyErrorCode.Unauthorized],
}
}
const deletedApiKey = await getRepository(ApiKey).remove(apiKey)
deletedApiKey.id = id
return {
apiKey: deletedApiKey,
apiKey: {
...deletedApiKey,
id,
key: null,
},
}
} catch (e) {
log.error(e)
return {
errorCodes: [DeleteApiKeyErrorCode.BadRequest],
errorCodes: [RevokeApiKeyErrorCode.BadRequest],
}
}
})

View file

@ -30,7 +30,6 @@ import {
createLabelResolver,
createNewsletterEmailResolver,
createReminderResolver,
deleteApiKeyResolver,
deleteHighlightResolver,
deleteLabelResolver,
deleteNewsletterEmailResolver,
@ -56,6 +55,7 @@ import {
newsletterEmailsResolver,
reminderResolver,
reportItemResolver,
revokeApiKeyResolver,
saveArticleReadingProgressResolver,
saveFileResolver,
savePageResolver,
@ -160,7 +160,7 @@ export const functionResolvers = {
addPopularRead: addPopularReadResolver,
setWebhook: setWebhookResolver,
deleteWebhook: deleteWebhookResolver,
deleteApiKey: deleteApiKeyResolver,
revokeApiKey: revokeApiKeyResolver,
},
Query: {
me: getMeUserResolver,
@ -581,5 +581,5 @@ export const functionResolvers = {
...resultResolveTypeResolver('DeleteWebhook'),
...resultResolveTypeResolver('Webhook'),
...resultResolveTypeResolver('ApiKeys'),
...resultResolveTypeResolver('DeleteApiKey'),
...resultResolveTypeResolver('RevokeApiKey'),
}

View file

@ -1420,7 +1420,7 @@ const schema = gql`
union GenerateApiKeyResult = GenerateApiKeySuccess | GenerateApiKeyError
type GenerateApiKeySuccess {
apiKey: String!
apiKey: ApiKey!
}
type GenerateApiKeyError {
@ -1679,6 +1679,7 @@ const schema = gql`
type ApiKey {
id: ID!
name: String!
key: String
scopes: [String!]
createdAt: Date!
expiresAt: Date!
@ -1694,17 +1695,17 @@ const schema = gql`
BAD_REQUEST
}
union DeleteApiKeyResult = DeleteApiKeySuccess | DeleteApiKeyError
union RevokeApiKeyResult = RevokeApiKeySuccess | RevokeApiKeyError
type DeleteApiKeySuccess {
type RevokeApiKeySuccess {
apiKey: ApiKey!
}
type DeleteApiKeyError {
errorCodes: [DeleteApiKeyErrorCode!]!
type RevokeApiKeyError {
errorCodes: [RevokeApiKeyErrorCode!]!
}
enum DeleteApiKeyErrorCode {
enum RevokeApiKeyErrorCode {
UNAUTHORIZED
BAD_REQUEST
NOT_FOUND
@ -1777,7 +1778,7 @@ const schema = gql`
addPopularRead(name: String!): AddPopularReadResult!
setWebhook(input: SetWebhookInput!): SetWebhookResult!
deleteWebhook(id: ID!): DeleteWebhookResult!
deleteApiKey(id: ID!): DeleteApiKeyResult!
revokeApiKey(id: ID!): RevokeApiKeyResult!
}
# FIXME: remove sort from feedArticles after all cached tabs are closed

View file

@ -22,7 +22,7 @@ const testAPIKey = (apiKey: string): supertest.Test => {
return graphqlRequest(query, apiKey)
}
describe('generate api key', () => {
describe('Api Key resolver', () => {
const username = 'fake_user'
let authToken: string
@ -46,15 +46,18 @@ describe('generate api key', () => {
await deleteTestUser(username)
})
beforeEach(() => {
query = `
describe('generate api key', () => {
beforeEach(() => {
query = `
mutation {
generateApiKey(input: {
name: "${name}"
expiresAt: "${expiresAt}"
}) {
... on GenerateApiKeySuccess {
apiKey
apiKey {
key
}
}
... on GenerateApiKeyError {
errorCodes
@ -62,33 +65,92 @@ describe('generate api key', () => {
}
}
`
})
context('when api key is not expired', () => {
before(() => {
name = 'test'
expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString()
})
it('should generate an api key', async () => {
const response = await graphqlRequest(query, authToken)
expect(response.body.data.generateApiKey.apiKey).to.be.a('string')
context('when api key is not expired', () => {
before(() => {
name = 'test'
expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString()
})
return testAPIKey(response.body.data.generateApiKey.apiKey).expect(200)
it('should generate an api key', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
expect(response.body.data.generateApiKey.apiKey.key).to.be.a('string')
return testAPIKey(response.body.data.generateApiKey.apiKey.key).expect(
200
)
})
})
context('when api key is expired', () => {
before(() => {
name = 'test-expired'
expiresAt = new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString()
})
it('should generate an expired api key', async () => {
const response = await graphqlRequest(query, authToken).expect(200)
expect(response.body.data.generateApiKey.apiKey.key).to.be.a('string')
return testAPIKey(response.body.data.generateApiKey.apiKey.key).expect(
500
)
})
})
})
context('when api key is expired', () => {
before(() => {
name = 'test-expired'
expiresAt = new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString()
describe('revoke api key', () => {
let apiKey: string
let apiKeyId: string
before(async () => {
query = `
mutation {
generateApiKey(input: {
name: "test-revoke"
expiresAt: "${new Date(
Date.now() + 1000 * 60 * 60 * 24
).toISOString()}"
}) {
... on GenerateApiKeySuccess {
apiKey {
id
key
}
}
... on GenerateApiKeyError {
errorCodes
}
}
}
`
const response = await graphqlRequest(query, authToken)
apiKey = response.body.data.generateApiKey.apiKey.key
apiKeyId = response.body.data.generateApiKey.apiKey.id
})
it('should generate an expired api key', async () => {
const response = await graphqlRequest(query, authToken)
expect(response.body.data.generateApiKey.apiKey).to.be.a('string')
it('should revoke an api key', async () => {
query = `
mutation {
revokeApiKey(id: "${apiKeyId}") {
... on RevokeApiKeySuccess {
apiKey {
id
}
}
... on RevokeApiKeyError {
errorCodes
}
}
}
`
return testAPIKey(response.body.data.generateApiKey.apiKey).expect(500)
const response = await graphqlRequest(query, authToken).expect(200)
expect(response.body.data.revokeApiKey.apiKey.id).to.be.a('string')
return testAPIKey(apiKey).expect(500)
})
})
})