14 Commits

Author SHA1 Message Date
Lukas F. Hartmann
820203625c don't default to app volume mount; create s3 bucket on boot; fix revAll gulp step 2017-04-07 18:01:23 +02:00
Martin Guether
03059b67f1 add gulp stuff to build process 2017-04-07 15:34:33 +02:00
Martin Guether
1426bc9c24 updated storage config 2017-04-07 13:07:09 +02:00
Martin Guether
bd0471dad6 added docker ignore 2017-04-07 12:03:58 +02:00
Martin Guether
bbdcb2b2fe Merge remote-tracking branch 'origin/master' into docker
# Conflicts:
#	README.md
2017-04-07 12:00:28 +02:00
Martin Guether
af5335025f fixed crash on console 2017-04-07 11:58:29 +02:00
Martin Guether
f9cf8ba7e8 update ports and variables for docker compose bootstrap 2017-04-07 11:55:07 +02:00
Martin Guether
9877977750 add configuration lines to readme 2017-04-07 11:05:12 +02:00
Martin Guether
bda60bf877 add engine to package.json 2017-04-07 11:04:58 +02:00
Martin Guether
7605b8f373 node update 2017-04-07 10:59:10 +02:00
Martin Guether
dfcfd7f0b8 added binary dependencies to readme 2017-04-07 10:57:33 +02:00
Martin Guether
a3e2129b79 added experiemental docker support 2017-04-07 10:50:48 +02:00
Martin Guether
2e34b317a4 update packages 2017-04-07 10:39:35 +02:00
Martin Guether
d887d56dd3 fixed schema import for artifact 2017-04-07 10:39:24 +02:00
18 changed files with 203 additions and 99 deletions

14
.dockerignore Normal file
View File

@@ -0,0 +1,14 @@
.DS_Store
.git
logs
*.log
scripts
pids
*.pid
*.seed
lib-cov
coverage
.grunt
.lock-wscript
build/Release
node_modules

19
Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
FROM spacedeck/docker-baseimage:latest
ENV NODE_ENV production
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
RUN npm install gulp-rev-replace gulp-clean gulp-fingerprint gulp-rev gulp-rev-all gulp-rev-replace
RUN npm install -g --save-dev gulp
COPY . /usr/src/app
RUN gulp styles
RUN npm cache clean
CMD [ "npm", "start" ]
EXPOSE 9666

View File

