Compare commits

...

14 Commits

38 changed files with 650 additions and 244 deletions

View File

@ -30,6 +30,7 @@ const FlitterUnits = {
* available to the middleware-routing-controller stack. * available to the middleware-routing-controller stack.
*/ */
'Upload' : new (require('flitter-upload/UploadUnit'))(), 'Upload' : new (require('flitter-upload/UploadUnit'))(),
'CORS' : new (require('./app/CorsUnit'))(),
/* /*
* The Core Flitter Units * The Core Flitter Units

45
app/CorsUnit.js Normal file
View File

@ -0,0 +1,45 @@
const Unit = require('libflitter/Unit')
const cors = require('cors')
/*
* The Miscellaneous Unit
* -------------------------------------------------------------
* This is a Unit file where you should make any modifications that
* your application may need such as custom Express add-ons. Changes
* here are loaded after the core Flitter units, but before the other
* units (secondary, custom, error, and App), so they are available to
* other units in the stack.
*/
class CorsUnit extends Unit {
/*
* Initializes the unit class.
* This is called OUTSIDE of a Flitter context,
* so no other contexts are available. Modifications here
* take place before any part of Flitter is loaded or available.
*/
constructor(){
super()
}
/*
* Initialize the actual Unit.
* This is where most of the changes will go.
* This is provided an instance of the Express app
* so any custom changes can be made. The core Flitter
* contexts are available here, so things like config(),
* model(), etc. work.
*/
async go(app, context){
app.express.use(cors());
}
name(){
return "cors"
}
}
module.exports = exports = CorsUnit

View File

@ -1,4 +1,5 @@
const Unit = require('libflitter/Unit') const Unit = require('libflitter/Unit')
const cors = require('cors')
/* /*
* The Miscellaneous Unit * The Miscellaneous Unit
@ -32,15 +33,25 @@ class MiscUnit extends Unit {
* model(), etc. work. * model(), etc. work.
*/ */
async go(app, context){ async go(app, context){
String.prototype.capitalize = function(){
return this.charAt(0).toUpperCase() + this.slice(1)
}
// do stuff here // do stuff here
global.devbug = { global.devbug = {
version: '0.6.0', version: '0.7.0',
get_inline: function(type, project){
let code = this.code[type];
if (!code) return false
code = code.replace(/{{ Project API Key }}/g, project.uuid).replace(/{{ Server URL }}/g, _flitter.config('server.url'))
return code
},
code: { code: {
node: `require("devbugjs") node: `require("devbugjs")
dbsetup({ dbsetup({
\tserver: "https://CHANGEME:8000/", // DevBug Server URL \tserver: "{{ Server URL }}", // DevBug Server URL
\tproject: "CHANGEME", // Project API Key \tproject: "{{ Project API Key }}", // Project API Key
})`, })`,
api: `// Send a multipart/form-data POST request to: api: `// Send a multipart/form-data POST request to:
// http://#{_flitter.config('server.url')}/api/v1/out/<project api key> // http://#{_flitter.config('server.url')}/api/v1/out/<project api key>
@ -58,46 +69,71 @@ dbsetup({
// =========================================================== // ===========================================================
// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER // DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER
// TODO: REMOVE BEFORE COMMITTING // TODO: REMOVE BEFORE COMMITTING
$dev_outs = []; function devbug_microtime($difftime = 0){
$time = explode(' ', microtime()); return ((float)$time[1]+(float)$time[0])-$difftime; }
$GLOBALS['devbug_dev_outs'] = [];
$GLOBALS['devbug_dev_out_iters'] = [];
$GLOBALS['devbug_bench_iters'] = [];
$GLOBALS['devbug_mark_time'] = devbug_microtime();
function out($key, $what, $group = null){ function out($key, $what, $group = null){
global $dev_outs; $dev_outs = $GLOBALS['devbug_dev_outs'];
if ( $group ){ if ( $group ){
if ( !array_key_exists($group, $dev_outs) ){ if ( !array_key_exists($group, $dev_outs) ) $dev_outs[$group] = [ $key => $what ];
$dev_outs[$group] = [ $key => $what ]; else $dev_outs[$group][$key] = $what;
} }
else { else $dev_outs[$key] = $what;
$dev_outs[$group][$key] = $what; $GLOBALS['devbug_dev_outs'] = $dev_outs;
}
}
else {
$dev_outs[$key] = $what;
}
} }
function breakpoint($continue = false, $name = null){ function breakpoint($continue = false, $name = null){
global $dev_outs; $dev_outs = $GLOBALS['devbug_dev_outs'];
$devbug = "http://localhost:8000/"; $devbug = "{{ Server URL }}/";
$project_api_key = "CHANGEME"; $project_api_key = "{{ Project API Key }}";
$bt = debug_backtrace(); $bt = debug_backtrace();
$caller = array_shift($bt); $caller = array_shift($bt);
$time = devbug_microtime();
$dev_outs['DevBug Summary'] = [
'Start Time' => $GLOBALS['devbug_mark_time'],
'Breakpoint Time' => $time,
'Total Execution Time' => $time - $GLOBALS['devbug_mark_time'],
'Breakpoint Stacktrace' => $caller,
];
// Send to devbug server // Send to devbug server
$ch = curl_init(); $ch = curl_init();
$url = $devbug.'api/v1/out/'.$project_api_key; $url = $devbug.'api/v1/out/'.$project_api_key;
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [ curl_setopt($ch, CURLOPT_POSTFIELDS, [
'data' => json_encode([ 'data' => json_encode([
'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'], 'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'],
'data' => $dev_outs, 'data' => $dev_outs,
]) ])
]); ]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $odata = curl_exec($ch);
if ( !$continue ) { exit(); }
$odata = curl_exec($ch);
if ( !$continue ) { exit(); }
} }
function devbugtime($prefix = 'time: '){ $mt = explode(' ', microtime()); $mt = $mt[1].' '.$mt[0]; return $prefix.$mt; }
function outt($key, $what, $group = null){ out(devbugtime($key), $what, $group); }
function outi($key, $what, $group = null){
$keyname = $group ? $key.$group : $key;
if ( !$GLOBALS['devbug_dev_out_iters'][$keyname] ) $GLOBALS['devbug_dev_out_iters'][$keyname] = 0;
out($key.'_'.$GLOBALS['devbug_dev_out_iters'][$keyname], $what, $group);
$GLOBALS['devbug_dev_out_iters'][$keyname]++;
}
function point(){
if ( !$GLOBALS['devbug_current_bench'] ) benchmark();
$bt = debug_backtrace();
$caller = array_shift($bt);
out('point: '.$caller['file'].': '.$caller['line'], devbugtime(), $GLOBALS['devbug_current_bench']);
}
function benchmark($name = "DevBug"){ $GLOBALS['devbug_current_bench'] = "Benchmark: ".$name; point(); }
function benchmarki($name = "DevBug"){
if ( !$GLOBALS['devbug_bench_iters'][$name] ) $GLOBALS['devbug_bench_iters'][$name] = 1;
benchmark($name.'('.$GLOBALS['devbug_bench_iters'][$name].')');
$GLOBALS['devbug_bench_iters'][$name]++;
}
function devbug_chop($string, $at=120){ return substr($string, 0, 30); }
// ===========================================================`, // ===========================================================`,
}, },
permission: { permission: {

View File

@ -40,7 +40,7 @@ const devbug = {
json(data){ json(data){
return JSON.stringify(JSON.rmref(JSON.decycle(data))); return JSON.stringify(JSON.rmref(JSON.decycle(data)));
}, },
breakpoint(name, exception = false){ breakpoint(except = false, name){
var e = new Error(); var e = new Error();
this.libs(() => { this.libs(() => {
var s = e.stack.split('at'); var caller = ''; var s = e.stack.split('at'); var caller = '';

View File

@ -1,52 +0,0 @@
// ===========================================================
// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER
// TODO: REMOVE BEFORE COMMITTING
let outs = {}
let devbug_url = 'http://localhost:8000/'
let project_api_key = 'CHANGEME'
const out = (key, what, group="") => {
if ( group ){
if ( Object.keys(outs).includes(group) ) outs[group][key] = what
else outs[group] = {}; outs[group][key] = what
}
else {
outs[key] = what
}
}
const breakpoint = (html = false, name = null) => {
var e = new Error();
(function() {
// Load better json
var js_decycle = document.createElement("script");
js_decycle.src = devbug_url+"assets/cycle.js";
js_decycle.type = 'text/javascript';
js_decycle.onload = () => {
// Load the script
var script = document.createElement("script");
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js';
script.type = 'text/javascript';
script.onload = () => {
var $ = window.jQuery;
$(() => {
var s = e.stack.split('at'); var caller = '';
if ( s.length < 3 ) s = e.stack.split('@')
if ( s.length > 2 ) caller = s[2].trim()
else if ( s.length > 1 ) caller = s[1]
else caller = 'Unable to determine stacktrace'
var data = new FormData();
console.log(JSON.decycle({brief: (name ? name : 'Breakpoint: ')+caller,data: outs}))
data.append('data', JSON.stringify(JSON.rmref(JSON.decycle({brief: (name ? name : 'Breakpoint: ')+caller,data: outs}))))
$.ajax({
url: devbug_url+'api/v1/out/'+project_api_key,
data: data, cache: false, contentType: false, processData: false, method: 'POST', type: 'POST',
success: (res) => { console.log('DevBug POST Completed'); console.log(res) }
})
});
};
document.getElementsByTagName("head")[0].appendChild(script);
}
document.getElementsByTagName("head")[0].appendChild(js_decycle);
})();
}
window.out = out; window.breakpoint = breakpoint;
// ===========================================================

View File

@ -40,3 +40,5 @@ window.onscroll = () => {
navbar.classList.remove('sticky') navbar.classList.remove('sticky')
} }
} }
window.devbug_editor_theme = 'ace/theme/idle_fingers'

View File

@ -95,7 +95,7 @@ class v1 {
const user = await _flitter.model('User').findOne({uuid: invite.by_user_id}) const user = await _flitter.model('User').findOne({uuid: invite.by_user_id})
if ( !user ) _flitter.error(res, 500, {reason: 'This user no longer exists. Sorry.'}) if ( !user ) _flitter.error(res, 500, {reason: 'This user no longer exists. Sorry.'})
return _flitter.view(res, 'dash_v1:accept', {invite, project, user}) return _flitter.view(res, 'dash_v1:accept', {invite, project, created_by_user: user})
} }
async invite_accept(req, res, next){ async invite_accept(req, res, next){

View File

@ -138,7 +138,38 @@ class v1 {
return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'}) return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'})
} }
return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, snippets, project, outs, show_back: true, title: 'View: '+project.name }) return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, snippets, project, outs, show_back: true, window_back: true, title: 'View: '+project.name })
}
async project_view_inline_helper(req, res, next){
const project = await Project.findById(req.params.id)
if ( !project ){
return _flitter.error(res, 404, {reason: 'Project not found with the specified ID.'})
}
if ( !await devbug.permission.project.view(project, req.session.auth.user) ){
return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'})
}
const code = devbug.get_inline(req.params.type, project)
if ( !code ) return _flitter.error(res, 404, {reason: 'Inline helper snippet not found with the specified type.'})
let type;
if ( req.params.type === 'node' ) type = 'javascript'
else if ( req.params.type === 'php' ) type = 'php'
else type = 'text'
return _flitter.view(res, 'dash_v1:in_editor', {
user: req.session.auth.user,
project,
show_back: true,
readonly: true,
editor_code: code,
editor_lang: 'ace/mode/'+type,
title: 'Inline Helper for '+project.name+' ('+req.params.type+')'
})
} }
async out_view(req, res, next){ async out_view(req, res, next){
@ -166,6 +197,37 @@ class v1 {
return _flitter.view(res, 'dash_v1:out', {project, user: req.session.auth.user, out, prettyd:pretty, show_back: true, title: out.brief, title_small: true }); return _flitter.view(res, 'dash_v1:out', {project, user: req.session.auth.user, out, prettyd:pretty, show_back: true, title: out.brief, title_small: true });
} }
async out_latest(req, res, next){
const project = await Project.findById(req.params.project)
if ( !project || (!await devbug.permission.project.view(project, req.session.auth.user)) ){
return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'})
}
const out = await Out.findOne({project_id: project.id}, {}, { sort: { 'created': -1 } })
if ( !out ){
return _flitter.error(res, 404, {reason: 'This project has no outputs yet.'})
}
let pretty
try {
pretty = JSON.stringify(JSON.parse(out.data), null, 4)
console.log('Pretty out: ', pretty)
}
catch (e){
return _flitter.error(res, 500, {reason: 'Unable to parse output data. Data contains invalid JSON.'})
}
return _flitter.view(res, 'dash_v1:out', {
project,
user: req.session.auth.user,
out,
prettyd:pretty,
show_back: true,
title: `Latest output: ${out.brief} <small>(${out.created.toLocaleString({timeZone: 'America/Chicago'})})</small>`,
title_small: true
});
}
async out_delete(req, res, next){ async out_delete(req, res, next){
const out = await Out.findById(req.params.id) const out = await Out.findById(req.params.id)

View File

@ -6,7 +6,9 @@
* globally using the model() function. * globally using the model() function.
*/ */
const Greeting = { const Greeting = {
name: String, schema: {
name: String,
},
} }
module.exports = Greeting module.exports = Greeting

View File

@ -5,10 +5,11 @@
/** /**
* This model stores the role data from Flitter-auth. * This model stores the role data from Flitter-auth.
* *
* @type {Object}
*/ */
module.exports = exports = { module.exports = exports = {
name: String, schema: {
permissions: [String], name: String,
data: String, permissions: [String],
data: String,
},
} }

View File

@ -8,13 +8,14 @@
* stored instead of cleartext. The data field is for JSON data that * stored instead of cleartext. The data field is for JSON data that
* holds various non-DB essential pieces of information about users. * holds various non-DB essential pieces of information about users.
* *
* @type {Object}
*/ */
module.exports = exports = { module.exports = exports = {
username: String, schema: {
password: String, username: String,
data: String, password: String,
uuid: String, data: String,
role: String, uuid: String,
permissions: [String], role: String,
permissions: [String],
},
} }

View File

@ -4,10 +4,12 @@
* Put some description here! * Put some description here!
*/ */
const File = { const File = {
original_name: String, schema: {
new_name: String, original_name: String,
mime: String, new_name: String,
type: String, mime: String,
type: String,
},
} }
module.exports = exports = File module.exports = exports = File

View File

@ -4,11 +4,16 @@
* Put some description here! * Put some description here!
*/ */
const Invite = { const Invite = {
project_id: String, schema: {
by_user_id: String, project_id: String,
api_type: String, by_user_id: String,
created_on: Date, api_type: String,
used: { type: Boolean, default: false } created_on: Date,
used: {
type: Boolean,
default: false
}
},
} }
module.exports = exports = Invite module.exports = exports = Invite

View File

@ -4,10 +4,15 @@
* Put some description here! * Put some description here!
*/ */
const Out = { const Out = {
project_id: String, schema: {
created: { type: Date, default: Date.now }, project_id: String,
brief: String, created: {
data: String, type: Date,
default: Date.now
},
brief: String,
data: String,
},
} }
module.exports = exports = Out module.exports = exports = Out

View File

@ -5,13 +5,21 @@
*/ */
const uuid = require('uuid/v4') const uuid = require('uuid/v4')
const Project = { const Project = {
name: String, schema: {
user_id: String, name: String,
archived: { type: Boolean, default: false }, user_id: String,
data: String, archived: {
shared_user_ids: [String], type: Boolean,
edit_user_ids: [String], default: false
uuid: { type: String, default: uuid } },
data: String,
shared_user_ids: [String],
edit_user_ids: [String],
uuid: {
type: String,
default: uuid
}
},
} }
module.exports = exports = Project module.exports = exports = Project

View File

@ -5,16 +5,24 @@
*/ */
const uuid = require('uuid/v4') const uuid = require('uuid/v4')
const Snippet = { const Snippet = {
name: String, schema: {
user_id: String, name: String,
archived: { type: Boolean, default: false }, user_id: String,
data: String, archived: {
shared_user_ids: [String], type: Boolean,
edit_user_ids: [String], default: false
uuid: { type: String, default: uuid }, },
public_share: String, data: String,
mode: String, shared_user_ids: [String],
project_id: String, edit_user_ids: [String],
uuid: {
type: String,
default: uuid
},
public_share: String,
mode: String,
project_id: String,
},
} }
module.exports = exports = Snippet module.exports = exports = Snippet

View File

@ -3,7 +3,8 @@
* ------------------------------------------------------------- * -------------------------------------------------------------
* Put some description here! * Put some description here!
*/ */
class Debug { const Middleware = require('libflitter/middleware/Middleware')
class Debug extends Middleware {
/* /*
* Run the middleware test. * Run the middleware test.
@ -11,10 +12,10 @@ class Debug {
* It should either call the next function in the stack, * It should either call the next function in the stack,
* or it should handle the response accordingly. * or it should handle the response accordingly.
*/ */
test(req, res, next, args = {}){ test(req, res, next, args = {}) {
console.log('DEBUGGING LAYER:') console.log('DEBUGGING LAYER:')
console.log('Incoming destination: '+req.originalUrl) console.log('Incoming destination: ' + req.originalUrl)
console.log('Incoming method: '+req.method) console.log('Incoming method: ' + req.method)
/* /*
* Call the next function in the stack. * Call the next function in the stack.

View File

@ -6,7 +6,8 @@
* the '/' route is accessed. It can be injected in routes globally using * the '/' route is accessed. It can be injected in routes globally using
* the global mw() function. * the global mw() function.
*/ */
class HomeLogger { const Middleware = require('libflitter/middleware/Middleware')
class HomeLogger extends Middleware {
/* /*
* Run the middleware test. * Run the middleware test.
@ -14,7 +15,7 @@ class HomeLogger {
* It should either call the next function in the stack, * It should either call the next function in the stack,
* or it should handle the response accordingly. * or it should handle the response accordingly.
*/ */
test(req, res, next){ test(req, res, next) {
console.log("Home was accessed!") console.log("Home was accessed!")
/* /*

View File

@ -8,7 +8,8 @@
* *
* @class * @class
*/ */
class Permission { const Middleware = require('libflitter/middleware/Middleware')
class Permission extends Middleware {
/** /**
* Run the middleware's check. If an authenticated session exists and the user has the specified permission, * Run the middleware's check. If an authenticated session exists and the user has the specified permission,
@ -19,27 +20,29 @@ class Permission {
* @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue. * @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue.
* @param {string} permission - Name of the permission to require * @param {string} permission - Name of the permission to require
*/ */
async test(req, res, next, permission){ async test(req, res, next, permission) {
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){ if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
if ( req.session.auth.user.permissions && req.session.auth.user.permissions.includes(permission) ){ if (req.session.auth.user.permissions && req.session.auth.user.permissions.includes(permission)) {
next() next()
} } else if (req.session.auth.user.role) {
else if ( req.session.auth.user.role ){
const Role = _flitter.model('auth:Role') const Role = _flitter.model('auth:Role')
const role = await Role.findOne({name: req.session.auth.user.role}) const role = await Role.findOne({
name: req.session.auth.user.role
})
if ( role.permissions.includes(permission) ){ if (role.permissions.includes(permission)) {
next() next()
} else {
return _flitter.error(res, 401, {
reason: 'Insufficient user permissions.'
})
} }
else { } else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'}) return _flitter.error(res, 401, {
} reason: 'Insufficient user permissions.'
})
} }
else { } else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
}
else {
req.session.destination = req.originalUrl req.session.destination = req.originalUrl
return res.redirect('/auth/login') return res.redirect('/auth/login')
} }

View File

@ -8,7 +8,8 @@
* *
* @class * @class
*/ */
class RequireAuth { const Middleware = require('libflitter/middleware/Middleware')
class RequireAuth extends Middleware {
/** /**
* Run the middleware's check. If an authenticated session exists, let the request continue. * Run the middleware's check. If an authenticated session exists, let the request continue.
@ -18,14 +19,13 @@ class RequireAuth {
* @param {Express/Response} res - the corresponding Express response * @param {Express/Response} res - the corresponding Express response
* @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue. * @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue.
*/ */
test(req, res, next){ test(req, res, next) {
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){ if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
/* /*
* Call the next function in the stack. * Call the next function in the stack.
*/ */
next() next()
} } else {
else {
req.session.destination = req.originalUrl req.session.destination = req.originalUrl
return res.redirect('/auth/login') return res.redirect('/auth/login')
} }

View File

@ -8,7 +8,8 @@
* *
* @class * @class
*/ */
class RequireGuest { const Middleware = require('libflitter/middleware/Middleware')
class RequireGuest extends Middleware {
/** /**
* Run the middleware test. If an authenticated session exists, redirect the user to an error page. * Run the middleware test. If an authenticated session exists, redirect the user to an error page.
@ -17,8 +18,8 @@ class RequireGuest {
* @param {Express/Response} res - the corresponding Express response * @param {Express/Response} res - the corresponding Express response
* @param {Function} next - The callback to continue the Express request handling stack. This is called if the middleware check passes. * @param {Function} next - The callback to continue the Express request handling stack. This is called if the middleware check passes.
*/ */
test(req, res, next){ test(req, res, next) {
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){ if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
return _flitter.view(res, 'errors/requires_guest') return _flitter.view(res, 'errors/requires_guest')
} }

View File

@ -8,7 +8,8 @@
* *
* @class * @class
*/ */
class Role { const Middleware = require('libflitter/middleware/Middleware')
class Role extends Middleware {
/** /**
* Run the middleware's check. If an authenticated session exists and the user has the specified role, * Run the middleware's check. If an authenticated session exists and the user has the specified role,
@ -19,16 +20,16 @@ class Role {
* @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue. * @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue.
* @param {string} role - Name of the role to require * @param {string} role - Name of the role to require
*/ */
test(req, res, next, role){ test(req, res, next, role) {
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){ if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
if ( req.session.auth.user.role && req.session.auth.user.role === role ){ if (req.session.auth.user.role && req.session.auth.user.role === role) {
next() next()
} else {
return _flitter.error(res, 401, {
reason: 'Insufficient user permissions.'
})
} }
else { } else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
}
else {
req.session.destination = req.originalUrl req.session.destination = req.originalUrl
return res.redirect('/auth/login') return res.redirect('/auth/login')
} }

View File

@ -3,7 +3,8 @@
* ------------------------------------------------------------- * -------------------------------------------------------------
* Put some description here! * Put some description here!
*/ */
class Invite { const Middleware = require('libflitter/middleware/Middleware')
class Invite extends Middleware {
/* /*
* Run the middleware test. * Run the middleware test.
@ -11,8 +12,8 @@ class Invite {
* It should either call the next function in the stack, * It should either call the next function in the stack,
* or it should handle the response accordingly. * or it should handle the response accordingly.
*/ */
test(req, res, next, args = {}){ test(req, res, next, args = {}) {
if ( req.session.invite && !req.originalUrl.includes('/dash/v1/invitation/accept') ){ if (req.session.invite && !req.originalUrl.includes('/dash/v1/invitation/accept')) {
return res.redirect('/dash/v1/invitation/accept') return res.redirect('/dash/v1/invitation/accept')
} }

View File

@ -39,6 +39,7 @@ const v1 = {
'/project/new': [ _flitter.controller('dash:v1').new_project_show ], '/project/new': [ _flitter.controller('dash:v1').new_project_show ],
'/project/view/:id': [ _flitter.controller('dash:v1').project_view ], '/project/view/:id': [ _flitter.controller('dash:v1').project_view ],
'/project/view/:id/inline/:type': [ _flitter.controller('dash:v1').project_view_inline_helper ],
'/project/delete/:id': [ _flitter.controller('dash:v1').project_delete_show ], '/project/delete/:id': [ _flitter.controller('dash:v1').project_delete_show ],
'/project/edit/:id': [ _flitter.controller('dash:v1').project_edit_show ], '/project/edit/:id': [ _flitter.controller('dash:v1').project_edit_show ],
'/:api/share/:id': [ _flitter.controller('dash:v1').project_share_show ], '/:api/share/:id': [ _flitter.controller('dash:v1').project_share_show ],
@ -56,6 +57,7 @@ const v1 = {
'/using_devbug/:page': [ _flitter.controller('dash:v1').show_usage_page ], '/using_devbug/:page': [ _flitter.controller('dash:v1').show_usage_page ],
'/out/view/:id': [ _flitter.controller('dash:v1').out_view ], '/out/view/:id': [ _flitter.controller('dash:v1').out_view ],
'/out/view-latest/:project': [ _flitter.controller('dash:v1').out_latest ],
'/out/delete/:id/:project': [ _flitter.controller('dash:v1').out_delete ], '/out/delete/:id/:project': [ _flitter.controller('dash:v1').out_delete ],
'/code': [ _flitter.controller('dash:v1').view_code ], '/code': [ _flitter.controller('dash:v1').view_code ],

View File

@ -1,19 +1,150 @@
html html
head head
title Sharing Invitation | DevBug title #{title ? title : "Accept Invitation | DevBug"}
link(rel='stylesheet' href='/assets/dash_v1.css') style(type="text/css").
script(src='/assets/dash_v1.js') @import url(https://fonts.googleapis.com/css?family=Roboto:300);
body
.page-header .login-page {
.devbug-header DevBug | v#{devbug.version} #{(project ? " | Project: "+project.name : "")} width: 500px;
h1 Accept Invitation? padding: 6% 0 0;
ul.navul margin: auto;
li.navli }
a.nava(href='/dash/v1') Dashboard Login
.spacer .form {
p You've been invited to view the debugging #{invite.api_type} "#{project.name}" by #{user.username}. position: relative;
p To accept this invitation, you must have a DevBug account. You may be redirected to the registration portal. z-index: 1;
a.btn(href='/api/v1/invitation/'+invite.id+'/accept') Accept background: #FFFFFF;
br max-width: 500px;
h3 What's DevBug? min-width: 360px;
p DevBug is a debugging output server used to help developers work more efficiently. Using inline-code clients, developers can output variables and data from their programs. This data is stored in a DevBug project, where it can easily be shared with others. margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
font-family: "Roboto", sans-serif;
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
color: #006a81;
}
.form button, .form-button {
font-family: "Roboto", sans-serif;
text-transform: uppercase;
outline: 0;
background: #006a81;
width: 100%;
border: 0;
padding: 12px;
color: #FFFFFF;
font-size: 16px;
-webkit-transition: background 0.6s;
-moz-transition: background 0.6s;
-ms-transition: background 0.6s;
-o-transition: background 0.6s;
transition: background 0.6s;
cursor: pointer;
}
.form button:hover, .form button:active, .form button:focus, .form-button:hover, .form-button:active, .form-button:focus {
background: #00b3da;
}
.form-button {
text-decoration: none;
}
.form .message {
margin: 15px 0 0;
color: #b3b3b3;
font-size: 12px;
}
.form .message a {
color: #006a81;
text-decoration: none;
}
.container .info h1 {
margin: 0 0 15px;
padding: 0;
font-size: 36px;
font-weight: 300;
color: #1a1a1a;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
body {
background: #c7dbdf;
font-family: "Roboto", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.flitter-logo {
height: 100px;
margin-bottom: 15px;
}
.form-title, .form-subtitle {
font-family: "Roboto", sans-serif;
font-size: 16pt;
color: #006a81;
}
.form-subtitle {
text-align: left;
/*margin-top: 50px;*/
font-size: 14pt;
padding: 15px;
padding-bottom: 0;
padding-top: 0;
margin-bottom: 0;
}
.left-body {
text-align: left;
padding: 15px;
margin-top: 0;
}
.row-item {
margin-left: 10px;
}
.item-row {
margin-top: 65px;
}
.body-sep {
margin-top: 45px;
margin-bottom: 45px;
}
body
.login-page
.form
img.flitter-logo(src="/assets/flitter.png")
p.form-title View #{invite.api_type.capitalize()}: #{project.name}
p.left-body You've been invited to view a debugging #{invite.api_type} by #{created_by_user.username}. To accept this invitation, you must have a DevBug account. You may be redirected to the sign-in portal.
.item-row
a.form-button.row-item-first(href='/api/v1/invitation/'+invite.id+'/accept') Accept & View
a.form-button.row-item(href='/dash/v1') Decline
hr.body-sep
p.form-subtitle What's DevBug?
p.left-body DevBug is a debugging output server used to help developers work more efficiently. Using inline-code clients, developers can output variables and data from their programs. This data is stored in a DevBug project, where it can easily be shared with others.

View File

@ -2,4 +2,4 @@ extends ./template
block content block content
p #{text} p #{text}
form(method='post' action=destination) form(method='post' action=destination)
button(type='submit') Yes, I'm sure. button.btn(type='submit') Yes, I'm sure.

View File

@ -11,7 +11,7 @@ html
- var e_project = (user && project && devbug.permission.project.sync_edit(project, user)) - var e_project = (user && project && devbug.permission.project.sync_edit(project, user))
#pre-header-content DevBug | v#{devbug.version} #{(user ? " | User: "+user.username : "")} #{(e_project ? " | Project: "+project.name+" | API: "+project.uuid : "")} #{((_flitter.config('server.environment') === 'development') ? " | Development" : "" )} | <i>Editor Mode</i> #pre-header-content DevBug | v#{devbug.version} #{(user ? " | User: "+user.username : "")} #{(e_project ? " | Project: "+project.name+" | API: "+project.uuid : "")} #{((_flitter.config('server.environment') === 'development') ? " | Development" : "" )} | <i>Editor Mode</i>
#title-header #title-header
#title-header-content-sm #{title ? title : 'DevBug Dashboard'} #title-header-content-sm !{title ? title : 'DevBug Dashboard'}
.iheader .iheader
block header block header
.idiv .idiv
@ -26,7 +26,14 @@ html
a#navbar-usage(href='/dash/v1/using_devbug/main') Using DevBug a#navbar-usage(href='/dash/v1/using_devbug/main') Using DevBug
li.navbar-right li.navbar-right
a#navbar-logout(href='/auth/logout') Logout a#navbar-logout(href='/auth/logout') Logout
if show_back if show_back && (!project || window_back)
li.navbar-right li.navbar-right
a#navbar-back(href='javascript:window.history.back()') Back a#navbar-back(href='javascript:window.history.back()') Back
else if show_back && project
li.navbar-right
a#navbar-back(href='/dash/v1/project/view/'+project.id) Back to Project
if project && !hide_project_latest
li.navbar-right
a#navbar-project-latest(href="/dash/v1/out/view-latest/"+project.id) View Latest Output
script(src="/assets/dash_v1.js")
block scripts block scripts

View File

@ -0,0 +1,17 @@
extends ./editor_template
block content
pre#editor #{ editor_code ? editor_code : '' }
input#preset_mode(type='hidden' value=editor_lang ? editor_lang : 'ace/mode/text')
block scripts
script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js")
script.
const readonly = #{!!readonly}
const preset_mode = document.getElementById('preset_mode').value
const editor = ace.edit('editor');
editor.setTheme(window.devbug_editor_theme);
console.log('preset mode: ', preset_mode);
editor.session.setMode(preset_mode);
if ( readonly ){
editor.setOption('readOnly', true)
}

View File

@ -15,6 +15,8 @@ block content
ul(style='list-style-type: none; margin: 0; padding: 0;') ul(style='list-style-type: none; margin: 0; padding: 0;')
li.action-li li.action-li
a.action(href='/dash/v1/project/view/'+project.id) View a.action(href='/dash/v1/project/view/'+project.id) View
li.action-li
a.action(href='/dash/v1/out/view-latest/'+project.id) Latest Output
li.action-li li.action-li
a.action(href='/dash/v1/project/share/'+project.id) Share a.action(href='/dash/v1/project/share/'+project.id) Share
li.action-li li.action-li

View File

@ -6,6 +6,6 @@ block scripts
script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js") script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js")
script. script.
const editor = ace.edit('editor'); const editor = ace.edit('editor');
editor.setTheme('ace/theme/cobalt'); editor.setTheme(window.devbug_editor_theme);
editor.session.setMode('ace/mode/json'); editor.session.setMode('ace/mode/json');
editor.setOption('readOnly', true); editor.setOption('readOnly', true);

View File

@ -96,7 +96,7 @@ block scripts
const readonly = #{!!readonly} const readonly = #{!!readonly}
const preset_mode = document.getElementById('preset_mode').value const preset_mode = document.getElementById('preset_mode').value
const editor = ace.edit('editor'); const editor = ace.edit('editor');
editor.setTheme('ace/theme/cobalt'); editor.setTheme(window.devbug_editor_theme);
console.log('preset mode: ', preset_mode); console.log('preset mode: ', preset_mode);
editor.session.setMode(preset_mode); editor.session.setMode(preset_mode);
document.getElementById('snippet_mode').value = preset_mode document.getElementById('snippet_mode').value = preset_mode

View File

@ -14,11 +14,19 @@ html
a#navbar-home(href='/dash/v1') Home a#navbar-home(href='/dash/v1') Home
li li
a#navbar-usage(href='/dash/v1/using_devbug/main') Using DevBug a#navbar-usage(href='/dash/v1/using_devbug/main') Using DevBug
block navbar-left
li.navbar-right li.navbar-right
a#navbar-logout(href='/auth/logout') Logout a#navbar-logout(href='/auth/logout') Logout
if show_back if show_back && (!project || window_back)
li.navbar-right li.navbar-right
a#navbar-back(href='javascript:window.history.back()') Back a#navbar-back(href='javascript:window.history.back()') Back
else if show_back && project
li.navbar-right
a#navbar-back(href='/dash/v1/project/view/'+project.id) Back to Project
if project && !hide_project_latest
li.navbar-right
a#navbar-project-latest(href="/dash/v1/out/view-latest/"+project.id) View Latest Output
block navbar-right
.content .content
block content block content
block scripts block scripts

View File

@ -1,11 +1,11 @@
extends ../template extends ../template
block content block content
h3 DevBug supports ECMAscript on the web. h3 DevBug supports ECMAScript on the web.
p To use the client, include the ECMAscript client file in your application, as early as possible. This file is hosted by your local DevBug server, and is available <a href="/assets/agents/web.js" target="_blank">here.</a> Then, set the project API key and server addresses (see the code snippet below). This gives you access to the global <code>out()</code> and <code>breakpoint()</code> functions. Here's how to use them: p To use the client, include the ECMAScript client file in your application, as early as possible. This file is hosted by your local DevBug server, and is available <a href="/assets/agents/ecma5.js" target="_blank">here.</a> Then, set the project API key and server addresses (see the code snippet below). This gives you access to the global <code>out()</code> and <code>breakpoint()</code> functions. Here's how to use them:
h4 <code>out(<i>info</i>, <i>data</i>)</code> - output data to DevBug h4 <code>out(<i>info</i>, <i>data</i>)</code> - output data to DevBug
p This function is similar to logging data. It stores data to be outputted to DevBug. The first parameter should be a string with a brief description of the data, and the second is the data to be outputted. Note that the info string should be unique and multiple outputs with the same name will overwrite their predecessors. It's important to note that calling this function doesn't actually <i>send</i> any data to DevBug. Instead, it stores it to be sent. p This function is similar to logging data. It stores data to be outputted to DevBug. The first parameter should be a string with a brief description of the data, and the second is the data to be outputted. Note that the info string should be unique and multiple outputs with the same name will overwrite their predecessors. It's important to note that calling this function doesn't actually <i>send</i> any data to DevBug. Instead, it stores it to be sent.
h4 <code>breakpoint(<i>continue = false</i>, <i>name = ""</i>)</code> - send the outputted data to DevBug h4 <code>breakpoint(<i>continue = false</i>, <i>name = ""</i>)</code> - send the outputted data to DevBug
p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The <code>continue</code> parameter determines whether or not program execution continues, or if the interpreter's exit method is called. The <code>name</code> parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. Note that the continuation parameter is non-functional in browser-based ECMAscript. p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The <code>continue</code> parameter determines whether or not program execution continues, or if the interpreter's exit method is called. The <code>name</code> parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. Note that the continuation parameter is non-functional in browser-based ECMAScript. Instead, the breakpoint throws an exception.
pre#editor.inline // Run the following as early in your application as your can:&#10;devbug_url="http://localhost:8000/";&#10;project_api_key="CHANGEME"; pre#editor.inline // Run the following as early in your application as your can:&#10;devbug_url="http://localhost:8000/";&#10;project_api_key="CHANGEME";
block scripts block scripts

View File

@ -1,6 +1,23 @@
extends ./template extends ./template
block content block content
h3 Project API Key: #{project.uuid} h2 Project API Key:
pre
code #{project.uuid}
h2 Inline Helpers
p You can use the links below to generate inline helper scripts which are pre-configured for this project.
ul(style='list-style-type: none; margin: 0; padding: 0;')
li.action-li
a.btn(href=project.id+'/inline/node') Node.js
//li.action-li
// a.btn(href=project.id+'/inline/ecma') JavaScript (Web)
li.action-li
a.btn(href=project.id+'/inline/php') PHP
//li.action-li
// a.btn(href=project.id+'/inline/api') DevBug API
br
br
h2 Code Snippets h2 Code Snippets
a.btn(href='/dash/v1/project/snippet/'+project.id+'/new') + a.btn(href='/dash/v1/project/snippet/'+project.id+'/new') +
@ -26,6 +43,7 @@ block content
a.action(href='/dash/v1/snippet/share/'+snippet.id) Share a.action(href='/dash/v1/snippet/share/'+snippet.id) Share
h2 Development Outputs h2 Development Outputs
a.btn(href='/dash/v1/out/view-latest/'+project.id) Latest
table table
thead thead
tr tr

View File

@ -18,5 +18,15 @@
"id": 1560988609, "id": 1560988609,
"name": "move_database_unit_before_express_unit", "name": "move_database_unit_before_express_unit",
"migratedOn": "2019-06-21T00:31:38.019Z" "migratedOn": "2019-06-21T00:31:38.019Z"
},
{
"id": 1565741502,
"name": "convert_to_new_model_schema_definitions",
"migratedOn": "2019-08-15T14:58:30.109Z"
},
{
"id": 1565925593,
"name": "make_existing_middleware_extend_base_class",
"migratedOn": "2019-08-16T14:49:39.934Z"
} }
] ]

View File

@ -16,12 +16,14 @@
"author": "Garrett Mills <garrett@glmdev.tech> (https://glmdev.tech/)", "author": "Garrett Mills <garrett@glmdev.tech> (https://glmdev.tech/)",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cors": "^2.8.5",
"flitter-auth": "^0.4.0", "flitter-auth": "^0.4.0",
"flitter-cli": "^0.10.0", "flitter-cli": "^0.10.0",
"flitter-flap": "^0.2.2", "flitter-flap": "^0.4.0",
"flitter-forms": "^0.7.2", "flitter-forms": "^0.7.2",
"flitter-upload": "^0.7.6", "flitter-upload": "^0.7.6",
"libflitter": "^0.27.4", "js-beautify": "^1.10.2",
"libflitter": "^0.31.1",
"stringify-object": "^3.3.0" "stringify-object": "^3.3.0"
} }
} }

4
todo.txt Normal file
View File

@ -0,0 +1,4 @@
- Standardize inline TypeScript - load dynamically?
- Standardize inline PHP
- Serve jQuery from local server assets
- Use a closer-matching Ace theme

127
yarn.lock
View File

@ -487,7 +487,7 @@ command-line-args@^5.0.2:
lodash.camelcase "^4.3.0" lodash.camelcase "^4.3.0"
typical "^4.0.0" typical "^4.0.0"
commander@^2.5.0, commander@^2.9.0: commander@^2.19.0, commander@^2.5.0, commander@^2.9.0:
version "2.20.0" version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
@ -512,6 +512,14 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
config-chain@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
dependencies:
ini "^1.3.4"
proto-list "~1.2.1"
connect-mongodb-session@^2.2.0: connect-mongodb-session@^2.2.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/connect-mongodb-session/-/connect-mongodb-session-2.2.0.tgz#3d70bc9912756bfdfd2aeeda4def1fd9e07c69a6" resolved "https://registry.yarnpkg.com/connect-mongodb-session/-/connect-mongodb-session-2.2.0.tgz#3d70bc9912756bfdfd2aeeda4def1fd9e07c69a6"
@ -577,6 +585,14 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cors@^2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
dependencies:
object-assign "^4"
vary "^1"
debug@2.6.9, debug@^2.1.0, debug@^2.1.1: debug@2.6.9, debug@^2.1.0, debug@^2.1.1:
version "2.6.9" version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -701,6 +717,16 @@ dotenv@^6.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064"
integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==
editorconfig@^0.15.3:
version "0.15.3"
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==
dependencies:
commander "^2.19.0"
lru-cache "^4.1.5"
semver "^5.6.0"
sigmund "^1.0.1"
ee-first@1.1.1: ee-first@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -851,12 +877,13 @@ flitter-cli@^0.10.0:
mkdirp "^0.5.1" mkdirp "^0.5.1"
nesh "^1.7.0" nesh "^1.7.0"
flitter-flap@^0.2.2: flitter-flap@^0.4.0:
version "0.2.2" version "0.4.0"
resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.2.2.tgz#5735567510ba85ebfede2e1ed47dc2f36c0e962b" resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.4.0.tgz#ab1cdfc5b9ffe0b5b9fe2e3a8bdc87e9aac82c0e"
integrity sha512-iy1RqEcls36NDTGO6u/IZ58z/2yQFeR1Sa/BqTGkKzPQFOBoxMl7uoFSsMvmiwH9d6qJDOZ5SE2jGTav9NJNtw== integrity sha512-1pfGAckDJ7RZIK6qheAz2dwA4PV/03Z7rPhhVuDqZbuemtiozLgDLPQXzGwSLQESWNuG6CBg3KMEd0CPppB1/Q==
dependencies: dependencies:
del "^4.1.0" del "^4.1.0"
js-beautify "^1.10.2"
node-migration "^1.0.1" node-migration "^1.0.1"
touch "^3.1.0" touch "^3.1.0"
@ -1060,7 +1087,7 @@ inherits@2, inherits@2.0.3, inherits@~2.0.1, inherits@~2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@~1.3.0: ini@^1.3.4, ini@~1.3.0:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@ -1173,6 +1200,17 @@ isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
js-beautify@^1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178"
integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ==
dependencies:
config-chain "^1.1.12"
editorconfig "^0.15.3"
glob "^7.1.3"
mkdirp "~0.5.1"
nopt "~4.0.1"
js-stringify@^1.0.1: js-stringify@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
@ -1244,24 +1282,6 @@ leven@^1.0.2:
resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3" resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3"
integrity sha1-kUS27ryl8dBoAWnxpncNzqYLdcM= integrity sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=
libflitter@^0.27.4:
version "0.27.4"
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.27.4.tgz#858a49c0be7424b47eab36295cd1c001a3b32b61"
integrity sha512-/62fjAJCu/7dh1xQMdpNhV4LofAGGKB615dXTnWGvUBXWSYwtlwZuEWzcooEO4SdyT+ooeyTpVxy8XauFGX8pA==
dependencies:
busboy-body-parser "^0.3.2"
connect-mongodb-session "^2.2.0"
dotenv "^6.2.0"
es6-promisify "^6.0.1"
express "^4.16.4"
express-favicon "^2.0.1"
express-session "^1.15.6"
mongoose "^5.4.13"
pug "^2.0.3"
recursive-readdir "^2.2.2"
recursive-readdir-async "^1.1.3"
uuid "^3.3.2"
libflitter@^0.3.5: libflitter@^0.3.5:
version "0.3.6" version "0.3.6"
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.3.6.tgz#748d1fb9d5abcda61393eedb735f9cb875d1701f" resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.3.6.tgz#748d1fb9d5abcda61393eedb735f9cb875d1701f"
@ -1277,6 +1297,24 @@ libflitter@^0.3.5:
recursive-readdir "^2.2.2" recursive-readdir "^2.2.2"
uuid "^3.3.2" uuid "^3.3.2"
libflitter@^0.31.1:
version "0.31.1"
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.31.1.tgz#a513a4bd7acbdf8ba3ce91d1fdf837dfcc3217ca"
integrity sha512-z/mURNOe1aZLIWG7W2A8/fUPYkalRdqQmTfCLhyDWDJ2Nho+vGGLp9GLbiY9rj1I+W/x5U5p+W7Vv6EtYru+PA==
dependencies:
busboy-body-parser "^0.3.2"
connect-mongodb-session "^2.2.0"
dotenv "^6.2.0"
es6-promisify "^6.0.1"
express "^4.16.4"
express-favicon "^2.0.1"
express-session "^1.15.6"
mongoose "^5.4.13"
pug "^2.0.3"
recursive-readdir "^2.2.2"
recursive-readdir-async "^1.1.3"
uuid "^3.3.2"
lodash-node@^3.9.3: lodash-node@^3.9.3:
version "3.10.2" version "3.10.2"
resolved "https://registry.yarnpkg.com/lodash-node/-/lodash-node-3.10.2.tgz#2598d5b1b54e6a68b4cb544e5c730953cbf632f7" resolved "https://registry.yarnpkg.com/lodash-node/-/lodash-node-3.10.2.tgz#2598d5b1b54e6a68b4cb544e5c730953cbf632f7"
@ -1322,6 +1360,14 @@ longest@^1.0.1:
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
lru-cache@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
media-typer@0.3.0: media-typer@0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@ -1403,7 +1449,7 @@ minizlib@^1.1.1:
dependencies: dependencies:
minipass "^2.2.1" minipass "^2.2.1"
mkdirp@^0.5.0, mkdirp@^0.5.1: mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
version "0.5.1" version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@ -1559,7 +1605,7 @@ node-pre-gyp@0.12.0:
semver "^5.3.0" semver "^5.3.0"
tar "^4" tar "^4"
nopt@^4.0.1: nopt@^4.0.1, nopt@~4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
@ -1602,7 +1648,7 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
object-assign@^4.0.1, object-assign@^4.1.0: object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@ -1742,6 +1788,11 @@ promise@^7.0.1:
dependencies: dependencies:
asap "~2.0.3" asap "~2.0.3"
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
proxy-addr@~2.0.4: proxy-addr@~2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
@ -1750,6 +1801,11 @@ proxy-addr@~2.0.4:
forwarded "~0.1.2" forwarded "~0.1.2"
ipaddr.js "1.8.0" ipaddr.js "1.8.0"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
pug-attrs@^2.0.3: pug-attrs@^2.0.3:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.3.tgz#a3095f970e64151f7bdad957eef55fb5d7905d15" resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.3.tgz#a3095f970e64151f7bdad957eef55fb5d7905d15"
@ -2088,6 +2144,11 @@ semver@^5.1.0, semver@^5.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
send@0.16.2: send@0.16.2:
version "0.16.2" version "0.16.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
@ -2137,6 +2198,11 @@ sift@7.0.1:
resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08" resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08"
integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g== integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==
sigmund@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
signal-exit@^3.0.0: signal-exit@^3.0.0:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
@ -2410,7 +2476,7 @@ validator@^10.11.0:
resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228" resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228"
integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw== integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==
vary@~1.1.2: vary@^1, vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
@ -2465,6 +2531,11 @@ y18n@^3.2.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
yallist@^3.0.0, yallist@^3.0.2: yallist@^3.0.0, yallist@^3.0.2:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"