-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Federico Feroldi
committed
Aug 23, 2019
1 parent
3ba6de0
commit 0ab21d0
Showing
4 changed files
with
228 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// tslint:disable:no-any no-duplicate-string no-big-function | ||
|
||
jest.mock("winston"); | ||
|
||
import { right } from "fp-ts/lib/Either"; | ||
import { none, some } from "fp-ts/lib/Option"; | ||
|
||
import { FiscalCode, NonEmptyString } from "italia-ts-commons/lib/strings"; | ||
|
||
import { | ||
NewMessageWithoutContent, | ||
RetrievedMessageWithoutContent | ||
} from "io-functions-commons/dist/src/models/message"; | ||
|
||
import { ServiceId } from "io-functions-commons/dist/generated/definitions/ServiceId"; | ||
import { TimeToLiveSeconds } from "io-functions-commons/dist/generated/definitions/TimeToLiveSeconds"; | ||
|
||
import { response as MockResponse } from "jest-mock-express"; | ||
|
||
import { GetMessagesHandler } from "../handler"; | ||
|
||
const aFiscalCode = "FRLFRC74E04B157I" as FiscalCode; | ||
|
||
const aNewMessageWithoutContent: NewMessageWithoutContent = { | ||
createdAt: new Date(), | ||
fiscalCode: aFiscalCode, | ||
id: "A_MESSAGE_ID" as NonEmptyString, | ||
indexedId: "A_MESSAGE_ID" as NonEmptyString, | ||
isPending: true, | ||
kind: "INewMessageWithoutContent", | ||
senderServiceId: "test" as ServiceId, | ||
senderUserId: "u123" as NonEmptyString, | ||
timeToLiveSeconds: 3600 as TimeToLiveSeconds | ||
}; | ||
|
||
const aRetrievedMessageWithoutContent: RetrievedMessageWithoutContent = { | ||
...aNewMessageWithoutContent, | ||
_self: "xyz", | ||
_ts: 1, | ||
kind: "IRetrievedMessageWithoutContent" | ||
}; | ||
|
||
describe("GetMessagesHandler", () => { | ||
it("should respond with the messages for the recipient", async () => { | ||
const mockIterator = { | ||
executeNext: jest | ||
.fn() | ||
.mockImplementationOnce(() => | ||
Promise.resolve(right(some([aRetrievedMessageWithoutContent]))) | ||
) | ||
.mockImplementationOnce(() => Promise.resolve(right(none))) | ||
}; | ||
|
||
const mockMessageModel = { | ||
findMessages: jest.fn(() => mockIterator) | ||
}; | ||
|
||
const getMessagesHandler = GetMessagesHandler(mockMessageModel as any); | ||
|
||
const result = await getMessagesHandler(aFiscalCode); | ||
|
||
expect(result.kind).toBe("IResponseSuccessJsonIterator"); | ||
|
||
const mockResponse = MockResponse(); | ||
await result.apply(mockResponse); | ||
|
||
expect(mockIterator.executeNext).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"bindings": [ | ||
{ | ||
"authLevel": "function", | ||
"type": "httpTrigger", | ||
"direction": "in", | ||
"name": "req", | ||
"route": "v1/messages/{fiscalcode}", | ||
"methods": [ | ||
"get" | ||
] | ||
}, | ||
{ | ||
"type": "http", | ||
"direction": "out", | ||
"name": "res" | ||
} | ||
], | ||
"scriptFile": "../dist/GetMessages/index.js" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as express from "express"; | ||
|
||
import { IResponseErrorValidation } from "italia-ts-commons/lib/responses"; | ||
import { FiscalCode } from "italia-ts-commons/lib/strings"; | ||
|
||
import { | ||
filterResultIterator, | ||
mapResultIterator | ||
} from "io-functions-commons/dist/src/utils/documentdb"; | ||
import { retrievedMessageToPublic } from "io-functions-commons/dist/src/utils/messages"; | ||
import { FiscalCodeMiddleware } from "io-functions-commons/dist/src/utils/middlewares/fiscalcode"; | ||
import { | ||
withRequestMiddlewares, | ||
wrapRequestHandler | ||
} from "io-functions-commons/dist/src/utils/request_middleware"; | ||
import { | ||
IResponseErrorQuery, | ||
IResponseSuccessJsonIterator, | ||
ResponseJsonIterator | ||
} from "io-functions-commons/dist/src/utils/response"; | ||
|
||
import { MessageModel } from "io-functions-commons/dist/src/models/message"; | ||
|
||
import { CreatedMessageWithoutContent } from "io-functions-commons/dist/generated/definitions/CreatedMessageWithoutContent"; | ||
|
||
/** | ||
* Type of a GetMessages handler. | ||
* | ||
* GetMessages expects a FiscalCode as input and returns the Messages | ||
* as output or a Validation error. | ||
* | ||
* TODO: add full results and paging | ||
*/ | ||
type IGetMessagesHandler = ( | ||
fiscalCode: FiscalCode | ||
) => Promise< | ||
| IResponseSuccessJsonIterator<CreatedMessageWithoutContent> | ||
| IResponseErrorValidation | ||
| IResponseErrorQuery | ||
>; | ||
|
||
/** | ||
* Handles requests for getting all message for a recipient. | ||
*/ | ||
export function GetMessagesHandler( | ||
messageModel: MessageModel | ||
): IGetMessagesHandler { | ||
return async fiscalCode => { | ||
const retrievedMessagesIterator = messageModel.findMessages(fiscalCode); | ||
const validMessagesIterator = filterResultIterator( | ||
retrievedMessagesIterator, | ||
// isPending is true when the message has been received from the sender | ||
// but it's still being processed | ||
message => message.isPending !== true | ||
); | ||
const publicExtendedMessagesIterator = mapResultIterator( | ||
validMessagesIterator, | ||
retrievedMessageToPublic | ||
); | ||
return ResponseJsonIterator(publicExtendedMessagesIterator); | ||
}; | ||
} | ||
|
||
/** | ||
* Wraps a GetMessages handler inside an Express request handler. | ||
*/ | ||
export function GetMessages( | ||
messageModel: MessageModel | ||
): express.RequestHandler { | ||
const handler = GetMessagesHandler(messageModel); | ||
const middlewaresWrap = withRequestMiddlewares(FiscalCodeMiddleware); | ||
return wrapRequestHandler(middlewaresWrap(handler)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Context } from "@azure/functions"; | ||
|
||
import * as express from "express"; | ||
import * as winston from "winston"; | ||
|
||
import { DocumentClient as DocumentDBClient } from "documentdb"; | ||
|
||
import * as documentDbUtils from "io-functions-commons/dist/src/utils/documentdb"; | ||
import { getRequiredStringEnv } from "io-functions-commons/dist/src/utils/env"; | ||
import { secureExpressApp } from "io-functions-commons/dist/src/utils/express"; | ||
import { AzureContextTransport } from "io-functions-commons/dist/src/utils/logging"; | ||
import { setAppContext } from "io-functions-commons/dist/src/utils/middlewares/context_middleware"; | ||
|
||
import { | ||
MESSAGE_COLLECTION_NAME, | ||
MessageModel | ||
} from "io-functions-commons/dist/src/models/message"; | ||
|
||
import createAzureFunctionHandler from "io-functions-express/dist/src/createAzureFunctionsHandler"; | ||
|
||
import { GetMessages } from "./handler"; | ||
|
||
// Setup Express | ||
const app = express(); | ||
secureExpressApp(app); | ||
|
||
const cosmosDbUri = getRequiredStringEnv("CUSTOMCONNSTR_COSMOSDB_URI"); | ||
const cosmosDbKey = getRequiredStringEnv("CUSTOMCONNSTR_COSMOSDB_KEY"); | ||
const cosmosDbName = getRequiredStringEnv("COSMOSDB_NAME"); | ||
const messageContainerName = getRequiredStringEnv("MESSAGE_CONTAINER_NAME"); | ||
|
||
const documentDbDatabaseUrl = documentDbUtils.getDatabaseUri(cosmosDbName); | ||
const messagesCollectionUrl = documentDbUtils.getCollectionUri( | ||
documentDbDatabaseUrl, | ||
MESSAGE_COLLECTION_NAME | ||
); | ||
|
||
const documentClient = new DocumentDBClient(cosmosDbUri, { | ||
masterKey: cosmosDbKey | ||
}); | ||
|
||
const messageModel = new MessageModel( | ||
documentClient, | ||
messagesCollectionUrl, | ||
messageContainerName | ||
); | ||
|
||
app.get("/api/v1/messages/:fiscalcode", GetMessages(messageModel)); | ||
|
||
const azureFunctionHandler = createAzureFunctionHandler(app); | ||
|
||
// tslint:disable-next-line: no-let | ||
let logger: Context["log"] | undefined; | ||
const contextTransport = new AzureContextTransport(() => logger, { | ||
level: "debug" | ||
}); | ||
winston.add(contextTransport); | ||
|
||
// Binds the express app to an Azure Function handler | ||
function httpStart(context: Context): void { | ||
logger = context.log; | ||
setAppContext(app, context); | ||
azureFunctionHandler(context); | ||
} | ||
|
||
export default httpStart; |