@@ -12,10 +12,9 @@ var uglify = require('gulp-uglify');
var fingerprint = require('gulp-fingerprint');
var rev = require('gulp-rev');
var RevAll = require('gulp-rev-all');
var revAll = require('gulp-rev-all');
gulp.task('rev', () => {
var revAll = new RevAll();
return gulp.src(['public/**'])
.pipe(gulp.dest('build/assets'))
.pipe(revAll.revision())

View File

@@ -23,16 +23,16 @@ We appreciate filed issues, pull requests and general discussion.
Spacedeck uses the following major building blocks:
- Node.js 4.x (Backend / API)
- Vue.js (Frontend)
- Node.js 7.x (Backend / API)
- MongoDB 3.x (Datastore)
- Redis 3.x (Datastore for realtime channels)
- Vue.js (Frontend)
It also has some binary dependencies for media conversion and PDF export:
- imagemagick
- imagemagick, graphicsmagick, libav(+codecs, ffmpeg replacement), audiowaveform (https://github.com/bbcrd/audiowaveform), phantomjs (http://phantomjs.org/)
Currently, media files are stored in Amazon S3, so you need an Amazon AWS account and have the ```AWS_ACCESS_KEY_ID``` and ```AWS_SECRET_ACCESS_KEY``` environment variables defined. For sending emails, Amazon SES is required.
Currently, media files are stored in Amazon S3, so you need an Amazon AWS account and have the ```AWS_ACCESS_KEY_ID``` and ```AWS_SECRET_ACCESS_KEY``` environment variables defined. For sending emails in production, Amazon SES is required.
To install Spacedeck, you need node.js 4.x and a running MongoDB instance. Then, to install all node dependencies, run
@@ -42,10 +42,22 @@ To rebuild the frontend CSS styles (you need to do this at least once):
gulp styles
# Configuration
see: config/config.json
# Run
export NODE_ENV=development
npm start
open http://localhost:9666
# experimental docker(compose) support
We have a docker base image at https://github.com/spacedeck/docker-baseimage that includes all required binaries. Based on this image we can use Docker-Compose to bootstrap a Spacedeck including data storages.
docker-compose build
docker-compose run -e ENV=development -p 9666:9666 -e NODE_ENV=development spacedeck-open
# License

6
app.js
View File

@@ -47,7 +47,7 @@ swig.setFilter('cdn', function(input, idx) {
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
if (app.get('env') != 'development') {
if (isProduction) {
app.set('views', path.join(__dirname, 'build', 'views'));
app.use(favicon(path.join(__dirname, 'build', 'assets', 'images', 'favicon.png')));
app.use(express.static(path.join(__dirname, 'build', 'assets')));
@@ -121,11 +121,11 @@ if (app.get('env') == 'development') {
module.exports = app;
// CONNECT TO DATABASE
const mongoHost = process.env.MONGO_PORT_27017_TCP_ADDR || 'localhost';
const mongoHost = process.env.MONGO_PORT_27017_TCP_ADDR || 'db';
mongoose.connect('mongodb://' + mongoHost + '/spacedeck');
// START WEBSERVER
const port = 9000;
const port = 9666;
const server = http.Server(app).listen(port, () => {

View File

@@ -1,7 +1,8 @@
{
"endpoint": "http://localhost:9000",
"storage_bucket": "my_spacedeck_s3_bucket",
"storage_cdn": "xyz.cloudfront.net",
"endpoint": "http://localhost:9666",
"storage_bucket": "sdeck-development",
"storage_cdn": "http://localhost:9123/sdeck-development",
"storage_endpoint": "http://storage:9000",
"google_access" : "",
"google_secret" : "",
"admin_pass": "very_secret_admin_password",

34
docker-compose.yml Normal file
View File

@@ -0,0 +1,34 @@
version: '2'
services:
sync:
image: redis
storage:
image: minio/minio
environment:
- MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
- MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
ports:
- 9123:9000
command: server /export
db:
image: mongo
spacedeck-open:
environment:
- env=development
- MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
- MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
build: .
volumes:
# - ./:/usr/src/app
- /usr/src/app/node_modules
command: npm start
ports:
- 9666:9666
depends_on:
- db
- sync
- storage
links:
- storage
- db
- sync

View File

@@ -32,31 +32,36 @@ module.exports = {
};
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) {
return browser.createPage(function (err, page) {
console.log("page created, opening ",space_url);
if(err){
console.log(err);
}else{
return browser.createPage(function (err, page) {
console.log("page created, opening ",space_url);
if (type=="pdf") {
var psz = {
width: space.advanced.width+"px",
height: space.advanced.height+"px"
};
page.set('paperSize', psz);
}
if (type=="pdf") {
var psz = {
width: space.advanced.width+"px",
height: space.advanced.height+"px"
};
page.set('paperSize', psz);
}
page.set('settings.resourceTimeout',timeout);
page.set('settings.javascriptEnabled',false);
page.set('settings.resourceTimeout',timeout);
page.set('settings.javascriptEnabled',false);
return page.open(space_url, function (err,status) {
page.render(export_path, function() {
on_success_called = true;
if (on_success) {
on_success(export_path);
}
page.close();
browser.exit();
return page.open(space_url, function (err,status) {
page.render(export_path, function() {
on_success_called = true;
if (on_success) {
on_success(export_path);
}
page.close();
browser.exit();
});
});
});
});
}
}, {
onExit: on_exit
});

View File

@@ -5,7 +5,7 @@ const websockets = require('./websockets');
module.exports = {
connectRedis(){
const redisHost = process.env.REDIS_PORT_6379_TCP_ADDR || 'localhost';
const redisHost = process.env.REDIS_PORT_6379_TCP_ADDR || 'sync';
this.connection = new RedisConnection(6379, redisHost);
},
sendMessage(action, model, attributes, channelId) {

View File

@@ -6,11 +6,34 @@ AWS.config.region = 'eu-central-1';
var fs = require('fs');
var config = require('config');
var cdn = config.get("storage_cdn");
var storage_endpoint = config.get("storage_endpoint");
const bucketName = "sdeck-fresh-development";
const ep = new AWS.Endpoint(storage_endpoint);
AWS.config.update(new AWS.Config({
accessKeyId: process.env.MINIO_ACCESS_KEY,
secretAccessKey: process.env.MINIO_SECRET_KEY,
region: 'us-east-1',
s3ForcePathStyle: true,
signatureVersion: 'v4'
}));
const s3 = new AWS.S3({
endpoint: ep
});
s3.createBucket({
Bucket: config.get("storage_bucket"),
ACL: "public-read",
GrantRead: "*"
}, (err,res) => {
console.log("createBucket",err,res);
});
module.exports = {
removeFile: (path, callback) => {
const s3 = new AWS.S3({
region: 'eu-central-1'
});
const bucket = config.get("storage_bucket");
s3.deleteObject({
Bucket: bucket, Key: path
@@ -28,7 +51,7 @@ module.exports = {
callback({error:"missing path"}, null);
return;
}
console.log("[s3] uploading", localFilePath, " to ", fileName);
console.log("[storage] uploading", localFilePath, " to ", fileName);
const bucket = config.get("storage_bucket");
const fileStream = fs.createReadStream(localFilePath);
@@ -39,11 +62,6 @@ module.exports = {
}
});
fileStream.on('open', function () {
// FIXME
var s3 = new AWS.S3({
region: 'eu-central-1'
});
s3.putObject({
Bucket: bucket,
Key: fileName,
@@ -54,7 +72,7 @@ module.exports = {
console.error(err);
callback(err);
}else {
const url = "https://"+ config.get("storage_cdn") + "/" + fileName;
const url = cdn + "/" + fileName;
console.log("[s3]" + localFilePath + " to " + url);
callback(null, url);
}

View File

@@ -3,7 +3,7 @@ require('../models/schema');
const WebSocketServer = require('ws').Server;
const Redis = require('ioredis');
const RedisConnection = require('ioredis');
const async = require('async');
const _ = require("underscore");
const mongoose = require("mongoose");
@@ -12,7 +12,7 @@ const crypto = require('crypto');
module.exports = {
startWebsockets: function(server){
this.setupSubscription();
this.state = new Redis(6379, process.env.REDIS_PORT_6379_TCP_ADDR || 'localhost');
this.state = new RedisConnection(6379, process.env.REDIS_PORT_6379_TCP_ADDR || 'sync');
if(!this.current_websockets){
this.current_websockets = [];
@@ -117,7 +117,7 @@ module.exports = {
},
setupSubscription: function() {
this.cursorSubscriber = new Redis(6379, process.env.REDIS_PORT_6379_TCP_ADDR || 'localhost');
this.cursorSubscriber = new RedisConnection(6379, process.env.REDIS_PORT_6379_TCP_ADDR || 'sync');
this.cursorSubscriber.subscribe(['cursors', 'users', 'updates'], function (err, count) {
console.log("[redis] websockets to " + count + " topics." );
});

View File

@@ -3,7 +3,7 @@
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports.artifactSchema = mongoose.model('Artifact', {
module.exports.artifactSchema = Schema({
mime: String,
thumbnail_uri: String,
space_id: Schema.Types.ObjectId,

View File

@@ -45,7 +45,7 @@ module.exports.teamSchema.index({
module.exports.teamSchema.statics.getTeamForHost = (host, cb) => {
if (host != "127.0.0.1:9000") { //phantomjs check
if (host != "127.0.0.1:9666") { //phantomjs check
let subDomainParts = host.split('.');
if (subDomainParts.length > 2) {

View File

@@ -6,24 +6,27 @@
"start": "nodemon -e .js,.html bin/www",
"test": "mocha"
},
"engines" : {
"node" : ">=7.8.0"
},
"dependencies": {
"archiver": "0.14.4",
"async": "1.3.0",
"aws-sdk": "2.1.39",
"basic-auth": "1.0.3",
"bcrypt": "*",
"body-parser": "~1.13.1",
"cheerio": "0.19.0",
"config": "1.14.0",
"cookie-parser": "~1.3.5",
"csurf": "1.8.3",
"debug": "~2.2.0",
"archiver": "1.3.0",
"async": "2.3.0",
"aws-sdk": "2.39.0",
"basic-auth": "1.1.0",
"bcryptjs": "2.4.3",
"body-parser": "~1.17.1",
"cheerio": "0.22.0",
"config": "1.25.1",
"cookie-parser": "~1.4.3",
"csurf": "1.9.0",
"debug": "~2.6.3",
"execSync": "latest",
"express": "~4.13.0",
"glob": "5.0.14",
"gm": "1.18.1",
"googleapis": "2.1.3",
"gulp": "^3.9.0",
"glob": "7.1.1",
"gm": "1.23.0",
"googleapis": "18.0.0",
"gulp": "^3.9.1",
"gulp-concat": "2.6.0",
"gulp-eslint": "*",
"gulp-express": "0.3.0",
@@ -31,51 +34,50 @@
"gulp-sass": "^2.0.3",
"gulp-uglify": "^1.5.1",
"gulp-util": "^3.0.6",
"helmet": "^1.1.0",
"i18n-2": "0.4.6",
"ioredis": "1.6.1",
"helmet": "^3.5.0",
"i18n-2": "0.6.3",
"ioredis": "2.5.0",
"lodash": "^4.3.0",
"log-timestamp": "latest",
"md5": "2.0.0",
"moment": "2.10.6",
"mongoose": "4.4.3",
"morgan": "1.6.1",
"node-sass-middleware": "0.8.0",
"pdfkit": "0.7.1",
"validator": "5.2.0",
"md5": "2.2.1",
"moment": "2.18.1",
"mongoose": "4.9.3",
"morgan": "1.8.1",
"node-sass-middleware": "0.11.0",
"pdfkit": "0.8.0",
"validator": "7.0.0",
"node-phantom-simple": "2.2.4",
"phantomjs-prebuilt": "2.1.7",
"phantomjs-prebuilt": "2.1.14",
"pm2": "latest",
"qr-image": "3.1.0",
"raven": "0.8.1",
"request": "2.60.0",
"qr-image": "3.2.0",
"raven": "1.2.0",
"request": "2.81.0",
"sanitize-html": "^1.11.1",
"serve-favicon": "~2.3.0",
"serve-favicon": "~2.4.2",
"swig": "1.4.2",
"slug": "0.9.1",
"underscore": "1.8.3",
"weak": "1.0.0",
"ws": "0.7.2"
"weak": "1.0.1",
"ws": "2.2.3"
},
"devDependencies": {
"express": "^4.13.3",
"gulp": "^3.9.0",
"gulp": "^3.9.1",
"gulp-clean": "^0.3.2",
"gulp-concat": "^2.6.0",
"gulp-eslint": "^1.1.0",
"gulp-eslint": "^3.0.1",
"gulp-express": "^0.3.0",
"gulp-fingerprint": "^0.3.2",
"gulp-nodemon": "^2.0.4",
"gulp-rev": "^6.0.1",
"gulp-rev-all": "^0.8.22",
"gulp-rev": "^7.1.2",
"gulp-rev-all": "^0.9.7",
"gulp-rev-replace": "^0.4.3",
"gulp-sass": "^2.1.0",
"gulp-uglify": "^1.4.2",
"mocha": "*",
"nodemon": "*",
"should": "^7.1.0",
"supertest": "^1.1.0",
"winston": "^1.0.1"
"gulp-sass": "^3.1.0",
"gulp-uglify": "^2.1.2",
"nodemon": "1.11.0",
"should": "^11.2.1",
"supertest": "^3.0.0",
"winston": "^2.3.1"
},
"description": "",
"main": "Gulpfile.js",

View File

@@ -3,7 +3,7 @@
var config = require('config');
require('../../models/schema');
var bcrypt = require('bcrypt');
var bcrypt = require('bcryptjs');
var crypo = require('crypto');
var express = require('express');

View File

@@ -9,7 +9,7 @@ var mailer = require('../../helpers/mailer');
var fs = require('fs');
var _ = require('underscore');
var crypto = require('crypto');
var bcrypt = require('bcrypt');
var bcrypt = require('bcryptjs');
var express = require('express');
var router = express.Router();

View File

@@ -6,7 +6,7 @@ require('../../models/schema');
var mailer = require('../../helpers/mailer');
var uploader = require('../../helpers/uploader');
var bcrypt = require('bcrypt');
var bcrypt = require('bcryptjs');
var crypo = require('crypto');
var swig = require('swig');
var async = require('async');

View File

@@ -23,10 +23,10 @@
{% if process.env.NODE_ENV != "production" %}
var ENV = {
name: 'development',
webHost: "localhost:9000",
webEndpoint:"http://localhost:9000",
apiEndpoint: "http://localhost:9000",
websocketsEndpoint: "ws://localhost:9000"
webHost: "localhost:9666",
webEndpoint:"http://localhost:9666",
apiEndpoint: "http://localhost:9666",
websocketsEndpoint: "ws://localhost:9666"
};
{% endif %}