mirror of
https://github.com/xiaoxinpro/nginx-proxy-manager-zh.git
synced 2025-01-22 21:08:13 -05:00
Ongoing rewrite work
This commit is contained in:
parent
30924a6922
commit
54d220a191
74
src/backend/internal/dead-host.js
Normal file
74
src/backend/internal/dead-host.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const error = require('../lib/error');
|
||||||
|
const deadHostModel = require('../models/dead_host');
|
||||||
|
|
||||||
|
function omissions () {
|
||||||
|
return ['is_deleted'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalDeadHost = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All Hosts
|
||||||
|
*
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [search_query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: (access, expand, search_query) => {
|
||||||
|
return access.can('dead_hosts:list')
|
||||||
|
.then(access_data => {
|
||||||
|
let query = deadHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.groupBy('id')
|
||||||
|
.omit(['is_deleted'])
|
||||||
|
.orderBy('domain_name', 'ASC');
|
||||||
|
|
||||||
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', access.token.get('attrs').id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query is used for searching
|
||||||
|
if (typeof search_query === 'string') {
|
||||||
|
query.where(function () {
|
||||||
|
this.where('domain_name', 'like', '%' + search_query + '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
|
query.eager('[' + expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report use
|
||||||
|
*
|
||||||
|
* @param {Integer} user_id
|
||||||
|
* @param {String} visibility
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getCount: (user_id, visibility) => {
|
||||||
|
let query = deadHostModel
|
||||||
|
.query()
|
||||||
|
.count('id as count')
|
||||||
|
.where('is_deleted', 0);
|
||||||
|
|
||||||
|
if (visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.first()
|
||||||
|
.then(row => {
|
||||||
|
return parseInt(row.count, 10);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = internalDeadHost;
|
279
src/backend/internal/proxy-host.js
Normal file
279
src/backend/internal/proxy-host.js
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const error = require('../lib/error');
|
||||||
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
|
|
||||||
|
function omissions () {
|
||||||
|
return ['is_deleted'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalProxyHost = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
create: (access, data) => {
|
||||||
|
let auth = data.auth || null;
|
||||||
|
delete data.auth;
|
||||||
|
|
||||||
|
data.avatar = data.avatar || '';
|
||||||
|
data.roles = data.roles || [];
|
||||||
|
|
||||||
|
if (typeof data.is_disabled !== 'undefined') {
|
||||||
|
data.is_disabled = data.is_disabled ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return access.can('proxy_hosts:create', data)
|
||||||
|
.then(() => {
|
||||||
|
data.avatar = gravatar.url(data.email, {default: 'mm'});
|
||||||
|
|
||||||
|
return userModel
|
||||||
|
.query()
|
||||||
|
.omit(omissions())
|
||||||
|
.insertAndFetch(data);
|
||||||
|
})
|
||||||
|
.then(user => {
|
||||||
|
if (auth) {
|
||||||
|
return authModel
|
||||||
|
.query()
|
||||||
|
.insert({
|
||||||
|
user_id: user.id,
|
||||||
|
type: auth.type,
|
||||||
|
secret: auth.secret,
|
||||||
|
meta: {}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(user => {
|
||||||
|
// Create permissions row as well
|
||||||
|
let is_admin = data.roles.indexOf('admin') !== -1;
|
||||||
|
|
||||||
|
return userPermissionModel
|
||||||
|
.query()
|
||||||
|
.insert({
|
||||||
|
user_id: user.id,
|
||||||
|
visibility: is_admin ? 'all' : 'user',
|
||||||
|
proxy_hosts: 'manage',
|
||||||
|
redirection_hosts: 'manage',
|
||||||
|
dead_hosts: 'manage',
|
||||||
|
streams: 'manage',
|
||||||
|
access_lists: 'manage'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return internalProxyHost.get(access, {id: user.id, expand: ['permissions']});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Integer} data.id
|
||||||
|
* @param {String} [data.email]
|
||||||
|
* @param {String} [data.name]
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
update: (access, data) => {
|
||||||
|
if (typeof data.is_disabled !== 'undefined') {
|
||||||
|
data.is_disabled = data.is_disabled ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return access.can('proxy_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
|
||||||
|
// Make sure that the user being updated doesn't change their email to another user that is already using it
|
||||||
|
// 1. get user we want to update
|
||||||
|
return internalProxyHost.get(access, {id: data.id})
|
||||||
|
.then(user => {
|
||||||
|
|
||||||
|
// 2. if email is to be changed, find other users with that email
|
||||||
|
if (typeof data.email !== 'undefined') {
|
||||||
|
data.email = data.email.toLowerCase().trim();
|
||||||
|
|
||||||
|
if (user.email !== data.email) {
|
||||||
|
return internalProxyHost.isEmailAvailable(data.email, data.id)
|
||||||
|
.then(available => {
|
||||||
|
if (!available) {
|
||||||
|
throw new error.ValidationError('Email address already in use - ' + data.email);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No change to email:
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(user => {
|
||||||
|
if (user.id !== data.id) {
|
||||||
|
// Sanity check that something crazy hasn't happened
|
||||||
|
throw new error.InternalValidationError('User could not be updated, IDs do not match: ' + user.id + ' !== ' + data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.avatar = gravatar.url(data.email || user.email, {default: 'mm'});
|
||||||
|
|
||||||
|
return userModel
|
||||||
|
.query()
|
||||||
|
.omit(omissions())
|
||||||
|
.patchAndFetchById(user.id, data)
|
||||||
|
.then(saved_user => {
|
||||||
|
return _.omit(saved_user, omissions());
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return internalProxyHost.get(access, {id: data.id});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} [data]
|
||||||
|
* @param {Integer} [data.id] Defaults to the token user
|
||||||
|
* @param {Array} [data.expand]
|
||||||
|
* @param {Array} [data.omit]
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
get: (access, data) => {
|
||||||
|
if (typeof data === 'undefined') {
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data.id === 'undefined' || !data.id) {
|
||||||
|
data.id = access.token.get('attrs').id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return access.can('proxy_hosts:get', data.id)
|
||||||
|
.then(() => {
|
||||||
|
let query = userModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('id', data.id)
|
||||||
|
.allowEager('[permissions]')
|
||||||
|
.first();
|
||||||
|
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
query.omit(data.omit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
|
query.eager('[' + data.expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (row) {
|
||||||
|
return _.omit(row, omissions());
|
||||||
|
} else {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Integer} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
delete: (access, data) => {
|
||||||
|
return access.can('proxy_hosts:delete', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalProxyHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then(user => {
|
||||||
|
if (!user) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure user can't delete themselves
|
||||||
|
if (user.id === access.token.get('attrs').id) {
|
||||||
|
throw new error.PermissionError('You cannot delete yourself.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return userModel
|
||||||
|
.query()
|
||||||
|
.where('id', user.id)
|
||||||
|
.patch({
|
||||||
|
is_deleted: 1
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All Hosts
|
||||||
|
*
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [search_query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: (access, expand, search_query) => {
|
||||||
|
return access.can('proxy_hosts:list')
|
||||||
|
.then(access_data => {
|
||||||
|
let query = proxyHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.groupBy('id')
|
||||||
|
.omit(['is_deleted'])
|
||||||
|
.orderBy('domain_name', 'ASC');
|
||||||
|
|
||||||
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', access.token.get('attrs').id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query is used for searching
|
||||||
|
if (typeof search_query === 'string') {
|
||||||
|
query.where(function () {
|
||||||
|
this.where('domain_name', 'like', '%' + search_query + '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
|
query.eager('[' + expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report use
|
||||||
|
*
|
||||||
|
* @param {Integer} user_id
|
||||||
|
* @param {String} visibility
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getCount: (user_id, visibility) => {
|
||||||
|
let query = proxyHostModel
|
||||||
|
.query()
|
||||||
|
.count('id as count')
|
||||||
|
.where('is_deleted', 0);
|
||||||
|
|
||||||
|
if (visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.first()
|
||||||
|
.then(row => {
|
||||||
|
return parseInt(row.count, 10);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = internalProxyHost;
|
74
src/backend/internal/redirection-host.js
Normal file
74
src/backend/internal/redirection-host.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const error = require('../lib/error');
|
||||||
|
const redirectionHostModel = require('../models/redirection_host');
|
||||||
|
|
||||||
|
function omissions () {
|
||||||
|
return ['is_deleted'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalProxyHost = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All Hosts
|
||||||
|
*
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [search_query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: (access, expand, search_query) => {
|
||||||
|
return access.can('redirection_hosts:list')
|
||||||
|
.then(access_data => {
|
||||||
|
let query = redirectionHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.groupBy('id')
|
||||||
|
.omit(['is_deleted'])
|
||||||
|
.orderBy('domain_name', 'ASC');
|
||||||
|
|
||||||
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', access.token.get('attrs').id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query is used for searching
|
||||||
|
if (typeof search_query === 'string') {
|
||||||
|
query.where(function () {
|
||||||
|
this.where('domain_name', 'like', '%' + search_query + '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
|
query.eager('[' + expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report use
|
||||||
|
*
|
||||||
|
* @param {Integer} user_id
|
||||||
|
* @param {String} visibility
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getCount: (user_id, visibility) => {
|
||||||
|
let query = redirectionHostModel
|
||||||
|
.query()
|
||||||
|
.count('id as count')
|
||||||
|
.where('is_deleted', 0);
|
||||||
|
|
||||||
|
if (visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.first()
|
||||||
|
.then(row => {
|
||||||
|
return parseInt(row.count, 10);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = internalProxyHost;
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const internalProxyHost = require('./proxy-host');
|
||||||
|
const internalRedirectionHost = require('./redirection-host');
|
||||||
|
const internalDeadHost = require('./dead-host');
|
||||||
|
const internalStream = require('./stream');
|
||||||
|
|
||||||
const internalReport = {
|
const internalReport = {
|
||||||
|
|
||||||
@ -11,14 +15,27 @@ const internalReport = {
|
|||||||
*/
|
*/
|
||||||
getHostsReport: access => {
|
getHostsReport: access => {
|
||||||
return access.can('reports:hosts', 1)
|
return access.can('reports:hosts', 1)
|
||||||
.then(() => {
|
.then(access_data => {
|
||||||
|
let user_id = access.token.get('attrs').id;
|
||||||
|
|
||||||
|
let promises = [
|
||||||
|
internalProxyHost.getCount(user_id, access_data.visibility),
|
||||||
|
internalRedirectionHost.getCount(user_id, access_data.visibility),
|
||||||
|
internalStream.getCount(user_id, access_data.visibility),
|
||||||
|
internalDeadHost.getCount(user_id, access_data.visibility)
|
||||||
|
];
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
})
|
||||||
|
.then(counts => {
|
||||||
return {
|
return {
|
||||||
proxy: 12,
|
proxy: counts.shift(),
|
||||||
redirection: 2,
|
redirection: counts.shift(),
|
||||||
stream: 1,
|
stream: counts.shift(),
|
||||||
'404': 0
|
dead: counts.shift()
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
74
src/backend/internal/stream.js
Normal file
74
src/backend/internal/stream.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const error = require('../lib/error');
|
||||||
|
const streamModel = require('../models/stream');
|
||||||
|
|
||||||
|
function omissions () {
|
||||||
|
return ['is_deleted'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalStream = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All Hosts
|
||||||
|
*
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [search_query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: (access, expand, search_query) => {
|
||||||
|
return access.can('streams:list')
|
||||||
|
.then(access_data => {
|
||||||
|
let query = streamModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.groupBy('id')
|
||||||
|
.omit(['is_deleted'])
|
||||||
|
.orderBy('incoming_port', 'ASC');
|
||||||
|
|
||||||
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', access.token.get('attrs').id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query is used for searching
|
||||||
|
if (typeof search_query === 'string') {
|
||||||
|
query.where(function () {
|
||||||
|
this.where('incoming_port', 'like', '%' + search_query + '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
|
query.eager('[' + expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report use
|
||||||
|
*
|
||||||
|
* @param {Integer} user_id
|
||||||
|
* @param {String} visibility
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getCount: (user_id, visibility) => {
|
||||||
|
let query = streamModel
|
||||||
|
.query()
|
||||||
|
.count('id as count')
|
||||||
|
.where('is_deleted', 0);
|
||||||
|
|
||||||
|
if (visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.first()
|
||||||
|
.then(row => {
|
||||||
|
return parseInt(row.count, 10);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = internalStream;
|
@ -1,11 +1,24 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some Notes: This is a friggin complicated piece of code.
|
||||||
|
*
|
||||||
|
* "scope" in this file means "where did this token come from and what is using it", so 99% of the time
|
||||||
|
* the "scope" is going to be "user" because it would be a user token. This is not to be confused with
|
||||||
|
* the "role" which could be "user" or "admin". The scope in fact, could be "worker" or anything else.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const logger = require('../logger').access;
|
||||||
const validator = require('ajv');
|
const validator = require('ajv');
|
||||||
const error = require('./error');
|
const error = require('./error');
|
||||||
const userModel = require('../models/user');
|
const userModel = require('../models/user');
|
||||||
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
const TokenModel = require('../models/token');
|
const TokenModel = require('../models/token');
|
||||||
const roleSchema = require('./access/roles.json');
|
const roleSchema = require('./access/roles.json');
|
||||||
|
const permsSchema = require('./access/permissions.json');
|
||||||
|
|
||||||
module.exports = function (token_string) {
|
module.exports = function (token_string) {
|
||||||
let Token = new TokenModel();
|
let Token = new TokenModel();
|
||||||
@ -14,6 +27,7 @@ module.exports = function (token_string) {
|
|||||||
let object_cache = {};
|
let object_cache = {};
|
||||||
let allow_internal_access = false;
|
let allow_internal_access = false;
|
||||||
let user_roles = [];
|
let user_roles = [];
|
||||||
|
let permissions = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the Token object from the token string
|
* Loads the Token object from the token string
|
||||||
@ -28,7 +42,7 @@ module.exports = function (token_string) {
|
|||||||
reject(new error.PermissionError('Permission Denied'));
|
reject(new error.PermissionError('Permission Denied'));
|
||||||
} else {
|
} else {
|
||||||
resolve(Token.load(token_string)
|
resolve(Token.load(token_string)
|
||||||
.then((data) => {
|
.then(data => {
|
||||||
token_data = data;
|
token_data = data;
|
||||||
|
|
||||||
// At this point we need to load the user from the DB and make sure they:
|
// At this point we need to load the user from the DB and make sure they:
|
||||||
@ -43,8 +57,10 @@ module.exports = function (token_string) {
|
|||||||
.where('id', token_data.attrs.id)
|
.where('id', token_data.attrs.id)
|
||||||
.andWhere('is_deleted', 0)
|
.andWhere('is_deleted', 0)
|
||||||
.andWhere('is_disabled', 0)
|
.andWhere('is_disabled', 0)
|
||||||
.first('id')
|
.allowEager('[permissions]')
|
||||||
.then((user) => {
|
.eager('[permissions]')
|
||||||
|
.first()
|
||||||
|
.then(user => {
|
||||||
if (user) {
|
if (user) {
|
||||||
// make sure user has all scopes of the token
|
// make sure user has all scopes of the token
|
||||||
// The `user` role is not added against the user row, so we have to just add it here to get past this check.
|
// The `user` role is not added against the user row, so we have to just add it here to get past this check.
|
||||||
@ -62,7 +78,9 @@ module.exports = function (token_string) {
|
|||||||
} else {
|
} else {
|
||||||
initialised = true;
|
initialised = true;
|
||||||
user_roles = user.roles;
|
user_roles = user.roles;
|
||||||
|
permissions = user.permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new error.AuthError('User cannot be loaded for Token');
|
throw new error.AuthError('User cannot be loaded for Token');
|
||||||
}
|
}
|
||||||
@ -99,6 +117,34 @@ module.exports = function (token_string) {
|
|||||||
resolve(token_user_id ? [token_user_id] : []);
|
resolve(token_user_id ? [token_user_id] : []);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Proxy Hosts
|
||||||
|
case 'proxy_hosts':
|
||||||
|
let query = proxyHostModel
|
||||||
|
.query()
|
||||||
|
.select('id')
|
||||||
|
.andWhere('is_deleted', 0);
|
||||||
|
|
||||||
|
if (permissions.visibility === 'user') {
|
||||||
|
query.andWhere('owner_user_id', token_user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(query
|
||||||
|
.then(rows => {
|
||||||
|
let result = [];
|
||||||
|
_.forEach(rows, (rule_row) => {
|
||||||
|
result.push(rule_row.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// enum should not have less than 1 item
|
||||||
|
if (!result.length) {
|
||||||
|
result.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
// DEFAULT: null
|
// DEFAULT: null
|
||||||
default:
|
default:
|
||||||
resolve(null);
|
resolve(null);
|
||||||
@ -209,7 +255,13 @@ module.exports = function (token_string) {
|
|||||||
[permission]: {
|
[permission]: {
|
||||||
data: data,
|
data: data,
|
||||||
scope: Token.get('scope'),
|
scope: Token.get('scope'),
|
||||||
roles: user_roles
|
roles: user_roles,
|
||||||
|
permission_visibility: permissions.visibility,
|
||||||
|
permission_proxy_hosts: permissions.proxy_hosts,
|
||||||
|
permission_redirection_hosts: permissions.redirection_hosts,
|
||||||
|
permission_dead_hosts: permissions.dead_hosts,
|
||||||
|
permission_streams: permissions.streams,
|
||||||
|
permission_access_lists: permissions.access_lists
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,9 +275,9 @@ module.exports = function (token_string) {
|
|||||||
|
|
||||||
permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json');
|
permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json');
|
||||||
|
|
||||||
//console.log('objectSchema:', JSON.stringify(objectSchema, null, 2));
|
//logger.debug('objectSchema:', JSON.stringify(objectSchema, null, 2));
|
||||||
//console.log('permissionSchema:', JSON.stringify(permissionSchema, null, 2));
|
//logger.debug('permissionSchema:', JSON.stringify(permissionSchema, null, 2));
|
||||||
//console.log('data_schema:', JSON.stringify(data_schema, null, 2));
|
//logger.debug('data_schema:', JSON.stringify(data_schema, null, 2));
|
||||||
|
|
||||||
let ajv = validator({
|
let ajv = validator({
|
||||||
verbose: true,
|
verbose: true,
|
||||||
@ -236,17 +288,21 @@ module.exports = function (token_string) {
|
|||||||
coerceTypes: true,
|
coerceTypes: true,
|
||||||
schemas: [
|
schemas: [
|
||||||
roleSchema,
|
roleSchema,
|
||||||
|
permsSchema,
|
||||||
objectSchema,
|
objectSchema,
|
||||||
permissionSchema
|
permissionSchema
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
return ajv.validate('permissions', data_schema);
|
return ajv.validate('permissions', data_schema)
|
||||||
|
.then(() => {
|
||||||
|
return data_schema[permission];
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
//console.log(err.message);
|
//logger.error(err.message);
|
||||||
//console.log(err.errors);
|
//logger.error(err.errors);
|
||||||
|
|
||||||
throw new error.PermissionError('Permission Denied', err);
|
throw new error.PermissionError('Permission Denied', err);
|
||||||
});
|
});
|
||||||
|
23
src/backend/lib/access/dead_hosts-list.json
Normal file
23
src/backend/lib/access/dead_hosts-list.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_dead_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_dead_hosts": {
|
||||||
|
"$ref": "perms#/definitions/view"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
15
src/backend/lib/access/permissions.json
Normal file
15
src/backend/lib/access/permissions.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "perms",
|
||||||
|
"definitions": {
|
||||||
|
"view": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(view|manage)$"
|
||||||
|
},
|
||||||
|
"manage": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(manage)$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
23
src/backend/lib/access/proxy_hosts-list.json
Normal file
23
src/backend/lib/access/proxy_hosts-list.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_proxy_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_proxy_hosts": {
|
||||||
|
"$ref": "perms#/definitions/view"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
src/backend/lib/access/redirection_hosts-list.json
Normal file
23
src/backend/lib/access/redirection_hosts-list.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_redirection_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_redirection_hosts": {
|
||||||
|
"$ref": "perms#/definitions/view"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
src/backend/lib/access/streams-list.json
Normal file
23
src/backend/lib/access/streams-list.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_streams", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_streams": {
|
||||||
|
"$ref": "perms#/definitions/view"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -3,5 +3,6 @@ const {Signale} = require('signale');
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
global: new Signale({scope: 'Global '}),
|
global: new Signale({scope: 'Global '}),
|
||||||
migrate: new Signale({scope: 'Migrate '}),
|
migrate: new Signale({scope: 'Migrate '}),
|
||||||
express: new Signale({scope: 'Express '})
|
express: new Signale({scope: 'Express '}),
|
||||||
|
access: new Signale({scope: 'Access '})
|
||||||
};
|
};
|
||||||
|
@ -77,7 +77,6 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
table.integer('caching_enabled').notNull().unsigned().defaultTo(0);
|
table.integer('caching_enabled').notNull().unsigned().defaultTo(0);
|
||||||
table.integer('block_exploits').notNull().unsigned().defaultTo(0);
|
table.integer('block_exploits').notNull().unsigned().defaultTo(0);
|
||||||
table.json('meta').notNull();
|
table.json('meta').notNull();
|
||||||
table.unique(['domain_name', 'is_deleted']);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -96,7 +95,6 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
table.string('ssl_provider').notNull().defaultTo('');
|
table.string('ssl_provider').notNull().defaultTo('');
|
||||||
table.integer('block_exploits').notNull().unsigned().defaultTo(0);
|
table.integer('block_exploits').notNull().unsigned().defaultTo(0);
|
||||||
table.json('meta').notNull();
|
table.json('meta').notNull();
|
||||||
table.unique(['domain_name', 'is_deleted']);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -112,7 +110,6 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
table.integer('ssl_enabled').notNull().unsigned().defaultTo(0);
|
table.integer('ssl_enabled').notNull().unsigned().defaultTo(0);
|
||||||
table.string('ssl_provider').notNull().defaultTo('');
|
table.string('ssl_provider').notNull().defaultTo('');
|
||||||
table.json('meta').notNull();
|
table.json('meta').notNull();
|
||||||
table.unique(['domain_name', 'is_deleted']);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -130,7 +127,6 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
table.integer('tcp_forwarding').notNull().unsigned().defaultTo(0);
|
table.integer('tcp_forwarding').notNull().unsigned().defaultTo(0);
|
||||||
table.integer('udp_forwarding').notNull().unsigned().defaultTo(0);
|
table.integer('udp_forwarding').notNull().unsigned().defaultTo(0);
|
||||||
table.json('meta').notNull();
|
table.json('meta').notNull();
|
||||||
table.unique(['incoming_port', 'is_deleted']);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
48
src/backend/models/dead_host.js
Normal file
48
src/backend/models/dead_host.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Objection Docs:
|
||||||
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const db = require('../db');
|
||||||
|
const Model = require('objection').Model;
|
||||||
|
const User = require('./user');
|
||||||
|
|
||||||
|
Model.knex(db);
|
||||||
|
|
||||||
|
class DeadHost extends Model {
|
||||||
|
$beforeInsert () {
|
||||||
|
this.created_on = Model.raw('NOW()');
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
$beforeUpdate () {
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get name () {
|
||||||
|
return 'DeadHost';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get tableName () {
|
||||||
|
return 'dead_host';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get relationMappings () {
|
||||||
|
return {
|
||||||
|
owner: {
|
||||||
|
relation: Model.HasOneRelation,
|
||||||
|
modelClass: User,
|
||||||
|
join: {
|
||||||
|
from: 'dead_host.owner_user_id',
|
||||||
|
to: 'user.id'
|
||||||
|
},
|
||||||
|
modify: function (qb) {
|
||||||
|
qb.where('user.is_deleted', 0);
|
||||||
|
qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DeadHost;
|
48
src/backend/models/proxy_host.js
Normal file
48
src/backend/models/proxy_host.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Objection Docs:
|
||||||
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const db = require('../db');
|
||||||
|
const Model = require('objection').Model;
|
||||||
|
const User = require('./user');
|
||||||
|
|
||||||
|
Model.knex(db);
|
||||||
|
|
||||||
|
class ProxyHost extends Model {
|
||||||
|
$beforeInsert () {
|
||||||
|
this.created_on = Model.raw('NOW()');
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
$beforeUpdate () {
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get name () {
|
||||||
|
return 'ProxyHost';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get tableName () {
|
||||||
|
return 'proxy_host';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get relationMappings () {
|
||||||
|
return {
|
||||||
|
owner: {
|
||||||
|
relation: Model.HasOneRelation,
|
||||||
|
modelClass: User,
|
||||||
|
join: {
|
||||||
|
from: 'proxy_host.owner_user_id',
|
||||||
|
to: 'user.id'
|
||||||
|
},
|
||||||
|
modify: function (qb) {
|
||||||
|
qb.where('user.is_deleted', 0);
|
||||||
|
qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ProxyHost;
|
48
src/backend/models/redirection_host.js
Normal file
48
src/backend/models/redirection_host.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Objection Docs:
|
||||||
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const db = require('../db');
|
||||||
|
const Model = require('objection').Model;
|
||||||
|
const User = require('./user');
|
||||||
|
|
||||||
|
Model.knex(db);
|
||||||
|
|
||||||
|
class RedirectionHost extends Model {
|
||||||
|
$beforeInsert () {
|
||||||
|
this.created_on = Model.raw('NOW()');
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
$beforeUpdate () {
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get name () {
|
||||||
|
return 'RedirectionHost';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get tableName () {
|
||||||
|
return 'redirection_host';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get relationMappings () {
|
||||||
|
return {
|
||||||
|
owner: {
|
||||||
|
relation: Model.HasOneRelation,
|
||||||
|
modelClass: User,
|
||||||
|
join: {
|
||||||
|
from: 'redirection_host.owner_user_id',
|
||||||
|
to: 'user.id'
|
||||||
|
},
|
||||||
|
modify: function (qb) {
|
||||||
|
qb.where('user.is_deleted', 0);
|
||||||
|
qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = RedirectionHost;
|
48
src/backend/models/stream.js
Normal file
48
src/backend/models/stream.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Objection Docs:
|
||||||
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const db = require('../db');
|
||||||
|
const Model = require('objection').Model;
|
||||||
|
const User = require('./user');
|
||||||
|
|
||||||
|
Model.knex(db);
|
||||||
|
|
||||||
|
class Stream extends Model {
|
||||||
|
$beforeInsert () {
|
||||||
|
this.created_on = Model.raw('NOW()');
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
$beforeUpdate () {
|
||||||
|
this.modified_on = Model.raw('NOW()');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get name () {
|
||||||
|
return 'Stream';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get tableName () {
|
||||||
|
return 'stream';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get relationMappings () {
|
||||||
|
return {
|
||||||
|
owner: {
|
||||||
|
relation: Model.HasOneRelation,
|
||||||
|
modelClass: User,
|
||||||
|
join: {
|
||||||
|
from: 'stream.owner_user_id',
|
||||||
|
to: 'user.id'
|
||||||
|
},
|
||||||
|
modify: function (qb) {
|
||||||
|
qb.where('user.is_deleted', 0);
|
||||||
|
qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Stream;
|
@ -30,6 +30,10 @@ router.get('/', (req, res/*, next*/) => {
|
|||||||
router.use('/tokens', require('./tokens'));
|
router.use('/tokens', require('./tokens'));
|
||||||
router.use('/users', require('./users'));
|
router.use('/users', require('./users'));
|
||||||
router.use('/reports', require('./reports'));
|
router.use('/reports', require('./reports'));
|
||||||
|
router.use('/nginx/proxy-hosts', require('./nginx/proxy_hosts'));
|
||||||
|
router.use('/nginx/redirection-hosts', require('./nginx/redirection_hosts'));
|
||||||
|
router.use('/nginx/dead-hosts', require('./nginx/dead_hosts'));
|
||||||
|
router.use('/nginx/streams', require('./nginx/streams'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 404 for all other routes
|
* API 404 for all other routes
|
||||||
|
150
src/backend/routes/api/nginx/dead_hosts.js
Normal file
150
src/backend/routes/api/nginx/dead_hosts.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
const validator = require('../../../lib/validator');
|
||||||
|
const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
|
const internalDeadHost = require('../../../internal/dead-host');
|
||||||
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
|
let router = express.Router({
|
||||||
|
caseSensitive: true,
|
||||||
|
strict: true,
|
||||||
|
mergeParams: true
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /api/nginx/dead-hosts
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/dead-hosts
|
||||||
|
*
|
||||||
|
* Retrieve all dead-hosts
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
$ref: 'definitions#/definitions/query'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
||||||
|
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalDeadHost.getAll(res.locals.access, data.expand, data.query);
|
||||||
|
})
|
||||||
|
.then(rows => {
|
||||||
|
res.status(200)
|
||||||
|
.send(rows);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/dead-hosts
|
||||||
|
*
|
||||||
|
* Create a new dead-host
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/dead-hosts#/links/1/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
return internalDeadHost.create(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(201)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific dead-host
|
||||||
|
*
|
||||||
|
* /api/nginx/dead-hosts/123
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/dead-hosts/123
|
||||||
|
*
|
||||||
|
* Retrieve a specific dead-host
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
required: ['host_id'],
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
host_id: {
|
||||||
|
$ref: 'definitions#/definitions/id'
|
||||||
|
},
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
host_id: req.params.host_id,
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalDeadHost.get(res.locals.access, {
|
||||||
|
id: data.host_id,
|
||||||
|
expand: data.expand
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
res.status(200)
|
||||||
|
.send(row);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /api/nginx/dead-hosts/123
|
||||||
|
*
|
||||||
|
* Update and existing dead-host
|
||||||
|
*/
|
||||||
|
.put((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/dead-hosts#/links/2/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
payload.id = req.params.host_id;
|
||||||
|
return internalDeadHost.update(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /api/nginx/dead-hosts/123
|
||||||
|
*
|
||||||
|
* Update and existing dead-host
|
||||||
|
*/
|
||||||
|
.delete((req, res, next) => {
|
||||||
|
internalDeadHost.delete(res.locals.access, {id: req.params.host_id})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
150
src/backend/routes/api/nginx/proxy_hosts.js
Normal file
150
src/backend/routes/api/nginx/proxy_hosts.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
const validator = require('../../../lib/validator');
|
||||||
|
const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
|
const internalProxyHost = require('../../../internal/proxy-host');
|
||||||
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
|
let router = express.Router({
|
||||||
|
caseSensitive: true,
|
||||||
|
strict: true,
|
||||||
|
mergeParams: true
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /api/nginx/proxy-hosts
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/proxy-hosts
|
||||||
|
*
|
||||||
|
* Retrieve all proxy-hosts
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
$ref: 'definitions#/definitions/query'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
||||||
|
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalProxyHost.getAll(res.locals.access, data.expand, data.query);
|
||||||
|
})
|
||||||
|
.then(rows => {
|
||||||
|
res.status(200)
|
||||||
|
.send(rows);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/proxy-hosts
|
||||||
|
*
|
||||||
|
* Create a new proxy-host
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/proxy-hosts#/links/1/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
return internalProxyHost.create(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(201)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific proxy-host
|
||||||
|
*
|
||||||
|
* /api/nginx/proxy-hosts/123
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/proxy-hosts/123
|
||||||
|
*
|
||||||
|
* Retrieve a specific proxy-host
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
required: ['host_id'],
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
host_id: {
|
||||||
|
$ref: 'definitions#/definitions/id'
|
||||||
|
},
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
host_id: req.params.host_id,
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalProxyHost.get(res.locals.access, {
|
||||||
|
id: data.host_id,
|
||||||
|
expand: data.expand
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
res.status(200)
|
||||||
|
.send(row);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /api/nginx/proxy-hosts/123
|
||||||
|
*
|
||||||
|
* Update and existing proxy-host
|
||||||
|
*/
|
||||||
|
.put((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/proxy-hosts#/links/2/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
payload.id = req.params.host_id;
|
||||||
|
return internalProxyHost.update(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /api/nginx/proxy-hosts/123
|
||||||
|
*
|
||||||
|
* Update and existing proxy-host
|
||||||
|
*/
|
||||||
|
.delete((req, res, next) => {
|
||||||
|
internalProxyHost.delete(res.locals.access, {id: req.params.host_id})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
150
src/backend/routes/api/nginx/redirection_hosts.js
Normal file
150
src/backend/routes/api/nginx/redirection_hosts.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
const validator = require('../../../lib/validator');
|
||||||
|
const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
|
const internalRedirectionHost = require('../../../internal/redirection-host');
|
||||||
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
|
let router = express.Router({
|
||||||
|
caseSensitive: true,
|
||||||
|
strict: true,
|
||||||
|
mergeParams: true
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /api/nginx/redirection-hosts
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/redirection-hosts
|
||||||
|
*
|
||||||
|
* Retrieve all redirection-hosts
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
$ref: 'definitions#/definitions/query'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
||||||
|
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalRedirectionHost.getAll(res.locals.access, data.expand, data.query);
|
||||||
|
})
|
||||||
|
.then(rows => {
|
||||||
|
res.status(200)
|
||||||
|
.send(rows);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/redirection-hosts
|
||||||
|
*
|
||||||
|
* Create a new redirection-host
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/redirection-hosts#/links/1/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
return internalRedirectionHost.create(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(201)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific redirection-host
|
||||||
|
*
|
||||||
|
* /api/nginx/redirection-hosts/123
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/redirection-hosts/123
|
||||||
|
*
|
||||||
|
* Retrieve a specific redirection-host
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
required: ['host_id'],
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
host_id: {
|
||||||
|
$ref: 'definitions#/definitions/id'
|
||||||
|
},
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
host_id: req.params.host_id,
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalRedirectionHost.get(res.locals.access, {
|
||||||
|
id: data.host_id,
|
||||||
|
expand: data.expand
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
res.status(200)
|
||||||
|
.send(row);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /api/nginx/redirection-hosts/123
|
||||||
|
*
|
||||||
|
* Update and existing redirection-host
|
||||||
|
*/
|
||||||
|
.put((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/redirection-hosts#/links/2/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
payload.id = req.params.host_id;
|
||||||
|
return internalRedirectionHost.update(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /api/nginx/redirection-hosts/123
|
||||||
|
*
|
||||||
|
* Update and existing redirection-host
|
||||||
|
*/
|
||||||
|
.delete((req, res, next) => {
|
||||||
|
internalRedirectionHost.delete(res.locals.access, {id: req.params.host_id})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
150
src/backend/routes/api/nginx/streams.js
Normal file
150
src/backend/routes/api/nginx/streams.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
const validator = require('../../../lib/validator');
|
||||||
|
const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
|
const internalStream = require('../../../internal/stream');
|
||||||
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
|
let router = express.Router({
|
||||||
|
caseSensitive: true,
|
||||||
|
strict: true,
|
||||||
|
mergeParams: true
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /api/nginx/streams
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/streams
|
||||||
|
*
|
||||||
|
* Retrieve all streams
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
$ref: 'definitions#/definitions/query'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
||||||
|
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalStream.getAll(res.locals.access, data.expand, data.query);
|
||||||
|
})
|
||||||
|
.then(rows => {
|
||||||
|
res.status(200)
|
||||||
|
.send(rows);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/streams
|
||||||
|
*
|
||||||
|
* Create a new stream
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/streams#/links/1/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
return internalStream.create(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(201)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific stream
|
||||||
|
*
|
||||||
|
* /api/nginx/streams/123
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:stream_id')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/streams/123
|
||||||
|
*
|
||||||
|
* Retrieve a specific stream
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
required: ['stream_id'],
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
stream_id: {
|
||||||
|
$ref: 'definitions#/definitions/id'
|
||||||
|
},
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
stream_id: req.params.stream_id,
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
return internalStream.get(res.locals.access, {
|
||||||
|
id: data.stream_id,
|
||||||
|
expand: data.expand
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
res.status(200)
|
||||||
|
.send(row);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /api/nginx/streams/123
|
||||||
|
*
|
||||||
|
* Update and existing stream
|
||||||
|
*/
|
||||||
|
.put((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/streams#/links/2/schema'}, req.body)
|
||||||
|
.then(payload => {
|
||||||
|
payload.id = req.params.stream_id;
|
||||||
|
return internalStream.update(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /api/nginx/streams/123
|
||||||
|
*
|
||||||
|
* Update and existing stream
|
||||||
|
*/
|
||||||
|
.delete((req, res, next) => {
|
||||||
|
internalStream.delete(res.locals.access, {id: req.params.stream_id})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -3,7 +3,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const validator = require('../../lib/validator');
|
const validator = require('../../lib/validator');
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
const jwtdecode = require('../../lib/express/jwt-decode');
|
||||||
const pagination = require('../../lib/express/pagination');
|
|
||||||
const userIdFromMe = require('../../lib/express/user-id-from-me');
|
const userIdFromMe = require('../../lib/express/user-id-from-me');
|
||||||
const internalUser = require('../../internal/user');
|
const internalUser = require('../../internal/user');
|
||||||
const apiValidator = require('../../lib/validator/api');
|
const apiValidator = require('../../lib/validator/api');
|
||||||
|
203
src/backend/schema/endpoints/dead-hosts.json
Normal file
203
src/backend/schema/endpoints/dead-hosts.json
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "endpoints/dead-hosts",
|
||||||
|
"title": "Users",
|
||||||
|
"description": "Endpoints relating to Dead Hosts",
|
||||||
|
"stability": "stable",
|
||||||
|
"type": "object",
|
||||||
|
"definitions": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "../definitions.json#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name",
|
||||||
|
"example": "Jamie Curnow",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 100
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"description": "Nickname",
|
||||||
|
"example": "Jamie",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 50
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "../definitions.json#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"description": "Avatar",
|
||||||
|
"example": "http://somewhere.jpg",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 150,
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"description": "Roles",
|
||||||
|
"example": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"description": "Is Disabled",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"title": "List",
|
||||||
|
"description": "Returns a list of Users",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "GET",
|
||||||
|
"rel": "self",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create",
|
||||||
|
"description": "Creates a new User",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "create",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"nickname",
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Auth Credentials",
|
||||||
|
"example": {
|
||||||
|
"type": "password",
|
||||||
|
"secret": "bigredhorsebanana"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Update",
|
||||||
|
"description": "Updates a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "PUT",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Delete",
|
||||||
|
"description": "Deletes a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "DELETE",
|
||||||
|
"rel": "delete",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"$ref": "#/definitions/avatar"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
203
src/backend/schema/endpoints/proxy-hosts.json
Normal file
203
src/backend/schema/endpoints/proxy-hosts.json
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "endpoints/proxy-hosts",
|
||||||
|
"title": "Users",
|
||||||
|
"description": "Endpoints relating to Proxy Hosts",
|
||||||
|
"stability": "stable",
|
||||||
|
"type": "object",
|
||||||
|
"definitions": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "../definitions.json#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name",
|
||||||
|
"example": "Jamie Curnow",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 100
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"description": "Nickname",
|
||||||
|
"example": "Jamie",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 50
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "../definitions.json#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"description": "Avatar",
|
||||||
|
"example": "http://somewhere.jpg",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 150,
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"description": "Roles",
|
||||||
|
"example": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"description": "Is Disabled",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"title": "List",
|
||||||
|
"description": "Returns a list of Users",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "GET",
|
||||||
|
"rel": "self",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create",
|
||||||
|
"description": "Creates a new User",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "create",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"nickname",
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Auth Credentials",
|
||||||
|
"example": {
|
||||||
|
"type": "password",
|
||||||
|
"secret": "bigredhorsebanana"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Update",
|
||||||
|
"description": "Updates a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "PUT",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Delete",
|
||||||
|
"description": "Deletes a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "DELETE",
|
||||||
|
"rel": "delete",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"$ref": "#/definitions/avatar"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
203
src/backend/schema/endpoints/redirection-hosts.json
Normal file
203
src/backend/schema/endpoints/redirection-hosts.json
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "endpoints/redirection-hosts",
|
||||||
|
"title": "Users",
|
||||||
|
"description": "Endpoints relating to Redirection Hosts",
|
||||||
|
"stability": "stable",
|
||||||
|
"type": "object",
|
||||||
|
"definitions": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "../definitions.json#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name",
|
||||||
|
"example": "Jamie Curnow",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 100
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"description": "Nickname",
|
||||||
|
"example": "Jamie",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 50
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "../definitions.json#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"description": "Avatar",
|
||||||
|
"example": "http://somewhere.jpg",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 150,
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"description": "Roles",
|
||||||
|
"example": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"description": "Is Disabled",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"title": "List",
|
||||||
|
"description": "Returns a list of Users",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "GET",
|
||||||
|
"rel": "self",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create",
|
||||||
|
"description": "Creates a new User",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "create",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"nickname",
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Auth Credentials",
|
||||||
|
"example": {
|
||||||
|
"type": "password",
|
||||||
|
"secret": "bigredhorsebanana"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Update",
|
||||||
|
"description": "Updates a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "PUT",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Delete",
|
||||||
|
"description": "Deletes a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "DELETE",
|
||||||
|
"rel": "delete",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"$ref": "#/definitions/avatar"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
203
src/backend/schema/endpoints/streams.json
Normal file
203
src/backend/schema/endpoints/streams.json
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "endpoints/streams",
|
||||||
|
"title": "Users",
|
||||||
|
"description": "Endpoints relating to Streams",
|
||||||
|
"stability": "stable",
|
||||||
|
"type": "object",
|
||||||
|
"definitions": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "../definitions.json#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name",
|
||||||
|
"example": "Jamie Curnow",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 100
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"description": "Nickname",
|
||||||
|
"example": "Jamie",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 50
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "../definitions.json#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"description": "Avatar",
|
||||||
|
"example": "http://somewhere.jpg",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 2,
|
||||||
|
"maxLength": 150,
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"description": "Roles",
|
||||||
|
"example": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"description": "Is Disabled",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"title": "List",
|
||||||
|
"description": "Returns a list of Users",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "GET",
|
||||||
|
"rel": "self",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create",
|
||||||
|
"description": "Creates a new User",
|
||||||
|
"href": "/users",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "create",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"nickname",
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Auth Credentials",
|
||||||
|
"example": {
|
||||||
|
"type": "password",
|
||||||
|
"secret": "bigredhorsebanana"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Update",
|
||||||
|
"description": "Updates a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "PUT",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Delete",
|
||||||
|
"description": "Deletes a existing User",
|
||||||
|
"href": "/users/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "DELETE",
|
||||||
|
"rel": "delete",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"$ref": "#/definitions/name"
|
||||||
|
},
|
||||||
|
"nickname": {
|
||||||
|
"$ref": "#/definitions/nickname"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$ref": "#/definitions/email"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"$ref": "#/definitions/avatar"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"$ref": "#/definitions/roles"
|
||||||
|
},
|
||||||
|
"is_disabled": {
|
||||||
|
"$ref": "#/definitions/is_disabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,18 @@
|
|||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"$ref": "endpoints/users.json"
|
"$ref": "endpoints/users.json"
|
||||||
|
},
|
||||||
|
"proxy-hosts": {
|
||||||
|
"$ref": "endpoints/proxy-hosts.json"
|
||||||
|
},
|
||||||
|
"redirection-hosts": {
|
||||||
|
"$ref": "endpoints/redirection-hosts.json"
|
||||||
|
},
|
||||||
|
"dead-hosts": {
|
||||||
|
"$ref": "endpoints/dead-hosts.json"
|
||||||
|
},
|
||||||
|
"streams": {
|
||||||
|
"$ref": "endpoints/streams.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,26 @@ function makeExpansionString (expand) {
|
|||||||
return items.join(',');
|
return items.join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} path
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
function getAllObjects (path, expand, query) {
|
||||||
|
let params = [];
|
||||||
|
|
||||||
|
if (typeof expand === 'object' && expand !== null && expand.length) {
|
||||||
|
params.push('expand=' + makeExpansionString(expand));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof query === 'string') {
|
||||||
|
params.push('query=' + query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch('get', path + (params.length ? '?' + params.join('&') : ''));
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
status: function () {
|
status: function () {
|
||||||
return fetch('get', '');
|
return fetch('get', '');
|
||||||
@ -168,17 +188,7 @@ module.exports = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: function (expand, query) {
|
getAll: function (expand, query) {
|
||||||
let params = [];
|
return getAllObjects('users', expand, query);
|
||||||
|
|
||||||
if (typeof expand === 'object' && expand !== null && expand.length) {
|
|
||||||
params.push('expand=' + makeExpansionString(expand));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof query === 'string') {
|
|
||||||
params.push('query=' + query);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fetch('get', 'users' + (params.length ? '?' + params.join('&') : ''));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,6 +247,64 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Nginx: {
|
||||||
|
|
||||||
|
ProxyHosts: {
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: function (expand, query) {
|
||||||
|
return getAllObjects('nginx/proxy-hosts', expand, query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
RedirectionHosts: {
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: function (expand, query) {
|
||||||
|
return getAllObjects('nginx/redirection-hosts', expand, query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Streams: {
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: function (expand, query) {
|
||||||
|
return getAllObjects('nginx/streams', expand, query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
DeadHosts: {
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: function (expand, query) {
|
||||||
|
return getAllObjects('nginx/dead-hosts', expand, query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
AccessLists: {
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: function (expand, query) {
|
||||||
|
return getAllObjects('access-lists', expand, query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
Reports: {
|
Reports: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -244,6 +312,6 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
getHostStats: function () {
|
getHostStats: function () {
|
||||||
return fetch('get', 'reports/hosts');
|
return fetch('get', 'reports/hosts');
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -124,60 +124,70 @@ module.exports = {
|
|||||||
* Nginx Proxy Hosts
|
* Nginx Proxy Hosts
|
||||||
*/
|
*/
|
||||||
showNginxProxy: function () {
|
showNginxProxy: function () {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canView('proxy_hosts')) {
|
||||||
let controller = this;
|
let controller = this;
|
||||||
|
|
||||||
require(['./main', './nginx/proxy/main'], (App, View) => {
|
require(['./main', './nginx/proxy/main'], (App, View) => {
|
||||||
controller.navigate('/nginx/proxy');
|
controller.navigate('/nginx/proxy');
|
||||||
App.UI.showAppContent(new View());
|
App.UI.showAppContent(new View());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nginx Redirection Hosts
|
* Nginx Redirection Hosts
|
||||||
*/
|
*/
|
||||||
showNginxRedirection: function () {
|
showNginxRedirection: function () {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canView('redirection_hosts')) {
|
||||||
let controller = this;
|
let controller = this;
|
||||||
|
|
||||||
require(['./main', './nginx/redirection/main'], (App, View) => {
|
require(['./main', './nginx/redirection/main'], (App, View) => {
|
||||||
controller.navigate('/nginx/redirection');
|
controller.navigate('/nginx/redirection');
|
||||||
App.UI.showAppContent(new View());
|
App.UI.showAppContent(new View());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nginx Stream Hosts
|
* Nginx Stream Hosts
|
||||||
*/
|
*/
|
||||||
showNginxStream: function () {
|
showNginxStream: function () {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canView('streams')) {
|
||||||
let controller = this;
|
let controller = this;
|
||||||
|
|
||||||
require(['./main', './nginx/stream/main'], (App, View) => {
|
require(['./main', './nginx/stream/main'], (App, View) => {
|
||||||
controller.navigate('/nginx/stream');
|
controller.navigate('/nginx/stream');
|
||||||
App.UI.showAppContent(new View());
|
App.UI.showAppContent(new View());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nginx 404 Hosts
|
* Nginx Dead Hosts
|
||||||
*/
|
*/
|
||||||
showNginx404: function () {
|
showNginxDead: function () {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canView('dead_hosts')) {
|
||||||
let controller = this;
|
let controller = this;
|
||||||
|
|
||||||
require(['./main', './nginx/404/main'], (App, View) => {
|
require(['./main', './nginx/dead/main'], (App, View) => {
|
||||||
controller.navigate('/nginx/404');
|
controller.navigate('/nginx/404');
|
||||||
App.UI.showAppContent(new View());
|
App.UI.showAppContent(new View());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nginx Access
|
* Nginx Access
|
||||||
*/
|
*/
|
||||||
showNginxAccess: function () {
|
showNginxAccess: function () {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canView('access_lists')) {
|
||||||
let controller = this;
|
let controller = this;
|
||||||
|
|
||||||
require(['./main', './nginx/access/main'], (App, View) => {
|
require(['./main', './nginx/access/main'], (App, View) => {
|
||||||
controller.navigate('/nginx/access');
|
controller.navigate('/nginx/access');
|
||||||
App.UI.showAppContent(new View());
|
App.UI.showAppContent(new View());
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
<h1 class="page-title">Hi <%- getUserName() %></h1>
|
<h1 class="page-title">Hi <%- getUserName() %></h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% if (columns) { %>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 col-lg-3">
|
<% if (canShow('proxy_hosts')) { %>
|
||||||
|
<div class="col-sm-<%- 24 / columns %> col-lg-<%- 12 / columns %>">
|
||||||
<div class="card p-3">
|
<div class="card p-3">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span class="stamp stamp-md bg-green mr-3">
|
<span class="stamp stamp-md bg-green mr-3">
|
||||||
@ -15,8 +17,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
<% if (canShow('redirection_hosts')) { %>
|
||||||
|
<div class="col-sm-<%- 24 / columns %> col-lg-<%- 12 / columns %>">
|
||||||
<div class="card p-3">
|
<div class="card p-3">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span class="stamp stamp-md bg-yellow mr-3">
|
<span class="stamp stamp-md bg-yellow mr-3">
|
||||||
@ -28,8 +32,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
<% if (canShow('streams')) { %>
|
||||||
|
<div class="col-sm-<%- 24 / columns %> col-lg-<%- 12 / columns %>">
|
||||||
<div class="card p-3">
|
<div class="card p-3">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span class="stamp stamp-md bg-blue mr-3">
|
<span class="stamp stamp-md bg-blue mr-3">
|
||||||
@ -41,17 +47,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
<% if (canShow('dead_hosts')) { %>
|
||||||
|
<div class="col-sm-<%- 24 / columns %> col-lg-<%- 12 / columns %>">
|
||||||
<div class="card p-3">
|
<div class="card p-3">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span class="stamp stamp-md bg-red mr-3">
|
<span class="stamp stamp-md bg-red mr-3">
|
||||||
<i class="fe fe-zap-off"></i>
|
<i class="fe fe-zap-off"></i>
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<h4 class="m-0"><a href="/nginx/404"><%- getHostStat('404') %> <small>404 Hosts</small></a></h4>
|
<h4 class="m-0"><a href="/nginx/404"><%- getHostStat('dead') %> <small>404 Hosts</small></a></h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
<% } %>
|
||||||
|
@ -10,6 +10,7 @@ const template = require('./main.ejs');
|
|||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
template: template,
|
template: template,
|
||||||
id: 'dashboard',
|
id: 'dashboard',
|
||||||
|
columns: 0,
|
||||||
|
|
||||||
stats: {},
|
stats: {},
|
||||||
|
|
||||||
@ -38,7 +39,13 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return '-';
|
return '-';
|
||||||
}
|
},
|
||||||
|
|
||||||
|
canShow: function (perm) {
|
||||||
|
return Cache.User.isAdmin() || Cache.User.canView(perm);
|
||||||
|
},
|
||||||
|
|
||||||
|
columns: view.columns
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -57,5 +64,31 @@ module.exports = Mn.View.extend({
|
|||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} [model]
|
||||||
|
*/
|
||||||
|
preRender: function (model) {
|
||||||
|
this.columns = 0;
|
||||||
|
|
||||||
|
// calculate the available columns based on permissions for the objects
|
||||||
|
// and store as a variable
|
||||||
|
//let view = this;
|
||||||
|
let perms = ['proxy_hosts', 'redirection_hosts', 'streams', 'dead_hosts'];
|
||||||
|
|
||||||
|
perms.map(perm => {
|
||||||
|
this.columns += Cache.User.isAdmin() || Cache.User.canView(perm) ? 1 : 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent double rendering on initial calls
|
||||||
|
if (typeof model !== 'undefined') {
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.preRender();
|
||||||
|
this.listenTo(Cache.User, 'change', this.preRender);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
11
src/frontend/js/app/empty/main.ejs
Normal file
11
src/frontend/js/app/empty/main.ejs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<% if (title) { %>
|
||||||
|
<h1 class="h2 mb-3"><%- title %></h1>
|
||||||
|
<% }
|
||||||
|
|
||||||
|
if (subtitle) { %>
|
||||||
|
<p class="h4 text-muted font-weight-normal mb-7"><%- subtitle %></p>
|
||||||
|
<% }
|
||||||
|
|
||||||
|
if (link) { %>
|
||||||
|
<a class="btn btn-teal" href="#"><%- link %></a>
|
||||||
|
<% } %>
|
30
src/frontend/js/app/empty/main.js
Normal file
30
src/frontend/js/app/empty/main.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
className: 'text-center m-7',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
action: 'a'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.action': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.getOption('action')();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: function () {
|
||||||
|
return {
|
||||||
|
title: this.getOption('title'),
|
||||||
|
subtitle: this.getOption('subtitle'),
|
||||||
|
link: this.getOption('link'),
|
||||||
|
action: typeof this.getOption('action') === 'function'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
7
src/frontend/js/app/error/main.ejs
Normal file
7
src/frontend/js/app/error/main.ejs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<i class="fe fe-alert-triangle mr-2" aria-hidden="true"></i>
|
||||||
|
<%= code ? '<strong>' + code + '</strong> — ' : '' %>
|
||||||
|
<%- message %>
|
||||||
|
|
||||||
|
<% if (retry) { %>
|
||||||
|
<br><br><a href="#" class="btn btn-sm btn-warning retry">Try again</a>
|
||||||
|
<% } %>
|
29
src/frontend/js/app/error/main.js
Normal file
29
src/frontend/js/app/error/main.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
className: 'alert alert-icon alert-warning m-5',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
retry: 'a.retry'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.retry': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.getOption('retry')();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: function () {
|
||||||
|
return {
|
||||||
|
message: this.getOption('message'),
|
||||||
|
code: this.getOption('code'),
|
||||||
|
retry: typeof this.getOption('retry') === 'function'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
@ -1 +0,0 @@
|
|||||||
404
|
|
@ -1,9 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const Mn = require('backbone.marionette');
|
|
||||||
const template = require('./main.ejs');
|
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
|
||||||
template: template,
|
|
||||||
id: 'nginx-404'
|
|
||||||
});
|
|
32
src/frontend/js/app/nginx/dead/list/item.ejs
Normal file
32
src/frontend/js/app/nginx/dead/list/item.ejs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<td class="text-center">
|
||||||
|
<div class="avatar d-block" style="background-image: url(<%- avatar || '/images/default-avatar.jpg' %>)">
|
||||||
|
<span class="avatar-status <%- is_disabled ? 'bg-red' : 'bg-green' %>"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- name %></div>
|
||||||
|
<div class="small text-muted">
|
||||||
|
Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- email %></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- roles.join(', ') %></div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="item-action dropdown">
|
||||||
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit Details</a>
|
||||||
|
<a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a>
|
||||||
|
<a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> Set Password</a>
|
||||||
|
<% if (!isSelf()) { %>
|
||||||
|
<a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> Sign in as User</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete User</a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
72
src/frontend/js/app/nginx/dead/list/item.js
Normal file
72
src/frontend/js/app/nginx/dead/list/item.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const Controller = require('../../../controller');
|
||||||
|
const Api = require('../../../api');
|
||||||
|
const Cache = require('../../../cache');
|
||||||
|
const Tokens = require('../../../tokens');
|
||||||
|
const template = require('./item.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
tagName: 'tr',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
edit: 'a.edit-user',
|
||||||
|
permissions: 'a.edit-permissions',
|
||||||
|
password: 'a.set-password',
|
||||||
|
login: 'a.login',
|
||||||
|
delete: 'a.delete-user'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.edit': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.permissions': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPermissions(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.password': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPasswordForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.delete': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.login': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (Cache.User.get('id') !== this.model.get('id')) {
|
||||||
|
this.ui.login.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
|
||||||
|
Api.Users.loginAs(this.model.get('id'))
|
||||||
|
.then(res => {
|
||||||
|
Tokens.addToken(res.token, res.user.nickname || res.user.name);
|
||||||
|
window.location = '/';
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.login.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
isSelf: function () {
|
||||||
|
return Cache.User.get('id') === this.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(this.model, 'change', this.render);
|
||||||
|
}
|
||||||
|
});
|
10
src/frontend/js/app/nginx/dead/list/main.ejs
Normal file
10
src/frontend/js/app/nginx/dead/list/main.ejs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<thead>
|
||||||
|
<th width="30"> </th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Roles</th>
|
||||||
|
<th> </th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- items -->
|
||||||
|
</tbody>
|
29
src/frontend/js/app/nginx/dead/list/main.js
Normal file
29
src/frontend/js/app/nginx/dead/list/main.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const ItemView = require('./item');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
const TableBody = Mn.CollectionView.extend({
|
||||||
|
tagName: 'tbody',
|
||||||
|
childView: ItemView
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
tagName: 'table',
|
||||||
|
className: 'table table-hover table-outline table-vcenter text-nowrap card-table',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
body: {
|
||||||
|
el: 'tbody',
|
||||||
|
replaceElement: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.showChildView('body', new TableBody({
|
||||||
|
collection: this.collection
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
16
src/frontend/js/app/nginx/dead/main.ejs
Normal file
16
src/frontend/js/app/nginx/dead/main.ejs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">404 Hosts</h3>
|
||||||
|
<div class="card-options">
|
||||||
|
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-item">Add 404 Host</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body no-padding min-100">
|
||||||
|
<div class="dimmer active">
|
||||||
|
<div class="loader"></div>
|
||||||
|
<div class="dimmer-content list-region">
|
||||||
|
<!-- List Region -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
70
src/frontend/js/app/nginx/dead/main.js
Normal file
70
src/frontend/js/app/nginx/dead/main.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const DeadHostModel = require('../../../models/dead-host');
|
||||||
|
const Api = require('../../api');
|
||||||
|
const Controller = require('../../controller');
|
||||||
|
const ListView = require('./list/main');
|
||||||
|
const ErrorView = require('../../error/main');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
const EmptyView = require('../../empty/main');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
id: 'nginx-dead',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
list_region: '.list-region',
|
||||||
|
add: '.add-item',
|
||||||
|
dimmer: '.dimmer'
|
||||||
|
},
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
list_region: '@ui.list_region'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.add': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showNginxDeadForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
let view = this;
|
||||||
|
|
||||||
|
Api.Nginx.DeadHosts.getAll()
|
||||||
|
.then(response => {
|
||||||
|
if (!view.isDestroyed()) {
|
||||||
|
if (response && response.length) {
|
||||||
|
view.showChildView('list_region', new ListView({
|
||||||
|
collection: new DeadHostModel.Collection(response)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
view.showChildView('list_region', new EmptyView({
|
||||||
|
title: 'There are no 404 Hosts',
|
||||||
|
subtitle: 'Why don\'t you create one?',
|
||||||
|
link: 'Add 404 Host',
|
||||||
|
action: function () {
|
||||||
|
Controller.showNginxDeadForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
view.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
Controller.showNginxDead();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
view.ui.dimmer.removeClass('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
32
src/frontend/js/app/nginx/proxy/list/item.ejs
Normal file
32
src/frontend/js/app/nginx/proxy/list/item.ejs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<td class="text-center">
|
||||||
|
<div class="avatar d-block" style="background-image: url(<%- avatar || '/images/default-avatar.jpg' %>)">
|
||||||
|
<span class="avatar-status <%- is_disabled ? 'bg-red' : 'bg-green' %>"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- name %></div>
|
||||||
|
<div class="small text-muted">
|
||||||
|
Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- email %></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- roles.join(', ') %></div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="item-action dropdown">
|
||||||
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit Details</a>
|
||||||
|
<a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a>
|
||||||
|
<a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> Set Password</a>
|
||||||
|
<% if (!isSelf()) { %>
|
||||||
|
<a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> Sign in as User</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete User</a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
72
src/frontend/js/app/nginx/proxy/list/item.js
Normal file
72
src/frontend/js/app/nginx/proxy/list/item.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const Controller = require('../../../controller');
|
||||||
|
const Api = require('../../../api');
|
||||||
|
const Cache = require('../../../cache');
|
||||||
|
const Tokens = require('../../../tokens');
|
||||||
|
const template = require('./item.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
tagName: 'tr',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
edit: 'a.edit-user',
|
||||||
|
permissions: 'a.edit-permissions',
|
||||||
|
password: 'a.set-password',
|
||||||
|
login: 'a.login',
|
||||||
|
delete: 'a.delete-user'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.edit': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.permissions': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPermissions(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.password': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPasswordForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.delete': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.login': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (Cache.User.get('id') !== this.model.get('id')) {
|
||||||
|
this.ui.login.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
|
||||||
|
Api.Users.loginAs(this.model.get('id'))
|
||||||
|
.then(res => {
|
||||||
|
Tokens.addToken(res.token, res.user.nickname || res.user.name);
|
||||||
|
window.location = '/';
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.login.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
isSelf: function () {
|
||||||
|
return Cache.User.get('id') === this.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(this.model, 'change', this.render);
|
||||||
|
}
|
||||||
|
});
|
10
src/frontend/js/app/nginx/proxy/list/main.ejs
Normal file
10
src/frontend/js/app/nginx/proxy/list/main.ejs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<thead>
|
||||||
|
<th width="30"> </th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Roles</th>
|
||||||
|
<th> </th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- items -->
|
||||||
|
</tbody>
|
29
src/frontend/js/app/nginx/proxy/list/main.js
Normal file
29
src/frontend/js/app/nginx/proxy/list/main.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const ItemView = require('./item');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
const TableBody = Mn.CollectionView.extend({
|
||||||
|
tagName: 'tbody',
|
||||||
|
childView: ItemView
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
tagName: 'table',
|
||||||
|
className: 'table table-hover table-outline table-vcenter text-nowrap card-table',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
body: {
|
||||||
|
el: 'tbody',
|
||||||
|
replaceElement: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.showChildView('body', new TableBody({
|
||||||
|
collection: this.collection
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
@ -1 +1,16 @@
|
|||||||
proxy
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Proxy Hosts</h3>
|
||||||
|
<div class="card-options">
|
||||||
|
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-item">Add Proxy Host</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body no-padding min-100">
|
||||||
|
<div class="dimmer active">
|
||||||
|
<div class="loader"></div>
|
||||||
|
<div class="dimmer-content list-region">
|
||||||
|
<!-- List Region -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -1,9 +1,70 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Mn = require('backbone.marionette');
|
const Mn = require('backbone.marionette');
|
||||||
|
const ProxyHostModel = require('../../../models/proxy-host');
|
||||||
|
const Api = require('../../api');
|
||||||
|
const Controller = require('../../controller');
|
||||||
|
const ListView = require('./list/main');
|
||||||
|
const ErrorView = require('../../error/main');
|
||||||
const template = require('./main.ejs');
|
const template = require('./main.ejs');
|
||||||
|
const EmptyView = require('../../empty/main');
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
|
id: 'nginx-proxy',
|
||||||
template: template,
|
template: template,
|
||||||
id: 'nginx-proxy'
|
|
||||||
|
ui: {
|
||||||
|
list_region: '.list-region',
|
||||||
|
add: '.add-item',
|
||||||
|
dimmer: '.dimmer'
|
||||||
|
},
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
list_region: '@ui.list_region'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.add': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showNginxProxyForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
let view = this;
|
||||||
|
|
||||||
|
Api.Nginx.ProxyHosts.getAll()
|
||||||
|
.then(response => {
|
||||||
|
if (!view.isDestroyed()) {
|
||||||
|
if (response && response.length) {
|
||||||
|
view.showChildView('list_region', new ListView({
|
||||||
|
collection: new ProxyHostModel.Collection(response)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
view.showChildView('list_region', new EmptyView({
|
||||||
|
title: 'There are no Proxy Hosts',
|
||||||
|
subtitle: 'Why don\'t you create one?',
|
||||||
|
link: 'Add Proxy Host',
|
||||||
|
action: function () {
|
||||||
|
Controller.showNginxProxyForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
view.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
Controller.showNginxProxy();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
view.ui.dimmer.removeClass('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
32
src/frontend/js/app/nginx/redirection/list/item.ejs
Normal file
32
src/frontend/js/app/nginx/redirection/list/item.ejs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<td class="text-center">
|
||||||
|
<div class="avatar d-block" style="background-image: url(<%- avatar || '/images/default-avatar.jpg' %>)">
|
||||||
|
<span class="avatar-status <%- is_disabled ? 'bg-red' : 'bg-green' %>"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- name %></div>
|
||||||
|
<div class="small text-muted">
|
||||||
|
Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- email %></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- roles.join(', ') %></div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="item-action dropdown">
|
||||||
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit Details</a>
|
||||||
|
<a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a>
|
||||||
|
<a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> Set Password</a>
|
||||||
|
<% if (!isSelf()) { %>
|
||||||
|
<a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> Sign in as User</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete User</a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
72
src/frontend/js/app/nginx/redirection/list/item.js
Normal file
72
src/frontend/js/app/nginx/redirection/list/item.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const Controller = require('../../../controller');
|
||||||
|
const Api = require('../../../api');
|
||||||
|
const Cache = require('../../../cache');
|
||||||
|
const Tokens = require('../../../tokens');
|
||||||
|
const template = require('./item.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
tagName: 'tr',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
edit: 'a.edit-user',
|
||||||
|
permissions: 'a.edit-permissions',
|
||||||
|
password: 'a.set-password',
|
||||||
|
login: 'a.login',
|
||||||
|
delete: 'a.delete-user'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.edit': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.permissions': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPermissions(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.password': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPasswordForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.delete': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.login': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (Cache.User.get('id') !== this.model.get('id')) {
|
||||||
|
this.ui.login.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
|
||||||
|
Api.Users.loginAs(this.model.get('id'))
|
||||||
|
.then(res => {
|
||||||
|
Tokens.addToken(res.token, res.user.nickname || res.user.name);
|
||||||
|
window.location = '/';
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.login.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
isSelf: function () {
|
||||||
|
return Cache.User.get('id') === this.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(this.model, 'change', this.render);
|
||||||
|
}
|
||||||
|
});
|
10
src/frontend/js/app/nginx/redirection/list/main.ejs
Normal file
10
src/frontend/js/app/nginx/redirection/list/main.ejs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<thead>
|
||||||
|
<th width="30"> </th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Roles</th>
|
||||||
|
<th> </th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- items -->
|
||||||
|
</tbody>
|
29
src/frontend/js/app/nginx/redirection/list/main.js
Normal file
29
src/frontend/js/app/nginx/redirection/list/main.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const ItemView = require('./item');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
const TableBody = Mn.CollectionView.extend({
|
||||||
|
tagName: 'tbody',
|
||||||
|
childView: ItemView
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
tagName: 'table',
|
||||||
|
className: 'table table-hover table-outline table-vcenter text-nowrap card-table',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
body: {
|
||||||
|
el: 'tbody',
|
||||||
|
replaceElement: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.showChildView('body', new TableBody({
|
||||||
|
collection: this.collection
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
@ -1 +1,16 @@
|
|||||||
redirection
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Redirection Hosts</h3>
|
||||||
|
<div class="card-options">
|
||||||
|
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-item">Add Redirection Host</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body no-padding min-100">
|
||||||
|
<div class="dimmer active">
|
||||||
|
<div class="loader"></div>
|
||||||
|
<div class="dimmer-content list-region">
|
||||||
|
<!-- List Region -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -1,9 +1,70 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Mn = require('backbone.marionette');
|
const Mn = require('backbone.marionette');
|
||||||
|
const RedirectionHostModel = require('../../../models/redirection-host');
|
||||||
|
const Api = require('../../api');
|
||||||
|
const Controller = require('../../controller');
|
||||||
|
const ListView = require('./list/main');
|
||||||
|
const ErrorView = require('../../error/main');
|
||||||
const template = require('./main.ejs');
|
const template = require('./main.ejs');
|
||||||
|
const EmptyView = require('../../empty/main');
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
|
id: 'nginx-redirections',
|
||||||
template: template,
|
template: template,
|
||||||
id: 'nginx-redirection'
|
|
||||||
|
ui: {
|
||||||
|
list_region: '.list-region',
|
||||||
|
add: '.add-item',
|
||||||
|
dimmer: '.dimmer'
|
||||||
|
},
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
list_region: '@ui.list_region'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.add': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showNginxRedirectionForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
let view = this;
|
||||||
|
|
||||||
|
Api.Nginx.RedirectionHosts.getAll()
|
||||||
|
.then(response => {
|
||||||
|
if (!view.isDestroyed()) {
|
||||||
|
if (response && response.length) {
|
||||||
|
view.showChildView('list_region', new ListView({
|
||||||
|
collection: new RedirectionHostModel.Collection(response)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
view.showChildView('list_region', new EmptyView({
|
||||||
|
title: 'There are no Redirection Hosts',
|
||||||
|
subtitle: 'Why don\'t you create one?',
|
||||||
|
link: 'Add Redirection Host',
|
||||||
|
action: function () {
|
||||||
|
Controller.showNginxRedirectionForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
view.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
Controller.showNginxRedirection();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
view.ui.dimmer.removeClass('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
32
src/frontend/js/app/nginx/stream/list/item.ejs
Normal file
32
src/frontend/js/app/nginx/stream/list/item.ejs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<td class="text-center">
|
||||||
|
<div class="avatar d-block" style="background-image: url(<%- avatar || '/images/default-avatar.jpg' %>)">
|
||||||
|
<span class="avatar-status <%- is_disabled ? 'bg-red' : 'bg-green' %>"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- name %></div>
|
||||||
|
<div class="small text-muted">
|
||||||
|
Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- email %></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div><%- roles.join(', ') %></div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="item-action dropdown">
|
||||||
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit Details</a>
|
||||||
|
<a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a>
|
||||||
|
<a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> Set Password</a>
|
||||||
|
<% if (!isSelf()) { %>
|
||||||
|
<a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> Sign in as User</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete User</a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
72
src/frontend/js/app/nginx/stream/list/item.js
Normal file
72
src/frontend/js/app/nginx/stream/list/item.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const Controller = require('../../../controller');
|
||||||
|
const Api = require('../../../api');
|
||||||
|
const Cache = require('../../../cache');
|
||||||
|
const Tokens = require('../../../tokens');
|
||||||
|
const template = require('./item.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
tagName: 'tr',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
edit: 'a.edit-user',
|
||||||
|
permissions: 'a.edit-permissions',
|
||||||
|
password: 'a.set-password',
|
||||||
|
login: 'a.login',
|
||||||
|
delete: 'a.delete-user'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.edit': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.permissions': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPermissions(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.password': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserPasswordForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.delete': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showUserDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.login': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (Cache.User.get('id') !== this.model.get('id')) {
|
||||||
|
this.ui.login.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
|
||||||
|
Api.Users.loginAs(this.model.get('id'))
|
||||||
|
.then(res => {
|
||||||
|
Tokens.addToken(res.token, res.user.nickname || res.user.name);
|
||||||
|
window.location = '/';
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.login.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
isSelf: function () {
|
||||||
|
return Cache.User.get('id') === this.id;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(this.model, 'change', this.render);
|
||||||
|
}
|
||||||
|
});
|
10
src/frontend/js/app/nginx/stream/list/main.ejs
Normal file
10
src/frontend/js/app/nginx/stream/list/main.ejs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<thead>
|
||||||
|
<th width="30"> </th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Roles</th>
|
||||||
|
<th> </th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- items -->
|
||||||
|
</tbody>
|
29
src/frontend/js/app/nginx/stream/list/main.js
Normal file
29
src/frontend/js/app/nginx/stream/list/main.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const ItemView = require('./item');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
const TableBody = Mn.CollectionView.extend({
|
||||||
|
tagName: 'tbody',
|
||||||
|
childView: ItemView
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
tagName: 'table',
|
||||||
|
className: 'table table-hover table-outline table-vcenter text-nowrap card-table',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
body: {
|
||||||
|
el: 'tbody',
|
||||||
|
replaceElement: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.showChildView('body', new TableBody({
|
||||||
|
collection: this.collection
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
@ -1 +1,16 @@
|
|||||||
stream
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Streams</h3>
|
||||||
|
<div class="card-options">
|
||||||
|
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-item">Add Stream</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body no-padding min-100">
|
||||||
|
<div class="dimmer active">
|
||||||
|
<div class="loader"></div>
|
||||||
|
<div class="dimmer-content list-region">
|
||||||
|
<!-- List Region -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -1,9 +1,70 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Mn = require('backbone.marionette');
|
const Mn = require('backbone.marionette');
|
||||||
|
const StreamModel = require('../../../models/stream');
|
||||||
|
const Api = require('../../api');
|
||||||
|
const Controller = require('../../controller');
|
||||||
|
const ListView = require('./list/main');
|
||||||
|
const ErrorView = require('../../error/main');
|
||||||
const template = require('./main.ejs');
|
const template = require('./main.ejs');
|
||||||
|
const EmptyView = require('../../empty/main');
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
|
id: 'nginx-streams',
|
||||||
template: template,
|
template: template,
|
||||||
id: 'nginx-stream'
|
|
||||||
|
ui: {
|
||||||
|
list_region: '.list-region',
|
||||||
|
add: '.add-item',
|
||||||
|
dimmer: '.dimmer'
|
||||||
|
},
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
list_region: '@ui.list_region'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.add': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showNginxStreamForm();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
let view = this;
|
||||||
|
|
||||||
|
Api.Nginx.RedirectionHosts.getAll()
|
||||||
|
.then(response => {
|
||||||
|
if (!view.isDestroyed()) {
|
||||||
|
if (response && response.length) {
|
||||||
|
view.showChildView('list_region', new ListView({
|
||||||
|
collection: new StreamModel.Collection(response)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
view.showChildView('list_region', new EmptyView({
|
||||||
|
title: 'There are no Streams',
|
||||||
|
subtitle: 'Why don\'t you create one?',
|
||||||
|
link: 'Add Stream',
|
||||||
|
action: function () {
|
||||||
|
Controller.showNginxStreamForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
view.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
Controller.showNginxStream();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
view.ui.dimmer.removeClass('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ module.exports = Mn.AppRouter.extend({
|
|||||||
logout: 'logout',
|
logout: 'logout',
|
||||||
'nginx/proxy': 'showNginxProxy',
|
'nginx/proxy': 'showNginxProxy',
|
||||||
'nginx/redirection': 'showNginxRedirection',
|
'nginx/redirection': 'showNginxRedirection',
|
||||||
'nginx/404': 'showNginx404',
|
'nginx/404': 'showNginxDead',
|
||||||
'nginx/stream': 'showNginxStream',
|
'nginx/stream': 'showNginxStream',
|
||||||
'nginx/access': 'showNginxAccess',
|
'nginx/access': 'showNginxAccess',
|
||||||
'*default': 'showDashboard'
|
'*default': 'showDashboard'
|
||||||
|
@ -51,5 +51,9 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
return 'Sign out';
|
return 'Sign out';
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(Cache.User, 'change', this.render);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8,15 +8,28 @@
|
|||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a href="#" class="nav-link" data-toggle="dropdown"><i class="fe fe-monitor"></i> Hosts</a>
|
<a href="#" class="nav-link" data-toggle="dropdown"><i class="fe fe-monitor"></i> Hosts</a>
|
||||||
<div class="dropdown-menu dropdown-menu-arrow">
|
<div class="dropdown-menu dropdown-menu-arrow">
|
||||||
|
<% if (canShow('proxy_hosts')) { %>
|
||||||
<a href="/nginx/proxy" class="dropdown-item ">Proxy Hosts</a>
|
<a href="/nginx/proxy" class="dropdown-item ">Proxy Hosts</a>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (canShow('redirection_hosts')) { %>
|
||||||
<a href="/nginx/redirection" class="dropdown-item ">Redirections</a>
|
<a href="/nginx/redirection" class="dropdown-item ">Redirections</a>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (canShow('streams')) { %>
|
||||||
<a href="/nginx/stream" class="dropdown-item ">Streams</a>
|
<a href="/nginx/stream" class="dropdown-item ">Streams</a>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (canShow('dead_hosts')) { %>
|
||||||
<a href="/nginx/404" class="dropdown-item ">404 Hosts</a>
|
<a href="/nginx/404" class="dropdown-item ">404 Hosts</a>
|
||||||
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<% if (canShow('access_lists')) { %>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/nginx/access" class="nav-link"><i class="fe fe-lock"></i> Access Lists</a>
|
<a href="/nginx/access" class="nav-link"><i class="fe fe-lock"></i> Access Lists</a>
|
||||||
</li>
|
</li>
|
||||||
|
<% } %>
|
||||||
<% if (showUsers()) { %>
|
<% if (showUsers()) { %>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/users" class="nav-link"><i class="fe fe-users"></i> Users</a>
|
<a href="/users" class="nav-link"><i class="fe fe-users"></i> Users</a>
|
||||||
|
@ -17,14 +17,25 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click @ui.links': function (e) {
|
'click @ui.links': function (e) {
|
||||||
|
let href = $(e.currentTarget).attr('href');
|
||||||
|
if (href !== '#') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Controller.navigate($(e.currentTarget).attr('href'), true);
|
Controller.navigate(href, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
templateContext: {
|
templateContext: {
|
||||||
showUsers: function () {
|
showUsers: function () {
|
||||||
return Cache.User.isAdmin();
|
return Cache.User.isAdmin();
|
||||||
|
},
|
||||||
|
|
||||||
|
canShow: function (perm) {
|
||||||
|
return Cache.User.isAdmin() || Cache.User.canView(perm);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(Cache.User, 'change', this.render);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add_user: '.add-user',
|
add: '.add-item',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ module.exports = Mn.View.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click @ui.add_user': function (e) {
|
'click @ui.add': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Controller.showUserForm(new UserModel.Model());
|
Controller.showUserForm(new UserModel.Model());
|
||||||
}
|
}
|
||||||
@ -37,15 +37,19 @@ module.exports = Mn.View.extend({
|
|||||||
view.showChildView('list_region', new ListView({
|
view.showChildView('list_region', new ListView({
|
||||||
collection: new UserModel.Collection(response)
|
collection: new UserModel.Collection(response)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Remove loader
|
|
||||||
view.ui.dimmer.removeClass('active');
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.log(err);
|
view.showChildView('list_region', new ErrorView({
|
||||||
//Controller.showError(err, 'Could not fetch Users');
|
code: err.code,
|
||||||
//view.trigger('loaded');
|
message: err.message,
|
||||||
|
retry: function () { Controller.showUsers(); }
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
view.ui.dimmer.removeClass('active');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
26
src/frontend/js/models/dead-host.js
Normal file
26
src/frontend/js/models/dead-host.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Backbone = require('backbone');
|
||||||
|
|
||||||
|
const model = Backbone.Model.extend({
|
||||||
|
idAttribute: 'id',
|
||||||
|
|
||||||
|
defaults: function () {
|
||||||
|
return {
|
||||||
|
created_on: null,
|
||||||
|
modified_on: null,
|
||||||
|
owner: null,
|
||||||
|
domain_name: '',
|
||||||
|
ssl_enabled: false,
|
||||||
|
ssl_provider: false,
|
||||||
|
meta: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Model: model,
|
||||||
|
Collection: Backbone.Collection.extend({
|
||||||
|
model: model
|
||||||
|
})
|
||||||
|
};
|
32
src/frontend/js/models/proxy-host.js
Normal file
32
src/frontend/js/models/proxy-host.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Backbone = require('backbone');
|
||||||
|
|
||||||
|
const model = Backbone.Model.extend({
|
||||||
|
idAttribute: 'id',
|
||||||
|
|
||||||
|
defaults: function () {
|
||||||
|
return {
|
||||||
|
created_on: null,
|
||||||
|
modified_on: null,
|
||||||
|
owner: null,
|
||||||
|
domain_name: '',
|
||||||
|
forward_ip: '',
|
||||||
|
forward_port: 0,
|
||||||
|
access_list_id: 0,
|
||||||
|
ssl_enabled: false,
|
||||||
|
ssl_provider: false,
|
||||||
|
ssl_forced: false,
|
||||||
|
caching_enabled: false,
|
||||||
|
block_exploits: false,
|
||||||
|
meta: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Model: model,
|
||||||
|
Collection: Backbone.Collection.extend({
|
||||||
|
model: model
|
||||||
|
})
|
||||||
|
};
|
29
src/frontend/js/models/redirection-host.js
Normal file
29
src/frontend/js/models/redirection-host.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Backbone = require('backbone');
|
||||||
|
|
||||||
|
const model = Backbone.Model.extend({
|
||||||
|
idAttribute: 'id',
|
||||||
|
|
||||||
|
defaults: function () {
|
||||||
|
return {
|
||||||
|
created_on: null,
|
||||||
|
modified_on: null,
|
||||||
|
owner: null,
|
||||||
|
domain_name: '',
|
||||||
|
forward_domain_name: '',
|
||||||
|
preserve_path: false,
|
||||||
|
ssl_enabled: false,
|
||||||
|
ssl_provider: false,
|
||||||
|
block_exploits: false,
|
||||||
|
meta: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Model: model,
|
||||||
|
Collection: Backbone.Collection.extend({
|
||||||
|
model: model
|
||||||
|
})
|
||||||
|
};
|
28
src/frontend/js/models/stream.js
Normal file
28
src/frontend/js/models/stream.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Backbone = require('backbone');
|
||||||
|
|
||||||
|
const model = Backbone.Model.extend({
|
||||||
|
idAttribute: 'id',
|
||||||
|
|
||||||
|
defaults: function () {
|
||||||
|
return {
|
||||||
|
created_on: null,
|
||||||
|
modified_on: null,
|
||||||
|
owner: null,
|
||||||
|
incoming_port: 0,
|
||||||
|
forward_ip: '',
|
||||||
|
forwarding_port: 0,
|
||||||
|
tcp_forwarding: true,
|
||||||
|
udp_forwarding: false,
|
||||||
|
meta: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Model: model,
|
||||||
|
Collection: Backbone.Collection.extend({
|
||||||
|
model: model
|
||||||
|
})
|
||||||
|
};
|
@ -17,8 +17,33 @@ const model = Backbone.Model.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
isAdmin: function () {
|
isAdmin: function () {
|
||||||
return _.indexOf(this.get('roles'), 'admin') !== -1;
|
return _.indexOf(this.get('roles'), 'admin') !== -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the perm has either `view` or `manage` value
|
||||||
|
*
|
||||||
|
* @param {String} item
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
canView: function (item) {
|
||||||
|
let permissions = this.get('permissions');
|
||||||
|
return permissions !== null && typeof permissions[item] !== 'undefined' && ['view', 'manage'].indexOf(permissions[item]) !== -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the perm has `manage` value
|
||||||
|
*
|
||||||
|
* @param {String} item
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
canManage: function (item) {
|
||||||
|
let permissions = this.get('permissions');
|
||||||
|
return permissions !== null && typeof permissions[item] !== 'undefined' && permissions[item] === 'manage';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user