Skip to content

Commit

Permalink
added auto updater of configurations files
Browse files Browse the repository at this point in the history
  • Loading branch information
Jes committed May 29, 2018
1 parent 4aa47ff commit 99baec0
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules
projects.json
sessions
build
github-release
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* visual diff for repository enabled projects (git)
* marking of events for shared users actions (cursor, selection, edition)
* user authentification per every project
* auto update from configuration files your projects and passwords

used the best multifunction web editor [ACE](https://ace.c9.io/) ever

Expand All @@ -21,19 +22,19 @@ npm i jesed
./jesed
```
enter your credentials and open http://localhost:3000/

#### Type for help
`./jesed --help`
#### Create new User
`./jesed user add me`
#### Add/modify projects
Run single time `./jesed` for project startup file creation
Modify the `projects.json` for your desire and restart service `sudo pm2 restart jesed`
Modify the `projects.json` for your desire with your favorite editor
#### For local use
`./jesed serve`
the application must be opened
#### For use with apache as service
```
sudo npm i -g pm2
sudo pm2 start package.json
cd config
sudo ./apache
```
open your domain url with /jesed/
open in your browser http://your-domain/jesed/ link
3 changes: 3 additions & 0 deletions app/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ function getFirstFile(paths) {

const unique = a => a.filter((elem, index, self) => index == self.indexOf(elem))

const arrRemove = (arr, cond) => (arr.map((o, i) => cond(o) ? i : -1).reverse().map(i => i >= 0 && arr.splice(i, 1)), arr);

module.exports = {
promisify,
atob,
getFirstFile,
unique,
walk,
getAllFiles,
arrRemove,
};
53 changes: 33 additions & 20 deletions app/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const FileStore = require('session-file-store')(session);
const passport = require('passport');
const Strategy = require('passport-http').DigestStrategy;

const {promisify, walk, getAllFiles} = require('./helpers');
const {promisify, arrRemove} = require('./helpers');
const wsOT = require('./services/ot');

const app = express();
const server = http.Server(app);
Expand All @@ -22,8 +23,37 @@ app.engine('.html', require('ejs').renderFile);

app.use(require('body-parser').urlencoded({ extended: false }));

module.exports = (config) => {
const tokens = {};
const checkAccess = (p, u) => p && u && p.editors && (p.editors.indexOf(u) >= 0 || p.editors.indexOf("*") >= 0);
const auth = p => (req, res, next) => {
req.project = p;
req.session.tokens || (req.session.tokens = {});
if (req.isAuthenticated() && checkAccess(p, req.user.id)) {
tokens[p.id][req.sessionID] || (req.session.tokens[p.id] = tokens[p.id][req.sessionID] = {user: req.user.id, token: md5(req.sessionID + new Date().getTime())});
next();
} else
res.redirect('/');
}

exports.addProject = (p) => {
tokens[p.id] || (tokens[p.id] = {})
p.ws = '/' + p.id + '/ws'
app.use('/' + p.id, auth(p), express.static(path.join(__dirname, '..', 'static', 'editor')))
app.use('/' + p.id, auth(p), require('./services'))
p.io = wsOT(server, p, tokens[p.id])
}

exports.removeProject = (p) => {
delete tokens[p.id];
arrRemove(app._router.stack, function routeCond(route) {
route.route && arrRemove(route.route.stack, routeCond);
return !route.regexp.fast_slash && route.regexp.test('/' + p.id);
})
//TODO: wsOT to use if removed?
p.io();
}

module.exports.init = (config) => {

passport.serializeUser(function(user, done) {
done(null, user.id);
Expand Down Expand Up @@ -63,26 +93,9 @@ const modAuth = (req, res, next) => {
})
}
app.use(modAuth);//, passport.authenticate('digest', { session: true }));
const checkAccess = (p, u) => p && u && p.editors && (p.editors.indexOf(u) >= 0 || p.editors.indexOf("*") >= 0);
const auth = p => (req, res, next) => {
req.project = p;
req.session.tokens || (req.session.tokens = {});
if (req.isAuthenticated() && checkAccess(p, req.user.id)) {
tokens[p.id][req.sessionID] || (req.session.tokens[p.id] = tokens[p.id][req.sessionID] = {user: req.user.id, token: md5(req.sessionID + new Date().getTime())});
next();
} else
res.redirect('/');
}

app.use('/nm', express.static(path.join(__dirname, '..', 'node_modules')));

config.projects.map(p => (
(tokens[p.id] || (tokens[p.id] = {})),
(p.ws = '/' + p.id + '/ws'),
app.use('/' + p.id, auth(p), express.static(path.join(__dirname, '..', 'static', 'editor'))),
app.use('/' + p.id, auth(p), require('./services')),
require('./services/ot')(server, p, tokens[p.id])
));
config.projects.map(exports.addProject)
app.get('/', function(req, res) {
if ('logout' in req.query) {
return res.status(401).send('<meta http-equiv="refresh" content="0; url=/">');
Expand Down
10 changes: 8 additions & 2 deletions app/services/ot.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ const setFile = (root, file, data) => promisify(fs.writeFile)(path.join(root, fi
module.exports = (server, project, tokens) => {
ns[project.ws] = {};
const io = new sio(server, {path: project.ws});
io.on('connection', function(socket) {
io.on('connection', connection)
function connection(socket) {
socket.on('ns', function (docId, token, name) {
if (Object.keys(tokens).map(i => tokens[i].token).indexOf(token) < 0) return;
getDoc(io, project, docId, name)
.then(ob => socket.emit('ns', docId, ob.type))
.catch(e => console.error(e))
});
});
}
chokidar.watch(project.path + '**', {
ignored: project.excludes || /node_modules/,
persistent: true,
Expand All @@ -39,6 +40,11 @@ module.exports = (server, project, tokens) => {
})
)
})
return function() {
io.removeListener('connection', connection);
io.path("recycled" + new Date().getTime());
delete io;
}
}
function canEdit(mime) {
var m = mime.split('/');
Expand Down
42 changes: 39 additions & 3 deletions jesed
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ const path = require('path');
const yargs = require('yargs');
const opn = require('open');
const prompt = require('prompt');
const chokidar = require('chokidar');

const {promisify, walk, getAllFiles} = require('./app/helpers');
const {promisify, walk, getAllFiles, arrRemove} = require('./app/helpers');
const server = require('./app/server');

const md5 = data => crypto.createHash('md5').update(data).digest("hex");
Expand Down Expand Up @@ -111,6 +112,40 @@ promisify(fs.stat)('projects.json')
.catch(e => getProjects(path.join(__dirname, 'projects.json.dist')).then(setProjects))
.then(args);

function watch() {
chokidar.watch('.htdigest', {
persistent: true,
})
.on('change', file => {
getPass()
.then(list => config.pass = list.reduce((p, i) => (p[i[0]] = i[2], p) , {}));
})

chokidar.watch('projects.json', {
persistent: true,
})
.on('change', file => {
const diff = (a, b) => a.filter(i => !b.find(j => j.id == i.id))
getProjects()
.then(now => {
//remove
arrRemove(config.projects, p => {
if (!now.find(i => p.id == i.id))
return server.removeProject(p), true;
})
//add
diff(now, config.projects).map(p => {
config.projects.push(p)
server.addProject(p)
});
//update
config.projects.map(p => {
var n = now.find(i => p.id == i.id)
n && Object.assign(p, n);
})
})
})
}
function serve(mode) {
Promise.all([
getPass(),
Expand All @@ -121,7 +156,8 @@ function serve(mode) {
Object.assign(config, files[2].config[mode])
config.pass = files[0].reduce((p, i) => (p[i[0]] = i[2], p) , {});
config.projects = files[1];
server(config);
server.init(config);
watch();
if (mode == 'local') {
console.log('open in browser url http://localhost:' + config.port);
try {
Expand All @@ -130,7 +166,7 @@ function serve(mode) {
}
})
.catch(e => {
// console.error('missing config', e)
console.error('missing config', e)
console.error('type `jesed user add` to add user at next time')
promptPass()
.then(a => serve(mode))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jesed",
"version": "0.1.5",
"version": "0.1.6",
"description": "online instant collaborative editor",
"main": "./jesed",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion static/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<body class="container mt-5">
<ul class="list-group">
<% projects.map(function(p) { %>
<li class="list-group-item"><a href="<%=p.id%>/"><%=p.name%></a></li>
<li class="list-group-item"><a href="<%=p.id%>/" title="Editors: <%=p.editors%>"><%=p.name%></a></li>
<% }) %>
<li class="list-group-item list-group-item-danger"><a href="?logout" onclick0="javascript:logout()">Logout</a></li>
</ul>
2 changes: 1 addition & 1 deletion upload
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ if [ ! -f ./github-release ]; then
wget -qO- https://github.com/aktau/github-release/releases/download/v0.7.2/linux-amd64-github-release.tar.bz2 |tar xvj --strip=3
fi

TAG=v0.1.5
TAG=v`./node_modules/.bin/json -f package.json -c 'console.log(this.version)'`
GH_TOKEN=`./node_modules/.bin/json -f ~/.github.json -c 'console.log(this.OAuth)'`

./github-release release \
Expand Down

0 comments on commit 99baec0

Please sign in to comment.