Skip to content

Commit

Permalink
Merge pull request #1 from LiquidGalaxyLAB/firebase-as-host
Browse files Browse the repository at this point in the history
Firebase as host
  • Loading branch information
zurfyx authored Jul 6, 2017
2 parents e157b81 + e6e4a88 commit 615cb5d
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 66 deletions.
3 changes: 0 additions & 3 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ module.exports = {
// File that handles Liquid Galaxy commands (such as flyto).
queriesPath: '/tmp/query.txt',

// Run Cron jobs (such as alive reports).
cronJobsEnabled: true,

// Firebase repository where all alive reports will be sent.
firebase: {
apiKey: 'AIzaSyAddzwazFGRJiC-GW35Zgr7XdhUk8x0890',
Expand Down
71 changes: 59 additions & 12 deletions firebase/database.rules.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,76 @@
{
"rules": {
"up": {
"$publicIp": {
"servers": {
"$uid": {
".write": "auth.token.email.beginsWith($uid + '@')",
".read": true,
".validate": "$publicIp.matches(/^[0-9]{1,3}%[0-9]{1,3}%[0-9]{1,3}%[0-9]{1,3}$/)",
"$reportUid": {
".write": "!data.exists() && newData.exists()",
".validate": "newData.hasChildren(['localIp', 'port', 'timestamp'])",
"localIp": {
".validate": "newData.val().matches(/^(10|172|192)\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/)"
"displayName": {
".validate": "newData.val().length < 200"
},
"lastOnline": {
".validate": "newData.val() === now"
},
"isOnline": {
".validate": "newData.isBoolean()"
},
"hasPassword": {
".validate": "newData.isBoolean()"
},
"$other": {
".validate": false
}
}
},
"passwords": {
"$serverUid": {
".write": "auth.token.email.beginsWith($serverUid + '@') || newData.val() === data.val()",
".read": false,
".validate": "newData.isString()"
}
},
"queue": {
"$serverUidWithKey": {
".write": true,
".read": true,
"$queueUid": {
"type": {
".validate": "newData.isString()"
},
"port": {
".validate": "newData.val() > 0 && newData.val() < 65535"
"value": {
".validate": "newData.isString()"
},
"timestamp": {
".validate": "newData.val() === now"
},
"optional": {
"$other": {
".validate": false
}
}
}
},
"ips": {
"$ip": {
".read": true,
".validate": "$ip.matches(/^[0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}:[0-9]{1,3}$/)",
"$serverUid": {
".write": "auth.token.email.beginsWith($serverUid + '@') || newData.val() === data.val()",
"displayName": {
".validate": "newData.val().length < 200"
},
"$other": {
"lastOnline": {
".validate": "newData.val() === now"
},
"isOnline": {
".validate": "newData.isBoolean()"
},
"$other":{
".validate": false
}
}
}
},
"$other": {
".validate": false
}
}
}
21 changes: 12 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,18 @@
"config": "^1.25.1",
"connect-redis": "^3.2.0",
"cookie-parser": "^1.4.3",
"cors": "^2.8.3",
"cron": "^1.2.1",
"debug": "^2.6.1",
"express": "^4.14.1",
"firebase": "^4.1.2",
"generate-password": "^1.3.0",
"http": "0.0.0",
"ip": "^1.1.5",
"mkdirp": "^0.5.1",
"mongoose": "^4.8.4",
"morgan": "^1.8.1",
"public-ip": "^2.3.5",
"shortid": "^2.2.8",
"socket.io": "^2.0.3",
"uuid": "^3.1.0",
"validator": "^7.0.0"
Expand Down
25 changes: 25 additions & 0 deletions src/cron/CronTask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const { CronJob } = require('cron');

const log = require('../helpers/log');

class CronTask {
constructor(name, cronTime, action) {
const newAction = async () => {
log.dev(`[CRON] Started "${name}"`);
await action();
log.dev(`[CRON] Finished "${name}"`);
};
this.action = newAction;
this.cronJob = new CronJob(cronTime, newAction);
}

executeOnce() {
return this.action();
}

start() {
this.cronJob.start();
}
}

module.exports = CronTask;
29 changes: 2 additions & 27 deletions src/cron/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,3 @@
const { CronJob } = require('cron');
const CronTask = require('./CronTask');

const log = require('../helpers/log');
const { up } = require('../services');

class CronTask {
constructor(name, cronTime, action) {
const newAction = async () => {
log.dev(`[CRON] Started "${name}"`);
await action();
log.dev(`[CRON] Finished "${name}"`);
};
this.cronJob = new CronJob(cronTime, newAction);
}
}

const cronTasks = [
new CronTask('Report Alive', '0,30 * * * * *', () => up.reportAlive()),
];

function startAll() {
this.cronTasks.map(cronTask => cronTask.cronJob.start());
}

module.exports = {
cronTasks,
startAll,
};
module.exports = { CronTask };
5 changes: 5 additions & 0 deletions src/firebase/__tests__/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"env": {
"mocha": true
}
}
10 changes: 10 additions & 0 deletions src/firebase/__tests__/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { expect } = require('chai');
const { encodeUid } = require('../utils');

describe('Firebase Auth', () => {
it('encoded email address should decode alright', () => {
const UID = 'loLlipOp';
const expected = [108, 111, 76, 108, 105, 112, 79, 112].join('');
expect(encodeUid(UID)).to.equal(expected);
});
});
76 changes: 76 additions & 0 deletions src/firebase/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* Authenticate server.
* Signs up new server with random credentials (stored in data/credentials.txt)
* Sign in with the stored credentials.
* (format deviceUid:editKey:devicePassword)
*/

const Promise = require('bluebird');
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const shortid = require('shortid');
const generatePassword = require('generate-password');
const firebase = require('firebase');

const { encodeUid } = require('./utils');

const readFile = Promise.promisify(fs.readFile);
const writeFile = Promise.promisify(fs.writeFile);
const createDir = Promise.promisify(mkdirp);

const CREDENTIALS_PATH = path.join('data/credentials.txt');

async function readCredentials() {
try {
const contents = await readFile(CREDENTIALS_PATH, { encoding: 'utf-8' });
const [uid, editKey, password] = contents.split(':');
return [uid, editKey, password];
} catch (error) {
return null;
}
}

async function generateCredentials() {
const uid = shortid.generate();
const editKey = generatePassword.generate({
length: 20,
numbers: true,
});
const password = '';
return [uid, editKey, password];
}

async function saveCredentials(values) {
const contents = values.join(':');
await createDir(path.join(CREDENTIALS_PATH, '..'));
return writeFile(CREDENTIALS_PATH, contents);
}

function encodeEmail(uid) {
const encodedUid = encodeUid(uid);
return `${encodedUid}@firebase.com`;
}

function signup([uid, editKey]) {
const emailVal = encodeEmail(uid);
const passwordVal = editKey;
return firebase.auth().createUserWithEmailAndPassword(emailVal, passwordVal);
}

function signin([uid, editKey]) {
const emailVal = encodeEmail(uid);
const passwordVal = editKey;
return firebase.auth().signInWithEmailAndPassword(emailVal, passwordVal);
}

module.exports = async () => {
let credentials = await readCredentials();
if (!credentials) {
credentials = await generateCredentials();
await saveCredentials(credentials);
await signup(credentials);
}
await signin(credentials);
return credentials;
};
29 changes: 26 additions & 3 deletions src/firebase/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,35 @@
const firebase = require('firebase');
const config = require('config');
const log = require('../helpers/log');

const CronTask = require('../cron/CronTask');
const auth = require('./auth');
const server = require('./server');
const queue = require('./queue');

const firebaseConfig = config.get('firebase');

function initialize() {
firebase.initializeApp(firebaseConfig);
return auth();
}

function bgReportAlive(serverUid) {
const cron = new CronTask('Report Alive', '0,30 * * * * *', () => server.reportAlive(serverUid));
cron.executeOnce();
cron.start();
}

function bgListenQueue(serverUid) {
queue.listenQueue(serverUid);
}

async function start() {
const [uid, , password] = await initialize();
log.info(`[Firebase] Signed in as ${uid} (${password ? `password ${password}` : 'no password'})`);

bgReportAlive(uid);
bgListenQueue(uid);
}

module.exports = {
initialize,
};
module.exports = { start };
Loading

0 comments on commit 615cb5d

Please sign in to comment.