Initial commit
This commit is contained in:
commit
2216758d14
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# NPM Dependency directory
|
||||||
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# Bower dependency directory
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
/build
|
||||||
|
|
||||||
|
/dump
|
||||||
|
|
||||||
|
/public
|
||||||
|
|
||||||
|
/server/uploads
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "gulp"]
|
||||||
|
path = gulp
|
||||||
|
url = https://github.com/thebitmill/gulp.git
|
||||||
23
assets/less/dragula.less
Normal file
23
assets/less/dragula.less
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
.gu-mirror {
|
||||||
|
position: fixed !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
// opacity: 0.8;
|
||||||
|
// -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
|
||||||
|
// filter: alpha(opacity=80);
|
||||||
|
}
|
||||||
|
.gu-hide {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.gu-unselectable {
|
||||||
|
-webkit-user-select: none !important;
|
||||||
|
-moz-user-select: none !important;
|
||||||
|
-ms-user-select: none !important;
|
||||||
|
user-select: none !important;
|
||||||
|
}
|
||||||
|
.gu-transit {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0.2;
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
||||||
|
filter: alpha(opacity=20);
|
||||||
|
}
|
||||||
29
assets/less/main.less
Normal file
29
assets/less/main.less
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
@import "./dragula";
|
||||||
|
|
||||||
|
div.container {
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
> div.location {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
padding: 40px;
|
||||||
|
&.over {
|
||||||
|
> .item {
|
||||||
|
transform: scale(1.3);
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.item {
|
||||||
|
transition: all 0.2s;
|
||||||
|
width: 100px !important;
|
||||||
|
height: 100px !important;
|
||||||
|
background: red;
|
||||||
|
border-radius: 300px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
55
client/index.js
Normal file
55
client/index.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { $, $$ } from 'dollr';
|
||||||
|
import dragula from 'dragula';
|
||||||
|
|
||||||
|
|
||||||
|
const result = $('pre');
|
||||||
|
const containers = $$('.location');
|
||||||
|
|
||||||
|
const drake = dragula(containers, {
|
||||||
|
revertOnSpill: true,
|
||||||
|
// accepts(el, target, source, sibling) {
|
||||||
|
// // console.log('accepts');
|
||||||
|
// // console.log(target);
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
|
drake.on('drop', (el, target, source) => {
|
||||||
|
drake.cancel();
|
||||||
|
|
||||||
|
if (target !== source) {
|
||||||
|
fetch('/api/trip', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
accepts: 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
from: source.dataset.location,
|
||||||
|
to: target.dataset.location,
|
||||||
|
}),
|
||||||
|
}).then((res) => {
|
||||||
|
return res.json();
|
||||||
|
}).then((json) => {
|
||||||
|
console.log(json);
|
||||||
|
result.textContent = JSON.stringify(json, null, ' ')
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log('error');
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
drake.on('over', (el, target, source) => {
|
||||||
|
if (target !== source) {
|
||||||
|
target.classList.add('over');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
drake.on('out', (el, target, source) => {
|
||||||
|
if (target !== source) {
|
||||||
|
target.classList.remove('over');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
26
client/master.jsx
Normal file
26
client/master.jsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { h } from 'jsx-node';
|
||||||
|
|
||||||
|
export default ({ articleUrl, protocol, hostname, websocketsPort, INITIAL_STATE, js, css, cssFile }) => {
|
||||||
|
return '<!doctype html>' + (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Journey</title>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
|
<link type="text/css" rel="stylesheet" href={`/css/main` + (css ? css.suffix : '') + '.css'} />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div data-location="home" class="location l01"><div data-location="home" class="item"><span>Home</span></div></div>
|
||||||
|
<div data-location="office" class="location l02"><div data-location="office" class="item"><span>Office</span></div></div>
|
||||||
|
<div data-location="brother" class="location l03"><div data-location="brother" class="item"><span>Brother</span></div></div>
|
||||||
|
<div data-location="therapist" class="location l04"><div data-location="therapist" class="item"><span>The Rapist</span></div></div>
|
||||||
|
</div>
|
||||||
|
<pre></pre>
|
||||||
|
<script src={"/js/app" + (js ? js.suffix : '') + '.js'} />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
};
|
||||||
10
client/pages/Error.jsx
Normal file
10
client/pages/Error.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { h } from 'jsx-node';
|
||||||
|
|
||||||
|
export default ({ error = {}, regions = {}}) => (
|
||||||
|
<section className="error page">
|
||||||
|
<h1>Oops!</h1>
|
||||||
|
<p>Ett problem har tyvärr uppstått.</p>
|
||||||
|
<h2>{error.status} {error.statusText}</h2>
|
||||||
|
<p>{error.message}</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
1
gulp
Submodule
1
gulp
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 1daad4b4629c3ddef1f60710a0f7f8a67af9d714
|
||||||
51
gulpconfig.js
Normal file
51
gulpconfig.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const p = require('path');
|
||||||
|
|
||||||
|
// modules > native
|
||||||
|
module.exports = {
|
||||||
|
// babel: {
|
||||||
|
// src: 'client/**/*.{js,jsx}',
|
||||||
|
// dest: 'build',
|
||||||
|
// babelrc: false,
|
||||||
|
// presets: ['es2015-node6', 'es2016', 'es2017', 'stage-0'],
|
||||||
|
// plugins: [
|
||||||
|
// 'add-module-exports',
|
||||||
|
// ['transform-react-jsx'],
|
||||||
|
// ['transform-react-remove-prop-types'],
|
||||||
|
// ['module-resolver', {
|
||||||
|
// alias: {
|
||||||
|
// lowline: 'lodash',
|
||||||
|
// react: 'jsx-node',
|
||||||
|
// 'easy-tz': 'easy-tz/cjs',
|
||||||
|
// 'mini-qs': 'querystring',
|
||||||
|
// },
|
||||||
|
// }],
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
|
||||||
|
rollup: {
|
||||||
|
// plugins: {
|
||||||
|
// babel: {
|
||||||
|
// include: [
|
||||||
|
// 'node_modules/mini-qs/**',
|
||||||
|
// 'node_modules/easy-path/**',
|
||||||
|
// 'node_modules/comkit/**',
|
||||||
|
// 'client/**',
|
||||||
|
// ],
|
||||||
|
// babelrc: false,
|
||||||
|
// presets: ['es2015-rollup', 'es2016', 'es2017', 'stage-0'],
|
||||||
|
// plugins: [
|
||||||
|
// ['transform-react-jsx', { pragma: 'h' }],
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
entries: [
|
||||||
|
'index.js',
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
'app.js',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
1
gulpfile.js
Symbolic link
1
gulpfile.js
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
gulp/gulpfile.js
|
||||||
90
package.json
Normal file
90
package.json
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"name": "journey",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "server/server.js",
|
||||||
|
"scripts": {
|
||||||
|
"gulp": "gulp",
|
||||||
|
"gulp:production": "NODE_ENV=production gulp",
|
||||||
|
"gulp:development": "NODE_ENV=development gulp",
|
||||||
|
"gulp:staging": "NODE_ENV=staging gulp",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Linus Miller <lohfu@lohfu.io> (https://lohfu.io/)",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"body-parser": "^1.16.1",
|
||||||
|
"chalk": "^1.1.3",
|
||||||
|
"cookie-parser": "^1.4.3",
|
||||||
|
"dollr": "^0.1.2",
|
||||||
|
"dragula": "^3.7.2",
|
||||||
|
"express": "^4.14.1",
|
||||||
|
"express-session": "^1.15.1",
|
||||||
|
"jsx-node": "^0.2.2",
|
||||||
|
"lodash": "^4.17.4",
|
||||||
|
"midwest": "github:thebitmill/midwest",
|
||||||
|
"midwest-service-errors": "^0.2.0",
|
||||||
|
"morgan": "^1.8.1",
|
||||||
|
"pg": "^6.1.2",
|
||||||
|
"require-dir": "^0.3.1",
|
||||||
|
"superagent": "^3.5.0",
|
||||||
|
"useragent": "^2.1.12",
|
||||||
|
"xml2json": "^0.11.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"app-module-path": "^1.1.0",
|
||||||
|
"autoprefixer": "^6.7.2",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-plugin-module-resolver": "^2.5.0",
|
||||||
|
"babel-plugin-transform-react-jsx": "^6.23.0",
|
||||||
|
"babel-plugin-transform-react-remove-prop-types": "^0.3.2",
|
||||||
|
"babel-preset-es2015": "^6.22.0",
|
||||||
|
"babel-preset-es2015-node6": "^0.4.0",
|
||||||
|
"babel-preset-es2015-rollup": "^3.0.0",
|
||||||
|
"babel-preset-es2016": "^6.22.0",
|
||||||
|
"babel-preset-es2017": "^6.22.0",
|
||||||
|
"babel-preset-stage-0": "^6.22.0",
|
||||||
|
"babel-preset-stage-1": "^6.22.0",
|
||||||
|
"babel-preset-stage-2": "^6.22.0",
|
||||||
|
"babel-preset-stage-3": "^6.22.0",
|
||||||
|
"browser-sync": "^2.18.8",
|
||||||
|
"chalk": "^1.1.3",
|
||||||
|
"csswring": "^5.1.1",
|
||||||
|
"eslint": "^3.15.0",
|
||||||
|
"eslint-config-airbnb": "^14.1.0",
|
||||||
|
"eslint-config-airbnb-base": "^11.1.0",
|
||||||
|
"eslint-plugin-import": "^2.2.0",
|
||||||
|
"eslint-plugin-jsx-a11y": "^4.0.0",
|
||||||
|
"eslint-plugin-react": "^6.9.0",
|
||||||
|
"gulp": "github:gulpjs/gulp#4.0",
|
||||||
|
"gulp-babel": "^6.1.2",
|
||||||
|
"gulp-less": "^3.3.0",
|
||||||
|
"gulp-postcss": "^6.3.0",
|
||||||
|
"gulp-rename": "^1.2.2",
|
||||||
|
"gulp-sourcemaps": "^2.4.1",
|
||||||
|
"gulp-svgmin": "^1.2.3",
|
||||||
|
"gulp-uglify": "^2.0.1",
|
||||||
|
"gulp-util": "^3.0.8",
|
||||||
|
"jsx-node": "^0.2.1",
|
||||||
|
"less": "^2.7.2",
|
||||||
|
"lodash": "^4.17.4",
|
||||||
|
"merge-stream": "^1.0.1",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"nodemon": "^1.11.0",
|
||||||
|
"postcss": "^5.2.12",
|
||||||
|
"pretty-hrtime": "^1.0.3",
|
||||||
|
"rimraf": "^2.5.4",
|
||||||
|
"rollup": "^0.41.4",
|
||||||
|
"rollup-plugin-babel": "^2.7.1",
|
||||||
|
"rollup-plugin-commonjs": "^7.0.0",
|
||||||
|
"rollup-plugin-node-resolve": "^2.0.0",
|
||||||
|
"rollup-plugin-replace": "^1.1.1",
|
||||||
|
"serialize-error": "^2.1.0",
|
||||||
|
"supertest": "^3.0.0",
|
||||||
|
"tap-spec": "^4.1.1",
|
||||||
|
"tape": "^4.6.3",
|
||||||
|
"through2": "^2.0.3",
|
||||||
|
"vinyl-buffer": "^1.0.0",
|
||||||
|
"vinyl-source-stream": "^1.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
server/config/dir.js
Normal file
7
server/config/dir.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const p = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
static: p.join(PWD, 'public'),
|
||||||
|
};
|
||||||
51
server/config/error-handler.js
Normal file
51
server/config/error-handler.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const errorTemplate = require('../../build/pages/Error');
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
post: (req, res, next) => {
|
||||||
|
res.template = errorTemplate;
|
||||||
|
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
mystify: {
|
||||||
|
properties: ['errors', 'message', 'name', 'status', 'statusText'],
|
||||||
|
},
|
||||||
|
|
||||||
|
log: {
|
||||||
|
// if database = true there has to be a mongoose model name ErrorModel
|
||||||
|
ignore: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = require('midwest-service-errors/stores/postgres');
|
||||||
|
|
||||||
|
module.exports = _.merge(defaults, {
|
||||||
|
development: {
|
||||||
|
log: {
|
||||||
|
store,
|
||||||
|
console: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testing: {
|
||||||
|
log: {
|
||||||
|
store: false,
|
||||||
|
console: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
staging: {
|
||||||
|
log: {
|
||||||
|
store,
|
||||||
|
console: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
log: {
|
||||||
|
store,
|
||||||
|
console: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}[ENV]);
|
||||||
4
server/config/globals.js
Normal file
4
server/config/globals.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// global.LOGIN_USER = 'linus.miller@bitmill.co';
|
||||||
|
// global.LOGIN_USER = 'zarac@zarac.se';
|
||||||
106
server/config/membership.js
Normal file
106
server/config/membership.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
site: require('./site'),
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
invite: {
|
||||||
|
from: `${config.site.title} Robot <${config.site.emails.robot}>`,
|
||||||
|
subject: `You have been invited to ${config.site.title}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
changePassword: {
|
||||||
|
from: `${config.site.title} Robot <${config.site.emails.robot}>`,
|
||||||
|
subject: `Password Reset Request for ${config.site.title}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
timeouts: {
|
||||||
|
// 1 day
|
||||||
|
changePassword: 24 * 60 * 60 * 1000,
|
||||||
|
// verify email
|
||||||
|
verifyEmail: 7 * 24 * 60 * 60 * 1000,
|
||||||
|
},
|
||||||
|
|
||||||
|
paths: {
|
||||||
|
register: '/register',
|
||||||
|
login: '/login',
|
||||||
|
forgotPassword: '/forgot',
|
||||||
|
resetPassword: '/reset',
|
||||||
|
verifyEmail: '/verify',
|
||||||
|
},
|
||||||
|
|
||||||
|
redirects: {
|
||||||
|
login: '/',
|
||||||
|
logout: '/login',
|
||||||
|
register: '/login',
|
||||||
|
},
|
||||||
|
|
||||||
|
remember: {
|
||||||
|
// if expires is defined, it will be used. otherwise maxage
|
||||||
|
expires: new Date('2038-01-19T03:14:07.000Z'),
|
||||||
|
// expires: Date.now() - 1,
|
||||||
|
maxAge: 30 * 24 * 60 * 60 * 1000,
|
||||||
|
},
|
||||||
|
|
||||||
|
messages: {
|
||||||
|
login: {
|
||||||
|
notLocal: 'Account requires external login.',
|
||||||
|
wrongPassword: 'Wrong password.',
|
||||||
|
noUserFound: 'No user registered with that email.',
|
||||||
|
noExternalUser: 'The account is not connected to this website.',
|
||||||
|
externalLoginFailed: 'External login failed.',
|
||||||
|
emailNotVerified: 'This account\'s email has not been verified.',
|
||||||
|
banned: 'User is banned.',
|
||||||
|
blocked: 'User is blocked due to too many login attempts.',
|
||||||
|
},
|
||||||
|
|
||||||
|
register: {
|
||||||
|
missingProperties: 'Oh no missing stuff',
|
||||||
|
notAuthorized: 'The email is not authorized to create an account.',
|
||||||
|
duplicateEmail: 'The email has already been registered.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
passport: {
|
||||||
|
local: {
|
||||||
|
usernameField: 'email',
|
||||||
|
},
|
||||||
|
|
||||||
|
scope: ['email'],
|
||||||
|
|
||||||
|
//providers: {
|
||||||
|
// facebook: {
|
||||||
|
// clientID: 'change-this-fool',
|
||||||
|
// clientSecret: 'change-this-fool',
|
||||||
|
// callbackURL: p.join(config.site.domain, '/auth/facebook/callback'),
|
||||||
|
// passReqToCallback: true
|
||||||
|
// },
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
userColumns: [
|
||||||
|
'givenName',
|
||||||
|
'familyName',
|
||||||
|
'dateBanned',
|
||||||
|
'dateBlocked',
|
||||||
|
'dateMuted',
|
||||||
|
'dateVerified',
|
||||||
|
// ['array(SELECT name FROM user_roles LEFT OUTER JOIN roles ON user_roles.role_id = roles.id WHERE user_roles.user_id = users.id)', 'roles'],
|
||||||
|
[`(SELECT array_to_json(array_agg(row_to_json(d)))
|
||||||
|
FROM (
|
||||||
|
SELECT id, name
|
||||||
|
FROM user_roles
|
||||||
|
LEFT OUTER JOIN roles ON user_roles.role_id = roles.id WHERE user_roles.user_id = users.id
|
||||||
|
ORDER BY roles.id DESC
|
||||||
|
) d
|
||||||
|
)`, 'roles'],
|
||||||
|
],
|
||||||
|
|
||||||
|
// needs to be even
|
||||||
|
tokenLength: 64,
|
||||||
|
// needs to be even
|
||||||
|
saltLength: 16,
|
||||||
|
};
|
||||||
10
server/config/port.js
Normal file
10
server/config/port.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const basePort = 3060;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
development: basePort,
|
||||||
|
testing: basePort + 1,
|
||||||
|
staging: basePort + 2,
|
||||||
|
production: basePort + 3,
|
||||||
|
}[ENV];
|
||||||
16
server/config/postgres.js
Normal file
16
server/config/postgres.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
user: 'newseri_supreme', // env var: PGUSER
|
||||||
|
database: 'newseri', // env var: PGDATABASE
|
||||||
|
password: 'oh-look-it-is-raining-news', // env var: PGPASSWORD
|
||||||
|
// host: '192.168.1.11', // Server hosting the postgres database
|
||||||
|
host: 'hq.bitmill.co', // Server hosting the postgres database
|
||||||
|
// port: 5432, // env var: PGPORT
|
||||||
|
port: 6543, // env var: PGPORT
|
||||||
|
max: 10, // max number of clients in the pool
|
||||||
|
idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Object.assign(defaults, {
|
||||||
|
}[ENV]);
|
||||||
38
server/config/session.js
Normal file
38
server/config/session.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const session = require('express-session');
|
||||||
|
|
||||||
|
let redisStore;
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
secret: 'asdfpoi7u987777777777777777777sdkafjxxjasdhfhsadfhashdfh`1111111khjjashdfkasjhdflGGGGGGGGGGaaa^^^^^^^^^^yaghsdfqw3u7679`',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const redisConfig = {
|
||||||
|
host: 'localhost',
|
||||||
|
port: 6379,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ENV === 'production') {
|
||||||
|
const RedisStore = require('connect-redis')(require('express-session'));
|
||||||
|
|
||||||
|
redisStore = new RedisStore(redisConfig);
|
||||||
|
|
||||||
|
redisStore.on('connect', () => {
|
||||||
|
console.info(`[${chalk.cyan('INIT')}] Redis connected succcessfully`);
|
||||||
|
});
|
||||||
|
|
||||||
|
redisStore.on('disconnect', () => {
|
||||||
|
throw new Error('Unable to connect to redis. Has it been started?');
|
||||||
|
});
|
||||||
|
|
||||||
|
config.store = redisStore;
|
||||||
|
} else {
|
||||||
|
config.store = new session.MemoryStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
|
|
||||||
34
server/config/shim.js
Normal file
34
server/config/shim.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
'https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js': [
|
||||||
|
'chrome <= 12',
|
||||||
|
'firefox <= 20',
|
||||||
|
'ie <= 9',
|
||||||
|
'opera <= 12',
|
||||||
|
'safari <= 5',
|
||||||
|
],
|
||||||
|
'https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.1/es6-shim.min.js': [
|
||||||
|
// 'https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js': [
|
||||||
|
// 'https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.16.0/polyfill.js': [
|
||||||
|
'chrome <= 51',
|
||||||
|
'edge <= 13',
|
||||||
|
'firefox <= 44',
|
||||||
|
'ie <= 11',
|
||||||
|
'safari <= 9',
|
||||||
|
],
|
||||||
|
'https://unpkg.com/es7-shim@latest/dist/es7-shim.min.js': [
|
||||||
|
'chrome <= 50',
|
||||||
|
'edge <= 14',
|
||||||
|
'firefox <= 46',
|
||||||
|
'ie <= 11',
|
||||||
|
'safari <= 10',
|
||||||
|
],
|
||||||
|
'https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js': [
|
||||||
|
'chrome <= 41',
|
||||||
|
'edge <= 13',
|
||||||
|
'firefox <= 38',
|
||||||
|
'ie <= 11',
|
||||||
|
'safari <= 9',
|
||||||
|
],
|
||||||
|
};
|
||||||
51
server/config/site.js
Normal file
51
server/config/site.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const domain = 'newseri.com';
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
domain,
|
||||||
|
title: 'Newseri Admin',
|
||||||
|
name: 'newseri-admin',
|
||||||
|
protocol: 'http',
|
||||||
|
get host() {
|
||||||
|
return this.port ? this.hostname + ':' + this.port : this.hostname;
|
||||||
|
},
|
||||||
|
get url() {
|
||||||
|
return this.protocol + '://' + this.host + '/';
|
||||||
|
},
|
||||||
|
emails: {
|
||||||
|
robot: 'no-reply@thecodebureau.com',
|
||||||
|
info: 'info@thecodebureau.com',
|
||||||
|
webmaster: 'webmaster@thecodebureau.com',
|
||||||
|
order: 'info@thecodebureau.com',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = _.merge(defaults, {
|
||||||
|
development: {
|
||||||
|
hostname: 'localhost',
|
||||||
|
port: process.env.EXTERNAL_PORT || process.env.PORT || require('./port'),
|
||||||
|
},
|
||||||
|
|
||||||
|
testing: {
|
||||||
|
hostname: 'localhost',
|
||||||
|
port: process.env.PORT || require('./port'),
|
||||||
|
},
|
||||||
|
|
||||||
|
staging: {
|
||||||
|
hostname: `admin.${domain}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
production: {
|
||||||
|
hostname: `admin.${domain}`,
|
||||||
|
protocol: 'https',
|
||||||
|
// emails: {
|
||||||
|
// robot: 'no-reply@' + domain,
|
||||||
|
// info: 'info@' + domain,
|
||||||
|
// webmaster: 'webmaster@' + domain,
|
||||||
|
// order: 'order@' + domain,
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
}[ENV]);
|
||||||
15
server/config/smtp.js
Normal file
15
server/config/smtp.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
auth: {
|
||||||
|
user: 'SMTP_Injection',
|
||||||
|
// dev key
|
||||||
|
pass: '2eec390c5b3f5d593c9f152179bf51e90b073784',
|
||||||
|
},
|
||||||
|
host: 'smtp.sparkpostmail.com',
|
||||||
|
port: 587,
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = _.merge(defaults, {}[ENV]);
|
||||||
6
server/db.js
Normal file
6
server/db.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const factory = require('midwest/util/db');
|
||||||
|
const conf = require('./config/postgres');
|
||||||
|
|
||||||
|
module.exports = factory(conf);
|
||||||
10
server/midwest.js
Normal file
10
server/midwest.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// const requireDir = require('require-dir');
|
||||||
|
// const membership = require('midwest-module-membership');
|
||||||
|
|
||||||
|
// const config = requireDir('./config', { camelcase: true });
|
||||||
|
// const db = require('./db');
|
||||||
|
|
||||||
|
|
||||||
|
// membership.configure(Object.assign({ db, site: config.site, smtp: config.smtp }, config.membership));
|
||||||
32
server/render.js
Normal file
32
server/render.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { h } = require('jsx-node');
|
||||||
|
|
||||||
|
module.exports = function (Component, Master) {
|
||||||
|
const locals = Object.assign({ query: this.req.query }, this.app.locals, this.locals);
|
||||||
|
|
||||||
|
let html;
|
||||||
|
|
||||||
|
if (typeof Master === 'function') {
|
||||||
|
if (typeof Component === 'function') {
|
||||||
|
return this.send(
|
||||||
|
h(Master, locals,
|
||||||
|
h(Component, locals)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component = Master;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Component !== 'function') {
|
||||||
|
throw new Error('Not a Component');
|
||||||
|
} else if (Component.prototype && Component.prototype.render) {
|
||||||
|
const i = new Component(locals);
|
||||||
|
html = i.render(i.props, i.state);
|
||||||
|
} else {
|
||||||
|
html = Component(locals);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.send(html);
|
||||||
|
};
|
||||||
67
server/routers/api.js
Normal file
67
server/routers/api.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
const request = require('superagent');
|
||||||
|
|
||||||
|
// import get from 'get-value';
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const xml2json = require('xml2json');
|
||||||
|
|
||||||
|
// const to = 'Lund Mellanvångsvägen';
|
||||||
|
// const from = 'Malmö Triangeln';
|
||||||
|
|
||||||
|
// request(`http://www.labs.skanetrafiken.se/v2.2/querypage.asp?inpPointFr=${encodeURIComponent(from)}&inpPointTo=${encodeURIComponent(to)}`).then((res) => {
|
||||||
|
// console.dir(xml2json.toJson(res.text, { object: true }), { colors: true, depth: null });
|
||||||
|
// });
|
||||||
|
|
||||||
|
const stations = {
|
||||||
|
home: {
|
||||||
|
id: '81016',
|
||||||
|
name: 'Lund Idrottsplatsen',
|
||||||
|
type: 'STOP_AREA',
|
||||||
|
},
|
||||||
|
|
||||||
|
office: {
|
||||||
|
name: 'Lund John Ericssons väg',
|
||||||
|
id: 81229,
|
||||||
|
type: 'STOP_AREA',
|
||||||
|
},
|
||||||
|
|
||||||
|
brother: {
|
||||||
|
id: '81831',
|
||||||
|
name: 'Lund Mellanvångsvägen',
|
||||||
|
type: 'STOP_AREA',
|
||||||
|
},
|
||||||
|
therapist: {
|
||||||
|
id: '80140',
|
||||||
|
name: 'Malmö Triangeln',
|
||||||
|
type: 'STOP_AREA',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const types = {
|
||||||
|
'STOP_AREA': 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = new (require('express')).Router();
|
||||||
|
|
||||||
|
function formatStation(json) {
|
||||||
|
return `${encodeURIComponent(json.name)}|${json.id}|${types[json.type]}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const journeysPath = [ 'soap:Envelope', 'soap:Body', 'GetJourneyResponse', 'GetJourneyResult', 'Journeys', 'Journey']
|
||||||
|
// http://www.labs.skanetrafiken.se/v2.2/resultspage.asp?cmdaction=next&selPointFr=malm%F6%20C|80000|0&selPointTo=landskrona|82000|0&LastStart=2017-02-23%2016:38
|
||||||
|
router.post('/trip', (req, res, next) => {
|
||||||
|
request(`http://www.labs.skanetrafiken.se/v2.2/resultspage.asp?cmdaction=next&selPointFr=${formatStation(stations[req.body.from])}&selPointTo=${formatStation(stations[req.body.to])}&LastStart=2017-02-23%2016:38`).then((response) =>{
|
||||||
|
const result = _.get(xml2json.toJson(response.text, { object: true }), journeysPath);
|
||||||
|
|
||||||
|
result.forEach((obj) => {
|
||||||
|
delete obj.Prices
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
106
server/routers/index.js
Normal file
106
server/routers/index.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// const masterTemplate = require('../client/public/components/Master');
|
||||||
|
const masterTemplate = require('../../build/master');
|
||||||
|
// const loginFormTemplate = require('../build/components/login-form/template');
|
||||||
|
// const registerFormTemplate = require('../build/components/register-form/template');
|
||||||
|
// const changePasswordFormTemplate = require('../build/components/change-password-form/template');
|
||||||
|
// const forgotPasswordFormTemplate = require('../build/components/forgot-password-form/template');
|
||||||
|
// const bareMasterTemplate = require('../build/bare-master');
|
||||||
|
|
||||||
|
const router = new (require('express')).Router();
|
||||||
|
|
||||||
|
const startCase = require('lodash/startCase');
|
||||||
|
|
||||||
|
const mw = {
|
||||||
|
// employees: require('midwest-service-employees/middleware'),
|
||||||
|
// errors: require('midwest-service-errors/middleware'),
|
||||||
|
// invites: require('midwest-module-membership/services/invites/middleware'),
|
||||||
|
// organization: require('midwest-service-organization/middleware'),
|
||||||
|
// permissions: require('midwest-module-membership/services/permissions/middleware'),
|
||||||
|
// users: require('midwest-module-membership/services/users/middleware'),
|
||||||
|
// regions: require('midwest-service-regions/middleware'),
|
||||||
|
// publishers: require('../services/publishers/middleware'),
|
||||||
|
// roles: require('midwest-module-membership/services/roles/middleware'),
|
||||||
|
// users: require('../services/users/users-middleware'),
|
||||||
|
shim: require('midwest/factories/shim')(require('../config/shim')),
|
||||||
|
};
|
||||||
|
|
||||||
|
// const {
|
||||||
|
// isAuthenticated,
|
||||||
|
// isAdmin,
|
||||||
|
// redirectUnauthorized,
|
||||||
|
// redirectAuthorized,
|
||||||
|
// } = require('midwest-module-membership/passport/authorization-middleware');
|
||||||
|
|
||||||
|
const allowedRoutes = ['forgot', 'reset', 'verify', 'login', 'register'];
|
||||||
|
|
||||||
|
// const config = {
|
||||||
|
// membership: require('../config/membership'),
|
||||||
|
// };
|
||||||
|
|
||||||
|
router
|
||||||
|
// .get(new RegExp(`/(?!(${allowedRoutes.join('|')}))`), isAdmin, redirectUnauthorized(config.membership.paths.login), (req, res, next) => {
|
||||||
|
// .get(new RegExp(`/(?!(${allowedRoutes.join('|')}))`), (req, res, next) => {
|
||||||
|
// .get(new RegExp(`/(?!(${allowedRoutes.join('|')}))`), isAuthenticated, redirectUnauthorized(config.membership.paths.login))
|
||||||
|
// .get(new RegExp(`/(?=(${allowedRoutes.join('|')}))`), redirectAuthorized(isAuthenticated, '/'))
|
||||||
|
.get('/', mw.shim, (req, res, next) => {
|
||||||
|
res.preventFlatten = true;
|
||||||
|
|
||||||
|
res.master = masterTemplate;
|
||||||
|
|
||||||
|
next();
|
||||||
|
})
|
||||||
|
// .get(new RegExp(`/${allowedRoutes.join('|')}`), redirectAuthenticated('/'), (req, res, next) => {
|
||||||
|
// res.preventFlatten = true;
|
||||||
|
|
||||||
|
// res.master = bareMasterTemplate;
|
||||||
|
|
||||||
|
// next();
|
||||||
|
// })
|
||||||
|
// .get('/login', (req, res, next) => {
|
||||||
|
// res.locals.scripts = ['/js/login.js'];
|
||||||
|
|
||||||
|
// res.template = loginFormTemplate;
|
||||||
|
|
||||||
|
// next();
|
||||||
|
// })
|
||||||
|
// .get('/register', mw.invites.findByTokenAndEmail, (req, res, next) => {
|
||||||
|
// res.locals.scripts = ['/js/register.js'];
|
||||||
|
|
||||||
|
// res.template = registerFormTemplate;
|
||||||
|
|
||||||
|
// next();
|
||||||
|
// })
|
||||||
|
// .get('/change-password', (req, res, next) => {
|
||||||
|
// res.locals.scripts = ['/js/change-password.js'];
|
||||||
|
|
||||||
|
// res.template = changePasswordFormTemplate;
|
||||||
|
|
||||||
|
// next();
|
||||||
|
// })
|
||||||
|
// .get('/forgot-password', (req, res, next) => {
|
||||||
|
// res.locals.scripts = ['/js/forgot-password.js'];
|
||||||
|
|
||||||
|
// res.template = forgotPasswordFormTemplate;
|
||||||
|
|
||||||
|
// next();
|
||||||
|
// .get('/membership/users/:id', mw.publishers.getAll, mw.roles.getAll, mw.users.findById, (req, res, next) => {
|
||||||
|
// console.log(res.locals.roles);
|
||||||
|
// // res.locals.allRoles = res.locals.roles;
|
||||||
|
// // console.log(res.locals);
|
||||||
|
// // res.locals.allPublishers = res.locals.publishers.filter((publisher) => !res.locals.user.publishers.some((p) => {
|
||||||
|
// // return publisher._id.toString() === p._id.toString();
|
||||||
|
// // }));
|
||||||
|
// // delete res.locals.roles;
|
||||||
|
// // delete res.locals.publishers;
|
||||||
|
// next();
|
||||||
|
// })
|
||||||
|
// .get('/errors', mw.errors.formatQuery, mw.errors.paginate, mw.errors.find)
|
||||||
|
// .get('/login')
|
||||||
|
// .get('/forgot')
|
||||||
|
// .get('/reset')
|
||||||
|
// .get('/verify')
|
||||||
|
;
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
117
server/server.js
Normal file
117
server/server.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main file that sets up the Express instance and node
|
||||||
|
*
|
||||||
|
* @module server/server
|
||||||
|
* @type {Express instance}
|
||||||
|
*/
|
||||||
|
|
||||||
|
global.ENV = process.env.NODE_ENV || 'development';
|
||||||
|
global.PWD = process.env.NODE_PWD || process.cwd();
|
||||||
|
|
||||||
|
// modules > native
|
||||||
|
const p = require('path');
|
||||||
|
|
||||||
|
if (ENV === 'development') {
|
||||||
|
// output filename in console log and colour console.dir
|
||||||
|
require('midwest/util/console');
|
||||||
|
// needed so symlinked modules get access to main projects node_modules/
|
||||||
|
require('app-module-path').addPath(p.join(PWD, 'node_modules'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// modules > 3rd party
|
||||||
|
const _ = require('lodash');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const express = require('express');
|
||||||
|
// const passport = require('passport');
|
||||||
|
const requireDir = require('require-dir');
|
||||||
|
|
||||||
|
// modules > express middlewares
|
||||||
|
const bodyParser = require('body-parser');
|
||||||
|
// const session = require('express-session');
|
||||||
|
// const cookieParser = require('cookie-parser');
|
||||||
|
|
||||||
|
// modules > midwest
|
||||||
|
const colorizeStack = require('midwest/util/colorize-stack');
|
||||||
|
|
||||||
|
// make error output stack pretty
|
||||||
|
process.on('uncaughtException', (err) => {
|
||||||
|
console.error(chalk.red('UNCAUGHT EXCEPTION'));
|
||||||
|
if (err.stack) {
|
||||||
|
console.error(colorizeStack(err.stack));
|
||||||
|
} else {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// midwest modules and services configuration
|
||||||
|
require('./midwest');
|
||||||
|
|
||||||
|
const config = requireDir('./config', { camelcase: true });
|
||||||
|
|
||||||
|
const prewares = [
|
||||||
|
express.static(config.dir.static, ENV === 'production' ? { maxAge: '1 year' } : null),
|
||||||
|
bodyParser.json(),
|
||||||
|
bodyParser.urlencoded({ extended: true }),
|
||||||
|
// cookieParser(),
|
||||||
|
// session(config.session),
|
||||||
|
// passport.initialize(),
|
||||||
|
// passport.session(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (ENV === 'development') {
|
||||||
|
// only log requests to console in development mode
|
||||||
|
prewares.unshift(require('morgan')('dev'));
|
||||||
|
// prewares.push(require('midwest-module-membership/passport/automatic-login'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const postwares = [
|
||||||
|
require('midwest/middleware/ensure-found'),
|
||||||
|
// transform and log error
|
||||||
|
require('midwest/factories/error-handler')(config.errorHandler),
|
||||||
|
// respond
|
||||||
|
require('midwest/middleware/responder'),
|
||||||
|
];
|
||||||
|
|
||||||
|
const server = express();
|
||||||
|
|
||||||
|
// get IP & whatnot from nginx proxy
|
||||||
|
server.set('trust proxy', true);
|
||||||
|
|
||||||
|
_.extend(server.locals, {
|
||||||
|
site: require('./config/site'),
|
||||||
|
});
|
||||||
|
|
||||||
|
// override default response render method for
|
||||||
|
// more convenient use with marko
|
||||||
|
server.response.render = require('./render');
|
||||||
|
|
||||||
|
try {
|
||||||
|
server.locals.js = require(p.join(PWD, 'public/js.json'));
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
server.locals.css = require(p.join(PWD, 'public/css.json'));
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
// load prewares
|
||||||
|
server.use(...prewares);
|
||||||
|
|
||||||
|
// mount routers
|
||||||
|
server.use(require('./routers/index'));
|
||||||
|
server.use('/api', require('./routers/api'));
|
||||||
|
// server.use('/auth', require('midwest-module-membership/passport/router'));
|
||||||
|
|
||||||
|
// load postwares
|
||||||
|
server.use(...postwares);
|
||||||
|
|
||||||
|
// Only start Express server when it is the main module (ie not required by test)
|
||||||
|
if (require.main === module) {
|
||||||
|
server.http = server.listen(config.port, () => {
|
||||||
|
console.info(`[${chalk.cyan('INIT')}] HTTP Server listening on port ${chalk.magenta(config.port)} (${chalk.yellow(ENV)})`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = server;
|
||||||
Loading…
Reference in New Issue
Block a user