diff --git a/.gitignore b/.gitignore index 47ccf0f..7f940ac 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ mobile/ios/**/xcuserdata/ npm-debug.log* yarn-debug.log* yarn-error.log* +local-*.json* diff --git a/README.md b/README.md index 7ef59f6..c8a6a4e 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,139 @@ This is the repository for the Deighton AR Training System. ## Development -Ensure the [snap-tools]() are installed. Then clone the repository, and from the root do: +### Pre-requisites + +Install locally: + +- NodeJS +- MongoDB +- RabbitMQ +- Redis + +The backend systems for this project have been developed and tested on macOS and Ubuntu systems. + +Follow the instructions for additional dependencies for the [`canvas`](https://www.npmjs.com/package/canvas) NPM package. + +For iOS development install Xcode. For Android development install Android Studio. + +### Website, Server and Mobile Bundler + +Ensure the [snap-tool](https://www.npmjs.com/package/snap-tool) is installed with `npm install -g snap-tool`. + +Clone this repository, and from the root do: ``` snap install snap start ``` -This will start the website, server and mobile app. +This will start the website, server and the `Metro` bundler for development builds of the mobile apps. + +### iOS App + +You'll need Xcode fully installed and running. To run the iOS mobile app, start Xcode, open the `DeightonAR.xcproject`, plug in a iPhone and run the project. + +### Android App + +To run the Android mobile app, start Android Studio, open the `mobile/android` project, plug in an Android device and run the project. + +## Production + +### Website + +To deploy the website for the 1st time do the following. + +- Install `nginx`, `mongodb`, `rabbitmq` and configure as desired. +- Order SSL certificate for site and install under `/etc/nginx/ssl`. +- Install `.conf` file for the site (see below for example) + +The `.conf` file for the site will look something like: + +``` +server { + listen 443 ssl; + server_name dar.kss.us.com; + ssl_certificate /etc/nginx/ssl/dar_kss_us_com_chained.crt; + ssl_certificate_key /etc/nginx/ssl/dar_kss_us_com.key; + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 5m; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + + root /home/ubuntu/deighton-ar/website; + + # Any route that starts with /api/ is for the backend + location /api/ { + proxy_pass http://127.0.0.1:3001/; + proxy_buffering off; + proxy_redirect off; # The backend doesn't redirect + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + # Any route containing a file extension + location ~ ^.+\..+$ { + try_files $uri =404; + } + + # Any route that doesn't have a file extension + location / { + try_files $uri $uri/ /index.html; + } +} +``` + +Run `nginx -t` to check configuration, then `nginx -s reload` to load it. API service will need to be set up to login (see next section). + +Create `admin` and `user` users with passwords for the MongoDB database. + +Install the `deighton-ar.service` file by copying it to the `/lib/systemd/system` directory and run `sudo systemctl --now enable deighton-ar` to start the service. + +Create a `service/config/local-production.json5` file an insert an MongoDB URI with appropriate password. + +For subsequent deployments, you can simply run: + +``` +cd website +npm run build +npm run deploy +``` + +### Service + +These instructions are for installation on Ubuntu. See [Install_Ubuntu_16.04_LTS_Service_Instance](https://github.com/jlyonsmith/HowTo/blob/master/Install_Ubuntu_16.04_LTS_Service_Instance.md) for detailed instructions on setting up a system appropriately. + +First, create a log file directories: + +``` +sudo mkdir /var/log/deighton-ar +sudo chown ubuntu:ubuntu /var/log/deighton-ar +``` + +Then do: + +``` +cd server +npm run build +npm run deploy +``` + +Then, on the server run: + +``` + +``` + +### iOS App + +You'll need an Apple Developer account. Set up appropriate AppID's in the developer port with plus signing keys installed correctly. Adjust project to use appropriate siging keys. + +TBD. + +### Android App + +TBD. diff --git a/server/.rsync-exclude b/server/.rsync-exclude new file mode 100644 index 0000000..89dcfad --- /dev/null +++ b/server/.rsync-exclude @@ -0,0 +1,6 @@ +.* +package-lock.json +src/ +scratch/ +node_modules/ +local-* diff --git a/server/config/local-development.json5 b/server/config/local-development.json5 deleted file mode 100644 index 141a570..0000000 --- a/server/config/local-development.json5 +++ /dev/null @@ -1,7 +0,0 @@ -{ - awsConfig: { - accessKeyId: 'AKIAJUP6XRVYDAXNTUNA', - secretAccessKey: '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', - region: 'us-west-2' - } -} diff --git a/server/config/production.json5 b/server/config/production.json5 index 1472f2e..b7cc030 100644 --- a/server/config/production.json5 +++ b/server/config/production.json5 @@ -1,7 +1,7 @@ { logDir: '/var/log/deighton-ar', api: { - port: '3001', + port: '3005', loginKey: '*', uploadTimout: 120, maxEmailTokenAgeInHours: 36, diff --git a/server/deighton-ar.service b/server/deighton-ar.service index 8dfe10e..09787d3 100644 --- a/server/deighton-ar.service +++ b/server/deighton-ar.service @@ -8,7 +8,7 @@ User=ubuntu Group=ubuntu WorkingDirectory=/home/ubuntu/deighton-ar/server Environment='NODE_ENV=production' -ExecStart=/usr/bin/node src/server.js +ExecStart=/usr/bin/node dist/server.js Restart=on-abort [Install] diff --git a/server/ops b/server/ops index 88f3d90..50db8b3 100755 --- a/server/ops +++ b/server/ops @@ -1,16 +1,16 @@ #!/bin/bash script_dir=$(dirname $0) -script="${script_dir}/src/bin/$1" +script="${script_dir}/dist/bin/${1}.js" if [[ -z "$1" ]]; then echo "usage: $(basename $0) " echo "" - echo "Available scripts are" - ls -1 ${script_dir}/src/bin + echo "Available commands are" + echo "" + find ${script_dir}/dist/bin -name \*.js -exec basename {} .js \; exit -1 fi - # For scripts that need config access export NODE_CONFIG_DIR="${script_dir}/config" diff --git a/server/package.json b/server/package.json index 8cc7e89..cf36377 100644 --- a/server/package.json +++ b/server/package.json @@ -5,9 +5,9 @@ "main": "src/server.js", "scripts": { "start": "babel-node src/server.js", - "start:prod": "NODE_ENV=production npm start", - "build": "babel src -d dist -s", - "serve": "NODE_ENV=production node dist/server.js", + "start:prod": "NODE_ENV=production node dist/server.js", + "build": "rm -rf dist && babel src -d dist -s", + "deploy": "rsync -vr -e ssh --exclude-from .rsync-exclude * ubuntu@tmr:deighton-ar/server/", "test": "jest", "actor:api": "monzilla 'src/api/**/*.js:src/database/**/*.js' -- babel-node src/api/index.js", "actor:api:debug": "babel-node --inspect-brk src/api/index.js", diff --git a/server/src/bin/addUser.js b/server/src/bin/addUser.js index 6bc3f12..cd4288c 100644 --- a/server/src/bin/addUser.js +++ b/server/src/bin/addUser.js @@ -10,7 +10,7 @@ import util from 'util' import autoBind from 'auto-bind2' -class SendMessageTool { +class AddUserTool { constructor(toolName, log) { autoBind(this) this.toolName = toolName @@ -20,7 +20,9 @@ class SendMessageTool { async run() { const mongoUri = config.get('uri.mongo') - new DB().connect(mongoUri).then((db) => { + try { + const db = await new DB().connect(mongoUri) + console.log(`Connected to MongoDB at ${mongoUri}`) const User = db.User @@ -33,18 +35,16 @@ class SendMessageTool { let password = readlineSync.question('Password? ', {hideEchoBack: true}) let cr = credential() - util.promisify(cr.hash)(password).then((json) => { - user.passwordHash = JSON.parse(json) + const json = await util.promisify(cr.hash)(password) - return user.save() - }).then((savedUser) => { - console.log(`User is ${user}`) - process.exit(0) - }).catch((error) => { - console.log(`error: ${error.message}`) - process.exit(-1) - }) - }) + user.passwordHash = JSON.parse(json) + + const savedUser = await user.save() + + console.log(`User is ${user}`) + } catch(error) { + console.log(`error: ${error.message}`) + } } } @@ -54,7 +54,7 @@ const log = { warning: function() { console.error(chalk.yellow('warning:', [...arguments].join(' ')))} } -const tool = new AddUserTool('add-user', log) +const tool = new AddUserTool('addUser', log) tool.run(process.argv.slice(2)).then((exitCode) => { process.exit(exitCode) diff --git a/server/src/bin/sendMessage.js b/server/src/bin/sendMessage.js index 7614666..5514e45 100644 --- a/server/src/bin/sendMessage.js +++ b/server/src/bin/sendMessage.js @@ -110,7 +110,7 @@ const log = { warning: function() { console.error(chalk.yellow('warning:', [...arguments].join(' ')))} } -const tool = new SendMessageTool('send-message', log) +const tool = new SendMessageTool('sendMessage', log) tool.run(process.argv.slice(2)).then((exitCode) => { process.exit(exitCode) diff --git a/server/src/server.js b/server/src/server.js index e6286f8..a0452e9 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -3,6 +3,8 @@ import { ServerTool } from './ServerTool' import pino from 'pino' import * as pinoExpress from 'pino-pretty-express' import path from 'path' +import fs from 'fs' +import config from 'config' const serviceName = 'dar-server' const isProduction = (process.env.NODE_ENV == 'production') diff --git a/website/package.json b/website/package.json index d9f1a6f..04a6e84 100644 --- a/website/package.json +++ b/website/package.json @@ -59,6 +59,7 @@ "scripts": { "start": "node scripts/start.js", "build": "node scripts/build.js", + "deploy": "rsync -vr -e ssh build/* ubuntu@tmr:deighton-ar/website/", "lint": "eslint --ext .js --ext .jsx src/", "lint:fix": "eslint --ext .js --ext .jsx --fix src/" },