diff --git a/diagrams/architecture/document-events-processing.py b/diagrams/architecture/document-events-processing.py new file mode 100644 index 0000000..f0b137f --- /dev/null +++ b/diagrams/architecture/document-events-processing.py @@ -0,0 +1,15 @@ +from diagrams import Cluster, Diagram, Edge +from diagrams.aws.general import User +from diagrams.aws.compute import Lambda +from diagrams.aws.network import APIGateway +from diagrams.aws.integration import SNS, SQS + +with Diagram("Document Event Processing", show=False): + + api = APIGateway("Documents API") + lambda_processor = Lambda("Document Processor") + sns_documentevents = SNS("Document Events") + sqs_processing = SQS("Processing Queue") + + staging = User("User") + staging - Edge(label="Create Document") - api - Edge(label="Document Event") - sns_documentevents - Edge(label="Create Event") - sqs_processing - Edge(label="Additional Document Processing") - lambda_processor \ No newline at end of file diff --git a/diagrams/architecture/document_event_processing.png b/diagrams/architecture/document_event_processing.png new file mode 100644 index 0000000..e425973 Binary files /dev/null and b/diagrams/architecture/document_event_processing.png differ diff --git a/docs/platform/api_security.md b/docs/platform/api_security.md index 78554ab..f217bc3 100644 --- a/docs/platform/api_security.md +++ b/docs/platform/api_security.md @@ -2,79 +2,80 @@ sidebar_position: 3 --- -# API Security +# Security -![Authentication](./img/formkiq_authentication.png) - -The FormKiQ API is built on top of [AWS API Gateway](https://aws.amazon.com/api-gateway/). API Gateway offers the flexibility to empowers customers to choose the most suitable authentication method based on their specific application requirements. +## Overview -The FormKiQ installation deploys multiple copies of the API, with each one using a different authentication mechanism. This allows you to choose the authentication mechanism that suits your needs. +FormKiQ is designed with a robust security framework to safeguard user data and sensitive information. FormKiQ employs a Role-Based Access Control (RBAC) as its default security mechanism, ensuring a streamlined and efficient authorization process for all users. The RBAC system assigns roles to users based on their responsibilities, granting access only to the resources essential for their tasks. -The FormKiQ API URL(s) can be found in the CloudFormation outputs of your FormKiQ stack. - -![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) +:::note +By default the `AdminEmail` configured during the installation process is setup as an administrator with full access +::: -:::note: -[FormKiQ Enterprise](https://www.formkiq.com/products/formkiq-enterprise) users have additional authentication options like Security Assertion Markup Language (SAML). +:::note +[FormKiQ Pro/Enterprise](https://www.formkiq.com/products/formkiq-enterprise) users have the ability to use Attribute-based Access Control (ABAC) through [Open Policy Agent](https://www.openpolicyagent.org/). ::: -## JSON Web Token(JWT) +## Groups -JWT authentication, also known as [JSON Web Token](https://jwt.io/introduction) authentication, is a method used to verify the identity of users or systems accessing web applications or APIs. It is based on the use of digitally signed tokens containing encoded claims about the user's identity and permissions. +FormKiQ supports multi-tenancy environments by defining user group(s) and then linking these groups to the different FormKiQ site(s). Each user can be associated with one or more groups, reflecting their role or responsibilities within the platform. These groups, in turn, determine the user's access privileges across different sites within the platform. -By default, FormKiQ uses [Amazon Cognito](https://aws.amazon.com/cognito) as the JWT Issuer and authorization is handled through role-based access control assigned to each user. +The user's groups link to the FormKiQ's sites that the user will be granted access to; users can be in one or more groups, granting access to specific sites with specified roles. -The API that uses the JWT authentication can be found in the CloudFormation Outputs of the FormKiQ installation under the `HttpApiUrl` key. +| Group | Description +| -------- | ------- | +| Admins | Administrator group access | +| authentication_only | Authentication only group access | +| **site name** | Read/Write/Delete access to **site_name** | +| **site name**_read | Read access to site **site_name** | -![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) -## AWS IAM +FormKiQ comes with 4 groups by default. -[IAM Authentication](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-access-control-iam.html) allows customers to call the FormKiQ API by signing requests using [Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) with AWS credentials. +* **Admins** - Users in this group have full administrative privileges to all sites -The API that uses the JWT authentication can be found in the CloudFormation Outputs of the FormKiQ installation under the `IamApiUrl` key. +* **authentication_only** - Users in this group can authenticate and receive a access token, but do not have access to any sites. Used mainly with the Document Sharing API to share specific folders / documents with a user -![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) +* **default** - The "default" FormKiQ site that is created on installation. Users in this group will have read/write/delete access to the "default" site. -:::note: -You need the IAM execute-api permission to be able to use IAM Authentication and all requests will be run with administration privileges. -::: +* **default_read** - The "default" FormKiQ site that is created on installation. Users in this group will have read access to the "default" site. -## API Key +Here is what the groups in [Amazon Cognito](https://aws.amazon.com/cognito) looks like by default. -FormKiQ allows for the generating of an API key that can be used to access the FormKiQ API for a particular `SiteId`. +![Security Roles Example](./img/security-roles-examples.png) -The API key can be generated using the `POST /configuration/apiKeys` API endpoint using credentials with `administrator` privileges. +:::note +The Cognito User pool can be found by visiting the [Cognito Console](https://console.aws.amazon.com/cognito) page and searching for the `AppEnvironment` name you configured during installation. -The API that uses the Key authentication can be found in the CloudFormation Outputs of the FormKiQ installation under the `KeyApiUrl` key. +![Cognito Home](./img/cognito-home.png) +::: -![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) +### Add Multi-Tenant Site -:::note: -Each API key is only valid for a particular SiteId. -::: +Creating a new Multi-Tenant Site is as easy as creating a new group and adding users to the group. -## Amazon Cognito +To add a new group to Amazon Cognito: -FormKiQ comes with a fully-functional console for interacting with documents, built using React. This console can be referenced when creating custom applications that will interact with the FormKiQ Document API. The console URL can be found in the CloudFormation outputs. +* Open the [Amazon Cognito Console](https://console.aws.amazon.com/cognito) +* Click on the `Group` tab and click `Create Group` -![CloudFormation Outputs Console Url](./img/cf-outputs-consoleurl.png) +![Cognito Home](./img/cognito-add-group.png) -Console access is controlled through the [Amazon Cognito JWT authorizer](https://aws.amazon.com/cognito). By default the `AdminEmail` configured during the CloudFormation creation is created as an administrator user. +* Enter a `Group Name` and click `Create Group` -Additional users can be added manually through the [Cognito Console](https://console.aws.amazon.com/cognito). +![Cognito Home](./img/cognito-create-group.png) -### Create User +The site has now been created and you can add users to this group to give them access to the finance site. -To add a new user, start by visiting the [Cognito Console](https://console.aws.amazon.com/cognito). You should find the Cognito User pool with the configured `AppEnvironment` in the name. +![Cognito Group List](./img/cognito-groups-list-finance.png) -![Cognito Home](./img/cognito-home.png) +### Add User to Site -:::note: +:::note If you do not see a Cognito User pool, check that the region you are in matches the region where you have installed FormKiQ. ::: -![Cognito Users Tab](./img/Cognito Create User) +![Cognito Users Tab](./img/cognito-create-user.png) Clicking the Cognito Users tab, you should see the administrator user that was created during the installation process. @@ -95,15 +96,66 @@ Click the `Create user` button to finish creating the new user. The user receive The user is now created with read / write access to the default site id. -### Group Permissions -FormKiQ starts with three default groups. -* Admins - Group for administrators of FormKiQ -* default - Read / Write permission for the default site id -* default_read - Read permission for the default site id +## API Endpoints + +The FormKiQ API is built on top of [AWS API Gateway](https://aws.amazon.com/api-gateway/). API Gateway offers the flexibility to empowers customers to choose the most suitable authentication and authorization methods based on their specific application requirements. + +By default FormKiQ API supports 3 different types of authorization: -![Cognito Group List](./img/cognito-group-list.png) +* JSON Web Token(JWT) Authorizers -By default if a user belongs to no groups, it will be given the "default" group permissions. By clicking on any of the groups users can be easily added or removed. +* Amazon Identity and Access Management (IAM) authorization + +* API Key authorization + +![Authentication](./img/formkiq_authentication.png) + +FormKiQ supports these different authorization mechanisms by deplying multiple copies of the API. This allows you to use the authentication mechanism that suits your needs. + +The FormKiQ API URL(s) can be found in the CloudFormation outputs of your FormKiQ stack. + +![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) +:::note +[FormKiQ Enterprise](https://www.formkiq.com/products/formkiq-enterprise) users have additional authentication options like Security Assertion Markup Language (SAML) or custom authentication mechanisms +::: + +### JSON Web Token(JWT) Authorizers + +JWT authentication, also known as [JSON Web Token](https://jwt.io/introduction) authentication, is a method used to verify the identity of users or systems accessing web applications or APIs. It is based on the use of digitally signed tokens containing encoded claims about the user's identity and permissions. + +By default, FormKiQ uses [Amazon Cognito](https://aws.amazon.com/cognito) as the JWT Issuer and authorization is handled through role-based access control assigned to each user. + +The API that uses the JWT authentication can be found in the CloudFormation Outputs of the FormKiQ installation under the `HttpApiUrl` key. + +![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) + +### Amazon Identity and Access Management (IAM) authorization + +[IAM Authentication](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-access-control-iam.html) allows customers to call the FormKiQ API by signing requests using [Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) with AWS credentials. + +IAM Authentication is typically used for machine-to-machine authorization as there is no user information inside of the token. + +The API that uses the IAM authentication can be found in the CloudFormation Outputs of the FormKiQ installation under the `IamApiUrl` key. + +![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) + +:::note +You need the IAM execute-api permission to be able to use IAM Authentication and all requests will be run with administration privileges. +::: + +### API Key + +FormKiQ allows for the generating of an API key that can be used to access the FormKiQ API for a particular `SiteId`. + +The API key can be generated using the `POST /configuration/apiKeys` API endpoint using credentials with `administrator` privileges. + +The API that uses the Key authentication can be found in the CloudFormation Outputs of the FormKiQ installation under the `KeyApiUrl` key. + +![CloudFormation Outputs API Urls](./img/cf-outputs-apiurls.png) + +:::note +Each API key is only valid for a particular SiteId. +::: diff --git a/docs/platform/building_from_source.md b/docs/platform/building_from_source.md index b718bd9..a7a95bc 100644 --- a/docs/platform/building_from_source.md +++ b/docs/platform/building_from_source.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 --- # Building from Source diff --git a/docs/platform/costs.md b/docs/platform/costs.md index a34d840..a15cb7a 100644 --- a/docs/platform/costs.md +++ b/docs/platform/costs.md @@ -4,8 +4,8 @@ sidebar_position: 7 # Costs -FormKiQ was created using [serverless technology](https://aws.amazon.com/serverless). This means that there are no servers to manage; everything is managed by AWS. All AWS services FormKiQ uses have pay-per-usage billing. You can start using FormKiQ with very little cost. - +FormKiQ is built using [serverless technology](https://aws.amazon.com/serverless). This means that there are no servers to manage; everything is managed by AWS. All of the AWS services FormKiQ uses have pay-per-usage billing (with only one exception, OpenSearch, an add-on module). You can start using FormKiQ with very little cost. + In fact, AWS provides a [free tier](https://aws.amazon.com/free) to all AWS accounts. This means that some AWS services you can use for **free**, assuming you are able to stay within the usage limits. Below is the list of services FormKiQ uses and their approximate usage costs, so give you an idea on how much it costs to run FormKiQ. (All costs in USD) | Service | Cost | @@ -17,3 +17,63 @@ In fact, AWS provides a [free tier](https://aws.amazon.com/free) to all AWS acco | [Amazon CloudFront](https://aws.amazon.com/cloudfront/pricing) | $0.085 per GB of Data Transfer Out to Internet | | [Amazon S3](https://aws.amazon.com/s3/pricing) | $0.023 per GB / Month | | [AWS Lambda](https://aws.amazon.com/lambda/pricing) | approx. first 400,000 requests Free per Month ($0.0000168667 per additional request) | + +## Cost Estimator + +Because of AWS' pay-per-usage model, it can be difficult to determine approximately what your hosting fees will be. The [AWS Pricing Calculator](https://calculator.aws/#/) can be useful to establish general costs. Below we have scenarios that gives you an idea of what your costs maybe. + +These scenarios do NOT include AWS' free tier or potential cost savings when higher usage tiers are reached. + +:::note +All prices are shown in USD +::: + +### Adding - 1 million documents + +Scenario: Adding 1 million documents, each document is 1 MB in size + +| Service | Unit | Cost | +| -------- | ------- | ------- | +| Amazon DynamoDB Storage | 1 GB (each document stores about 350 bytes of data) | $0.25 | +| Amazon DynamoDB Write | 3 million requests | $7.00 | +| AWS Lambda | 2 million requests (200ms avg per document) | $10.00 | +| Amazon S3 PUT requests | 2 million | $10.00 | +| Amazon S3 (Standard Storage) | 1 TB | $30.00 per month | +| or Amazon S3 (Glacier Instant Retrieval Storage) | 1 TB | $5.00 per month | +| |Total ($) | $57.25 or $32.25 | + +### Viewing - 1 million documents + +Scenario: Viewing 1 million documents, each document is 1 MB in size + +| Service | Unit | Cost | +| -------- | ------- | ------- | +| Amazon DynamoDB Read Requests | 1 million requests | $0.13 | +| Amazon S3 Data Transfer | 1 TB | $92.16 | +| |Total ($) | $92.29 | + +### OCR - 1 million PDF documents + +Scenario: Extracting text from PDF document + +FormKiQ supports extracting text from a PDF document in two ways that have a different cost structure/features; many PDFs that were created electronically can have their text extracted programatically, without requiring OCR. For documents that are not fully digitized, such as documents that were scanned from paper or came from a photograph, OCR would be required. + +FormKiQ determines whether or not OCR is required automatically. + +| Service | Unit | Cost | +| -------- | ------- | ------- | +| AWS Lambda (Programmatically, for fully-digital PDFs) | 1 million requests (30 million pages) (600ms avg per document) | $20.20 | +| [AWS Textract](https://aws.amazon.com/pm/textract) (for PDFs that are not fully digital) | 1 million pages (text only) | $1500.00 | + + +### OCR - 1 million images + +Scenario: Extracting text from images, such as PNG + +FormKiQ supports extracting text from a PNG document in two ways that have a different cost structure/features. + +| Service | Unit | Cost | +| -------- | ------- | ------- | +| [Tesseract](https://github.com/tesseract-ocr/tesseract) (using AWS Lambda) | 1 million requests (1 million pages) (3000ms avg per document) | $100.20 | +| [AWS Textract](https://aws.amazon.com/pm/textract) | 1 million pages (text only) | $1500.00 | + diff --git a/docs/platform/database_schema.md b/docs/platform/database_schema.md new file mode 100644 index 0000000..08556a3 --- /dev/null +++ b/docs/platform/database_schema.md @@ -0,0 +1,442 @@ +--- +sidebar_position: 8 +--- + +# DynamoDB Schema + +[Amazon DynamoDB](https://aws.amazon.com/dynamodb) is a NoSQL database service designed for high-performance, scalable, and low-latency applications. + +In a DynamoDB table, the primary key is a fundamental component of the database schema, used to uniquely identify and organize items within a table. The primary key consists of two attributes: the partition key (PK) and the sort key (SK). The partition key is the primary attribute used to distribute data across multiple partitions for scalability. + +The table may also include Global Secondary Indexes named using the prefix (GSI) which can be employed to facilitate efficient querying of data based on different attributes. + +## Multi-Tenant + +When an entity is stored for a specific `SiteId` other than the `default` site. The format of the `PK` is prefixed with `SiteId/`. + +For example: When using a siteId of `finance`, the PK will store a document using `finance/docx#`. + +## Documents + +The following are the entities related to `Documents`. + +### Document + +The Document Entity consists of attributes that capture essential information about a document. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "document" | +| GSI1PK | ShortDate(yyyy-MM-ddd) | +| GSI1SK | FullDate("yyyy-MM-dd’T’HH:mm:ssZ") + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| inserteddate | Inserted Date | +| lastModifiedDate | Last Modified Date | +| userId | Create by user | +| path | Document path | +| deepLinkPath | Document deep link path | +| contentType | Mime Content Type | +| checksum | Document content checksum | +| tagSchemaId | Tag Schema for document | + +### Child Document + +A Child Document Entity includes attributes that capture details specific to the subsidiary document. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "document#" + childDocumentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| inserteddate | Inserted Date | +| lastModifiedDate | Last Modified Date | +| userId | Create by user | +| path | Document path | +| deepLinkPath | Document deep link path | +| contentType | Mime Content Type | +| checksum | Document content checksum | +| tagSchemaId | Tag Schema for document | +| belongsToDocumentId | Parent Id of document | + +### Document (Soft Delete) + +A "soft delete" Document is moved into a different PK namespace than all other documents. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "softdelete#doc#" | +| SK | "softdelete#document" + documentId | +| GSI1PK | ShortDate(yyyy-MM-ddd) | +| GSI1SK | FullDate("yyyy-MM-dd’T’HH:mm:ssZ") + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| inserteddate | Inserted Date | +| lastModifiedDate | Last Modified Date | +| userId | Create by user | +| path | Document path | +| deepLinkPath | Document deep link path | +| contentType | Mime Content Type | +| checksum | Document content checksum | +| tagSchemaId | Tag Schema for document | + +### Document Ocr + +Contains all information about any optical character recognition (OCR) data for the document. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "ocr#" | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| inserteddate | Inserted Date | +| userId | Create by user | +| contentType | Mime Content Type | +| ocrEngine | Ocr Engine Used (textract, tesseract) | +| jobId | Ocr Job Id | + +### Document Actions + +Contains list of document actions. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "action#" + idx + "#" + type | +| GSI1PK | "action#" + type + "#" + queueId | +| GSI1SK | "action#" + documentId + "#" + yyyy-MM-dd’T’HH:mm:ssZ | +| GSI2PK | "actions#" + status | +| GSI2SK | "action#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| type | Type of Action | +| status | Status of Action | +| parameters | Parameters for Action | +| metadata | Metadata for Action | +| userId | Create by user | +| inserteddate | Inserted Date | +| startDate | Start Date of action | +| completedDate | Completed Date | +| message | Action message | +| queueId | Queue Id | +| workflowId | Workflow Id | +| workflowStepId | Workflow Step Id | +| workflowLastStep | Workflow Last Step | + +### Document Tag + +Document Tag(s) entity. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "tags#" + tagKey | +| GSI1PK | "tag#" + tagKey + “#” + tagValue | +| GSI1SK | "yyyy-MM-dd’T’HH:mm:ssZ" + “#” + documentId | +| GSI2PK | "tag#" + tagKey | +| GSI2SK | tagValue + "#" + yyyy-MM-dd’T’HH:mm:ssZ + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| type | Type of Tag | +| tagValue | Tag Value | +| userId | Create by user | +| inserteddate | Inserted Date | + +### Document Tag (Multi-Value) + +Document Tag(s) entity with multiple values. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "tags#" + tagKey + "#idx" + index | +| GSI1PK | "tag#" + tagKey + “#” + tagValue | +| GSI1SK | "yyyy-MM-dd’T’HH:mm:ssZ" + “#” + documentId | +| GSI2PK | "tag#" + tagKey | +| GSI2SK | tagValue + "#" + yyyy-MM-dd’T’HH:mm:ssZ + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| type | Type of Tag | +| tagValue | Tag Value | +| tagValues | Tag Values | +| userId | Create by user | +| inserteddate | Inserted Date | + +### Document Activity + +Contains list of document activties. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "doc#" + documentId | +| SK | "activity#" + yyyy-MM-dd’T’HH:mm:ssZ | +| GSI1PK | "activity#user#" + username | +| GSI1SK | "activity#" + yyyy-MM-dd’T’HH:mm:ssZ + "#" + documentId | +| GSI2PK | "activity#" | +| GSI2SK | "activity#" + yyyy-MM-dd’T’HH:mm:ssZ + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| type | Type of User Activity (view, add, change, delete) | +| userId | Create by user | +| inserteddate | Inserted Date | + +## Document TagSchema + +The Document TagSchema entity and attributes. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "tagSchemas#" + documentId | +| SK | "schema#" | +| GSI1PK | "tagSchemas#" | +| GSI1SK | "ts#" + name + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| inserteddate | Inserted Date | +| userId | Create by user | +| name | Name of TagSchema | +| schema | TagSchema JSON document | + +## Document Shares + +The following are the entities related to sharing of Documents. + +### Shares + +A list of shares for a particular user role. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "shares#" + (group/user) + "#" + name | +| SK | "share#" + siteId + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| type | Type of Share (File or Directory) +| inserteddate | Inserted Date | +| userId | Create by user | +| path | Folder path | +| name | Name of share | +| siteId | SiteId share is part of | +| permissionType | Type of permission | +| permissions | List of permissions | + +### Document Share + +A list of shares for a particular user role. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "shares#" + documentId | +| SK | "share" | +| GSI1PK | "share#" + name; | +| GSI1SK | "share#" + path + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Share Idenifier | +| sharedDocumentId | Shared Document Id | +| name | Name of share | +| type | Type of Share (File or Directory) +| inserteddate | Inserted Date | +| userId | Create by user | +| path | Folder path | +| name | Name of share | +| siteId | SiteId share is part of | +| permissionType | Type of permission | +| permissions | List of permissions | + +### Document Folder + +Document folder / file listing index. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "global#folders#" + parentDocumentId | +| SK | "ff#" + path OR "fi#" + path | +| GSI1PK (folder only) | "folder#" + documentId | +| GSI1SK (folder only) | "folder" | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Share Idenifier | +| path | Folder path | +| type | Type of Share (File or Directory) +| parentDocumentId | Parent Document Id | +| inserteddate | Inserted Date | +| lastModifiedDate | Last Modified Date | +| userId | Create by user | + +### Queue + +Queue entity object. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "queues#" + this.documentId | +| SK | "queue" | +| GSI1PK | "queues#" | +| GSI1SK | "queue#" + name + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Share Idenifier | +| name | Name of Queue | + +## Workflows + +The following are the entities related to `Workflows`. + +### Workflow + +The workflow entity consists of attributes that capture essential information about a workflow. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "workflows#" + documentId | +| SK | "workflow" | +| GSI1PK | "workflows#" | +| GSI1SK | "workflow#" + name + "#" + documentId | +| GSI2PK | "workflows#" | +| GSI2SK | "workflow#" + status + "#" + name + "#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| name | Name of Workflow | +| inUse | Whether Workflow is in use | +| status | Workflow status | +| description | Workflow description | +| userId | Create by user | +| json | Workflow JSON blob | + +### Document Workflow + +The document workflow entity consists of attributes that capture essential information about a document in a workflow. + +#### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "wfdoc#" + documentId | +| SK | "wf#" + workflowId | +| GSI1PK | "wfdoc#" + documentId | +| GSI1SK | "wf#" + workflowName + "#" + workflowId | +| GSI2PK | "wf#" + workflowId | +| GSI2SK | "wfdoc#" + documentId | + +#### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| documentId | Document Idenifier | +| workflowId | Workflow identifier | +| workflowName | Workflow name | +| status | Workflow status | +| actionPk | Action PK | +| actionSk | Action SK | +| currentStepId | Current Workflow step Id | + +## API Keys + +Api Key(s) allow access to API. + +### Entity Key Schema + +| Attributes | Format | +| -------- | ------- | +| PK | "apikeys#" | +| SK | "apikey#" + apiKey | +| GSI1PK | siteId + "/apikeys#" | +| GSI1SK | "apikey#" + name + apiKey | +| GSI2PK | siteId/“apikeys#” | +| GSI2SK | “apikey#” + apiKey (mask) | + +### Entity Attributes + +| Attributes | Description | +| -------- | ------- | +| apiKey | API Key | +| name | API Key Name | +| userId | Create by user | +| siteId | Site Identifier +| permissions | List of API Key permissions (read/write/delete) | +| inserteddate | Inserted Date | \ No newline at end of file diff --git a/docs/platform/img/cognito-add-group.png b/docs/platform/img/cognito-add-group.png new file mode 100644 index 0000000..76f267e Binary files /dev/null and b/docs/platform/img/cognito-add-group.png differ diff --git a/docs/platform/img/cognito-create-group.png b/docs/platform/img/cognito-create-group.png new file mode 100644 index 0000000..ba91f8d Binary files /dev/null and b/docs/platform/img/cognito-create-group.png differ diff --git a/docs/platform/img/cognito-groups-list-finance.png b/docs/platform/img/cognito-groups-list-finance.png new file mode 100644 index 0000000..7ae545d Binary files /dev/null and b/docs/platform/img/cognito-groups-list-finance.png differ diff --git a/docs/platform/img/security-roles-examples.png b/docs/platform/img/security-roles-examples.png new file mode 100644 index 0000000..83aad38 Binary files /dev/null and b/docs/platform/img/security-roles-examples.png differ diff --git a/docs/tutorials/document-event-processing.md b/docs/tutorials/document-event-processing.md new file mode 100644 index 0000000..c02274f --- /dev/null +++ b/docs/tutorials/document-event-processing.md @@ -0,0 +1,400 @@ +--- +sidebar_position: 1 +--- + +# Document Event Processing + +FormKiQ's [document events](/docs/platform/overview#document-events) allow you to easily extend the document processing functionality in FormKiQ and to automatically perform tasks when documents are created, updated or deleted. + +This example will show how to create a serverless application that will listen for when a document is created and add custom tags to it. + +![Serverless Application Flow](./img/document-event-processing.png) + +We are going to build an application using the [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html). The AWS Serverless Application Model (AWS SAM) is an open source framework that you can use to build serverless applications on AWS. + +All code can be found in tutorials [GitHub repository](https://github.com/formkiq/tutorials/tree/master/java/document-events). + +## Prerequisite + +- Download and install [AWS CLI](https://aws.amazon.com/cli) +- Download and install [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) + +## Sam init + +Creating a SAM project is easy using the SAM CLI. In any directory, run the sam project initialization. +``` +sam init +``` + +This will initialize your SAM project. The SAM CLI will ask you a number of questions on how to configure your project. SAM provides a number of templates for different types of projects. This will help you to get up and running quickly. In general, you should pick all the options shown below (including leaving certain fields blank for the default values), though you may choose a different option in your project for **Which runtime would you like to use?**. This tutorial will be done in Java17, but you can adapt this tutorial easily for any language, so you can select the language you are most familiar with, especially if you choose to add your own custom functionality. + +``` +Which template source would you like to use? + 1 - AWS Quick Start Templates + 2 - Custom Template Location +Choice: 1 + +Choose an AWS Quick Start application template + 1 - Hello World Example + ... +Template: 1 + +Use the most popular runtime and package type? (Python and zip) [y/N]: +Choice: N + +Which runtime would you like to use? + 1 - aot.dotnet7 (provided.al2) + 2 - dotnet6 + 3 - go1.x + 4 - go (provided.al2) + 5 - graalvm.java11 (provided.al2) + 6 - graalvm.java17 (provided.al2) + 7 - java17 + ... +Runtime: 7 + +What package type would you like to use? + 1 - Zip (artifact is a zip uploaded to S3) + 2 - Image (artifact is an image uploaded to an ECR image repository) +Package type: 1 + +Which dependency manager would you like to use? + 1 - gradle + 2 - maven +Dependency manager: 1 + +Project name [sam-app]: document-events + + ----------------------- + Generating application: + ----------------------- + Name: document-events + Runtime: java17 + Dependency Manager: gradle + Application Template: hello-world +``` + +The `document-events` project has now been created. It is a basic project as it only contains a single [AWS Lambda](https://aws.amazon.com/lambda/) based on the **Quick Start:** template. + +## Java Update + +We will now update the Java Lambda code to process FormKiQ's document events that come through [Amazon SNS](https://aws.amazon.com/sns/). + +We need to update the `HelloWorldFunction/src/build.gradle` file and update the `repositories` to add the maven snapshots repository. + +``` +repositories { + mavenCentral() + maven { + url "https://oss.sonatype.org/content/repositories/snapshots/" + } +} +``` + +We also need to add 2 dependencies we will need as shown below. + +``` +dependencies { + ... + + implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1' + implementation group: 'com.formkiq', name: 'client', version:'1.13.0-SNAPSHOT' + + ... +} +``` + +Next, we will update the `HelloWorldFunction/src/main/java/helloworld/App.java` lambda function to process the document event SQS messages. + +Change +``` +public class App implements RequestHandler { +``` +to +``` +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; + +public class App implements RequestHandler { +``` + +Using the FormKiQ client library create a DocumentTagsApi instance which will allow us to use Java code to call the POST /documents/{documentId}/tags API endpoint. + +``` +import com.formkiq.client.api.DocumentTagsApi; +import com.formkiq.client.invoker.ApiClient; +import com.formkiq.client.invoker.ApiException; +import com.formkiq.client.model.AddDocumentTag; +import com.formkiq.client.model.AddDocumentTagsRequest; + +private DocumentTagsApi getDocumentTagsApi() { + // Environment Variable Defining the FormKiQ API URL + // that uses IAM authorization + String url = System.getenv("IAM_API_URL"); + + // Create API Client and set the signing credentials + ApiClient apiClient = new ApiClient().setReadTimeout(0).setBasePath(url); + apiClient.setAWS4Configuration(System.getenv("AWS_ACCESS_KEY_ID"), + System.getenv("AWS_SECRET_ACCESS_KEY"), System.getenv("AWS_SESSION_TOKEN"), + System.getenv("AWS_REGION"), "execute-api"); + + // Create FormKiQ DocumentTags API + return new DocumentTagsApi(apiClient); +} +``` + +Lastly, add update the handleRequest method to process SQS messages and add a new tag for every document that is created. + +``` +public Void handleRequest(final SQSEvent input, final Context context) { + + DocumentTagsApi documentTagsApi = getDocumentTagsApi(); + + // Loop through all the SQS Messages + for(SQSMessage msg : input.getRecords()){ + + String body = msg.getBody(); + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + Map bodyMap = gson.fromJson(body, Map.class); + Map documentEvent = gson.fromJson(bodyMap.get("Message"), Map.class); + + String siteId = documentEvent.get("siteId"); + String documentId = documentEvent.get("documentId"); + + context.getLogger().log("processing siteId: " + siteId + " documentId: " + documentId); + + AddDocumentTagsRequest req = new AddDocumentTagsRequest(); + req.addTagsItem(new AddDocumentTag().key("somekey").value("somevalue")); + + try { + documentTagsApi.addDocumentTags(documentId, req, siteId, null); + } catch (ApiException e) { + e.printStackTrace(); + } + } + + return null; +} +``` + +Finally, since we've rewrote the Lambda function the `AppTest.java` is no longer valid and can be removed. + +``` +rm HelloWorldFunction/src/test/java/helloworld/AppTest.java +``` + +## CloudFormation Update + +Next, we will update the [CloudFormation](https://aws.amazon.com/cloudformation/) contained in the `template.yaml` to setup the AWS infrastructure. + +We will: + +* Create a new SQS queue that will hold the messages the Lambda function will process + +* Connect the Lambda function to the SQS queue + +* Connect the SQS queue to the FormKiQ SNS Document Event topic + +Edit the `template.yaml` + +Below the `Globals:` element, add the following block which will require the FormKiQ a `AppEnvironment` parameter when we deploy this function. + +``` +Parameters: + + AppEnvironment: + Type: String + Description: Unique Application Environment Identifier, IE dev/staging/prod + AllowedPattern: "[a-zA-Z0-9_.-/]+" + Default: prod +``` + +Add the following block under the `Resources:` element which add a SQS queue and a policy that allows the SNS service to send messages to the queue. + +``` + ProcessorQueue: + Type: "AWS::SQS::Queue" + Properties: + VisibilityTimeout: 900 + ReceiveMessageWaitTimeSeconds: 20 + Tags: + - Key: "StackName" + Value: + Fn::Sub: "${AWS::StackName}" + + ProcessorQueuePolicy: + Type: AWS::SQS::QueuePolicy + DependsOn: + - ProcessorQueue + Properties: + PolicyDocument: + Version: '2012-10-17' + Id: QueuePolicy + Statement: + - Sid: snsSendMessagesToQueue + Effect: Allow + Principal: + Service: sns.amazonaws.com + Action: + - sqs:SendMessage + Resource: + Fn::GetAtt: + - ProcessorQueue + - Arn + Condition: + StringEquals: + aws:SourceAccount: + Ref: AWS::AccountId + Queues: + - Ref: ProcessorQueue +``` + +This next block, connects the SQS queue added above to the FormKiQ SNS Document Events topic. It uses the FilterPolicy to only accept document "create" events. + +``` + SnsDocumentsCreateSubscriptionSqs: + Type: AWS::SNS::Subscription + DependsOn: + - ProcessorQueue + Properties: + Protocol: sqs + Endpoint: + Fn::GetAtt: + - ProcessorQueue + - Arn + TopicArn: + Fn::Sub: '{{resolve:ssm:/formkiq/${AppEnvironment}/sns/DocumentEventArn}}' + FilterPolicy: '{"type": ["create"]}' +``` + +Next, replace the `HelloWorldFunction:` element with the block below. We need to add an environment variable and connect the SQS queue to the Lambda function. We also will add the `AmazonAPIGatewayInvokeFullAccess` policy to the function which will allow it to call the FormKiQ API. + +``` + HelloWorldFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: HelloWorldFunction + Handler: helloworld.App::handleRequest + Runtime: java17 + Architectures: + - x86_64 + MemorySize: 512 + Policies: + - AmazonAPIGatewayInvokeFullAccess + Environment: + Variables: + IAM_API_URL: + Fn::Sub: '{{resolve:ssm:/formkiq/${AppEnvironment}/api/DocumentsIamUrl}}' + Events: + CreateSQSEvent: + Type: SQS + Properties: + Queue: + Fn::GetAtt: + - ProcessorQueue + - Arn + BatchSize: 1 +``` + +Finally remove the `HelloWorldApi:` block under the `Outputs:` as it is no longer needed with our changes. + +## Sam Build + +Now that the SAM project has been updated, let's try deploy it to AWS. This step assumes you have configured your AWS CLI with an `Access key ID` and `Secret access key`. Instructions for configuring can be found [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). We are also assuming you have access to deploy SAM projects as well, which is expected unless you are working within an organization that has various roles within AWS. + +Before you can deploy a SAM project to AWS, you need to first build the project. You can do this by running the following command in the project directory: +``` +sam build +``` + +Building the sam project will generate the following output: +``` +Building codeuri: . runtime: nodejs12.x metadata: {} functions: ['SNSPayloadLogger'] +... + +Build Succeeded + +Built Artifacts : .aws-sam/build +Built Template : .aws-sam/build/template.yaml + +Commands you can use next +========================= +[*] Invoke Function: sam local invoke +[*] Deploy: sam deploy --guided +``` + +## Sam Deploy + +Now that the project has been built successfully, the project can be deployed using the following command: +``` +sam deploy --guided +``` + +Running this deploy command will ask a number of deployment questions. Use the defaults, as shown below, as a guided response. + +:::note +Make sure you pick the same `AWS Region` and `Parameter AppEnvironment` to match your FormKiQ installation. +::: + +``` +Configuring SAM deploy +====================== + + Setting default arguments for 'sam deploy' + ========================================= + Stack Name [document-events]: + AWS Region [us-east-1]: + Parameter AppEnvironment [prod]: + #Shows you resources changes to be deployed and require a 'Y' to initiate deploy + Confirm changes before deploy [Y/n]: + #SAM needs permission to be able to create roles to connect to the resources in your template + Allow SAM CLI IAM role creation [Y/n]: + #Preserves the state of previously provisioned resources when an operation fails + Disable rollback [y/N]: + Save arguments to configuration file [Y/n]: + SAM configuration file [samconfig.toml]: + SAM configuration environment [default]: + +Initiating deployment +===================== +... + +CloudFormation events from changeset +----------------------------------------------------------------------------------------------------------------- +ResourceStatus ResourceType LogicalResourceId ResourceStatusReason +----------------------------------------------------------------------------------------------------------------- +CREATE_IN_PROGRESS AWS::SNS::Topic SimpleTopic - +... +CREATE_COMPLETE AWS::CloudFormation::Stack sam-app - +----------------------------------------------------------------------------------------------------------------- + +Successfully created/updated stack - document-events in us-east-1 +``` + +## Test Integration + +To test the integration of the Lambda function with FormKiQ document events. Log into the FormKiQ console. + +![FormKiQ Console](./img/document-events-console.png) + +Upload a new document. + +![FormKiQ Console Document Upload](./img/document-events-console-add-document.png) + +Once the document has been uploaded, select the Add/edit metadata button. + +![FormKiQ Console Document Upload](./img/document-events-console-edit-metadata.png) + +When viewing the document's metadata, you should see the `somekey` tag. + +![FormKiQ Console Document Upload](./img/document-events-console-view-metadata.png) + +## Summary + +And there you have it! We have shown how easy it is to add custom document processing using FormKiQ's Document Events. + +This is just the tip of the iceberg when it comes to working with the FormKiQ APIs. + +If you have any questions, reach out to us on our https://github.com/formkiq/formkiq-core or https://formkiq.com. diff --git a/docs/tutorials/formkiq-document-api-with-zapier.md b/docs/tutorials/formkiq-document-api-with-zapier.md index fe264bf..045ff1d 100644 --- a/docs/tutorials/formkiq-document-api-with-zapier.md +++ b/docs/tutorials/formkiq-document-api-with-zapier.md @@ -1,8 +1,8 @@ --- -sidebar_position: 1 +sidebar_position: 2 --- -# Using FormKiQ Document API with Zapier +# Zapier Integration This tutorial will take you through how to use the FormKiQ Webhook API with https://zapier.com. diff --git a/docs/tutorials/formkiq-plugin.md b/docs/tutorials/formkiq-plugin.md deleted file mode 100644 index 0c223d5..0000000 --- a/docs/tutorials/formkiq-plugin.md +++ /dev/null @@ -1,312 +0,0 @@ ---- -sidebar_position: 3 ---- - -# FormKiQ Document Events - -FormKiQ is built to be extended and customized to be whatever you want it to be. Using FormKiQ's [Document Events](/docs/platform/overview#document-events) makes it really easy to automatically perform tasks when documents are created, updated or deleted. - -Our example will show how you can quickly and easily create a serverless application that will install FormKiQ and add a Lambda that will listen for when a document is added, updated, or removed via Amazon Simple Notification Service (SNS). - -![Serverless Application Flow](./img/SAM-CLI-with-FormKiQ-Document-Event.png) - -We are going to build this plugin using the [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html). The AWS Serverless Application Model (AWS SAM) is an open source framework that you can use to build serverless applications on AWS. Using AWS SAM isn't a requirement for creating a plugin; you can use anything as long as it can subscribe to the document event's [AWS SNS Topic](https://docs.aws.amazon.com/sns/). AWS provides a ton of [developer documentation](https://docs.aws.amazon.com/sns/latest/dg/index.html), and it's really easy to integrate this into your existing application. - -All code can be found in [GitHub repository](https://github.com/formkiq/formkiq-core-sam-app). - -## Requirements - -- Download and install [AWS CLI](https://aws.amazon.com/cli) -- Download and install [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) - -## Create New Project - -Creating a SAM project is easy using the SAM CLI. In any directory, run the sam project initialization. -``` -sam init -``` - -This will initialize your SAM project. The SAM CLI will ask you a number of questions on how to configure your project. SAM provides a number of templates for different types of projects. This will help you to get up and running quickly. In general, you should pick all the options shown below (including leaving certain fields blank for the default values), though you may choose a different option in your project for **Which runtime would you like to use?**. This tutorial will be done in NodeJS, but you can adapt this tutorial easily for any language, so you can select the language you are most familiar with, especially if you choose to add your own custom functionality once we're done. Because we are connecting this project to FormKiQ's document event SNS topic, it's important to use the **Quick Start: SNS** template. - -``` -Which template source would you like to use? - 1 - AWS Quick Start Templates - 2 - Custom Template Location -Choice: 1 -What package type would you like to use? - 1 - Zip (artifact is a zip uploaded to S3) - 2 - Image (artifact is an image uploaded to an ECR image repository) -Package type: 1 - -Which runtime would you like to use? - 1 - nodejs12.x - 2 - python3.8 - 3 - ruby2.7 - 4 - go1.x - 5 - java11 - 6 - dotnetcore3.1 - 7 - nodejs10.x - 8 - python3.7 - 9 - python3.6 - 10 - python2.7 - 11 - ruby2.5 - 12 - java8.al2 - 13 - java8 - 14 - dotnetcore2.1 -Runtime: 1 - -Project name [sam-app]: - -Cloning app templates from https://github.com/aws/aws-sam-cli-app-templates - -AWS quick start application templates: - 1 - Hello World Example - 2 - Step Functions Sample App (Stock Trader) - 3 - Quick Start: From Scratch - 4 - Quick Start: Scheduled Events - 5 - Quick Start: S3 - 6 - Quick Start: SNS - 7 - Quick Start: SQS - 8 - Quick Start: Web Backend -Template selection: 6 - - ----------------------- - Generating application: - ----------------------- - Name: sam-app - Runtime: nodejs12.x - Dependency Manager: npm - Application Template: quick-start-sns - Output Directory: . - - Next steps can be found in the README file at ./sam-app/README.md -``` - -The `sam-app` project has now been created. It is a basic project as it only contains a single [AWS Lambda](https://aws.amazon.com/lambda/) based on the **Quick Start: SNS** template. This lambda function will execute when it receives a message from an SNS topic and will print out the SNS message. - -## Building and Deploying - -Now that the SAM project has been created, let's try deploy it to AWS. This step assumes you have configured your AWS CLI with an `Access key ID` and `Secret access key`. Instructions for configuring can be found [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). We are also assuming you have access to deploy SAM projects as well, which is expected unless you are working within an organization that has various roles within AWS. - -Before you can deploy a SAM project to AWS, you need to first build the project. You can do this by running the following command in the project directory: -``` -sam build -``` - -Building the sam project will generate the following output: -``` -Building codeuri: . runtime: nodejs12.x metadata: {} functions: ['SNSPayloadLogger'] -... - -Build Succeeded - -Built Artifacts : .aws-sam/build -Built Template : .aws-sam/build/template.yaml - -Commands you can use next -========================= -[*] Invoke Function: sam local invoke -[*] Deploy: sam deploy --guided -``` - -Now that the project has been built successfully, the project can be deployed using the following command: -``` -sam deploy --guided -``` - -Running this deploy command will ask a number of deployment questions. Use the defaults, as shown below, as a guided response. -``` -Configuring SAM deploy -====================== - - Looking for config file [samconfig.toml] : Not found - - Setting default arguments for 'sam deploy' - ========================================= - Stack Name [sam-app]: - AWS Region [us-east-1]: - #Shows you resources changes to be deployed and require a 'Y' to initiate deploy - Confirm changes before deploy [y/N]: - #SAM needs permission to be able to create roles to connect to the resources in your template - Allow SAM CLI IAM role creation [Y/n]: - Save arguments to configuration file [Y/n]: - SAM configuration file [samconfig.toml]: - SAM configuration environment [default]: - - Looking for resources needed for deployment: Found! - - Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-1bskr8g39amsn - A different default S3 bucket can be set in samconfig.toml - - Saved arguments to config file - Running 'sam deploy' for future deployments will use the parameters saved above. - The above parameters can be changed by modifying samconfig.toml - Learn more about samconfig.toml syntax at - https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html - -Uploading to sam-app/6f21042ca6c0c6260c7cba7403387aa8 8724 / 8724.0 (100.00%) - - Deploying with following values - =============================== - Stack name : sam-app - Region : us-east-1 - Confirm changeset : False - Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1bskr8g39amsn - Capabilities : ["CAPABILITY_IAM"] - Parameter overrides : {} - Signing Profiles : {} - -Initiating deployment -===================== -... - -CloudFormation events from changeset ------------------------------------------------------------------------------------------------------------------ -ResourceStatus ResourceType LogicalResourceId ResourceStatusReason ------------------------------------------------------------------------------------------------------------------ -CREATE_IN_PROGRESS AWS::SNS::Topic SimpleTopic - -... -CREATE_COMPLETE AWS::CloudFormation::Stack sam-app - ------------------------------------------------------------------------------------------------------------------ - -Successfully created/updated stack - sam-app in us-east-1 -``` - -## Add FormKiQ to Project - -Now that `sam-app` has been successfully deployed, let's add FormKiQ to the project. - -1. download the latest version of formkiq-core-X.X.X.zip from https://github.com/formkiq/formkiq-core/releases -2. unzip formkiq-core-x.x.x.zip into a directory named `formkiq-core`, under the `sam-app` project folder; this name and location, `./sam-app/formkiq-core` needs to be exact for our SAM project to find the files it needs - -Inside the `sam-app` project folder, you'll find the template.yml file. This file is used by SAM to deploy resources to your AWS account. If you look inside the template.yml file, you'll see that there are two resources currently deployed, a Lambda function and an SNS topic. We are going to add FormKiQ as a resource, and then change the SNS topic used by default to the Document Event SNS topic that is triggered by FormKiQ. - -First, edit the `template.yml` file and replace the following `SimpleTopic` block: - -``` - SimpleTopic: - Type: AWS::SNS::Topic -``` - -with the FormKiQ resource block show below: - -``` - FormKiQ: - Type: AWS::Serverless::Application - Properties: - Location: formkiq-core/template.yaml - Parameters: - AdminEmail: -``` - -be sure to replace with your email address), and make sure the indentation is the same. This block will import the template.yaml file that comes with FormKiQ, which was added to the `sam-app` project when you extracted the `formkiq-core-X.X.X.zip` into the `formkiq-core` folder inside your project. - -Next, adjust the Lambda function instructions to use FormKiQ's Document Event SNS topic, instead of SimpleTopic: - -``` - Topic: !Ref SimpleTopic -``` -changes to: -``` - Topic: !GetAtt FormKiQ.Outputs.SnsDocumentEventArn -``` - -The next change we need is to make sure that the FormKiQ resource is created *before* our lambda; if not, SAM will try and attach the Lambda function to the SNS topic before the topic has been created. We can set the order by adding a `DependsOn` block to the Lambda function as shown below, within the `SNSPayloadLogger` block: -``` - SNSPayloadLogger: - Type: AWS::Serverless::Function - DependsOn: FormKiQ -``` - -The last change we need to make in the template file is a way of retrieving the FormKiQ API URL we'll need for testing our plugin. The easiest way to get that URL is by adding an `Outputs` at the bottom of the template.yml file. At the bottom of the file, add the following: -``` -Outputs: - HttpApiUrl: - Description: "The URL for the API endpoint that uses Cognito authorization" - Value: !GetAtt FormKiQ.Outputs.HttpApiUrl -``` - -Now that the template.yml has been updated, the project needs to be built again by running this command: -``` -sam build -``` - -Once the build has completed successfully, we can deploy the changes to AWS: - -``` -sam deploy --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND CAPABILITY_NAMED_IAM -``` - -Now FormKiQ has been added to the project, and the Lambda has been connected to receive all document events. Now we are ready to test it. - -## Test Plugin - -To test the integration of the Lambda function with FormKiQ, our first step is to create a document using the FormKiQ API. We will then be able to look at the Lambda logs to see the Document Event executing in our Lambda. - -In order to call the FormKiQ API, we first need to retrieve the API URL. Since the API URL was added to the Outputs of the `template.yml` file, running the following command will display the configuration information of the `sam-app` project, and within that you will see the FormKiQ API URL under the `HttpApiUrl` key. - -``` -aws cloudformation describe-stacks --stack-name sam-app --region us-east-1 -``` - -This should return the following: -``` -{ - "Stacks": [ - { - "StackName": "sam-app", - ... - "Outputs": [ - { - "OutputKey": "HttpApiUrl", - "OutputValue": "https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com", - "Description": "The URL for the API endpoint that uses Cognito authorization" - } - ] - } - ] -} -``` - -As you can see, the FormKiQ API URL is something like https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com; using the URL from the output along with the `curl` command, we can use FormKiQ's `/public/documents` API to create a JSON document: - -``` -curl -X POST -H "Content-Type: application/json" \ --d '{ "content":"{\"name\":\"John Smith\"}"}' \ -"https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/public/documents" -``` - -You should receive a response that contains the `documentId` of the document that was created, much like this: -``` -{"documentId":"52b1ce4b-3ae7-4b3c-8a9e-4f6451293a7e"} -``` - -Now that the document has been added, we need to verify that the Lambda function received the Document Event message. Using the SAM CLI, you can easily see the logs produced by the Lambda function, using the following command: -``` -sam logs -n SNSPayloadLogger --stack-name sam-app --region us-east-1 -``` - -You should see information similar to this: - -``` -[...] -INFO {"Records":[{"EventSource":"aws:sns","EventVersion":"1.0","EventSubscriptionArn":"arn:aws:sns:us-east-1:622653865277:sam-app-FormKiQ-VFZO4JRVW32O-CoreStorage-15CU1GQ019S6X-SnsDocumentEvent-GJB32BVSTTCP:4052fb08-1a84-4c08-aa3c-5de11ac80848","Sns":{"Type":"Notification","MessageId":"cf14f4ee-5f25-5be2-bb95-ac62191ea4bc","TopicArn":"arn:aws:sns:us-east-1:622653865277:sam-app-FormKiQ-VFZO4JRVW32O-CoreStorage-15CU1GQ019S6X-SnsDocumentEvent-GJB32BVSTTCP","Subject":null,"Message":"{\"siteId\":\"default\",\"documentId\":\"52b1ce4b-3ae7-4b3c-8a9e-4f6451293a7e\",\"s3key\":\"52b1ce4b-3ae7-4b3c-8a9e-4f6451293a7e\",\"s3bucket\":\"formkiq-core-prod-documents-622653865277\",\"type\":\"create\",\"userId\":\"public\",\"content\":\"{\\\"name\\\":\\\"John Smith\\\"}\"}","Timestamp":"2021-01-28T04:56:27.825Z","SignatureVersion":"1","Signature":"NL6asm/0AVxW7fMarzrfoJBbTKww7evZRNnIpigeKGMGRnyjm4UQmMw+ZntudE+VXRjSEhB6DTElT/6rz0/Io4O3aVN9TieoaiEBePThSq939mhrlBQ4Ns84Zqvq/kF3mLHSKJNk676uI1dt4lgVQsRvjPmgWGTeAlxCHBk8f9f38W5MIT0CgP5y+DyMihGtZcK0h474giBmThV3DpbJpgjetgtQuRGsOmfign9KYeGOzjiMqufgoAzoYL7nC7IZFWUZkgbQ2kxJAo0QUyE69z5pFY2BfZCXKY6V9imKwm9kgyDj+padKS6ToMZ5ipt6y5btkT8aDWaoSivO8zcrzA==","SigningCertUrl":"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem","UnsubscribeUrl":"https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:622653865277:sam-app-FormKiQ-VFZO4JRVW32O-CoreStorage-15CU1GQ019S6X-SnsDocumentEvent-GJB32BVSTTCP:4052fb08-1a84-4c08-aa3c-5de11ac80848","MessageAttributes":{"siteId":{"Type":"String","Value":"default"},"type":{"Type":"String","Value":"create"},"userId":{"Type":"String","Value":"public"}}}}]}` -[...] -``` - -Extracting the `Message` payload you can see the document event information: -``` -{ - "siteId": "default", - "documentId": "52b1ce4b-3ae7-4b3c-8a9e-4f6451293a7e", - "s3key": "52b1ce4b-3ae7-4b3c-8a9e-4f6451293a7e", - "s3bucket": "formkiq-core-prod-documents-622653865277", - "type": "create", - "userId": "public", - "content": "{\"name\":\"John Smith\"}" -} -``` - -From the Message object, you can see that this was a *create* type of message and you can see the documentId along with the contents of the message we sent. Our sample plugin simply logs the receipt of the message, but you have full control over what your Lambda can do. For instance, you can take that information and POST it to a third-party webhook, sending the data to one or more downstream applications. You could also take the content of the message and send it to another service within AWS. - -With SAM CLI's easy-to-use process and FormKiQ's robust document management, the only limitation for custom workflows and integrations is your imagination! \ No newline at end of file diff --git a/docs/tutorials/img/document-event-processing.png b/docs/tutorials/img/document-event-processing.png new file mode 100644 index 0000000..177bf6f Binary files /dev/null and b/docs/tutorials/img/document-event-processing.png differ diff --git a/docs/tutorials/img/document-events-console-add-document.png b/docs/tutorials/img/document-events-console-add-document.png new file mode 100644 index 0000000..c158f94 Binary files /dev/null and b/docs/tutorials/img/document-events-console-add-document.png differ diff --git a/docs/tutorials/img/document-events-console-edit-metadata.png b/docs/tutorials/img/document-events-console-edit-metadata.png new file mode 100644 index 0000000..f05cb75 Binary files /dev/null and b/docs/tutorials/img/document-events-console-edit-metadata.png differ diff --git a/docs/tutorials/img/document-events-console-view-metadata.png b/docs/tutorials/img/document-events-console-view-metadata.png new file mode 100644 index 0000000..2b1acf0 Binary files /dev/null and b/docs/tutorials/img/document-events-console-view-metadata.png differ diff --git a/docs/tutorials/img/document-events-console.png b/docs/tutorials/img/document-events-console.png new file mode 100644 index 0000000..e394436 Binary files /dev/null and b/docs/tutorials/img/document-events-console.png differ diff --git a/docs/tutorials/multitenant.md b/docs/tutorials/multitenant.md index 559b79f..2207a3e 100644 --- a/docs/tutorials/multitenant.md +++ b/docs/tutorials/multitenant.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 --- # Multi-Tenant Users diff --git a/docs/tutorials/using-a-server-side-proxy.md b/docs/tutorials/using-a-server-side-proxy.md index df5433c..37ee8c7 100644 --- a/docs/tutorials/using-a-server-side-proxy.md +++ b/docs/tutorials/using-a-server-side-proxy.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 4 --- # Using a Server-Side Proxy