├── .dockerignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── config.yml ├── dependabot.yml └── workflows │ ├── main.yml │ └── manual.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── README.md ├── examples ├── .gitignore └── docker-compose.yml └── install ├── app ├── client │ └── dist │ │ └── config-dist.js ├── config │ └── custom-environment-variables.json ├── install.js └── server.js ├── assets ├── functions │ └── 10-formio-api └── templates │ ├── config.template.js │ └── project.default.json └── etc ├── cont-init.d └── 10-formio-api └── services.available └── 10-formio-api └── run /.dockerignore: -------------------------------------------------------------------------------- 1 | examples/ 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [tiredofit] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: If something isn't working right.. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Summary 11 | 12 | 13 | 14 | 15 | ### Steps to reproduce 16 | 17 | 18 | 19 | 20 | ### What is the expected *correct* behavior? 21 | 22 | 23 | 24 | 25 | ### Relevant logs and/or screenshots 26 | 27 | 28 | 29 | ### Environment 30 | 31 | 32 | - Image version / tag: 33 | - Host OS: 34 | 35 |
36 | Any logs | docker-compose.yml 37 |
38 | 39 | 40 | 41 | ### Possible fixes 42 | 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea or feature 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | --- 11 | name: Feature Request 12 | about: Suggest an idea for this project 13 | 14 | --- 15 | 16 | **Description of the feature** 17 | 18 | 19 | **Benftits of feature** 20 | 21 | 22 | **Additional context** 23 | 24 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: "build_image" 2 | 3 | on: 4 | push: 5 | paths: 6 | - "**" 7 | - "!README.md" 8 | 9 | jobs: 10 | build: 11 | uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 12 | #uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 13 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_armv7_arm64.yml@main 14 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_arm64.yml@main 15 | secrets: inherit 16 | -------------------------------------------------------------------------------- /.github/workflows/manual.yml: -------------------------------------------------------------------------------- 1 | name: "manual_build_image" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | Manual Build: 7 | description: 'Manual Build' 8 | required: false 9 | 10 | jobs: 11 | build: 12 | uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 13 | #uses: tiredofit/github_actions/.github/workflows/default_amd64.yml@main 14 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_armv7_arm64.yml@main 15 | #uses: tiredofit/github_actions/.github/workflows/default_amd64_arm64.yml@main 16 | secrets: inherit 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.7.2 2022-05-24 2 | 3 | ### Added 4 | - Alpine 3.16 base 5 | 6 | ### Changed 7 | - FormIO 2.4.1 8 | 9 | 10 | ## 1.7.1 2022-04-05 11 | 12 | ### Changed 13 | - Switch to packaged node 14 | - Add sendgrid module 15 | 16 | 17 | ## 1.7.0 2022-04-05 18 | 19 | ### Added 20 | - FormIO 2.4.0 21 | 22 | 23 | ## 1.6.1 2020-09-12 24 | 25 | ### Added 26 | - Use Python3 when building 27 | - FormIO 1.9.0.9 28 | 29 | 30 | ## 1.6.0 2020-07-02 31 | 32 | ### Added 33 | - Formio 1.87.0 34 | 35 | ### Changed 36 | - Cleanup as per bash shellcheck 37 | 38 | 39 | ## 1.5.8 2020-06-15 40 | 41 | ### Added 42 | - Formio API 1.8.5 43 | 44 | 45 | ## 1.5.7 2020-05-26 46 | 47 | ### Added 48 | - FormIO 1.79.0 49 | - Added FORMIO_MANAGER_HOST 50 | - Fixed Client application URL mangling upstream 51 | - Moved Env vars to functions file 52 | 53 | ## 1.5.6 2020-05-01 54 | 55 | ### Added 56 | - FormIO API 1.76.0 57 | 58 | 59 | ## 1.5.5 2020-03-04 60 | 61 | ### Changed 62 | - Remove last trace of nginx logration scripts 63 | 64 | 65 | ## 1.5.4 2020-02-12 66 | 67 | ### Added 68 | - FormIO 1.63.10 69 | 70 | 71 | ## 1.5.3 2020-01-29 72 | 73 | ### Added 74 | - FormIO API 1.63.9 75 | 76 | 77 | ## 1.5.2 2020-01-10 78 | 79 | ### Added 80 | - FormIO 1.63.7 81 | 82 | 83 | ## 1.5.1 2020-01-02 84 | 85 | ### Changed 86 | - Additional changes to support new tiredofit/alpine base image 87 | 88 | 89 | ## 1.5.0 2019-12-29 90 | 91 | ### Added 92 | - Support for new tiredofit/alpine base image 93 | 94 | ## 1.4.4 2019-12-11 95 | 96 | ### Added 97 | - FormIO API 1.63.2 98 | 99 | 100 | ## 1.4.3 2019-12-09 101 | 102 | ### Added 103 | - FormIO API 1.62.0 104 | 105 | 106 | ## 1.4.2 2019-12-05 107 | 108 | ### Added 109 | - FormIO API Version 1.61.0 110 | 111 | 112 | ## 1.4.1 2019-11-18 113 | 114 | ### Added 115 | - FormIO 1.60.8 116 | 117 | 118 | ## 1.4.0 2019-11-12 Dave Conroy 119 | 120 | * FormIO 1.60.7 121 | * Node 13 122 | 123 | ## 1.3.5 2019-10-31 Dave Conroy 124 | 125 | * FormIO 1.60.6 126 | 127 | ## 1.3.4 2019-10-29 Dave Conroy 128 | 129 | * FormIO 1.60.5 130 | 131 | ## 1.3.3 2019-10-21 Dave Conroy 132 | 133 | * FormIO 1.60.3 134 | 135 | ## 1.3.2 2019-10-08 Dave Conroy 136 | 137 | * FormIO 1.60.2 138 | 139 | ## 1.3.1 2019-09-25 Dave Conroy 140 | 141 | * FormIO 1.60.0 142 | 143 | ## 1.3 2019-09-21 Dave Conroy 144 | 145 | * FormIO 1.59.0 146 | * Remove Nginx Option 147 | 148 | ## 1.2.15 2019-09-13 Dave Conroy 149 | 150 | * FormIO 1.58.0 151 | 152 | ## 1.2.14 2019-09-10 Dave Conroy 153 | 154 | * FormIO 1.57.0 155 | 156 | ## 1.2.13 2019-09-10 Dave Conroy 157 | 158 | * FormIO 1.56.0 159 | 160 | ## 1.2.12 2019-09-09 Dave Conroy 161 | 162 | * FormIO 1.55.0 163 | 164 | ## 1.2.11 2019-08-31 Dave Conroy 165 | 166 | * FormIO 1.52.0 167 | 168 | ## 1.2.10 2019-08-28 Dave Conroy 169 | 170 | * FormIO 1.50.0 171 | 172 | ## 1.2.9 2019-08-14 Dave Conroy 173 | 174 | * FormIO 1.49.0 175 | 176 | ## 1.2.8 2019-07-22 Dave Conroy 177 | 178 | * FormIO 1.48.2 179 | 180 | ## 1.2.7 2019-05-21 Dave Conroy 181 | 182 | * FormIO 1.46.0 183 | 184 | ## 1.2.6 2019-04-25 Dave Conroy 185 | 186 | * FormIO 1.45.0 187 | * NodeJS 12 188 | 189 | ## 1.2.5 2019-04-12 Dave Conroy 190 | 191 | * FormIO 1.44.6 192 | 193 | ## 1.2.4 2019-04-04 Dave Conroy 194 | 195 | * FormIO 1.44.1 196 | 197 | ## 1.2.3 2019-03-25 Dave Conroy 198 | 199 | * FormIO 1.43.1 200 | 201 | ## 1.2.2 2019-03-24 Dave Conroy 202 | 203 | * FormIO 1.43.0 204 | 205 | ## 1.2.1 2019-02-21 Dave Conroy 206 | 207 | * FormIO 1.41.3 208 | 209 | ## 1.2.0 2019-02-15 Dave Conroy 210 | 211 | * Add `ENABLE_NGINX` option to let nginx serve API to assist with CORS issues 212 | * Image size cleanup 213 | 214 | ## 1.1.7 2019-02-13 Dave Conroy 215 | 216 | * FormIO 1.41.0 217 | 218 | ## 1.1.6 2019-02-08 Dave Conroy 219 | 220 | * Use NodeJS 11 221 | 222 | ## 1.1.5 2019-01-25 Dave Conroy 223 | 224 | * Bump to Formio 1.40.0 225 | 226 | ## 1.1.4 2019-01-07 Dave Conroy 227 | 228 | * Update to Formio 1.38.0 229 | 230 | ## 1.1.3 2018-12-03 Dave Conroy 231 | 232 | * Update to FormIO 1.37.6 233 | 234 | ## 1.1.2 2018-12-03 Dave Conroy 235 | 236 | * Update to FormIO 1.37.5 237 | 238 | ## 1.1.1 2018-10-07 Dave Conroy 239 | 240 | * Update to FormIO 1.35.0 241 | 242 | ## 1.1 2018-09-03 Dave Conroy 243 | 244 | * Add versioning support for API and builder 245 | * Cleanup Startup Scripts (Waiting for Mongo) 246 | 247 | ## 1.0 2018-08-21 Dave Conroy 248 | 249 | * Switch to Alpine base 250 | * NodeJS 10 251 | 252 | ## 0.5 2017-12-01 Dave Conroy 253 | 254 | * Switched to Debian Stretch as base 255 | * NodeJS 9.2 256 | * Now only installs API and Frontend (No additional applications) 257 | * Reverse Proxy Works 258 | 259 | ## 0.4 2017-09-09 Dave Conroy 260 | 261 | * Update README.md 262 | * Further Refinements for automated install 263 | * Changed Install to occur on first boot instead of in Dockerfile for data persistence 264 | 265 | ## 0.3 2017-09-09 Dave Conroy 266 | 267 | * Automated Installation Routine 268 | * Added Nginx Reverse Proxy 269 | 270 | ## 0.2 2017-09-07 Dave Conroy 271 | 272 | * Environment Variable Settings Addition 273 | 274 | ## 0.1 2017-09-07 Dave Conroy 275 | 276 | * Initial Release 277 | * Alpine Edge 278 | 279 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/tiredofit/alpine:3.16 2 | LABEL maintainer="Dave Conroy (github.com/tiredofit)" 3 | 4 | ### Set Defaults 5 | ENV FORMIO_VERSION=v2.4.1 \ 6 | FORMIO_CLIENT_VERSION=master \ 7 | CONTAINER_ENABLE_MESSAGING=FALSE \ 8 | CONTAINER_ENABLE_SCHEDULING=FALSE \ 9 | CONTAINER_NAME=formio-api-app 10 | 11 | ### Install Runtime Dependencies 12 | RUN set -x && \ 13 | sed -i "/www-data/d" /etc/group* && \ 14 | addgroup -S -g 82 www-data && \ 15 | adduser -D -S -h /app -s /sbin/nologin -G www-data -g "Node" -u 3000 nodejs && \ 16 | apk update && \ 17 | apk upgrade && \ 18 | apk add -t .formio-build-deps \ 19 | git \ 20 | g++ \ 21 | make \ 22 | python3 \ 23 | && \ 24 | apk add -t .formio-run-deps \ 25 | nodejs \ 26 | npm \ 27 | yarn \ 28 | && \ 29 | \ 30 | sudo -u nodejs git clone -b $FORMIO_VERSION https://github.com/formio/formio.git /app/ && \ 31 | sudo -u nodejs git clone -b $FORMIO_CLIENT_VERSION https://github.com/formio/formio-app-formio.git /app/client && \ 32 | \ 33 | cd /app && \ 34 | sudo -u nodejs npm install && \ 35 | sudo -u nodejs npm install sendgrid && \ 36 | \ 37 | ### Misc & Cleanup 38 | mkdir -p /app/templates && \ 39 | chown -R nodejs. /app && \ 40 | apk del .formio-build-deps && \ 41 | rm -rf /tmp/* /var/cache/apk/* 42 | 43 | WORKDIR /app/ 44 | 45 | ### Networking Configuration 46 | EXPOSE 3001 47 | 48 | ### Add Files 49 | COPY install / 50 | 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Dave Conroy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # github.com/tiredofit/docker-formio-api 2 | 3 | [![Docker Pulls](https://img.shields.io/docker/pulls/tiredofit/formio-api.svg)](https://hub.docker.com/r/tiredofit/formio-api) 4 | [![Docker Stars](https://img.shields.io/docker/stars/tiredofit/formio-api.svg)](https://hub.docker.com/r/tiredofit/formio-api) 5 | 6 | ## About 7 | 8 | This will build a container for [Formio API Server](https://www.form.io/) A form server based on NodeJS. 9 | 10 | This Container uses customized [Alpine](https://hub.docker.com/r/tiredofit/alpine) as a base image along with NodeJS 14. 11 | 12 | [Changelog](CHANGELOG.md) 13 | 14 | ## Maintainer 15 | 16 | - [Dave Conroy](https://github.com/tiredofit) 17 | 18 | ## Table of Contents 19 | 20 | - [Introduction](#introduction) 21 | - [Authors](#authors) 22 | - [Table of Contents](#table-of-contents) 23 | - [Prerequisites](#prerequisites) 24 | - [Installation](#installation) 25 | - [Quick Start](#quick-start) 26 | - [Configuration](#configuration) 27 | - [Persistent Storage](#persistent-storage) 28 | - [Environment Variables](#environment-variables) 29 | - [Mail Options](#mail-options) 30 | - [Networking](#networking) 31 | - [Maintenance](#maintenance) 32 | - [Shell Access](#shell-access) 33 | - [References](#references) 34 | 35 | ## Prerequisites and Assumptions 36 | 37 | - This image assumes that you are using a reverse proxy such as [jwilder/nginx-proxy](https://github.com/jwilder/nginx-proxy) and 38 | optionally the [Let's Encrypt Proxy Companion @ 39 | https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) in 40 | order to serve your pages. However, it will run just fine on it's own if you map appropriate ports. 41 | 42 | - You must use have an seperate MongoDB container instance setup for storage of data before running this container on its own. 43 | 44 | ## Installation 45 | 46 | Automated builds of the image are available on [Docker Hub](https://hub.docker.com/r/tiredofit/formio-api) and is the 47 | recommended method of installation. 48 | 49 | 50 | ```bash 51 | docker pull docker.io/tiredofit/formio-api 52 | ``` 53 | 54 | ### Quick Start 55 | 56 | * The quickest way to get started is using [docker-compose](https://docs.docker.com/compose/). See the examples folder for a working 57 | [docker-compose.yml](examples/docker-compose.yml) that can be modified for development or production use. 58 | 59 | * Set various [environment variables](#environment-variables) to understand the capabilities of this image. 60 | * Map [persistent storage](#data-volumes) for access to configuration and data files for backup. 61 | 62 | Once started, visit your defined hostname or IP Address and port and login using the values provided in the `ROOT_EMAIL` and 63 | `ROOT_PASS` variables below. 64 | 65 | 66 | ## Configuration 67 | 68 | ### Persistent Storage 69 | 70 | 71 | | Parameter | Description | 72 | | ---------------- | ---------------------------------------------- | 73 | | `/app/templates` | Drop your exported Form.IO json templates here | 74 | 75 | ### Environment Variables 76 | 77 | Along with the Environment Variables from the [Base image](https://hub.docker.com/r/tiredofit/alpine) below is the complete list of 78 | available options that can be used to customize your installation. 79 | 80 | 81 | | Parameter | Description | 82 | | ------------------ | -------------------------------------------------------------- | 83 | | `PROJECT_TEMPLATE` | The project template to use (leave empty for default template) | 84 | | `ROOT_EMAIL` | Administrator email for login e.g. `admin@example.com` | 85 | | `ROOT_PASS` | Password for login e.g. `password` | 86 | | `DB_USER` | Optional Database user for MongoDB e.g. `formio` | 87 | | `DB_PASS` | Optional Database password for MongoDB e.g. `password` | 88 | | `DB_PORT` | MongoDB Port - Default `27017` | 89 | | `DB_SECRET` | MongoDB Encryption Secret - Default `secret` | 90 | | `JWT_SECRET` | JWT Secret - Default `secret` | 91 | | `JWT_EXPIRE_TIME` | JWT Expire Time in Seconds - Default `240` | 92 | 93 | #### Mail Options 94 | 95 | | Parameter | Description | 96 | | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 97 | | `EMAIL_TYPE` | How to send email - Options are `sendgrid`, `mandrill` - Default `sendgrid` | 98 | | `EMAIL_USER` | Sendgrid Mail Username e.g. `username@example.com` | 99 | | `EMAIL_PASS` | Sendgrid Mail password e.g. `password` | 100 | | `EMAIL_KEY` | Mandrill API Key | 101 | | `MAIL_SENDGRID_API_KEY` | (optional) Sendgrid API Key | 102 | | `GMAIL_USER` | (optional) Gmail Username | 103 | | `GMAIL_PASS` | (optional) Gmail Password | 104 | | `MAIL_MANDRILL_API_KEY` | (optional) Mandrill API Key | 105 | | `SMTP_HOST` | Hostname of SMTP Server | 106 | | `SMTP_SSL` | Should SSL be used for connection to SMTP `TRUE` `FALSE` | 107 | | `SMTP_USER` | SMTP Username e.g. `username@example.com` | 108 | | `SMTP_PASS` | SMTP password e.g. `password` | 109 | | `SMTP_PORT` | SMTP Port | 110 | | `EMAIL_OVERRIDE` | Ignore all options and use this: `# example: {"transport":"smtp","settings":{"port":2525,"host":"smtp.mailtrap.io","auth":{"user":"23esdffd53ac","pass":"324csdfsdf989a"}}}` | 111 | 112 | 113 | ### Networking 114 | 115 | The following ports are exposed. 116 | 117 | | Port | Description | 118 | | ------ | ----------------- | 119 | | `3001` | NodeJS API Server | 120 | 121 | 122 | ## Maintenance 123 | ### Shell Access 124 | 125 | For debugging and maintenance purposes you may want access the containers shell. 126 | 127 | ```bash 128 | docker exec -it (whatever your container name is e.g. formio) bash 129 | ``` 130 | 131 | ## References 132 | 133 | * https://www.form.io/ 134 | 135 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | ./dbbackup* 2 | ./data* 3 | ./logs* 4 | 5 | -------------------------------------------------------------------------------- /examples/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | 4 | formio-api-app: 5 | image: tiredofit/formio-api 6 | container_name: formio-api-app 7 | labels: 8 | - traefik.enable=true 9 | - traefik.frontend.rule=Host:formio.example.com 10 | - traefik.port=80 11 | - traefik.protocol=http 12 | - traefik.docker.network=proxy 13 | - traefik.backend=formio-api-app 14 | volumes: 15 | - ./templates:/app/templates 16 | environment: 17 | - VIRTUAL_HOST=formio.example.com 18 | - VIRTUAL_NETWORK=proxy 19 | - VIRTUAL_PORT=3001 20 | - LETSENCRYPT_HOST=formio.example.com 21 | - LETSENCRYPT_EMAIL=email@example.com 22 | 23 | - CONTAINER_NAME=formio-app 24 | 25 | - DB_HOST=formio-db-mongo 26 | 27 | - ROOT_EMAIL=admin@example.com 28 | - ROOT_PASS=password 29 | 30 | - DEBUG_MODE=FALSE 31 | - PROJECT_TEMPLATE=default 32 | networks: 33 | - proxy 34 | - internal 35 | - services 36 | restart: always 37 | 38 | formio-db-mongo: 39 | image: mongo 40 | container_name: formio-db-mongo 41 | volumes: 42 | - ./db:/data/db 43 | command: mongod --smallfiles 44 | environment: 45 | - CONTAINER_NAME=formio-db-mongo 46 | networks: 47 | - internal 48 | - services 49 | restart: unless-stopped 50 | 51 | formio-db-mongo-backup: 52 | image: tiredofit/db-backup 53 | container_name: formio-db-mongo-backup 54 | links: 55 | - formio-db-mongo 56 | volumes: 57 | - ./dbbackup:/backups 58 | environment: 59 | - DB_TYPE=mongo 60 | - DB_HOST=formio-db-mongo 61 | - DB_DUMP_FREQ=1440 62 | - DB_DUMP_BEGIN=0000 63 | - DB_CLEANUP_TIME=8640 64 | - MD5=TRUE 65 | - COMPRESSION=GZ 66 | networks: 67 | - internal 68 | - services 69 | restart: always 70 | 71 | networks: 72 | proxy: 73 | external: true 74 | internal: 75 | external: false 76 | services: 77 | external: true 78 | -------------------------------------------------------------------------------- /install/app/client/dist/config-dist.js: -------------------------------------------------------------------------------- 1 | var APP_URL = '{{ protocol }}://{{ host }}'; 2 | var API_URL = '{{ protocol }}://{{ host }}'; 3 | 4 | // Parse query string 5 | var query = {}; 6 | location.search.substr(1).split("&").forEach(function(item) { 7 | query[item.split("=")[0]] = item.split("=")[1] && decodeURIComponent(item.split("=")[1]); 8 | }); 9 | 10 | var appUrl = query.appUrl || APP_URL; 11 | var apiUrl = query.apiUrl || API_URL; 12 | 13 | angular.module('formioApp').constant('AppConfig', { 14 | appUrl: appUrl, 15 | apiUrl: apiUrl, 16 | forms: { 17 | userForm: appUrl + '/user', 18 | userLoginForm: appUrl + '/user/login' 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /install/app/config/custom-environment-variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": "FORMIO_PROTOCOL", 3 | "appHost": "FORMIO_HOST", 4 | "appPort": "FORMIO_PORT", 5 | "mongo": "MONGO", 6 | "mongoSecret": "MONGO_SECRET", 7 | "jwt": { 8 | "secret": "JWT_SECRET", 9 | "expireTime": "JWT_EXPIRE_TIME" 10 | }, 11 | "email": { 12 | "type": "EMAIL_TYPE", 13 | "username": "EMAIL_USER", 14 | "password": "EMAIL_PASS", 15 | "apiKey": "EMAIL_KEY" 16 | }, 17 | "settings": { 18 | "office365": { 19 | "tenant": "O365_TENANT", 20 | "clientId": "O365_CLIENT_ID", 21 | "email": "O365_EMAIL", 22 | "cert": "O365_CERT", 23 | "thumbprint": "O365_THUMBPRINT" 24 | }, 25 | "database": { 26 | "mysql": { 27 | "host": "MYSQL_HOST", 28 | "port": "MYSQL_PORT", 29 | "database": "MYSQL_DBNAME", 30 | "user": "MYSQL_USER", 31 | "password": "MYSQL_PASS" 32 | }, 33 | "mssql": { 34 | "host": "MSSQL_HOST", 35 | "port": "MSSQL_PORT", 36 | "database": "MSSQL_DBNAME", 37 | "user": "MSSQL_USER", 38 | "password": "MSSQL_PASS" 39 | } 40 | }, 41 | "email": { 42 | "gmail": { 43 | "auth": { 44 | "user": "GMAIL_USER", 45 | "pass": "GMAIL_PASS" 46 | } 47 | }, 48 | "smtp": { 49 | "host": "SMTP_HOST", 50 | "ssl": "SMTP_SSL", 51 | "port": "SMTP_PORT", 52 | "auth": { 53 | "user": "SMTP_USER", 54 | "pass": "SMTP_PASS" 55 | } 56 | } 57 | } 58 | }, 59 | "project": { 60 | "template": "PROJECT_TEMPLATE", 61 | "user": { 62 | "form": "USER_FORM", 63 | "loginForm": "USER_LOGIN_FORM" 64 | }, 65 | "root": { 66 | "email": "ROOT_EMAIL", 67 | "password": "ROOT_PASS" 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /install/app/install.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const async = require('async'); 4 | const fs = require('fs-extra'); 5 | const _ = require('lodash'); 6 | const nunjucks = require('nunjucks'); 7 | nunjucks.configure([], {watch: false}); 8 | const util = require('./src/util/util'); 9 | const debug = require('debug')('formio:error'); 10 | const path = require('path'); 11 | 12 | module.exports = function(formio, items, done) { 13 | // The client directory 14 | const client = path.join(__dirname, 'client'); 15 | 16 | // The formio project configuration 17 | const project = { 18 | config: {}, 19 | template: 'project.default.json', 20 | user: { 21 | form: 'user', 22 | loginForm: 'user/login', 23 | }, 24 | root: { 25 | email: 'admin@example.com', 26 | password: 'admin.123' 27 | } 28 | }; 29 | 30 | if (formio.config.project) { 31 | if (formio.config.project.template) { 32 | project.template = `project.${formio.config.project.template}.json`; 33 | } 34 | if (formio.config.project.root.email) { 35 | project.root.email = formio.config.project.root.email; 36 | } 37 | if (formio.config.project.root.password) { 38 | project.root.password = formio.config.project.root.password; 39 | } 40 | if (formio.config.project.user) { 41 | project.user.form = formio.config.project.user.form || 'user'; 42 | project.user.loginForm = formio.config.project.user.loginForm || 'user/login'; 43 | } 44 | } 45 | 46 | const pkgs = { 47 | api: path.join(__dirname, 'package.json'), 48 | client: path.join(__dirname, 'client', 'package.json') 49 | } 50 | 51 | // All the steps in the installation. 52 | const steps = { 53 | 54 | /** 55 | * Extract the client. 56 | * 57 | * @param done 58 | * @returns {*} 59 | */ 60 | configureClient: function(done) { 61 | if (!items.configure) { 62 | return done(); 63 | } 64 | 65 | let templateFile = path.join(__dirname, 'templates', 'config.template.js'); 66 | let directoryPath = client; 67 | 68 | // Get the package json file. 69 | let info = { 70 | api: {}, 71 | client: {} 72 | }; 73 | try { 74 | info.api = JSON.parse(fs.readFileSync(pkgs.api)); 75 | info.client = JSON.parse(fs.readFileSync(pkgs.client)); 76 | } 77 | catch (err) { 78 | debug(err); 79 | return done(err); 80 | } 81 | 82 | // Change the document root if we need to. 83 | if (info.client.formio && info.client.formio.docRoot) { 84 | directoryPath = path.join(directoryPath, info.client.formio.docRoot); 85 | } 86 | 87 | // Check that config.template.js exists 88 | if (!fs.existsSync(templateFile)) { 89 | templateFile = path.join(directoryPath, 'config.template.js'); 90 | 91 | if (!fs.existsSync(templateFile)) { 92 | return done('Missing config.template.js file'); 93 | } 94 | } 95 | 96 | // Change the project configuration. 97 | util.log('Configuring the client'.green); 98 | const config = fs.readFileSync(templateFile); 99 | const newConfig = nunjucks.renderString(config.toString(), { 100 | protocol: formio.config.protocol || 'http', 101 | host: formio.config.appHost || 'localhost', 102 | port: formio.config.appPort || '8080', 103 | userForm: project.user.form, 104 | userLoginForm: project.user.loginForm 105 | }); 106 | fs.writeFileSync(path.join(directoryPath, 'config.js'), newConfig); 107 | 108 | let configInfo = `API=${info.api.version}\nCLIENT=${info.client.version}\nSCHEMA=${info.api.schema}\nTEMPLATE=${info.api.templateVersion}\nCREATED=${Date.now() / 1000 | 0}`; 109 | fs.writeFileSync(path.join(__dirname, '.formio'), configInfo); 110 | 111 | done(); 112 | }, 113 | 114 | /** 115 | * Import the template. 116 | * @param done 117 | */ 118 | importTemplate: function(done) { 119 | if (!items.import) { 120 | return done(); 121 | } 122 | 123 | let templateFile = path.join(__dirname, 'templates', project.template); 124 | let directoryPath = client; 125 | 126 | // Get the package json file. 127 | let info = {}; 128 | try { 129 | info = JSON.parse(fs.readFileSync(path.join(directoryPath, 'package.json'))); 130 | } 131 | catch (err) { 132 | debug(err); 133 | return done(err); 134 | } 135 | 136 | // Change the document root if we need to. 137 | if (info.formio && info.formio.docRoot) { 138 | directoryPath = path.join(directoryPath, info.formio.docRoot); 139 | } 140 | 141 | // Check that config.template.js exists 142 | if (!fs.existsSync(templateFile)) { 143 | templateFile = path.join(directoryPath, 'project.json'); 144 | 145 | if (!fs.existsSync(templateFile)) { 146 | return done('Missing project.json file'.red); 147 | } 148 | } 149 | 150 | let template = {}; 151 | try { 152 | template = JSON.parse(fs.readFileSync(templateFile)); 153 | } 154 | catch (err) { 155 | debug(err); 156 | return done(err); 157 | } 158 | 159 | // Get the form.io service. 160 | util.log('Importing template'.green); 161 | const importer = require('./src/templates/import')({formio: formio}); 162 | importer.template(template, function(err, template) { 163 | if (err) { 164 | return done(err); 165 | } 166 | 167 | project.config = template; 168 | done(null, template); 169 | }); 170 | }, 171 | 172 | /** 173 | * Create the root user object. 174 | * 175 | * @param done 176 | */ 177 | createRootUser: function(done) { 178 | util.log('Checking if Root account exists') 179 | if (!items.user) { 180 | util.log('Root account already exists') 181 | return done(); 182 | } 183 | util.log('Creating root user account...'.green); 184 | util.log('Encrypting password'); 185 | formio.encrypt(project.root.password, function(err, hash) { 186 | if (err) { 187 | return done(err); 188 | } 189 | 190 | // Create the root user submission. 191 | util.log(`Creating root user account ${project.root.email}`); 192 | formio.resources.submission.model.create({ 193 | form: project.config.resources.admin._id, 194 | data: { 195 | email: project.root.email, 196 | password: hash 197 | }, 198 | roles: [ 199 | project.config.roles.administrator._id 200 | ] 201 | }, function(err, item) { 202 | if (err) { 203 | return done(err); 204 | } 205 | 206 | done(); 207 | }); 208 | }); 209 | } 210 | }; 211 | 212 | util.log('Setting up FormIO'); 213 | async.series([ 214 | steps.configureClient, 215 | steps.importTemplate, 216 | steps.createRootUser 217 | ], function(err, result) { 218 | if (err) { 219 | util.log(err); 220 | return done(err); 221 | } 222 | 223 | util.log('Install successful!'.green); 224 | done(); 225 | }); 226 | }; 227 | -------------------------------------------------------------------------------- /install/app/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * This is the Form.io application server. 5 | */ 6 | const express = require('express'); 7 | const nunjucks = require('nunjucks'); 8 | const fs = require('fs-extra'); 9 | const util = require('./src/util/util'); 10 | require('colors'); 11 | const Q = require('q'); 12 | const test = process.env.TEST_SUITE; 13 | 14 | module.exports = function(options) { 15 | options = options || {}; 16 | const q = Q.defer(); 17 | 18 | util.log(''); 19 | const rl = require('readline').createInterface({ 20 | input: require('fs').createReadStream('logo.txt') 21 | }); 22 | 23 | rl.on('line', function(line) { 24 | util.log( 25 | line.substring(0,4) + 26 | line.substring(4, 30).cyan.bold + 27 | line.substring(30, 33) + 28 | line.substring(33, 42).green.bold + 29 | line.substring(42) 30 | ); 31 | }); 32 | 33 | rl.on('close', function() { 34 | // Print the welcome screen. 35 | util.log(''); 36 | util.log(fs.readFileSync('welcome.txt').toString().green); 37 | }); 38 | 39 | // Use the express application. 40 | const app = options.app || express(); 41 | 42 | // Use the given config. 43 | const config = options.config || require('config'); 44 | 45 | // Configure nunjucks. 46 | nunjucks.configure('client', { 47 | autoescape: true, 48 | express: app 49 | }); 50 | 51 | // Mount the client application. 52 | app.use('/', express.static(`${__dirname}/client/dist`)); 53 | 54 | // Load the form.io server. 55 | const server = options.server || require('./index')(config); 56 | const hooks = options.hooks || {}; 57 | 58 | app.use(server.formio.middleware.restrictRequestTypes); 59 | server.init(hooks).then(function(formio) { 60 | // Called when we are ready to start the server. 61 | const start = function() { 62 | 63 | // Mount the Form.io API platform. 64 | app.use(options.mount || '/', server); 65 | 66 | // Allow tests access server internals. 67 | app.formio = formio; 68 | 69 | // Listen on the configured port. 70 | return q.resolve({ 71 | server: app, 72 | config: config 73 | }); 74 | }; 75 | 76 | // Which items should be installed. 77 | const install = { 78 | configure: false, 79 | import: false, 80 | user: false 81 | }; 82 | 83 | // If not a test, reconfigure client (required for port updates) 84 | if (!test) { 85 | install.configure = true; 86 | } 87 | 88 | // See if they have any forms available. 89 | formio.db.collection('forms').count(function(err, numForms) { 90 | 91 | // Import the project and create the user. 92 | install.import = true; 93 | install.user = true; 94 | 95 | // If there are forms, then go ahead and start the server. 96 | if ((!err && numForms > 0) || test) { 97 | install.import = false; 98 | install.user = false; 99 | if (!install.configure) { 100 | return start(); 101 | } 102 | } 103 | 104 | // Install. 105 | require('./install')(formio, install, function(err) { 106 | if (err) { 107 | return util.log(err.message); 108 | } 109 | 110 | // Start the server. 111 | start(); 112 | }); 113 | }); 114 | }); 115 | 116 | return q.promise; 117 | }; 118 | -------------------------------------------------------------------------------- /install/assets/functions/10-formio-api: -------------------------------------------------------------------------------- 1 | #!/command/with-contenv bash 2 | 3 | export DB_PORT=${DB_PORT:-"27017"} 4 | 5 | configure_url() { 6 | print_notice "Setting API and Manager Application to ${FORMIO_PROTOCOL}://${FORMIO_HOST}/" 7 | } -------------------------------------------------------------------------------- /install/assets/templates/config.template.js: -------------------------------------------------------------------------------- 1 | var APP_URL = '{{ protocol }}://{{ host }}:{{ port }}'; 2 | var API_URL = '{{ protocol }}://{{ host }}:{{ port }}'; 3 | 4 | // Parse query string 5 | var query = {}; 6 | location.search.substr(1).split("&").forEach(function(item) { 7 | query[item.split("=")[0]] = item.split("=")[1] && decodeURIComponent(item.split("=")[1]); 8 | }); 9 | 10 | var appUrl = query.appUrl || APP_URL; 11 | var apiUrl = query.apiUrl || API_URL; 12 | 13 | angular.module('formioApp').constant('AppConfig', { 14 | appUrl: appUrl, 15 | apiUrl: apiUrl, 16 | forms: { 17 | userForm: appUrl + '/{{ userForm }}', 18 | userLoginForm: appUrl + '/{{ userLoginForm }}' 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /install/assets/templates/project.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Form Manager", 3 | "name": "form-manager", 4 | "version": "2.0.0", 5 | "description": "Provides a usable Form Management system.", 6 | "preview": { 7 | "url": "https://formio.github.io/formio-app-formio/dist", 8 | "repo": "https://github.com/formio/formio-app-formio" 9 | }, 10 | "roles": { 11 | "administrator": { 12 | "title": "Administrator", 13 | "description": "A role for Administrative Users.", 14 | "admin": true 15 | }, 16 | "authenticated": { 17 | "title": "Authenticated", 18 | "description": "A role for Authenticated Users." 19 | }, 20 | "anonymous": { 21 | "title": "Anonymous", 22 | "description": "A role for Anonymous Users.", 23 | "default": true 24 | } 25 | }, 26 | "resources": { 27 | "user": { 28 | "title": "User", 29 | "type": "resource", 30 | "name": "user", 31 | "path": "user", 32 | "submissionAccess": [{ 33 | "type": "create_all", 34 | "roles": [ 35 | "administrator" 36 | ] 37 | }, 38 | { 39 | "type": "read_all", 40 | "roles": [ 41 | "administrator" 42 | ] 43 | }, 44 | { 45 | "type": "update_all", 46 | "roles": [ 47 | "administrator" 48 | ] 49 | }, 50 | { 51 | "type": "delete_all", 52 | "roles": [ 53 | "administrator" 54 | ] 55 | }, 56 | { 57 | "type": "create_own", 58 | "roles": [] 59 | }, 60 | { 61 | "type": "read_own", 62 | "roles": [] 63 | }, 64 | { 65 | "type": "update_own", 66 | "roles": [] 67 | }, 68 | { 69 | "type": "delete_own", 70 | "roles": [] 71 | } 72 | ], 73 | "access": [{ 74 | "type": "read_all", 75 | "roles": [ 76 | "anonymous", 77 | "authenticated", 78 | "administrator" 79 | ] 80 | }], 81 | "components": [{ 82 | "type": "email", 83 | "persistent": true, 84 | "unique": true, 85 | "protected": false, 86 | "defaultValue": "", 87 | "suffix": "", 88 | "prefix": "", 89 | "placeholder": "Enter your email address", 90 | "key": "email", 91 | "label": "Email", 92 | "inputType": "email", 93 | "tableView": true, 94 | "input": true, 95 | "validate": { 96 | "required": true, 97 | "unique": true 98 | } 99 | }, 100 | { 101 | "type": "password", 102 | "persistent": true, 103 | "protected": true, 104 | "suffix": "", 105 | "prefix": "", 106 | "placeholder": "Enter your password", 107 | "key": "password", 108 | "label": "Password", 109 | "inputType": "password", 110 | "tableView": false, 111 | "input": true, 112 | "validate": { 113 | "required": true 114 | } 115 | }, 116 | { 117 | "type": "button", 118 | "theme": "primary", 119 | "disableOnInvalid": true, 120 | "action": "submit", 121 | "block": false, 122 | "rightIcon": "", 123 | "leftIcon": "", 124 | "size": "md", 125 | "key": "submit", 126 | "tableView": false, 127 | "label": "Submit", 128 | "input": true 129 | } 130 | ] 131 | }, 132 | "admin": { 133 | "title": "Admin", 134 | "type": "resource", 135 | "name": "admin", 136 | "path": "admin", 137 | "submissionAccess": [{ 138 | "type": "create_all", 139 | "roles": [ 140 | "administrator" 141 | ] 142 | }, 143 | { 144 | "type": "read_all", 145 | "roles": [ 146 | "administrator" 147 | ] 148 | }, 149 | { 150 | "type": "update_all", 151 | "roles": [ 152 | "administrator" 153 | ] 154 | }, 155 | { 156 | "type": "delete_all", 157 | "roles": [ 158 | "administrator" 159 | ] 160 | }, 161 | { 162 | "type": "create_own", 163 | "roles": [] 164 | }, 165 | { 166 | "type": "read_own", 167 | "roles": [] 168 | }, 169 | { 170 | "type": "update_own", 171 | "roles": [] 172 | }, 173 | { 174 | "type": "delete_own", 175 | "roles": [] 176 | } 177 | ], 178 | "access": [{ 179 | "type": "read_all", 180 | "roles": [ 181 | "anonymous", 182 | "authenticated", 183 | "administrator" 184 | ] 185 | }], 186 | "components": [{ 187 | "type": "email", 188 | "persistent": true, 189 | "unique": true, 190 | "protected": false, 191 | "defaultValue": "", 192 | "suffix": "", 193 | "prefix": "", 194 | "placeholder": "Enter your email address", 195 | "key": "email", 196 | "label": "Email", 197 | "inputType": "email", 198 | "tableView": true, 199 | "input": true, 200 | "validate": { 201 | "required": true, 202 | "unique": true 203 | } 204 | }, 205 | { 206 | "type": "password", 207 | "persistent": true, 208 | "protected": true, 209 | "suffix": "", 210 | "prefix": "", 211 | "placeholder": "Enter your password", 212 | "key": "password", 213 | "label": "Password", 214 | "inputType": "password", 215 | "tableView": false, 216 | "input": true, 217 | "validate": { 218 | "required": true 219 | } 220 | }, 221 | { 222 | "type": "button", 223 | "theme": "primary", 224 | "disableOnInvalid": true, 225 | "action": "submit", 226 | "block": false, 227 | "rightIcon": "", 228 | "leftIcon": "", 229 | "size": "md", 230 | "key": "submit", 231 | "tableView": false, 232 | "label": "Submit", 233 | "input": true 234 | } 235 | ] 236 | } 237 | }, 238 | "forms": { 239 | "userLogin": { 240 | "title": "User Login", 241 | "type": "form", 242 | "name": "userLogin", 243 | "path": "user/login", 244 | "access": [{ 245 | "type": "read_all", 246 | "roles": [ 247 | "anonymous" 248 | ] 249 | }], 250 | "submissionAccess": [{ 251 | "type": "create_own", 252 | "roles": [ 253 | "anonymous" 254 | ] 255 | }], 256 | "components": [{ 257 | "type": "email", 258 | "persistent": true, 259 | "unique": false, 260 | "protected": false, 261 | "defaultValue": "", 262 | "suffix": "", 263 | "prefix": "", 264 | "placeholder": "Enter your email address", 265 | "key": "email", 266 | "lockKey": true, 267 | "label": "Email", 268 | "inputType": "email", 269 | "tableView": true, 270 | "input": true, 271 | "validate": { 272 | "required": true 273 | } 274 | }, 275 | { 276 | "type": "password", 277 | "persistent": true, 278 | "protected": true, 279 | "suffix": "", 280 | "prefix": "", 281 | "placeholder": "Enter your password", 282 | "key": "password", 283 | "lockKey": true, 284 | "label": "Password", 285 | "inputType": "password", 286 | "tableView": false, 287 | "input": true, 288 | "validate": { 289 | "required": true 290 | } 291 | }, 292 | { 293 | "type": "button", 294 | "theme": "primary", 295 | "disableOnInvalid": true, 296 | "action": "submit", 297 | "block": false, 298 | "rightIcon": "", 299 | "leftIcon": "", 300 | "size": "md", 301 | "key": "submit", 302 | "tableView": false, 303 | "label": "Submit", 304 | "input": true 305 | } 306 | ] 307 | }, 308 | "adminLogin": { 309 | "title": "Admin Login", 310 | "type": "form", 311 | "name": "adminLogin", 312 | "path": "admin/login", 313 | "access": [{ 314 | "type": "read_all", 315 | "roles": [ 316 | "anonymous" 317 | ] 318 | }], 319 | "submissionAccess": [{ 320 | "type": "create_own", 321 | "roles": [ 322 | "anonymous" 323 | ] 324 | }], 325 | "components": [{ 326 | "type": "email", 327 | "persistent": true, 328 | "unique": false, 329 | "protected": false, 330 | "defaultValue": "", 331 | "suffix": "", 332 | "prefix": "", 333 | "placeholder": "Enter your email address", 334 | "key": "email", 335 | "lockKey": true, 336 | "label": "Email", 337 | "inputType": "email", 338 | "tableView": true, 339 | "input": true, 340 | "validate": { 341 | "required": true 342 | } 343 | }, 344 | { 345 | "type": "password", 346 | "persistent": true, 347 | "protected": true, 348 | "suffix": "", 349 | "prefix": "", 350 | "placeholder": "Enter your password", 351 | "key": "password", 352 | "lockKey": true, 353 | "label": "Password", 354 | "inputType": "password", 355 | "tableView": false, 356 | "input": true, 357 | "validate": { 358 | "required": true 359 | } 360 | }, 361 | { 362 | "type": "button", 363 | "theme": "primary", 364 | "disableOnInvalid": true, 365 | "action": "submit", 366 | "block": false, 367 | "rightIcon": "", 368 | "leftIcon": "", 369 | "size": "md", 370 | "key": "submit", 371 | "tableView": false, 372 | "label": "Submit", 373 | "input": true 374 | } 375 | ] 376 | }, 377 | "userRegister": { 378 | "title": "User Register", 379 | "name": "userRegister", 380 | "path": "user/register", 381 | "type": "form", 382 | "access": [{ 383 | "type": "read_all", 384 | "roles": [ 385 | "anonymous" 386 | ] 387 | }], 388 | "submissionAccess": [{ 389 | "type": "create_own", 390 | "roles": [ 391 | "anonymous" 392 | ] 393 | }], 394 | "components": [{ 395 | "type": "email", 396 | "persistent": true, 397 | "unique": false, 398 | "protected": false, 399 | "defaultValue": "", 400 | "suffix": "", 401 | "prefix": "", 402 | "placeholder": "Enter your email address", 403 | "key": "email", 404 | "lockKey": true, 405 | "label": "Email", 406 | "inputType": "email", 407 | "tableView": true, 408 | "input": true, 409 | "validate": { 410 | "required": true, 411 | "unique": true 412 | } 413 | }, 414 | { 415 | "type": "password", 416 | "persistent": true, 417 | "protected": true, 418 | "suffix": "", 419 | "prefix": "", 420 | "placeholder": "Enter your password", 421 | "key": "password", 422 | "lockKey": true, 423 | "label": "Password", 424 | "inputType": "password", 425 | "tableView": false, 426 | "input": true, 427 | "validate": { 428 | "required": true 429 | } 430 | }, 431 | { 432 | "input": true, 433 | "tableView": false, 434 | "inputType": "password", 435 | "label": "Confirm Password", 436 | "key": "confirmPassword", 437 | "placeholder": "Confirm your password", 438 | "prefix": "", 439 | "suffix": "", 440 | "protected": true, 441 | "persistent": false, 442 | "type": "password", 443 | "validate": { 444 | "required": true, 445 | "custom": "valid = data.password === input;", 446 | "customMessage": "The passwords you entered do not match." 447 | } 448 | }, 449 | { 450 | "theme": "primary", 451 | "disableOnInvalid": true, 452 | "action": "submit", 453 | "block": false, 454 | "rightIcon": "", 455 | "leftIcon": "", 456 | "size": "md", 457 | "key": "submit", 458 | "label": "Submit", 459 | "input": true, 460 | "type": "button" 461 | } 462 | ] 463 | } 464 | }, 465 | "actions": { 466 | "userSave": { 467 | "title": "Save Submission", 468 | "name": "save", 469 | "form": "user", 470 | "handler": [ 471 | "before" 472 | ], 473 | "method": [ 474 | "create", 475 | "update" 476 | ], 477 | "priority": 11, 478 | "settings": {} 479 | }, 480 | "adminSave": { 481 | "title": "Save Submission", 482 | "name": "save", 483 | "form": "admin", 484 | "handler": [ 485 | "before" 486 | ], 487 | "method": [ 488 | "create", 489 | "update" 490 | ], 491 | "priority": 11, 492 | "settings": {} 493 | }, 494 | "userLogin": { 495 | "name": "login", 496 | "title": "Login", 497 | "form": "userLogin", 498 | "priority": 2, 499 | "method": [ 500 | "create" 501 | ], 502 | "handler": [ 503 | "before" 504 | ], 505 | "settings": { 506 | "resources": [ 507 | "user", 508 | "admin" 509 | ], 510 | "username": "email", 511 | "password": "password" 512 | } 513 | }, 514 | "adminLogin": { 515 | "name": "login", 516 | "title": "Login", 517 | "form": "adminLogin", 518 | "priority": 2, 519 | "method": [ 520 | "create" 521 | ], 522 | "handler": [ 523 | "before" 524 | ], 525 | "settings": { 526 | "resources": [ 527 | "admin" 528 | ], 529 | "username": "email", 530 | "password": "password" 531 | } 532 | }, 533 | "userRegisterSave": { 534 | "title": "Save Submission", 535 | "name": "save", 536 | "form": "userRegister", 537 | "handler": [ 538 | "before" 539 | ], 540 | "method": [ 541 | "create" 542 | ], 543 | "priority": 10, 544 | "settings": { 545 | "resource": "user", 546 | "fields": { 547 | "email": "email", 548 | "password": "password" 549 | } 550 | } 551 | }, 552 | "userRegisterLogin": { 553 | "name": "login", 554 | "title": "Login", 555 | "form": "userRegister", 556 | "priority": 2, 557 | "method": [ 558 | "create" 559 | ], 560 | "handler": [ 561 | "before" 562 | ], 563 | "settings": { 564 | "resources": [ 565 | "user" 566 | ], 567 | "username": "email", 568 | "password": "password" 569 | } 570 | }, 571 | "authenticatedRole": { 572 | "name": "role", 573 | "title": "Role Assignment", 574 | "form": "user", 575 | "priority": 1, 576 | "handler": [ 577 | "after" 578 | ], 579 | "method": [ 580 | "create" 581 | ], 582 | "settings": { 583 | "role": "authenticated", 584 | "type": "add", 585 | "association": "new" 586 | } 587 | }, 588 | "adminRole": { 589 | "name": "role", 590 | "title": "Role Assignment", 591 | "form": "admin", 592 | "priority": 1, 593 | "handler": [ 594 | "after" 595 | ], 596 | "method": [ 597 | "create" 598 | ], 599 | "settings": { 600 | "role": "administrator", 601 | "type": "add", 602 | "association": "new" 603 | } 604 | } 605 | } 606 | } 607 | -------------------------------------------------------------------------------- /install/etc/cont-init.d/10-formio-api: -------------------------------------------------------------------------------- 1 | #!/command/with-contenv bash 2 | 3 | source /assets/functions/00-container 4 | prepare_service 5 | PROCESS_NAME="formio-api" 6 | 7 | ### Sanity Check 8 | sanity_var DB_HOST "Database Host" 9 | sanity_var FORMIO_HOST "FormIO Hostname" 10 | db_ready mongo 11 | 12 | configure_url 13 | 14 | if [ ! -f /app/templates/project.default.json ] ; then cp -R /assets/templates/project.default.json /app/templates; fi; 15 | if [ ! -f /app/templates/config.template.js ] ; then cp -R /assets/templates/config.template.js /app/templates; fi; 16 | chown -R nodejs: /app 17 | 18 | liftoff -------------------------------------------------------------------------------- /install/etc/services.available/10-formio-api/run: -------------------------------------------------------------------------------- 1 | #!/command/with-contenv bash 2 | 3 | source /assets/functions/00-container 4 | prepare_service 5 | PROCESS_NAME="formio-api" 6 | 7 | check_container_initialized 8 | check_service_initialized init 9 | 10 | if [ -n "${DB_USER}" ] ; then DB_CREDSTRING=$DB_USER'@'; fi; 11 | if [ -n "${DB_PASS}" ] ; then DB_CREDSTRING=$DB_USER':'$DB_PASS'@'; fi; 12 | export DB_SECRET=${DB_SECRET:-"secret"} 13 | export FORMIO_MANAGER_HOST=${FORMIO_MANAGER_HOST:-"${FORMIO_HOST}"} 14 | export FORMIO_PROTOCOL=${FORMIO_PROTOCOL:-"https"} 15 | if [ "$FORMIO_PROTOCOL" = "http" ] ; then export FORMIO_PORT=80; else export FORMIO_PORT=443; fi; 16 | export JWT_SECRET=${JWT_SECRET:-"secret"} 17 | export JWT_EXPIRE_TIME=${JWT_EXPIRE_TIME:-"240"} 18 | export PROJECT_TEMPLATE=${PROJECT_TEMPLATE:-"default"} 19 | export USER_FORM=${USER_FORM:-"user"} 20 | export USER_LOGIN_FORM=${USER_LOGIN_FORM:-"admin/login"} 21 | export ROOT_EMAIL=${ROOT_EMAIL:-"admin@example.com"} 22 | export ROOT_PASS=${ROOT_PASS:-"password"} 23 | export MONGO=${DB_STRING:-'mongodb://'$DB_CRED_STRING$DB_HOST':'$DB_PORT'/'$PROJECT_TEMPLATE} 24 | liftoff 25 | 26 | print_start "Starting Formio API ${FORMIO_VERSION}" 27 | cd /app 28 | exec sudo -E -u nodejs HOME=/app npm start --------------------------------------------------------------------------------