Skip to content

Commit

Permalink
added implementation for create-item and apiKey authorizer
Browse files Browse the repository at this point in the history
  • Loading branch information
koljagralla committed Jan 26, 2024
1 parent 8743116 commit c78cdb4
Show file tree
Hide file tree
Showing 14 changed files with 974 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
// Will be recreated? If you delete this file and run `turbogate build` a boilerplate version of this file will be recreated.
import { LambdaRequestAuthorizerConfig } from 'turbogate';
import { defaultConfig } from '../../config/default-config';
import { IdentitySource } from 'aws-cdk-lib/aws-apigateway';

export const config: LambdaRequestAuthorizerConfig = {
lambda: {
...defaultConfig.lambda,
},
requestAuthorizer: {
...defaultConfig.requestAuthorizer,
identitySources: [IdentitySource.header('Authorization')],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { AutoSerializedAuthorizerContextZodType } from 'turbogate';
import { z } from 'zod';

export const zContext = z.object({
// myContextValue: z.string(),
// myOtherContextValue: z.object({/**... */})
apiKey: z.string(),
}) satisfies AutoSerializedAuthorizerContextZodType<any>;

export type Context = z.infer<typeof zContext>;
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import { AuthorizerDocs } from 'turbogate';

export const docs: AuthorizerDocs = {
// Example docs for JWT Bearer auth.
// See https://spec.openapis.org/oas/latest.html#security-scheme-object
type: 'http',
scheme: 'bearer',
type: 'apiKey',
in: 'header',
name: 'Authorization',
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { Env, EnvironmentDefinition } from 'turbogate';
import { ZodType, z } from 'zod';

export const zEnvironment = z.object({
// MY_ENV_VAR: Env.string,
// ANOTHER_VAR_THAT_SHOULD_BE_A_NUMBER: Env.number,
VALID_API_KEYS: Env.list,
}) satisfies ZodType<any, any, EnvironmentDefinition>;

export type Environment = z.infer<typeof zEnvironment>;
24 changes: 7 additions & 17 deletions lib/stacks/my-stack/my-api-turbogate/authorizer/apiKey/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,12 @@ export async function main(
environment: Environment,
event: LambdaAuthorizerInputEvent,
): Promise<['accept', Context] | ['deny']> {
// // Example minimal implementation:
// Minimal example of an authorizer that accepts any request with a valid API key in the Authorization header.
// In a real world scenario you probably would not want to expose the API key to the business layer via context
// But for demonstration purposes this is fine.
if (environment.VALID_API_KEYS.includes(event.headers.Authorization)) {
return ['accept', { apiKey: event.headers.Authorization }];
}

// // Extract relevant information from the event
// const authHeaderValue = event.headers['my-custom-auth-header'];

// // Check if the auth header is what we expect
// if (authHeaderValue === 'my-expected-auth-value') {
// // Grant access to the endpoint, include the required context
// const context = {
// myContextValue: 'my-context-value',
// };
// return ['accept', context];
// }

// // Deny access to the endpoint
// return ['deny'];

throw new Error('Not implemented');
return ['deny'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@
// Can be permanently deleted? No, code that is regenerated on every `turbogate build` call will break, so fixing broken code after deleting this won't make sense.
// Will be recreated? If you delete this file and run `turbogate build` a boilerplate version of this file will be recreated.

export const permissions = [
// 'MY_DYNAMO_1_READ',
// 'MY_DYNAMO_1_WRITE',
// 'MY_SQS_1_SEND_MESSAGE',
] as const;
export const permissions = [] as const;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { EndpointDocs } from 'turbogate';

export const docs: EndpointDocs = {
// Example docs:
// summary: "Creates a new item",
// description: "Creates a new item in the database. The ID of the item is generated by the database and returned in the response.",
summary: 'Creates a new item',
description:
'Creates a new item in the database. The ID of the item is generated by the backend. Upon success the whole item including the ID is returned.',
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { Env, EnvironmentDefinition } from 'turbogate';
import { ZodType, z } from 'zod';

export const zEnvironment = z.object({
// MY_ENV_VAR: Env.string,
// ANOTHER_VAR_THAT_SHOULD_BE_A_NUMBER: Env.number,
ITEMS_TABLE_NAME: Env.string,
}) satisfies ZodType<any, any, EnvironmentDefinition>;

export type Environment = z.infer<typeof zEnvironment>;
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,52 @@
// Can be edited? Yes, editing this file is intended. Please ensure to preserve the signature though.
// Can be permanently deleted? No, generated code will break (so technically yes, if you fix loads of errors but you probably should not).
// Will be recreated? If you delete this file and run `turbogate build` a boilerplate version of this file will be recreated.
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
import { Context } from 'aws-lambda';
import { HttpStatus } from 'turbogate';
import { v4 as uuidv4 } from 'uuid';
import { ItemRecord } from '../../../../database/items/item-record';
import { AuthorizerContext } from './authorizer';
import { Environment } from './environment';
import { Request } from './request';
import { Response } from './responses';
import { Context } from 'aws-lambda';

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

export async function main(
environment: Environment,
request: Request,
authorizerContext: AuthorizerContext,
lambdaContext: Context,
): Promise<Response> {
// Replace this with your business logic.
return {
statusCode: HttpStatus.NotImplemented,
};
try {
// Merge the request body with a generated ID
const item: ItemRecord = {
...request.body,
id: uuidv4(),
};

// Store the item in the DB
await docClient.send(
new PutCommand({
TableName: environment.ITEMS_TABLE_NAME,
Item: item,
}),
);

// Return the item
return {
statusCode: HttpStatus.Created,
body: item,
};
} catch (e) {
// Handle errors
console.log('Failed to create item in DB', e);
return {
statusCode: HttpStatus.InternalServerError,
body: undefined,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@
// Can be permanently deleted? No, code that is regenerated on every `turbogate build` call will break, so fixing broken code after deleting this won't make sense.
// Will be recreated? If you delete this file and run `turbogate build` a boilerplate version of this file will be recreated.

export const permissions = [
// 'MY_DYNAMO_1_READ',
// 'MY_DYNAMO_1_WRITE',
// 'MY_SQS_1_SEND_MESSAGE',
] as const;
export const permissions = ['ITEMS_TABLE_WRITE'] as const;
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
// Will be recreated? If you delete this file and run `turbogate build` a boilerplate version of this file will be recreated.
import { RequestDefinition } from 'turbogate';
import { ZodType, z } from 'zod';
import { zItemRecord } from '../../../../database/items/item-record';

export const zRequest = z.object({
body: z.undefined(),
body: zItemRecord.omit({ id: true }),
pathParameters: z.object({}),
queryParameters: z.object({}),
headers: z.object({}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,18 @@
// Can be permanently deleted? No, generated code will break (so technically yes, if you fix loads of errors but you probably should not).
// Will be recreated? If you delete this file and run `turbogate build` a boilerplate version of this file will be recreated.
import { InferResponseFromResponsesDeclaration, ResponsesDeclaration } from 'turbogate';
import { zItemRecord } from '../../../../database/items/item-record';
import { http400ValidationError } from '../../../shared/responses/http-400-validation-error';
import { http500InternalServerError } from '../../../shared/responses/http-500-internal-server-error';
import { http501NotImplemented } from '../../../shared/responses/http-501-not-implemented';
import { z } from 'zod';

export const responses = {
// Some common responses are already defined for you.
// You can change them in the shared/responses folder if you want.
...http400ValidationError,
...http500InternalServerError,
...http501NotImplemented,

// Example for a custom success response
// 200: {
// description: 'Everything is allright.',
// schema: z.object({ message: z.string() }),
// },
201: {
description: 'The item was created successfully. The whole created item is returned.',
schema: zItemRecord,
},
} as const satisfies ResponsesDeclaration;

export type Response = InferResponseFromResponsesDeclaration<typeof responses>;
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@
"typescript": "~5.3.3"
},
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.499.0",
"@aws-sdk/lib-dynamodb": "^3.499.0",
"@types/uuid": "^9.0.8",
"aws-cdk-lib": "^2.123.0",
"constructs": "^10.0.0",
"prettier": "^3.2.4",
"source-map-support": "^0.5.21",
"turbogate": "^2.0.2",
"uuid": "^9.0.1",
"zod": "^3.22.4"
}
}
}
Loading

0 comments on commit c78cdb4

Please sign in to comment.