somod-chat-service 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/message.d.ts +1 -1
- package/build/lib/message.js +4 -2
- package/build/lib/sessionUtil.d.ts +1 -1
- package/build/lib/sessionUtil.js +1 -2
- package/build/lib/types.d.ts +2 -14
- package/build/lib/types.js +1 -26
- package/build/parameters.json +1 -1
- package/build/serverless/functions/message.http.json +1 -1
- package/build/serverless/functions/message.js +4 -2
- package/build/serverless/functions/wsOnMessage.js +4 -2
- package/build/serverless/functions/wsOnMessage.websocket.json +1 -1
- package/build/serverless/template.json +1 -1
- package/package.json +1 -1
package/build/lib/message.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Message, MessageInput } from "./types";
|
|
2
2
|
export declare const putMessage: (tableName: string, userId: string, message: Omit<Message, "seqNo">) => Promise<Message>;
|
|
3
|
-
export declare const validateIncomingMessage: (message: MessageInput, userId: string) => Promise<{
|
|
3
|
+
export declare const validateIncomingMessage: (message: MessageInput, userId: string, typeToAllowedActionsMap: Record<string, string[]>) => Promise<{
|
|
4
4
|
statusCode: number;
|
|
5
5
|
headers: {
|
|
6
6
|
"Content-Type": string;
|
package/build/lib/message.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { marshall } from "@aws-sdk/util-dynamodb";
|
|
2
|
-
import { typeToAllowedActionsMap } from "./types";
|
|
3
2
|
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
|
|
4
3
|
import { threadCache } from "./threadCache";
|
|
5
4
|
const dynamodb = new DynamoDBClient();
|
|
@@ -21,7 +20,7 @@ export const putMessage = async (tableName, userId, message) => {
|
|
|
21
20
|
await dynamodb.send(putItemCommand);
|
|
22
21
|
return msg;
|
|
23
22
|
};
|
|
24
|
-
export const validateIncomingMessage = async (message, userId) => {
|
|
23
|
+
export const validateIncomingMessage = async (message, userId, typeToAllowedActionsMap) => {
|
|
25
24
|
let errorMessage = undefined;
|
|
26
25
|
const thread = await threadCache.get(message.threadId);
|
|
27
26
|
if (thread === undefined) {
|
|
@@ -30,6 +29,9 @@ export const validateIncomingMessage = async (message, userId) => {
|
|
|
30
29
|
else if (!thread.participants.includes(userId)) {
|
|
31
30
|
errorMessage = `Invalid threadId : from '${userId}' is not a participant in thread '${thread.id}'`;
|
|
32
31
|
}
|
|
32
|
+
else if (!typeToAllowedActionsMap[message.type]) {
|
|
33
|
+
errorMessage = `Invalid type : type must be one of (${typeToAllowedActionsMap[message.type].join(", ")})`;
|
|
34
|
+
}
|
|
33
35
|
else if (!typeToAllowedActionsMap[message.type].includes(message.action)) {
|
|
34
36
|
errorMessage = `Invalid action : action must be '${typeToAllowedActionsMap[message.type].join(",")}' for '${message.type}' type`;
|
|
35
37
|
}
|
|
@@ -7,5 +7,5 @@ export declare const Error: {
|
|
|
7
7
|
required: string;
|
|
8
8
|
invalid: string;
|
|
9
9
|
};
|
|
10
|
-
export declare const handleSessionToken: (userId: string, threadId: string, type: string, action: string, sessionToken?: string) => Promise<SessionIdResult>;
|
|
10
|
+
export declare const handleSessionToken: (userId: string, threadId: string, type: string, action: string, sessionRequirement: Record<string, Record<string, undefined | "thread" | "always">>, sessionToken?: string) => Promise<SessionIdResult>;
|
|
11
11
|
export {};
|
package/build/lib/sessionUtil.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { verify } from "jsonwebtoken";
|
|
2
|
-
import { sessionRequirement } from "./types";
|
|
3
2
|
import { threadCache } from "./threadCache";
|
|
4
3
|
const sessionJwtSecret = process.env.SESSION_SECRET ?? "";
|
|
5
4
|
const sessionForce = process.env.SESSION_FORCE ?? "";
|
|
@@ -7,7 +6,7 @@ export const Error = {
|
|
|
7
6
|
required: "missing required field: sessionToken",
|
|
8
7
|
invalid: "invalid field: sessionToken"
|
|
9
8
|
};
|
|
10
|
-
export const handleSessionToken = async (userId, threadId, type, action, sessionToken) => {
|
|
9
|
+
export const handleSessionToken = async (userId, threadId, type, action, sessionRequirement, sessionToken) => {
|
|
11
10
|
const result = { sessionId: "" };
|
|
12
11
|
if (sessionJwtSecret) {
|
|
13
12
|
if (!sessionToken) {
|
package/build/lib/types.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export type Thread = {
|
|
|
11
11
|
} & ThreadInput & ThreadSessionRequired;
|
|
12
12
|
export type MessageInput = {
|
|
13
13
|
threadId: string;
|
|
14
|
-
type: "text" | "image" | "control" | "call" | "
|
|
15
|
-
action: "new" | "edit" | "delete" | "
|
|
14
|
+
type: "text" | "image" | "control" | "audio-call" | "video-call";
|
|
15
|
+
action: "new" | "edit" | "delete" | "callStart" | "callConnect" | "callEnd";
|
|
16
16
|
message: string;
|
|
17
17
|
sessionToken?: string;
|
|
18
18
|
};
|
|
@@ -29,15 +29,3 @@ export type Session = {
|
|
|
29
29
|
startTime: number;
|
|
30
30
|
endTime: number;
|
|
31
31
|
};
|
|
32
|
-
export declare const typeToAllowedActionsMap: {
|
|
33
|
-
text: string[];
|
|
34
|
-
image: string[];
|
|
35
|
-
control: string[];
|
|
36
|
-
call: string[];
|
|
37
|
-
pooja: string[];
|
|
38
|
-
donation: string[];
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Store the message type and actions for which the session token is required
|
|
42
|
-
*/
|
|
43
|
-
export declare const sessionRequirement: Record<string, Record<string, undefined | "thread" | "always">>;
|
package/build/lib/types.js
CHANGED
|
@@ -1,26 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
text: ["new", "edit"],
|
|
3
|
-
image: ["new", "edit"],
|
|
4
|
-
control: [
|
|
5
|
-
"delete",
|
|
6
|
-
"sessionStart",
|
|
7
|
-
"sessionExtend",
|
|
8
|
-
"sessionEnd",
|
|
9
|
-
"sessionRequirementChange"
|
|
10
|
-
],
|
|
11
|
-
call: ["initiated", "declined"],
|
|
12
|
-
pooja: ["new", "edit"],
|
|
13
|
-
donation: ["new", "edit"]
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Store the message type and actions for which the session token is required
|
|
17
|
-
*/
|
|
18
|
-
export const sessionRequirement = {
|
|
19
|
-
text: { new: "thread", edit: "thread" },
|
|
20
|
-
image: { new: "thread", edit: "thread" },
|
|
21
|
-
control: {
|
|
22
|
-
sessionStart: "always",
|
|
23
|
-
sessionExtend: "always",
|
|
24
|
-
sessionEnd: "always"
|
|
25
|
-
}
|
|
26
|
-
};
|
|
1
|
+
export {};
|
package/build/parameters.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"parameters":{"chat.http-api.id":{"type":"string"},"chat.websocket-api.id":{"type":"string"},"chat.enable.websocket":{"type":"boolean","default":true},"dynamodb.pitr.enable":{"type":"boolean","default":false},"chat.session.jwt.secret":{"type":"string"},"chat.session.force":{"type":"boolean","default":false}}}
|
|
1
|
+
{"parameters":{"chat.http-api.id":{"type":"string"},"chat.websocket-api.id":{"type":"string"},"chat.enable.websocket":{"type":"boolean","default":true},"dynamodb.pitr.enable":{"type":"boolean","default":false},"chat.session.jwt.secret":{"type":"string"},"chat.session.force":{"type":"boolean","default":false},"chat.typeToAllowedActionsMap":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"default":{"text":["new","edit"],"image":["new","edit"],"control":["delete"],"audio-call":["callStart","callConnect","callEnd"],"video-call":["callStart","callConnect","callEnd"]}},"chat.sessionRequirementMap":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"enum":["thread","always"]}},"default":{"text":{"new":"thread","edit":"thread"},"image":{"new":"thread","edit":"thread"}}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"/post-message":{"POST":{"body":{"parser":"json","schema":{"type":"object","additionalProperties":false,"required":["threadId","type","action","message"],"properties":{"threadId":{"type":"string","pattern":"^[a-f0-9]{32}$"},"type":{"
|
|
1
|
+
{"/post-message":{"POST":{"body":{"parser":"json","schema":{"type":"object","additionalProperties":false,"required":["threadId","type","action","message"],"properties":{"threadId":{"type":"string","pattern":"^[a-f0-9]{32}$"},"type":{"type":"string","pattern":"^.{1,32}$"},"action":{"type":"string","pattern":"^.{1,32}$"},"message":{"type":"string","maxLength":512},"sessionToken":{"type":"string","maxLength":16384}}}}}},"/sync-messages":{"GET":{"parameters":[{"name":"from","in":"query","schema":{"type":"string","pattern":"^[0-9]*$"},"required":false}]}}}
|
|
@@ -8,13 +8,15 @@ import { handleSessionToken } from "../../lib/sessionUtil";
|
|
|
8
8
|
import { getUserIdFromEvent } from "../../lib/getUserIdFromEvent";
|
|
9
9
|
const dynamodb = new DynamoDBClient();
|
|
10
10
|
const builder = new RouteBuilder();
|
|
11
|
+
const typeToAllowedActionsMap = JSON.parse(process.env.MAP_OF_TYPE_ACTION ?? "{}");
|
|
12
|
+
const sessionRequirement = JSON.parse(process.env.MAP_OF_TYPE_ACTION_SESSION ?? "{}");
|
|
11
13
|
const postMessageHandler = async (request, event) => {
|
|
12
14
|
const userId = event.somodMiddlewareContext.get(UserProviderMiddlewareKey);
|
|
13
|
-
const messageValidationError = await validateIncomingMessage(request.body, userId);
|
|
15
|
+
const messageValidationError = await validateIncomingMessage(request.body, userId, typeToAllowedActionsMap);
|
|
14
16
|
if (messageValidationError) {
|
|
15
17
|
return messageValidationError;
|
|
16
18
|
}
|
|
17
|
-
const sessionIdResult = await handleSessionToken(userId, request.body.threadId, request.body.type, request.body.action, request.body.sessionToken);
|
|
19
|
+
const sessionIdResult = await handleSessionToken(userId, request.body.threadId, request.body.type, request.body.action, sessionRequirement, request.body.sessionToken);
|
|
18
20
|
if (sessionIdResult.error) {
|
|
19
21
|
return {
|
|
20
22
|
statusCode: 400,
|
|
@@ -4,13 +4,15 @@ import { v1 as v1uuid } from "uuid";
|
|
|
4
4
|
import { handleSessionToken } from "../../lib/sessionUtil";
|
|
5
5
|
import { getUserIdFromEvent } from "../../lib/getUserIdFromEvent";
|
|
6
6
|
const builder = new RouteBuilder();
|
|
7
|
+
const typeToAllowedActionsMap = JSON.parse(process.env.MAP_OF_TYPE_ACTION ?? "{}");
|
|
8
|
+
const sessionRequirement = JSON.parse(process.env.MAP_OF_TYPE_ACTION_SESSION ?? "{}");
|
|
7
9
|
builder.add("$default", async (message, event) => {
|
|
8
10
|
const userId = getUserIdFromEvent(event);
|
|
9
|
-
const messageValidationError = await validateIncomingMessage(message.body, userId);
|
|
11
|
+
const messageValidationError = await validateIncomingMessage(message.body, userId, typeToAllowedActionsMap);
|
|
10
12
|
if (messageValidationError) {
|
|
11
13
|
return messageValidationError;
|
|
12
14
|
}
|
|
13
|
-
const sessionIdResult = await handleSessionToken(userId, message.body.threadId, message.body.type, message.body.action, message.body.sessionToken);
|
|
15
|
+
const sessionIdResult = await handleSessionToken(userId, message.body.threadId, message.body.type, message.body.action, sessionRequirement, message.body.sessionToken);
|
|
14
16
|
if (sessionIdResult.error) {
|
|
15
17
|
return {
|
|
16
18
|
statusCode: 400,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$default":{"body":{"parser":"json","schema":{"type":"object","additionalProperties":false,"required":["wsMsgId","threadId","type","action","message"],"properties":{"wsMsgId":{"type":"string","pattern":"^[a-f0-9]{32}$"},"threadId":{"type":"string","pattern":"^[a-f0-9]{32}$"},"type":{"
|
|
1
|
+
{"$default":{"body":{"parser":"json","schema":{"type":"object","additionalProperties":false,"required":["wsMsgId","threadId","type","action","message"],"properties":{"wsMsgId":{"type":"string","pattern":"^[a-f0-9]{32}$"},"threadId":{"type":"string","pattern":"^[a-f0-9]{32}$"},"type":{"type":"string","pattern":"^.{1,32}$"},"action":{"type":"string","pattern":"^.{1,32}$"},"message":{"type":"string","maxLength":512},"sessionToken":{"type":"string","maxLength":16384}}}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"Resources":{"ChatApi":{"Type":"AWS::Serverless::HttpApi","SOMOD::Access":"public","SOMOD::Output":{"default":true},"Properties":{}},"ThreadTable":{"Type":"AWS::DynamoDB::Table","SOMOD::Access":"public","SOMOD::Output":{"default":true,"attributes":["Arn"]},"Properties":{"TableName":{"SOMOD::ResourceName":"Thread"},"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":{"SOMOD::Parameter":"dynamodb.pitr.enable"}},"KeySchema":[{"AttributeName":"id","KeyType":"HASH"}],"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"}]}},"MessageBox":{"Type":"AWS::DynamoDB::Table","SOMOD::Access":"public","SOMOD::Output":{"default":true,"attributes":["Arn","StreamArn"]},"Properties":{"TableName":{"SOMOD::ResourceName":"MessageBox"},"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":{"SOMOD::Parameter":"dynamodb.pitr.enable"}},"KeySchema":[{"AttributeName":"userId","KeyType":"HASH"},{"AttributeName":"seqNo","KeyType":"RANGE"}],"AttributeDefinitions":[{"AttributeName":"userId","AttributeType":"S"},{"AttributeName":"seqNo","AttributeType":"N"}],"StreamSpecification":{"StreamViewType":"NEW_IMAGE"}}},"MessageStreamHandlerDLQ":{"Type":"AWS::SQS::Queue","SOMOD::Output":{"default":true,"attributes":["Arn","QueueName","QueueUrl"]},"Properties":{"QueueName":{"SOMOD::ResourceName":"MessageStreamHandlerDLQ"}}},"MessageStreamHandler":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"FunctionName":{"SOMOD::ResourceName":"MsgStrmHandler"},"CodeUri":{"SOMOD::Function":{"name":"messageStreamHandler","type":"DynamoDB"}},"Environment":{"Variables":{"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}},"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"MSG_NOTIFICATION_TOPIC":{"SOMOD::Ref":{"resource":"MessageNotificationTopic"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:GetItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageNotificationTopic"}}],"Action":["sns:Publish"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageStreamHandlerDLQ","attribute":"Arn"}}],"Action":["sqs:SendMessage"]}]}],"Events":{"Stream":{"Type":"DynamoDB","Properties":{"Stream":{"SOMOD::Ref":{"resource":"MessageBox","attribute":"StreamArn"}},"BatchSize":1,"MaximumRetryAttempts":3,"StartingPosition":"LATEST","DestinationConfig":{"OnFailure":{"Destination":{"SOMOD::Ref":{"resource":"MessageStreamHandlerDLQ","attribute":"Arn"}}}}}}}}},"UserProviderMiddleware":{"Type":"SOMOD::Serverless::FunctionMiddleware","SOMOD::Access":"public","SOMOD::Output":{"default":true},"Properties":{"CodeUri":{"SOMOD::FunctionMiddleware":{"name":"userProvider"}}}},"Message":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"FunctionName":{"SOMOD::ResourceName":"MessageApi"},"CodeUri":{"SOMOD::Function":{"name":"message","type":"HttpApi","middlewares":[{"module":"somod-http-extension","resource":"SomodHttpMiddleware"},{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}},"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"SESSION_SECRET":{"SOMOD::Parameter":"chat.session.jwt.secret"},"SESSION_FORCE":{"SOMOD::Parameter":"chat.session.force"}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem","dynamodb:Query"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:GetItem"]}]}],"Events":{"PostMessage":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"POST","Path":"/post-message"}},"SyncMessages":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"GET","Path":"/sync-messages"}}}}},"Thread":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"FunctionName":{"SOMOD::ResourceName":"ThreadApi"},"CodeUri":{"SOMOD::Function":{"name":"thread","type":"HttpApi","middlewares":[{"module":"somod-http-extension","resource":"SomodHttpMiddleware"},{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:PutItem","dynamodb:GetItem","dynamodb:UpdateItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]}]}],"Events":{"CreateThread":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"POST","Path":"/thread"}},"GetThread":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"GET","Path":"/thread/{id}"}},"UpdateSessionRequireInThread":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"POST","Path":"/thread/{id}/session"}}}}},"MessageNotificationTopic":{"Type":"AWS::SNS::Topic","SOMOD::Access":"public","SOMOD::Output":{"default":true,"attributes":["TopicName"]},"Properties":{"TopicName":{"SOMOD::ResourceName":"MsgNotificationTopic"}}},"WebSocketApi":{"Type":"AWS::ApiGatewayV2::Api","SOMOD::Access":"public","Properties":{"Name":{"SOMOD::ResourceName":"ChatWebsocketApi"},"ProtocolType":"WEBSOCKET","RouteSelectionExpression":"$request.body.action"}},"ConnectRoute":{"Type":"AWS::ApiGatewayV2::Route","SOMOD::Access":"public","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteKey":"$connect","OperationName":"ConnectRoute","Target":{"Fn::Join":["/",["integrations",{"SOMOD::Ref":{"resource":"ConnectInteg"}}]]}}},"ConnectInteg":{"Type":"AWS::ApiGatewayV2::Integration","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Description":"Connect Integration","IntegrationType":"AWS_PROXY","IntegrationUri":{"Fn::Sub":["arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnConnectFunctionArn}/invocations",{"OnConnectFunctionArn":{"SOMOD::Ref":{"resource":"OnConnectFunction","attribute":"Arn"}}}]}}},"DisconnectRoute":{"Type":"AWS::ApiGatewayV2::Route","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteKey":"$disconnect","OperationName":"DisconnectRoute","Target":{"Fn::Join":["/",["integrations",{"SOMOD::Ref":{"resource":"DisconnectInteg"}}]]}}},"DisconnectInteg":{"Type":"AWS::ApiGatewayV2::Integration","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Description":"Disconnect Integration","IntegrationType":"AWS_PROXY","IntegrationUri":{"Fn::Sub":["arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnDisconnectFunctionArn}/invocations",{"OnDisconnectFunctionArn":{"SOMOD::Ref":{"resource":"OnDisconnectFunction","attribute":"Arn"}}}]}}},"DefaultRoute":{"Type":"AWS::ApiGatewayV2::Route","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteKey":"$default","OperationName":"DefaultRoute","Target":{"Fn::Join":["/",["integrations",{"SOMOD::Ref":{"resource":"DefaultInteg"}}]]}}},"DefaultRouteResponse":{"Type":"AWS::ApiGatewayV2::RouteResponse","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true},"Properties":{"RouteId":{"SOMOD::Ref":{"resource":"DefaultRoute"}},"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteResponseKey":"$default"}},"DefaultInteg":{"Type":"AWS::ApiGatewayV2::Integration","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Description":"Default Integration","IntegrationType":"AWS_PROXY","IntegrationUri":{"Fn::Sub":["arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnMessageFunctionArn}/invocations",{"OnMessageFunctionArn":{"SOMOD::Ref":{"resource":"OnMessageFunction","attribute":"Arn"}}}]}}},"DefaultIntegResponse":{"Type":"AWS::ApiGatewayV2::IntegrationResponse","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"IntegrationId":{"SOMOD::Ref":{"resource":"DefaultInteg"}},"IntegrationResponseKey":"$default"}},"Stage":{"Type":"AWS::ApiGatewayV2::Stage","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"StageName":"$default","ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"AutoDeploy":true}},"ConnectionsTable":{"Type":"AWS::DynamoDB::Table","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true,"attributes":["Arn"]},"Properties":{"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":{"SOMOD::Parameter":"dynamodb.pitr.enable"}},"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"},{"AttributeName":"userId","AttributeType":"S"}],"KeySchema":[{"AttributeName":"id","KeyType":"HASH"}],"GlobalSecondaryIndexes":[{"IndexName":"ByUserId","KeySchema":[{"AttributeName":"userId","KeyType":"HASH"}],"Projection":{"ProjectionType":"KEYS_ONLY"}}]}},"OnConnectFunction":{"Type":"AWS::Serverless::Function","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"attributes":["Arn"]},"Properties":{"CodeUri":{"SOMOD::Function":{"type":"WebSocket","name":"wsOnConnect","middlewares":[{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"CONNECTIONS_TABLE_NAME":{"SOMOD::Ref":{"resource":"ConnectionsTable"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ConnectionsTable","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]}]}]}},"OnConnectPermission":{"Type":"AWS::Lambda::Permission","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"Action":"lambda:InvokeFunction","FunctionName":{"SOMOD::Ref":{"resource":"OnConnectFunction"}},"Principal":"apigateway.amazonaws.com","SourceArn":{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/$default/$connect",{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}}},"OnDisconnectFunction":{"Type":"AWS::Serverless::Function","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"attributes":["Arn"]},"Properties":{"CodeUri":{"SOMOD::Function":{"type":"WebSocket","name":"wsOnDisconnect"}},"Environment":{"Variables":{"CONNECTIONS_TABLE_NAME":{"SOMOD::Ref":{"resource":"ConnectionsTable"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ConnectionsTable","attribute":"Arn"}}],"Action":["dynamodb:DeleteItem"]}]}]}},"OnDisconnectPermission":{"Type":"AWS::Lambda::Permission","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"Action":"lambda:InvokeFunction","FunctionName":{"SOMOD::Ref":{"resource":"OnDisconnectFunction"}},"Principal":"apigateway.amazonaws.com","SourceArn":{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/$default/$disconnect",{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}}},"OnMessageFunction":{"Type":"AWS::Serverless::Function","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"attributes":["Arn"]},"Properties":{"CodeUri":{"SOMOD::Function":{"type":"WebSocket","name":"wsOnMessage","middlewares":[{"module":"somod-websocket-extension","resource":"SomodWebSocketMiddleware"},{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}},"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"SESSION_SECRET":{"SOMOD::Parameter":"chat.session.jwt.secret"},"SESSION_FORCE":{"SOMOD::Parameter":"chat.session.force"}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:GetItem"]}]}]}},"OnMessagePermission":{"Type":"AWS::Lambda::Permission","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"Action":"lambda:InvokeFunction","FunctionName":{"SOMOD::Ref":{"resource":"OnMessageFunction"}},"Principal":"apigateway.amazonaws.com","SourceArn":{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/$default/$default",{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}}},"NotifyMessageFunction":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"CodeUri":{"SOMOD::Function":{"type":"SNS","name":"wsNotifyMessage"}},"Environment":{"Variables":{"CONNECTIONS_TABLE_NAME":{"SOMOD::Ref":{"resource":"ConnectionsTable"}},"CONNECTIONS_ENDPOINT":{"Fn::Sub":["https://${WebSocketApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}",{"WebSocketApi":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Stage":{"SOMOD::Ref":{"resource":"Stage"}}}]}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"Fn::Sub":["${ConnectionsTableArn}/index/ByUserId",{"ConnectionsTableArn":{"SOMOD::Ref":{"resource":"ConnectionsTable","attribute":"Arn"}}}]}],"Action":["dynamodb:Query"]}]},{"Statement":[{"Effect":"Allow","Action":["execute-api:ManageConnections"],"Resource":[{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*",{"WebSocketApi":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}]}]}],"Events":{"NotifyFromSNS":{"Type":"SNS","Properties":{"Topic":{"SOMOD::Ref":{"resource":"MessageNotificationTopic"}}}}},"Timeout":300}}},"Outputs":{"chat.http-api.id":{"Fn::Sub":["https://${apiId}.execute-api.${AWS::Region}.amazonaws.com/",{"apiId":{"SOMOD::Ref":{"resource":"ChatApi"}}}]},"chat.websocket-api.id":{"SOMOD::If":[{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},{"Fn::Sub":["wss://${apiId}.execute-api.${AWS::Region}.amazonaws.com/$default",{"apiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]},null]}}}
|
|
1
|
+
{"Resources":{"ChatApi":{"Type":"AWS::Serverless::HttpApi","SOMOD::Access":"public","SOMOD::Output":{"default":true},"Properties":{}},"ThreadTable":{"Type":"AWS::DynamoDB::Table","SOMOD::Access":"public","SOMOD::Output":{"default":true,"attributes":["Arn"]},"Properties":{"TableName":{"SOMOD::ResourceName":"Thread"},"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":{"SOMOD::Parameter":"dynamodb.pitr.enable"}},"KeySchema":[{"AttributeName":"id","KeyType":"HASH"}],"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"}]}},"MessageBox":{"Type":"AWS::DynamoDB::Table","SOMOD::Access":"public","SOMOD::Output":{"default":true,"attributes":["Arn","StreamArn"]},"Properties":{"TableName":{"SOMOD::ResourceName":"MessageBox"},"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":{"SOMOD::Parameter":"dynamodb.pitr.enable"}},"KeySchema":[{"AttributeName":"userId","KeyType":"HASH"},{"AttributeName":"seqNo","KeyType":"RANGE"}],"AttributeDefinitions":[{"AttributeName":"userId","AttributeType":"S"},{"AttributeName":"seqNo","AttributeType":"N"}],"StreamSpecification":{"StreamViewType":"NEW_IMAGE"}}},"MessageStreamHandlerDLQ":{"Type":"AWS::SQS::Queue","SOMOD::Output":{"default":true,"attributes":["Arn","QueueName","QueueUrl"]},"Properties":{"QueueName":{"SOMOD::ResourceName":"MessageStreamHandlerDLQ"}}},"MessageStreamHandler":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"FunctionName":{"SOMOD::ResourceName":"MsgStrmHandler"},"CodeUri":{"SOMOD::Function":{"name":"messageStreamHandler","type":"DynamoDB"}},"Environment":{"Variables":{"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}},"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"MSG_NOTIFICATION_TOPIC":{"SOMOD::Ref":{"resource":"MessageNotificationTopic"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:GetItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageNotificationTopic"}}],"Action":["sns:Publish"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageStreamHandlerDLQ","attribute":"Arn"}}],"Action":["sqs:SendMessage"]}]}],"Events":{"Stream":{"Type":"DynamoDB","Properties":{"Stream":{"SOMOD::Ref":{"resource":"MessageBox","attribute":"StreamArn"}},"BatchSize":1,"MaximumRetryAttempts":3,"StartingPosition":"LATEST","DestinationConfig":{"OnFailure":{"Destination":{"SOMOD::Ref":{"resource":"MessageStreamHandlerDLQ","attribute":"Arn"}}}}}}}}},"UserProviderMiddleware":{"Type":"SOMOD::Serverless::FunctionMiddleware","SOMOD::Access":"public","SOMOD::Output":{"default":true},"Properties":{"CodeUri":{"SOMOD::FunctionMiddleware":{"name":"userProvider"}}}},"Message":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"FunctionName":{"SOMOD::ResourceName":"MessageApi"},"CodeUri":{"SOMOD::Function":{"name":"message","type":"HttpApi","middlewares":[{"module":"somod-http-extension","resource":"SomodHttpMiddleware"},{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}},"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"SESSION_SECRET":{"SOMOD::Parameter":"chat.session.jwt.secret"},"SESSION_FORCE":{"SOMOD::Parameter":"chat.session.force"},"MAP_OF_TYPE_ACTION":{"SOMOD::JsonStringify":{"SOMOD::Parameter":"chat.typeToAllowedActionsMap"}},"MAP_OF_TYPE_ACTION_SESSION":{"SOMOD::JsonStringify":{"SOMOD::Parameter":"chat.sessionRequirementMap"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem","dynamodb:Query"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:GetItem"]}]}],"Events":{"PostMessage":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"POST","Path":"/post-message"}},"SyncMessages":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"GET","Path":"/sync-messages"}}}}},"Thread":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"FunctionName":{"SOMOD::ResourceName":"ThreadApi"},"CodeUri":{"SOMOD::Function":{"name":"thread","type":"HttpApi","middlewares":[{"module":"somod-http-extension","resource":"SomodHttpMiddleware"},{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:PutItem","dynamodb:GetItem","dynamodb:UpdateItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]}]}],"Events":{"CreateThread":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"POST","Path":"/thread"}},"GetThread":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"GET","Path":"/thread/{id}"}},"UpdateSessionRequireInThread":{"Type":"HttpApi","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"ChatApi"}},"Method":"POST","Path":"/thread/{id}/session"}}}}},"MessageNotificationTopic":{"Type":"AWS::SNS::Topic","SOMOD::Access":"public","SOMOD::Output":{"default":true,"attributes":["TopicName"]},"Properties":{"TopicName":{"SOMOD::ResourceName":"MsgNotificationTopic"}}},"WebSocketApi":{"Type":"AWS::ApiGatewayV2::Api","SOMOD::Access":"public","Properties":{"Name":{"SOMOD::ResourceName":"ChatWebsocketApi"},"ProtocolType":"WEBSOCKET","RouteSelectionExpression":"$request.body.action"}},"ConnectRoute":{"Type":"AWS::ApiGatewayV2::Route","SOMOD::Access":"public","Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteKey":"$connect","OperationName":"ConnectRoute","Target":{"Fn::Join":["/",["integrations",{"SOMOD::Ref":{"resource":"ConnectInteg"}}]]}}},"ConnectInteg":{"Type":"AWS::ApiGatewayV2::Integration","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Description":"Connect Integration","IntegrationType":"AWS_PROXY","IntegrationUri":{"Fn::Sub":["arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnConnectFunctionArn}/invocations",{"OnConnectFunctionArn":{"SOMOD::Ref":{"resource":"OnConnectFunction","attribute":"Arn"}}}]}}},"DisconnectRoute":{"Type":"AWS::ApiGatewayV2::Route","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteKey":"$disconnect","OperationName":"DisconnectRoute","Target":{"Fn::Join":["/",["integrations",{"SOMOD::Ref":{"resource":"DisconnectInteg"}}]]}}},"DisconnectInteg":{"Type":"AWS::ApiGatewayV2::Integration","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Description":"Disconnect Integration","IntegrationType":"AWS_PROXY","IntegrationUri":{"Fn::Sub":["arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnDisconnectFunctionArn}/invocations",{"OnDisconnectFunctionArn":{"SOMOD::Ref":{"resource":"OnDisconnectFunction","attribute":"Arn"}}}]}}},"DefaultRoute":{"Type":"AWS::ApiGatewayV2::Route","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteKey":"$default","OperationName":"DefaultRoute","Target":{"Fn::Join":["/",["integrations",{"SOMOD::Ref":{"resource":"DefaultInteg"}}]]}}},"DefaultRouteResponse":{"Type":"AWS::ApiGatewayV2::RouteResponse","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true},"Properties":{"RouteId":{"SOMOD::Ref":{"resource":"DefaultRoute"}},"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"RouteResponseKey":"$default"}},"DefaultInteg":{"Type":"AWS::ApiGatewayV2::Integration","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Description":"Default Integration","IntegrationType":"AWS_PROXY","IntegrationUri":{"Fn::Sub":["arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OnMessageFunctionArn}/invocations",{"OnMessageFunctionArn":{"SOMOD::Ref":{"resource":"OnMessageFunction","attribute":"Arn"}}}]}}},"DefaultIntegResponse":{"Type":"AWS::ApiGatewayV2::IntegrationResponse","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"IntegrationId":{"SOMOD::Ref":{"resource":"DefaultInteg"}},"IntegrationResponseKey":"$default"}},"Stage":{"Type":"AWS::ApiGatewayV2::Stage","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"StageName":"$default","ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"AutoDeploy":true}},"ConnectionsTable":{"Type":"AWS::DynamoDB::Table","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"default":true,"attributes":["Arn"]},"Properties":{"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":{"SOMOD::Parameter":"dynamodb.pitr.enable"}},"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"},{"AttributeName":"userId","AttributeType":"S"}],"KeySchema":[{"AttributeName":"id","KeyType":"HASH"}],"GlobalSecondaryIndexes":[{"IndexName":"ByUserId","KeySchema":[{"AttributeName":"userId","KeyType":"HASH"}],"Projection":{"ProjectionType":"KEYS_ONLY"}}]}},"OnConnectFunction":{"Type":"AWS::Serverless::Function","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"attributes":["Arn"]},"Properties":{"CodeUri":{"SOMOD::Function":{"type":"WebSocket","name":"wsOnConnect","middlewares":[{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"CONNECTIONS_TABLE_NAME":{"SOMOD::Ref":{"resource":"ConnectionsTable"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ConnectionsTable","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]}]}]}},"OnConnectPermission":{"Type":"AWS::Lambda::Permission","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"Action":"lambda:InvokeFunction","FunctionName":{"SOMOD::Ref":{"resource":"OnConnectFunction"}},"Principal":"apigateway.amazonaws.com","SourceArn":{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/$default/$connect",{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}}},"OnDisconnectFunction":{"Type":"AWS::Serverless::Function","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"attributes":["Arn"]},"Properties":{"CodeUri":{"SOMOD::Function":{"type":"WebSocket","name":"wsOnDisconnect"}},"Environment":{"Variables":{"CONNECTIONS_TABLE_NAME":{"SOMOD::Ref":{"resource":"ConnectionsTable"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ConnectionsTable","attribute":"Arn"}}],"Action":["dynamodb:DeleteItem"]}]}]}},"OnDisconnectPermission":{"Type":"AWS::Lambda::Permission","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"Action":"lambda:InvokeFunction","FunctionName":{"SOMOD::Ref":{"resource":"OnDisconnectFunction"}},"Principal":"apigateway.amazonaws.com","SourceArn":{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/$default/$disconnect",{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}}},"OnMessageFunction":{"Type":"AWS::Serverless::Function","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"SOMOD::Output":{"attributes":["Arn"]},"Properties":{"CodeUri":{"SOMOD::Function":{"type":"WebSocket","name":"wsOnMessage","middlewares":[{"module":"somod-websocket-extension","resource":"SomodWebSocketMiddleware"},{"resource":"UserProviderMiddleware"}]}},"Environment":{"Variables":{"MESSAGE_BOX_TABLE_NAME":{"SOMOD::Ref":{"resource":"MessageBox"}},"THREAD_TABLE_NAME":{"SOMOD::Ref":{"resource":"ThreadTable"}},"SESSION_SECRET":{"SOMOD::Parameter":"chat.session.jwt.secret"},"SESSION_FORCE":{"SOMOD::Parameter":"chat.session.force"},"MAP_OF_TYPE_ACTION":{"SOMOD::JsonStringify":{"SOMOD::Parameter":"chat.typeToAllowedActionsMap"}},"MAP_OF_TYPE_ACTION_SESSION":{"SOMOD::JsonStringify":{"SOMOD::Parameter":"chat.sessionRequirementMap"}}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"MessageBox","attribute":"Arn"}}],"Action":["dynamodb:PutItem"]},{"Effect":"Allow","Resource":[{"SOMOD::Ref":{"resource":"ThreadTable","attribute":"Arn"}}],"Action":["dynamodb:GetItem"]}]}]}},"OnMessagePermission":{"Type":"AWS::Lambda::Permission","SOMOD::CreateIf":{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},"Properties":{"Action":"lambda:InvokeFunction","FunctionName":{"SOMOD::Ref":{"resource":"OnMessageFunction"}},"Principal":"apigateway.amazonaws.com","SourceArn":{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiId}/$default/$default",{"ApiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}}},"NotifyMessageFunction":{"Type":"AWS::Serverless::Function","SOMOD::Access":"public","Properties":{"CodeUri":{"SOMOD::Function":{"type":"SNS","name":"wsNotifyMessage"}},"Environment":{"Variables":{"CONNECTIONS_TABLE_NAME":{"SOMOD::Ref":{"resource":"ConnectionsTable"}},"CONNECTIONS_ENDPOINT":{"Fn::Sub":["https://${WebSocketApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}",{"WebSocketApi":{"SOMOD::Ref":{"resource":"WebSocketApi"}},"Stage":{"SOMOD::Ref":{"resource":"Stage"}}}]}}},"Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Resource":[{"Fn::Sub":["${ConnectionsTableArn}/index/ByUserId",{"ConnectionsTableArn":{"SOMOD::Ref":{"resource":"ConnectionsTable","attribute":"Arn"}}}]}],"Action":["dynamodb:Query"]}]},{"Statement":[{"Effect":"Allow","Action":["execute-api:ManageConnections"],"Resource":[{"Fn::Sub":["arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WebSocketApi}/*",{"WebSocketApi":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]}]}]}],"Events":{"NotifyFromSNS":{"Type":"SNS","Properties":{"Topic":{"SOMOD::Ref":{"resource":"MessageNotificationTopic"}}}}},"Timeout":300}}},"Outputs":{"chat.http-api.id":{"Fn::Sub":["https://${apiId}.execute-api.${AWS::Region}.amazonaws.com/",{"apiId":{"SOMOD::Ref":{"resource":"ChatApi"}}}]},"chat.websocket-api.id":{"SOMOD::If":[{"SOMOD::Equals":[{"SOMOD::Parameter":"chat.enable.websocket"},true]},{"Fn::Sub":["wss://${apiId}.execute-api.${AWS::Region}.amazonaws.com/$default",{"apiId":{"SOMOD::Ref":{"resource":"WebSocketApi"}}}]},null]}}}
|
package/package.json
CHANGED