mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-11-04 01:15:14 +00:00 
			
		
		
		
	WIP
This commit is contained in:
		@@ -12,6 +12,8 @@ services:
 | 
				
			|||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - ./data/letsencrypt:/etc/letsencrypt
 | 
					      - ./data/letsencrypt:/etc/letsencrypt
 | 
				
			||||||
      - .:/srv/app
 | 
					      - .:/srv/app
 | 
				
			||||||
 | 
					      - ~/.yarnrc:/root/.yarnrc
 | 
				
			||||||
 | 
					      - ~/.npmrc:/root/.npmrc
 | 
				
			||||||
    depends_on:
 | 
					    depends_on:
 | 
				
			||||||
      - db
 | 
					      - db
 | 
				
			||||||
    links:
 | 
					    links:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,8 @@
 | 
				
			|||||||
    "jquery": "^3.3.1",
 | 
					    "jquery": "^3.3.1",
 | 
				
			||||||
    "jquery-mask-plugin": "^1.14.15",
 | 
					    "jquery-mask-plugin": "^1.14.15",
 | 
				
			||||||
    "jquery-serializejson": "^2.8.1",
 | 
					    "jquery-serializejson": "^2.8.1",
 | 
				
			||||||
 | 
					    "messageformat": "^2.0.2",
 | 
				
			||||||
 | 
					    "messageformat-loader": "^0.7.0",
 | 
				
			||||||
    "mini-css-extract-plugin": "^0.4.0",
 | 
					    "mini-css-extract-plugin": "^0.4.0",
 | 
				
			||||||
    "moment": "^2.22.2",
 | 
					    "moment": "^2.22.2",
 | 
				
			||||||
    "node-sass": "^4.9.0",
 | 
					    "node-sass": "^4.9.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ const internalDeadHost = {
 | 
				
			|||||||
                    .where('is_deleted', 0)
 | 
					                    .where('is_deleted', 0)
 | 
				
			||||||
                    .groupBy('id')
 | 
					                    .groupBy('id')
 | 
				
			||||||
                    .omit(['is_deleted'])
 | 
					                    .omit(['is_deleted'])
 | 
				
			||||||
                    .orderBy('domain_name', 'ASC');
 | 
					                    .orderBy('domain_names', 'ASC');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (access_data.permission_visibility !== 'all') {
 | 
					                if (access_data.permission_visibility !== 'all') {
 | 
				
			||||||
                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
					                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
				
			||||||
@@ -35,7 +35,7 @@ const internalDeadHost = {
 | 
				
			|||||||
                // Query is used for searching
 | 
					                // Query is used for searching
 | 
				
			||||||
                if (typeof search_query === 'string') {
 | 
					                if (typeof search_query === 'string') {
 | 
				
			||||||
                    query.where(function () {
 | 
					                    query.where(function () {
 | 
				
			||||||
                        this.where('domain_name', 'like', '%' + search_query + '%');
 | 
					                        this.where('domain_names', 'like', '%' + search_query + '%');
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										96
									
								
								src/backend/internal/host.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/backend/internal/host.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const _                    = require('lodash');
 | 
				
			||||||
 | 
					const error                = require('../lib/error');
 | 
				
			||||||
 | 
					const proxyHostModel       = require('../models/proxy_host');
 | 
				
			||||||
 | 
					const redirectionHostModel = require('../models/redirection_host');
 | 
				
			||||||
 | 
					const deadHostModel        = require('../models/dead_host');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const internalHost = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Internal use only, checks to see if the domain is already taken by any other record
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param   {String}   hostname
 | 
				
			||||||
 | 
					     * @param   {String}   [ignore_type]   'proxy', 'redirection', 'dead'
 | 
				
			||||||
 | 
					     * @param   {Integer}  [ignore_id]     Must be supplied if type was also supplied
 | 
				
			||||||
 | 
					     * @returns {Promise}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    isHostnameTaken: function (hostname, ignore_type, ignore_id) {
 | 
				
			||||||
 | 
					        let promises = [
 | 
				
			||||||
 | 
					            proxyHostModel
 | 
				
			||||||
 | 
					                .query()
 | 
				
			||||||
 | 
					                .where('is_deleted', 0)
 | 
				
			||||||
 | 
					                .andWhere('domain_names', 'like', '%' + hostname + '%'),
 | 
				
			||||||
 | 
					            redirectionHostModel
 | 
				
			||||||
 | 
					                .query()
 | 
				
			||||||
 | 
					                .where('is_deleted', 0)
 | 
				
			||||||
 | 
					                .andWhere('domain_names', 'like', '%' + hostname + '%'),
 | 
				
			||||||
 | 
					            deadHostModel
 | 
				
			||||||
 | 
					                .query()
 | 
				
			||||||
 | 
					                .where('is_deleted', 0)
 | 
				
			||||||
 | 
					                .andWhere('domain_names', 'like', '%' + hostname + '%')
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Promise.all(promises)
 | 
				
			||||||
 | 
					            .then(promises_results => {
 | 
				
			||||||
 | 
					                let is_taken = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (promises_results[0]) {
 | 
				
			||||||
 | 
					                    // Proxy Hosts
 | 
				
			||||||
 | 
					                    if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[0], ignore_type === 'proxy' && ignore_id ? ignore_id : 0)) {
 | 
				
			||||||
 | 
					                        is_taken = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (promises_results[1]) {
 | 
				
			||||||
 | 
					                    // Redirection Hosts
 | 
				
			||||||
 | 
					                    if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[1], ignore_type === 'redirection' && ignore_id ? ignore_id : 0)) {
 | 
				
			||||||
 | 
					                        is_taken = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (promises_results[1]) {
 | 
				
			||||||
 | 
					                    // Dead Hosts
 | 
				
			||||||
 | 
					                    if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[2], ignore_type === 'dead' && ignore_id ? ignore_id : 0)) {
 | 
				
			||||||
 | 
					                        is_taken = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    hostname: hostname,
 | 
				
			||||||
 | 
					                    is_taken: is_taken
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Private call only
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param   {String}  hostname
 | 
				
			||||||
 | 
					     * @param   {Array}   existing_rows
 | 
				
			||||||
 | 
					     * @param   {Integer} [ignore_id]
 | 
				
			||||||
 | 
					     * @returns {Boolean}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    _checkHostnameRecordsTaken: function (hostname, existing_rows, ignore_id) {
 | 
				
			||||||
 | 
					        let is_taken = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (existing_rows && existing_rows.length) {
 | 
				
			||||||
 | 
					            existing_rows.map(function (existing_row) {
 | 
				
			||||||
 | 
					                existing_row.domain_names.map(function (existing_hostname) {
 | 
				
			||||||
 | 
					                    // Does this domain match?
 | 
				
			||||||
 | 
					                    if (existing_hostname.toLowerCase() === hostname.toLowerCase()) {
 | 
				
			||||||
 | 
					                        if (!ignore_id || ignore_id !== existing_row.id) {
 | 
				
			||||||
 | 
					                            is_taken = true;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return is_taken;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = internalHost;
 | 
				
			||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
const _              = require('lodash');
 | 
					const _              = require('lodash');
 | 
				
			||||||
const error          = require('../lib/error');
 | 
					const error          = require('../lib/error');
 | 
				
			||||||
const proxyHostModel = require('../models/proxy_host');
 | 
					const proxyHostModel = require('../models/proxy_host');
 | 
				
			||||||
 | 
					const internalHost   = require('./host');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function omissions () {
 | 
					function omissions () {
 | 
				
			||||||
    return ['is_deleted'];
 | 
					    return ['is_deleted'];
 | 
				
			||||||
@@ -16,60 +17,39 @@ const internalProxyHost = {
 | 
				
			|||||||
     * @returns {Promise}
 | 
					     * @returns {Promise}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    create: (access, data) => {
 | 
					    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)
 | 
					        return access.can('proxy_hosts:create', data)
 | 
				
			||||||
            .then(() => {
 | 
					            .then(access_data => {
 | 
				
			||||||
                data.avatar = gravatar.url(data.email, {default: 'mm'});
 | 
					                // Get a list of the domain names and check each of them against existing records
 | 
				
			||||||
 | 
					                let domain_name_check_promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return userModel
 | 
					                data.domain_names.map(function (domain_name) {
 | 
				
			||||||
 | 
					                    domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return Promise.all(domain_name_check_promises)
 | 
				
			||||||
 | 
					                    .then(check_results => {
 | 
				
			||||||
 | 
					                        check_results.map(function (result) {
 | 
				
			||||||
 | 
					                            if (result.is_taken) {
 | 
				
			||||||
 | 
					                                throw new error.ValidationError(result.hostname + ' is already in use');
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .then(() => {
 | 
				
			||||||
 | 
					                // At this point the domains should have been checked
 | 
				
			||||||
 | 
					                data.owner_user_id = access.token.get('attrs').id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (typeof data.meta === 'undefined') {
 | 
				
			||||||
 | 
					                    data.meta = {};
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return proxyHostModel
 | 
				
			||||||
                    .query()
 | 
					                    .query()
 | 
				
			||||||
                    .omit(omissions())
 | 
					                    .omit(omissions())
 | 
				
			||||||
                    .insertAndFetch(data);
 | 
					                    .insertAndFetch(data);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .then(user => {
 | 
					            .then(row => {
 | 
				
			||||||
                if (auth) {
 | 
					                return _.omit(row, omissions());
 | 
				
			||||||
                    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']});
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -82,63 +62,49 @@ const internalProxyHost = {
 | 
				
			|||||||
     * @return {Promise}
 | 
					     * @return {Promise}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    update: (access, data) => {
 | 
					    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)
 | 
					        return access.can('proxy_hosts:update', data.id)
 | 
				
			||||||
            .then(() => {
 | 
					            .then(access_data => {
 | 
				
			||||||
 | 
					                // Get a list of the domain names and check each of them against existing records
 | 
				
			||||||
 | 
					                let domain_name_check_promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Make sure that the user being updated doesn't change their email to another user that is already using it
 | 
					                if (typeof data.domain_names !== 'undefined') {
 | 
				
			||||||
                // 1. get user we want to update
 | 
					                    data.domain_names.map(function (domain_name) {
 | 
				
			||||||
                return internalProxyHost.get(access, {id: data.id})
 | 
					                        domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'proxy', 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 => {
 | 
					                    return Promise.all(domain_name_check_promises)
 | 
				
			||||||
                if (user.id !== data.id) {
 | 
					                        .then(check_results => {
 | 
				
			||||||
                    // Sanity check that something crazy hasn't happened
 | 
					                            check_results.map(function (result) {
 | 
				
			||||||
                    throw new error.InternalValidationError('User could not be updated, IDs do not match: ' + user.id + ' !== ' + data.id);
 | 
					                                if (result.is_taken) {
 | 
				
			||||||
 | 
					                                    throw new error.ValidationError(result.hostname + ' is already in use');
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            });
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                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(() => {
 | 
					            .then(() => {
 | 
				
			||||||
                return internalProxyHost.get(access, {id: data.id});
 | 
					                return internalProxyHost.get(access, {id: data.id});
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .then(row => {
 | 
				
			||||||
 | 
					                if (row.id !== data.id) {
 | 
				
			||||||
 | 
					                    // Sanity check that something crazy hasn't happened
 | 
				
			||||||
 | 
					                    throw new error.InternalValidationError('Proxy Host could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return proxyHostModel
 | 
				
			||||||
 | 
					                    .query()
 | 
				
			||||||
 | 
					                    .omit(omissions())
 | 
				
			||||||
 | 
					                    .patchAndFetchById(row.id, data)
 | 
				
			||||||
 | 
					                    .then(saved_row => {
 | 
				
			||||||
 | 
					                        return _.omit(saved_row, omissions());
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param  {Access}   access
 | 
					     * @param  {Access}   access
 | 
				
			||||||
     * @param  {Object}   [data]
 | 
					     * @param  {Object}   data
 | 
				
			||||||
     * @param  {Integer}  [data.id]          Defaults to the token user
 | 
					     * @param  {Integer}  data.id
 | 
				
			||||||
     * @param  {Array}    [data.expand]
 | 
					     * @param  {Array}    [data.expand]
 | 
				
			||||||
     * @param  {Array}    [data.omit]
 | 
					     * @param  {Array}    [data.omit]
 | 
				
			||||||
     * @return {Promise}
 | 
					     * @return {Promise}
 | 
				
			||||||
@@ -153,14 +119,18 @@ const internalProxyHost = {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return access.can('proxy_hosts:get', data.id)
 | 
					        return access.can('proxy_hosts:get', data.id)
 | 
				
			||||||
            .then(() => {
 | 
					            .then(access_data => {
 | 
				
			||||||
                let query = userModel
 | 
					                let query = proxyHostModel
 | 
				
			||||||
                    .query()
 | 
					                    .query()
 | 
				
			||||||
                    .where('is_deleted', 0)
 | 
					                    .where('is_deleted', 0)
 | 
				
			||||||
                    .andWhere('id', data.id)
 | 
					                    .andWhere('id', data.id)
 | 
				
			||||||
                    .allowEager('[permissions]')
 | 
					                    .allowEager('[permissions]')
 | 
				
			||||||
                    .first();
 | 
					                    .first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (access_data.permission_visibility !== 'all') {
 | 
				
			||||||
 | 
					                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Custom omissions
 | 
					                // Custom omissions
 | 
				
			||||||
                if (typeof data.omit !== 'undefined' && data.omit !== null) {
 | 
					                if (typeof data.omit !== 'undefined' && data.omit !== null) {
 | 
				
			||||||
                    query.omit(data.omit);
 | 
					                    query.omit(data.omit);
 | 
				
			||||||
@@ -193,19 +163,14 @@ const internalProxyHost = {
 | 
				
			|||||||
            .then(() => {
 | 
					            .then(() => {
 | 
				
			||||||
                return internalProxyHost.get(access, {id: data.id});
 | 
					                return internalProxyHost.get(access, {id: data.id});
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .then(user => {
 | 
					            .then(row => {
 | 
				
			||||||
                if (!user) {
 | 
					                if (!row) {
 | 
				
			||||||
                    throw new error.ItemNotFoundError(data.id);
 | 
					                    throw new error.ItemNotFoundError(data.id);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Make sure user can't delete themselves
 | 
					                return proxyHostModel
 | 
				
			||||||
                if (user.id === access.token.get('attrs').id) {
 | 
					 | 
				
			||||||
                    throw new error.PermissionError('You cannot delete yourself.');
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return userModel
 | 
					 | 
				
			||||||
                    .query()
 | 
					                    .query()
 | 
				
			||||||
                    .where('id', user.id)
 | 
					                    .where('id', row.id)
 | 
				
			||||||
                    .patch({
 | 
					                    .patch({
 | 
				
			||||||
                        is_deleted: 1
 | 
					                        is_deleted: 1
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
@@ -231,7 +196,8 @@ const internalProxyHost = {
 | 
				
			|||||||
                    .where('is_deleted', 0)
 | 
					                    .where('is_deleted', 0)
 | 
				
			||||||
                    .groupBy('id')
 | 
					                    .groupBy('id')
 | 
				
			||||||
                    .omit(['is_deleted'])
 | 
					                    .omit(['is_deleted'])
 | 
				
			||||||
                    .orderBy('domain_name', 'ASC');
 | 
					                    .allowEager('[owner,access_list]')
 | 
				
			||||||
 | 
					                    .orderBy('domain_names', 'ASC');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (access_data.permission_visibility !== 'all') {
 | 
					                if (access_data.permission_visibility !== 'all') {
 | 
				
			||||||
                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
					                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
				
			||||||
@@ -240,7 +206,7 @@ const internalProxyHost = {
 | 
				
			|||||||
                // Query is used for searching
 | 
					                // Query is used for searching
 | 
				
			||||||
                if (typeof search_query === 'string') {
 | 
					                if (typeof search_query === 'string') {
 | 
				
			||||||
                    query.where(function () {
 | 
					                    query.where(function () {
 | 
				
			||||||
                        this.where('domain_name', 'like', '%' + search_query + '%');
 | 
					                        this.where('domain_names', 'like', '%' + search_query + '%');
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ const internalProxyHost = {
 | 
				
			|||||||
                    .where('is_deleted', 0)
 | 
					                    .where('is_deleted', 0)
 | 
				
			||||||
                    .groupBy('id')
 | 
					                    .groupBy('id')
 | 
				
			||||||
                    .omit(['is_deleted'])
 | 
					                    .omit(['is_deleted'])
 | 
				
			||||||
                    .orderBy('domain_name', 'ASC');
 | 
					                    .orderBy('domain_names', 'ASC');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (access_data.permission_visibility !== 'all') {
 | 
					                if (access_data.permission_visibility !== 'all') {
 | 
				
			||||||
                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
					                    query.andWhere('owner_user_id', access.token.get('attrs').id);
 | 
				
			||||||
@@ -35,7 +35,7 @@ const internalProxyHost = {
 | 
				
			|||||||
                // Query is used for searching
 | 
					                // Query is used for searching
 | 
				
			||||||
                if (typeof search_query === 'string') {
 | 
					                if (typeof search_query === 'string') {
 | 
				
			||||||
                    query.where(function () {
 | 
					                    query.where(function () {
 | 
				
			||||||
                        this.where('domain_name', 'like', '%' + search_query + '%');
 | 
					                        this.where('domain_names', 'like', '%' + search_query + '%');
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -290,6 +290,7 @@ const internalUser = {
 | 
				
			|||||||
                    .where('is_deleted', 0)
 | 
					                    .where('is_deleted', 0)
 | 
				
			||||||
                    .groupBy('id')
 | 
					                    .groupBy('id')
 | 
				
			||||||
                    .omit(['is_deleted'])
 | 
					                    .omit(['is_deleted'])
 | 
				
			||||||
 | 
					                    .allowEager('[permissions]')
 | 
				
			||||||
                    .orderBy('name', 'ASC');
 | 
					                    .orderBy('name', 'ASC');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Query is used for searching
 | 
					                // Query is used for searching
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,8 +301,8 @@ module.exports = function (token_string) {
 | 
				
			|||||||
                            });
 | 
					                            });
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .catch(err => {
 | 
					                    .catch(err => {
 | 
				
			||||||
                        //logger.error(err.message);
 | 
					                        logger.error(err.message);
 | 
				
			||||||
                        //logger.error(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/proxy_hosts-create.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/backend/lib/access/proxy_hosts-create.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/manage"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "roles": {
 | 
				
			||||||
 | 
					          "type": "array",
 | 
				
			||||||
 | 
					          "items": {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "enum": ["user"]
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/backend/lib/access/proxy_hosts-delete.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/backend/lib/access/proxy_hosts-delete.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/manage"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "roles": {
 | 
				
			||||||
 | 
					          "type": "array",
 | 
				
			||||||
 | 
					          "items": {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "enum": ["user"]
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/backend/lib/access/proxy_hosts-get.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/backend/lib/access/proxy_hosts-get.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/proxy_hosts-update.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/backend/lib/access/proxy_hosts-update.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/manage"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "roles": {
 | 
				
			||||||
 | 
					          "type": "array",
 | 
				
			||||||
 | 
					          "items": {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "enum": ["user"]
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -67,7 +67,7 @@ exports.up = function (knex/*, Promise*/) {
 | 
				
			|||||||
                table.dateTime('modified_on').notNull();
 | 
					                table.dateTime('modified_on').notNull();
 | 
				
			||||||
                table.integer('owner_user_id').notNull().unsigned();
 | 
					                table.integer('owner_user_id').notNull().unsigned();
 | 
				
			||||||
                table.integer('is_deleted').notNull().unsigned().defaultTo(0);
 | 
					                table.integer('is_deleted').notNull().unsigned().defaultTo(0);
 | 
				
			||||||
                table.string('domain_name').notNull();
 | 
					                table.json('domain_names').notNull();
 | 
				
			||||||
                table.string('forward_ip').notNull();
 | 
					                table.string('forward_ip').notNull();
 | 
				
			||||||
                table.integer('forward_port').notNull().unsigned();
 | 
					                table.integer('forward_port').notNull().unsigned();
 | 
				
			||||||
                table.integer('access_list_id').notNull().unsigned().defaultTo(0);
 | 
					                table.integer('access_list_id').notNull().unsigned().defaultTo(0);
 | 
				
			||||||
@@ -88,7 +88,7 @@ exports.up = function (knex/*, Promise*/) {
 | 
				
			|||||||
                table.dateTime('modified_on').notNull();
 | 
					                table.dateTime('modified_on').notNull();
 | 
				
			||||||
                table.integer('owner_user_id').notNull().unsigned();
 | 
					                table.integer('owner_user_id').notNull().unsigned();
 | 
				
			||||||
                table.integer('is_deleted').notNull().unsigned().defaultTo(0);
 | 
					                table.integer('is_deleted').notNull().unsigned().defaultTo(0);
 | 
				
			||||||
                table.string('domain_name').notNull();
 | 
					                table.json('domain_names').notNull();
 | 
				
			||||||
                table.string('forward_domain_name').notNull();
 | 
					                table.string('forward_domain_name').notNull();
 | 
				
			||||||
                table.integer('preserve_path').notNull().unsigned().defaultTo(0);
 | 
					                table.integer('preserve_path').notNull().unsigned().defaultTo(0);
 | 
				
			||||||
                table.integer('ssl_enabled').notNull().unsigned().defaultTo(0);
 | 
					                table.integer('ssl_enabled').notNull().unsigned().defaultTo(0);
 | 
				
			||||||
@@ -106,7 +106,7 @@ exports.up = function (knex/*, Promise*/) {
 | 
				
			|||||||
                    table.dateTime('modified_on').notNull();
 | 
					                    table.dateTime('modified_on').notNull();
 | 
				
			||||||
                    table.integer('owner_user_id').notNull().unsigned();
 | 
					                    table.integer('owner_user_id').notNull().unsigned();
 | 
				
			||||||
                    table.integer('is_deleted').notNull().unsigned().defaultTo(0);
 | 
					                    table.integer('is_deleted').notNull().unsigned().defaultTo(0);
 | 
				
			||||||
                    table.string('domain_name').notNull();
 | 
					                    table.json('domain_names').notNull();
 | 
				
			||||||
                    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();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										52
									
								
								src/backend/models/access_list.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/backend/models/access_list.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					// 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 AccessList 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 'AccessList';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get tableName () {
 | 
				
			||||||
 | 
					        return 'access_list';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get jsonAttributes () {
 | 
				
			||||||
 | 
					        return ['meta'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get relationMappings () {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            owner: {
 | 
				
			||||||
 | 
					                relation:   Model.HasOneRelation,
 | 
				
			||||||
 | 
					                modelClass: User,
 | 
				
			||||||
 | 
					                join:       {
 | 
				
			||||||
 | 
					                    from: 'access_list.owner_user_id',
 | 
				
			||||||
 | 
					                    to:   'user.id'
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                modify:     function (qb) {
 | 
				
			||||||
 | 
					                    qb.where('user.is_deleted', 0);
 | 
				
			||||||
 | 
					                    qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = AccessList;
 | 
				
			||||||
							
								
								
									
										51
									
								
								src/backend/models/access_list_auth.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/backend/models/access_list_auth.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					// Objection Docs:
 | 
				
			||||||
 | 
					// http://vincit.github.io/objection.js/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const db    = require('../db');
 | 
				
			||||||
 | 
					const Model = require('objection').Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Model.knex(db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AccessListAuth 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 'AccessListAuth';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get tableName () {
 | 
				
			||||||
 | 
					        return 'access_list_auth';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get jsonAttributes () {
 | 
				
			||||||
 | 
					        return ['meta'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get relationMappings () {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            access_list: {
 | 
				
			||||||
 | 
					                relation:   Model.HasOneRelation,
 | 
				
			||||||
 | 
					                modelClass: './access_list',
 | 
				
			||||||
 | 
					                join:       {
 | 
				
			||||||
 | 
					                    from: 'access_list_auth.access_list_id',
 | 
				
			||||||
 | 
					                    to:   'access_list.id'
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                modify:     function (qb) {
 | 
				
			||||||
 | 
					                    qb.where('access_list.is_deleted', 0);
 | 
				
			||||||
 | 
					                    qb.omit(['created_on', 'modified_on', 'is_deleted', 'access_list_id']);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = AccessListAuth;
 | 
				
			||||||
@@ -27,6 +27,10 @@ class DeadHost extends Model {
 | 
				
			|||||||
        return 'dead_host';
 | 
					        return 'dead_host';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get jsonAttributes () {
 | 
				
			||||||
 | 
					        return ['domain_names', 'meta'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get relationMappings () {
 | 
					    static get relationMappings () {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            owner: {
 | 
					            owner: {
 | 
				
			||||||
@@ -38,7 +42,7 @@ class DeadHost extends Model {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
                modify:     function (qb) {
 | 
					                modify:     function (qb) {
 | 
				
			||||||
                    qb.where('user.is_deleted', 0);
 | 
					                    qb.where('user.is_deleted', 0);
 | 
				
			||||||
                    qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
					                    qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const db    = require('../db');
 | 
					const db         = require('../db');
 | 
				
			||||||
const Model = require('objection').Model;
 | 
					const Model      = require('objection').Model;
 | 
				
			||||||
const User  = require('./user');
 | 
					const User       = require('./user');
 | 
				
			||||||
 | 
					const AccessList = require('./access_list');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Model.knex(db);
 | 
					Model.knex(db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,10 +14,14 @@ class ProxyHost extends Model {
 | 
				
			|||||||
    $beforeInsert () {
 | 
					    $beforeInsert () {
 | 
				
			||||||
        this.created_on  = Model.raw('NOW()');
 | 
					        this.created_on  = Model.raw('NOW()');
 | 
				
			||||||
        this.modified_on = Model.raw('NOW()');
 | 
					        this.modified_on = Model.raw('NOW()');
 | 
				
			||||||
 | 
					        this.domain_names.sort();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $beforeUpdate () {
 | 
					    $beforeUpdate () {
 | 
				
			||||||
        this.modified_on = Model.raw('NOW()');
 | 
					        this.modified_on = Model.raw('NOW()');
 | 
				
			||||||
 | 
					        if (typeof this.domain_names !== 'undefined') {
 | 
				
			||||||
 | 
					            this.domain_names.sort();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get name () {
 | 
					    static get name () {
 | 
				
			||||||
@@ -27,9 +32,13 @@ class ProxyHost extends Model {
 | 
				
			|||||||
        return 'proxy_host';
 | 
					        return 'proxy_host';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get jsonAttributes () {
 | 
				
			||||||
 | 
					        return ['domain_names', 'meta'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get relationMappings () {
 | 
					    static get relationMappings () {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            owner: {
 | 
					            owner:       {
 | 
				
			||||||
                relation:   Model.HasOneRelation,
 | 
					                relation:   Model.HasOneRelation,
 | 
				
			||||||
                modelClass: User,
 | 
					                modelClass: User,
 | 
				
			||||||
                join:       {
 | 
					                join:       {
 | 
				
			||||||
@@ -38,7 +47,19 @@ class ProxyHost extends Model {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
                modify:     function (qb) {
 | 
					                modify:     function (qb) {
 | 
				
			||||||
                    qb.where('user.is_deleted', 0);
 | 
					                    qb.where('user.is_deleted', 0);
 | 
				
			||||||
                    qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
					                    qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            access_list: {
 | 
				
			||||||
 | 
					                relation:   Model.HasOneRelation,
 | 
				
			||||||
 | 
					                modelClass: AccessList,
 | 
				
			||||||
 | 
					                join:       {
 | 
				
			||||||
 | 
					                    from: 'proxy_host.access_list_id',
 | 
				
			||||||
 | 
					                    to:   'access_list.id'
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                modify:     function (qb) {
 | 
				
			||||||
 | 
					                    qb.where('access_list.is_deleted', 0);
 | 
				
			||||||
 | 
					                    qb.omit(['id', 'created_on', 'modified_on', 'is_deleted']);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,10 @@ class RedirectionHost extends Model {
 | 
				
			|||||||
        return 'redirection_host';
 | 
					        return 'redirection_host';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get jsonAttributes () {
 | 
				
			||||||
 | 
					        return ['domain_names', 'meta'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get relationMappings () {
 | 
					    static get relationMappings () {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            owner: {
 | 
					            owner: {
 | 
				
			||||||
@@ -38,7 +42,7 @@ class RedirectionHost extends Model {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
                modify:     function (qb) {
 | 
					                modify:     function (qb) {
 | 
				
			||||||
                    qb.where('user.is_deleted', 0);
 | 
					                    qb.where('user.is_deleted', 0);
 | 
				
			||||||
                    qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
					                    qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,10 @@ class Stream extends Model {
 | 
				
			|||||||
        return 'stream';
 | 
					        return 'stream';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static get jsonAttributes () {
 | 
				
			||||||
 | 
					        return ['meta'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get relationMappings () {
 | 
					    static get relationMappings () {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            owner: {
 | 
					            owner: {
 | 
				
			||||||
@@ -38,7 +42,7 @@ class Stream extends Model {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
                modify:     function (qb) {
 | 
					                modify:     function (qb) {
 | 
				
			||||||
                    qb.where('user.is_deleted', 0);
 | 
					                    qb.where('user.is_deleted', 0);
 | 
				
			||||||
                    qb.omit(['created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
					                    qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -104,7 +104,7 @@ router
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
            .then(data => {
 | 
					            .then(data => {
 | 
				
			||||||
                return internalProxyHost.get(res.locals.access, {
 | 
					                return internalProxyHost.get(res.locals.access, {
 | 
				
			||||||
                    id:     data.host_id,
 | 
					                    id:     parseInt(data.host_id, 10),
 | 
				
			||||||
                    expand: data.expand
 | 
					                    expand: data.expand
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
@@ -123,7 +123,7 @@ router
 | 
				
			|||||||
    .put((req, res, next) => {
 | 
					    .put((req, res, next) => {
 | 
				
			||||||
        apiValidator({$ref: 'endpoints/proxy-hosts#/links/2/schema'}, req.body)
 | 
					        apiValidator({$ref: 'endpoints/proxy-hosts#/links/2/schema'}, req.body)
 | 
				
			||||||
            .then(payload => {
 | 
					            .then(payload => {
 | 
				
			||||||
                payload.id = req.params.host_id;
 | 
					                payload.id = parseInt(req.params.host_id, 10);
 | 
				
			||||||
                return internalProxyHost.update(res.locals.access, payload);
 | 
					                return internalProxyHost.update(res.locals.access, payload);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .then(result => {
 | 
					            .then(result => {
 | 
				
			||||||
@@ -139,7 +139,7 @@ router
 | 
				
			|||||||
     * Update and existing proxy-host
 | 
					     * Update and existing proxy-host
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    .delete((req, res, next) => {
 | 
					    .delete((req, res, next) => {
 | 
				
			||||||
        internalProxyHost.delete(res.locals.access, {id: req.params.host_id})
 | 
					        internalProxyHost.delete(res.locals.access, {id: parseInt(req.params.host_id, 10)})
 | 
				
			||||||
            .then(result => {
 | 
					            .then(result => {
 | 
				
			||||||
                res.status(200)
 | 
					                res.status(200)
 | 
				
			||||||
                    .send(result);
 | 
					                    .send(result);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,6 +134,31 @@
 | 
				
			|||||||
      "type": "string",
 | 
					      "type": "string",
 | 
				
			||||||
      "minLength": 8,
 | 
					      "minLength": 8,
 | 
				
			||||||
      "maxLength": 255
 | 
					      "maxLength": 255
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "domain_names": {
 | 
				
			||||||
 | 
					      "description": "Domain Names separated by a comma",
 | 
				
			||||||
 | 
					      "example": "*.jc21.com,blog.jc21.com",
 | 
				
			||||||
 | 
					      "type": "array",
 | 
				
			||||||
 | 
					      "maxItems": 15,
 | 
				
			||||||
 | 
					      "uniqueItems": true,
 | 
				
			||||||
 | 
					      "items": {
 | 
				
			||||||
 | 
					        "type": "string",
 | 
				
			||||||
 | 
					        "pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "ssl_enabled": {
 | 
				
			||||||
 | 
					      "description": "Is SSL Enabled",
 | 
				
			||||||
 | 
					      "example": true,
 | 
				
			||||||
 | 
					      "type": "boolean"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "ssl_forced": {
 | 
				
			||||||
 | 
					      "description": "Is SSL Forced",
 | 
				
			||||||
 | 
					      "example": false,
 | 
				
			||||||
 | 
					      "type": "boolean"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "ssl_provider": {
 | 
				
			||||||
 | 
					      "type": "string",
 | 
				
			||||||
 | 
					      "pattern": "^(letsencrypt|other)$"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "$schema": "http://json-schema.org/draft-07/schema#",
 | 
					  "$schema": "http://json-schema.org/draft-07/schema#",
 | 
				
			||||||
  "$id": "endpoints/proxy-hosts",
 | 
					  "$id": "endpoints/proxy-hosts",
 | 
				
			||||||
  "title": "Users",
 | 
					  "title": "Proxy Hosts",
 | 
				
			||||||
  "description": "Endpoints relating to Proxy Hosts",
 | 
					  "description": "Endpoints relating to Proxy Hosts",
 | 
				
			||||||
  "stability": "stable",
 | 
					  "stability": "stable",
 | 
				
			||||||
  "type": "object",
 | 
					  "type": "object",
 | 
				
			||||||
@@ -15,49 +15,78 @@
 | 
				
			|||||||
    "modified_on": {
 | 
					    "modified_on": {
 | 
				
			||||||
      "$ref": "../definitions.json#/definitions/modified_on"
 | 
					      "$ref": "../definitions.json#/definitions/modified_on"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "name": {
 | 
					    "domain_names": {
 | 
				
			||||||
      "description": "Name",
 | 
					      "$ref": "../definitions.json#/definitions/domain_names"
 | 
				
			||||||
      "example": "Jamie Curnow",
 | 
					    },
 | 
				
			||||||
 | 
					    "forward_ip": {
 | 
				
			||||||
      "type": "string",
 | 
					      "type": "string",
 | 
				
			||||||
      "minLength": 2,
 | 
					      "format": "ipv4"
 | 
				
			||||||
      "maxLength": 100
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "nickname": {
 | 
					    "forward_port": {
 | 
				
			||||||
      "description": "Nickname",
 | 
					      "type": "integer",
 | 
				
			||||||
      "example": "Jamie",
 | 
					      "minimum": 1,
 | 
				
			||||||
      "type": "string",
 | 
					      "maximum": 65535
 | 
				
			||||||
      "minLength": 2,
 | 
					 | 
				
			||||||
      "maxLength": 50
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "email": {
 | 
					    "ssl_enabled": {
 | 
				
			||||||
      "$ref": "../definitions.json#/definitions/email"
 | 
					      "$ref": "../definitions.json#/definitions/ssl_enabled"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "avatar": {
 | 
					    "ssl_forced": {
 | 
				
			||||||
      "description": "Avatar",
 | 
					      "$ref": "../definitions.json#/definitions/ssl_forced"
 | 
				
			||||||
      "example": "http://somewhere.jpg",
 | 
					 | 
				
			||||||
      "type": "string",
 | 
					 | 
				
			||||||
      "minLength": 2,
 | 
					 | 
				
			||||||
      "maxLength": 150,
 | 
					 | 
				
			||||||
      "readOnly": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "roles": {
 | 
					    "ssl_provider": {
 | 
				
			||||||
      "description": "Roles",
 | 
					      "$ref": "../definitions.json#/definitions/ssl_provider"
 | 
				
			||||||
      "example": [
 | 
					 | 
				
			||||||
        "admin"
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
      "type": "array"
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "is_disabled": {
 | 
					    "meta": {
 | 
				
			||||||
      "description": "Is Disabled",
 | 
					      "type": "object",
 | 
				
			||||||
      "example": false,
 | 
					      "additionalProperties": false,
 | 
				
			||||||
      "type": "boolean"
 | 
					      "properties": {
 | 
				
			||||||
 | 
					        "letsencrypt_email": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "format": "email"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "letsencrypt_agree": {
 | 
				
			||||||
 | 
					          "type": "boolean"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "properties": {
 | 
				
			||||||
 | 
					    "id": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/id"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "created_on": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/created_on"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "modified_on": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/modified_on"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "domain_names": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/domain_names"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "forward_ip": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/forward_ip"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "forward_port": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/forward_port"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "ssl_enabled": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/ssl_enabled"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "ssl_forced": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/ssl_forced"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "ssl_provider": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/ssl_provider"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "meta": {
 | 
				
			||||||
 | 
					      "$ref": "#/definitions/meta"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "links": [
 | 
					  "links": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "title": "List",
 | 
					      "title": "List",
 | 
				
			||||||
      "description": "Returns a list of Users",
 | 
					      "description": "Returns a list of Proxy Hosts",
 | 
				
			||||||
      "href": "/users",
 | 
					      "href": "/nginx/proxy-hosts",
 | 
				
			||||||
      "access": "private",
 | 
					      "access": "private",
 | 
				
			||||||
      "method": "GET",
 | 
					      "method": "GET",
 | 
				
			||||||
      "rel": "self",
 | 
					      "rel": "self",
 | 
				
			||||||
@@ -73,8 +102,8 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "title": "Create",
 | 
					      "title": "Create",
 | 
				
			||||||
      "description": "Creates a new User",
 | 
					      "description": "Creates a new Proxy Host",
 | 
				
			||||||
      "href": "/users",
 | 
					      "href": "/nginx/proxy-hosts",
 | 
				
			||||||
      "access": "private",
 | 
					      "access": "private",
 | 
				
			||||||
      "method": "POST",
 | 
					      "method": "POST",
 | 
				
			||||||
      "rel": "create",
 | 
					      "rel": "create",
 | 
				
			||||||
@@ -84,33 +113,31 @@
 | 
				
			|||||||
      "schema": {
 | 
					      "schema": {
 | 
				
			||||||
        "type": "object",
 | 
					        "type": "object",
 | 
				
			||||||
        "required": [
 | 
					        "required": [
 | 
				
			||||||
          "name",
 | 
					          "domain_names",
 | 
				
			||||||
          "nickname",
 | 
					          "forward_ip",
 | 
				
			||||||
          "email"
 | 
					          "forward_port"
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "properties": {
 | 
					        "properties": {
 | 
				
			||||||
          "name": {
 | 
					          "domain_names": {
 | 
				
			||||||
            "$ref": "#/definitions/name"
 | 
					            "$ref": "#/definitions/domain_names"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "nickname": {
 | 
					          "forward_ip": {
 | 
				
			||||||
            "$ref": "#/definitions/nickname"
 | 
					            "$ref": "#/definitions/forward_ip"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "email": {
 | 
					          "forward_port": {
 | 
				
			||||||
            "$ref": "#/definitions/email"
 | 
					            "$ref": "#/definitions/forward_port"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "roles": {
 | 
					          "ssl_enabled": {
 | 
				
			||||||
            "$ref": "#/definitions/roles"
 | 
					            "$ref": "#/definitions/ssl_enabled"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "is_disabled": {
 | 
					          "ssl_forced": {
 | 
				
			||||||
            "$ref": "#/definitions/is_disabled"
 | 
					            "$ref": "#/definitions/ssl_forced"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "auth": {
 | 
					          "ssl_provider": {
 | 
				
			||||||
            "type": "object",
 | 
					            "$ref": "#/definitions/ssl_provider"
 | 
				
			||||||
            "description": "Auth Credentials",
 | 
					          },
 | 
				
			||||||
            "example": {
 | 
					          "meta": {
 | 
				
			||||||
              "type": "password",
 | 
					            "$ref": "#/definitions/meta"
 | 
				
			||||||
              "secret": "bigredhorsebanana"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
@@ -122,8 +149,8 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "title": "Update",
 | 
					      "title": "Update",
 | 
				
			||||||
      "description": "Updates a existing User",
 | 
					      "description": "Updates a existing Proxy Host",
 | 
				
			||||||
      "href": "/users/{definitions.identity.example}",
 | 
					      "href": "/nginx/proxy-hosts/{definitions.identity.example}",
 | 
				
			||||||
      "access": "private",
 | 
					      "access": "private",
 | 
				
			||||||
      "method": "PUT",
 | 
					      "method": "PUT",
 | 
				
			||||||
      "rel": "update",
 | 
					      "rel": "update",
 | 
				
			||||||
@@ -133,20 +160,26 @@
 | 
				
			|||||||
      "schema": {
 | 
					      "schema": {
 | 
				
			||||||
        "type": "object",
 | 
					        "type": "object",
 | 
				
			||||||
        "properties": {
 | 
					        "properties": {
 | 
				
			||||||
          "name": {
 | 
					          "domain_names": {
 | 
				
			||||||
            "$ref": "#/definitions/name"
 | 
					            "$ref": "#/definitions/domain_names"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "nickname": {
 | 
					          "forward_ip": {
 | 
				
			||||||
            "$ref": "#/definitions/nickname"
 | 
					            "$ref": "#/definitions/forward_ip"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "email": {
 | 
					          "forward_port": {
 | 
				
			||||||
            "$ref": "#/definitions/email"
 | 
					            "$ref": "#/definitions/forward_port"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "roles": {
 | 
					          "ssl_enabled": {
 | 
				
			||||||
            "$ref": "#/definitions/roles"
 | 
					            "$ref": "#/definitions/ssl_enabled"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "is_disabled": {
 | 
					          "ssl_forced": {
 | 
				
			||||||
            "$ref": "#/definitions/is_disabled"
 | 
					            "$ref": "#/definitions/ssl_forced"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "ssl_provider": {
 | 
				
			||||||
 | 
					            "$ref": "#/definitions/ssl_provider"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "meta": {
 | 
				
			||||||
 | 
					            "$ref": "#/definitions/meta"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
@@ -158,8 +191,8 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "title": "Delete",
 | 
					      "title": "Delete",
 | 
				
			||||||
      "description": "Deletes a existing User",
 | 
					      "description": "Deletes a existing Proxy Host",
 | 
				
			||||||
      "href": "/users/{definitions.identity.example}",
 | 
					      "href": "/nginx/proxy-hosts/{definitions.identity.example}",
 | 
				
			||||||
      "access": "private",
 | 
					      "access": "private",
 | 
				
			||||||
      "method": "DELETE",
 | 
					      "method": "DELETE",
 | 
				
			||||||
      "rel": "delete",
 | 
					      "rel": "delete",
 | 
				
			||||||
@@ -170,34 +203,5 @@
 | 
				
			|||||||
        "type": "boolean"
 | 
					        "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"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -264,6 +264,25 @@ module.exports = {
 | 
				
			|||||||
             */
 | 
					             */
 | 
				
			||||||
            create: function (data) {
 | 
					            create: function (data) {
 | 
				
			||||||
                return fetch('post', 'nginx/proxy-hosts', data);
 | 
					                return fetch('post', 'nginx/proxy-hosts', data);
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /**
 | 
				
			||||||
 | 
					             * @param   {Object}   data
 | 
				
			||||||
 | 
					             * @param   {Integer}  data.id
 | 
				
			||||||
 | 
					             * @returns {Promise}
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            update: function (data) {
 | 
				
			||||||
 | 
					                let id = data.id;
 | 
				
			||||||
 | 
					                delete data.id;
 | 
				
			||||||
 | 
					                return fetch('put', 'nginx/proxy-hosts/' + id, data);
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /**
 | 
				
			||||||
 | 
					             * @param   {Integer}  id
 | 
				
			||||||
 | 
					             * @returns {Promise}
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            delete: function (id) {
 | 
				
			||||||
 | 
					                return fetch('delete', 'nginx/proxy-hosts/' + id);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -147,6 +147,19 @@ module.exports = {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Proxy Host Delete Confirm
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param model
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    showNginxProxyDeleteConfirm: function (model) {
 | 
				
			||||||
 | 
					        if (Cache.User.isAdmin() || Cache.User.canManage('proxy_hosts')) {
 | 
				
			||||||
 | 
					            require(['./main', './nginx/proxy/delete'], function (App, View) {
 | 
				
			||||||
 | 
					                App.UI.showModalDialog(new View({model: model}));
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Nginx Redirection Hosts
 | 
					     * Nginx Redirection Hosts
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								src/frontend/js/app/nginx/proxy/delete.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/frontend/js/app/nginx/proxy/delete.ejs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					<div class="modal-content">
 | 
				
			||||||
 | 
					    <div class="modal-header">
 | 
				
			||||||
 | 
					        <h5 class="modal-title">Delete Proxy Host</h5>
 | 
				
			||||||
 | 
					        <button type="button" class="close cancel" aria-label="Close" data-dismiss="modal"> </button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="modal-body">
 | 
				
			||||||
 | 
					        <form>
 | 
				
			||||||
 | 
					            <div class="row">
 | 
				
			||||||
 | 
					                <div class="col-sm-12 col-md-12">
 | 
				
			||||||
 | 
					                    Are you sure you want to delete the Proxy host for: <strong><%- domain_names.join(', ') %></strong>?
 | 
				
			||||||
 | 
					                    <% if (ssl_enabled) { %>
 | 
				
			||||||
 | 
					                        <br><br>
 | 
				
			||||||
 | 
					                        The SSL certificates attached will be removed, this action cannot be recovered.
 | 
				
			||||||
 | 
					                    <% } %>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="modal-footer">
 | 
				
			||||||
 | 
					        <button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button>
 | 
				
			||||||
 | 
					        <button type="button" class="btn btn-danger save">Yes I'm Sure</button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/frontend/js/app/nginx/proxy/delete.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/frontend/js/app/nginx/proxy/delete.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Mn         = require('backbone.marionette');
 | 
				
			||||||
 | 
					const template   = require('./delete.ejs');
 | 
				
			||||||
 | 
					const Controller = require('../../controller');
 | 
				
			||||||
 | 
					const Api        = require('../../api');
 | 
				
			||||||
 | 
					const App        = require('../../main');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require('jquery-serializejson');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = Mn.View.extend({
 | 
				
			||||||
 | 
					    template:  template,
 | 
				
			||||||
 | 
					    className: 'modal-dialog',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui: {
 | 
				
			||||||
 | 
					        form:    'form',
 | 
				
			||||||
 | 
					        buttons: '.modal-footer button',
 | 
				
			||||||
 | 
					        cancel:  'button.cancel',
 | 
				
			||||||
 | 
					        save:    'button.save'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    events: {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        'click @ui.save': function (e) {
 | 
				
			||||||
 | 
					            e.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Api.Nginx.ProxyHosts.delete(this.model.get('id'))
 | 
				
			||||||
 | 
					                .then(() => {
 | 
				
			||||||
 | 
					                    Controller.showNginxProxy();
 | 
				
			||||||
 | 
					                    App.UI.closeModal();
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .catch(err => {
 | 
				
			||||||
 | 
					                    alert(err.message);
 | 
				
			||||||
 | 
					                    this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -13,22 +13,23 @@
 | 
				
			|||||||
                <!-- Details -->
 | 
					                <!-- Details -->
 | 
				
			||||||
                <div role="tabpanel" class="tab-pane active" id="details">
 | 
					                <div role="tabpanel" class="tab-pane active" id="details">
 | 
				
			||||||
                    <div class="row">
 | 
					                    <div class="row">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <div class="col-sm-12 col-md-12">
 | 
					                        <div class="col-sm-12 col-md-12">
 | 
				
			||||||
                            <div class="form-group">
 | 
					                            <div class="form-group">
 | 
				
			||||||
                                <label class="form-label">Domain Name <span class="form-required">*</span></label>
 | 
					                                <label class="form-label">Domain Names <span class="form-required">*</span></label>
 | 
				
			||||||
                                <input name="domain_name" type="text" class="form-control" placeholder="example.com or *.example.com" value="<%- domain_name %>" pattern="(\*\.)?[a-z0-9\.]+" required title="Please enter a valid domain name. Domain wildcards are allowed: *.yourdomain.com">
 | 
					                                <input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>" required>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="col-sm-8 col-md-8">
 | 
					                        <div class="col-sm-8 col-md-8">
 | 
				
			||||||
                            <div class="form-group">
 | 
					                            <div class="form-group">
 | 
				
			||||||
                                <label class="form-label">Forward IP <span class="form-required">*</span></label>
 | 
					                                <label class="form-label">Forward IP <span class="form-required">*</span></label>
 | 
				
			||||||
                                <input type="text" name="forward_ip" class="form-control" placeholder="000.000.000.000" autocomplete="off" maxlength="15" required>
 | 
					                                <input type="text" name="forward_ip" class="form-control text-monospace" placeholder="000.000.000.000" value="<%- forward_ip %>" autocomplete="off" maxlength="15" required>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="col-sm-4 col-md-4">
 | 
					                        <div class="col-sm-4 col-md-4">
 | 
				
			||||||
                            <div class="form-group">
 | 
					                            <div class="form-group">
 | 
				
			||||||
                                <label class="form-label">Forward Port <span class="form-required">*</span></label>
 | 
					                                <label class="form-label">Forward Port <span class="form-required">*</span></label>
 | 
				
			||||||
                                <input name="forward_port" type="number" class="form-control" placeholder="80" value="<%- forward_port %>" required>
 | 
					                                <input name="forward_port" type="number" class="form-control text-monospace" placeholder="80" value="<%- forward_port %>" required>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ const ProxyHostModel = require('../../../models/proxy-host');
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
require('jquery-serializejson');
 | 
					require('jquery-serializejson');
 | 
				
			||||||
require('jquery-mask-plugin');
 | 
					require('jquery-mask-plugin');
 | 
				
			||||||
 | 
					require('selectize');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = Mn.View.extend({
 | 
					module.exports = Mn.View.extend({
 | 
				
			||||||
    template:  template,
 | 
					    template:  template,
 | 
				
			||||||
@@ -18,7 +19,7 @@ module.exports = Mn.View.extend({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ui: {
 | 
					    ui: {
 | 
				
			||||||
        form:         'form',
 | 
					        form:         'form',
 | 
				
			||||||
        domain_name:  'input[name="domain_name"]',
 | 
					        domain_names: 'input[name="domain_names"]',
 | 
				
			||||||
        forward_ip:   'input[name="forward_ip"]',
 | 
					        forward_ip:   'input[name="forward_ip"]',
 | 
				
			||||||
        buttons:      '.modal-footer button',
 | 
					        buttons:      '.modal-footer button',
 | 
				
			||||||
        cancel:       'button.cancel',
 | 
					        cancel:       'button.cancel',
 | 
				
			||||||
@@ -73,6 +74,10 @@ module.exports = Mn.View.extend({
 | 
				
			|||||||
                data[idx] = item;
 | 
					                data[idx] = item;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (typeof data.domain_names === 'string' && data.domain_names) {
 | 
				
			||||||
 | 
					                data.domain_names = data.domain_names.split(',');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Process
 | 
					            // Process
 | 
				
			||||||
            this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
 | 
					            this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
 | 
				
			||||||
            let method = Api.Nginx.ProxyHosts.create;
 | 
					            let method = Api.Nginx.ProxyHosts.create;
 | 
				
			||||||
@@ -118,9 +123,18 @@ module.exports = Mn.View.extend({
 | 
				
			|||||||
        this.ui.ssl_enabled.trigger('change');
 | 
					        this.ui.ssl_enabled.trigger('change');
 | 
				
			||||||
        this.ui.ssl_provider.trigger('change');
 | 
					        this.ui.ssl_provider.trigger('change');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.ui.domain_name[0].oninvalid = function () {
 | 
					        this.ui.domain_names.selectize({
 | 
				
			||||||
            this.setCustomValidity('Please enter a valid domain name. Domain wildcards are allowed: *.yourdomain.com');
 | 
					            delimiter:    ',',
 | 
				
			||||||
        };
 | 
					            persist:      false,
 | 
				
			||||||
 | 
					            maxOptions:   15,
 | 
				
			||||||
 | 
					            create:       function (input) {
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    value: input,
 | 
				
			||||||
 | 
					                    text:  input
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            createFilter: /^(?:\*\.)?(?:[^.*]+\.?)+[^.]$/
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initialize: function (options) {
 | 
					    initialize: function (options) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,32 +1,40 @@
 | 
				
			|||||||
<td class="text-center">
 | 
					<td class="text-center">
 | 
				
			||||||
    <div class="avatar d-block" style="background-image: url(<%- avatar || '/images/default-avatar.jpg' %>)">
 | 
					    <div class="avatar d-block" style="background-image: url(<%- owner.avatar || '/images/default-avatar.jpg' %>)" title="Owned by <%- owner.name %>">
 | 
				
			||||||
        <span class="avatar-status <%- is_disabled ? 'bg-red' : 'bg-green' %>"></span>
 | 
					        <span class="avatar-status <%- owner.is_disabled ? 'bg-red' : 'bg-green' %>"></span>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
    <div><%- name %></div>
 | 
					    <div>
 | 
				
			||||||
 | 
					        <% domain_names.map(function(host) {
 | 
				
			||||||
 | 
					            %>
 | 
				
			||||||
 | 
					            <span class="tag"><%- host %></span>
 | 
				
			||||||
 | 
					            <%
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        %>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
    <div class="small text-muted">
 | 
					    <div class="small text-muted">
 | 
				
			||||||
        Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
 | 
					        Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
    <div><%- email %></div>
 | 
					    <div class="text-monospace"><%- forward_ip %>:<%- forward_port %></div>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
    <div><%- roles.join(', ') %></div>
 | 
					    <div><%- ssl_enabled && ssl_provider ? ssl_provider : 'HTTP only' %></div>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
 | 
					<td>
 | 
				
			||||||
 | 
					    <div><%- access_list_id ? access_list.name : 'Public' %></div>
 | 
				
			||||||
 | 
					</td>
 | 
				
			||||||
 | 
					<% if (canManage) { %>
 | 
				
			||||||
<td class="text-center">
 | 
					<td class="text-center">
 | 
				
			||||||
    <div class="item-action dropdown">
 | 
					    <div class="item-action dropdown">
 | 
				
			||||||
        <a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
 | 
					        <a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
 | 
				
			||||||
        <div class="dropdown-menu dropdown-menu-right">
 | 
					        <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 dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit</a>
 | 
				
			||||||
            <a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a>
 | 
					            <a href="#" class="logs dropdown-item"><i class="dropdown-icon fe fe-book"></i> Logs</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>
 | 
					            <div class="dropdown-divider"></div>
 | 
				
			||||||
            <a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete User</a>
 | 
					            <a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete</a>
 | 
				
			||||||
            <% } %>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
 | 
					<% } %>
 | 
				
			||||||
@@ -4,7 +4,6 @@ const Mn         = require('backbone.marionette');
 | 
				
			|||||||
const Controller = require('../../../controller');
 | 
					const Controller = require('../../../controller');
 | 
				
			||||||
const Api        = require('../../../api');
 | 
					const Api        = require('../../../api');
 | 
				
			||||||
const Cache      = require('../../../cache');
 | 
					const Cache      = require('../../../cache');
 | 
				
			||||||
const Tokens     = require('../../../tokens');
 | 
					 | 
				
			||||||
const template   = require('./item.ejs');
 | 
					const template   = require('./item.ejs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = Mn.View.extend({
 | 
					module.exports = Mn.View.extend({
 | 
				
			||||||
@@ -12,58 +11,24 @@ module.exports = Mn.View.extend({
 | 
				
			|||||||
    tagName:  'tr',
 | 
					    tagName:  'tr',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ui: {
 | 
					    ui: {
 | 
				
			||||||
        edit:        'a.edit-user',
 | 
					        edit:   'a.edit',
 | 
				
			||||||
        permissions: 'a.edit-permissions',
 | 
					        delete: 'a.delete'
 | 
				
			||||||
        password:    'a.set-password',
 | 
					 | 
				
			||||||
        login:       'a.login',
 | 
					 | 
				
			||||||
        delete:      'a.delete-user'
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    events: {
 | 
					    events: {
 | 
				
			||||||
        'click @ui.edit': function (e) {
 | 
					        'click @ui.edit': function (e) {
 | 
				
			||||||
            e.preventDefault();
 | 
					            e.preventDefault();
 | 
				
			||||||
            Controller.showUserForm(this.model);
 | 
					            Controller.showNginxProxyForm(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) {
 | 
					        'click @ui.delete': function (e) {
 | 
				
			||||||
            e.preventDefault();
 | 
					            e.preventDefault();
 | 
				
			||||||
            Controller.showUserDeleteConfirm(this.model);
 | 
					            Controller.showNginxProxyDeleteConfirm(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: {
 | 
					    templateContext: {
 | 
				
			||||||
        isSelf: function () {
 | 
					        canManage: Cache.User.canManage('proxy_hosts')
 | 
				
			||||||
            return Cache.User.get('id') === this.id;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initialize: function () {
 | 
					    initialize: function () {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,12 @@
 | 
				
			|||||||
<thead>
 | 
					<thead>
 | 
				
			||||||
    <th width="30"> </th>
 | 
					    <th width="30"> </th>
 | 
				
			||||||
    <th>Name</th>
 | 
					    <th>Source</th>
 | 
				
			||||||
    <th>Email</th>
 | 
					    <th>Destination</th>
 | 
				
			||||||
    <th>Roles</th>
 | 
					    <th>SSL</th>
 | 
				
			||||||
 | 
					    <th>Access</th>
 | 
				
			||||||
 | 
					    <% if (canManage) { %>
 | 
				
			||||||
    <th> </th>
 | 
					    <th> </th>
 | 
				
			||||||
 | 
					    <% } %>
 | 
				
			||||||
</thead>
 | 
					</thead>
 | 
				
			||||||
<tbody>
 | 
					<tbody>
 | 
				
			||||||
    <!-- items -->
 | 
					    <!-- items -->
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Mn         = require('backbone.marionette');
 | 
					const Mn       = require('backbone.marionette');
 | 
				
			||||||
const ItemView   = require('./item');
 | 
					const ItemView = require('./item');
 | 
				
			||||||
const template   = require('./main.ejs');
 | 
					const template = require('./main.ejs');
 | 
				
			||||||
 | 
					const Cache    = require('../../../cache');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TableBody = Mn.CollectionView.extend({
 | 
					const TableBody = Mn.CollectionView.extend({
 | 
				
			||||||
    tagName:   'tbody',
 | 
					    tagName:   'tbody',
 | 
				
			||||||
@@ -21,6 +22,10 @@ module.exports = Mn.View.extend({
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    templateContext: {
 | 
				
			||||||
 | 
					        canManage: Cache.User.canManage('proxy_hosts')
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onRender: function () {
 | 
					    onRender: function () {
 | 
				
			||||||
        this.showChildView('body', new TableBody({
 | 
					        this.showChildView('body', new TableBody({
 | 
				
			||||||
            collection: this.collection
 | 
					            collection: this.collection
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@ module.exports = Mn.View.extend({
 | 
				
			|||||||
    onRender: function () {
 | 
					    onRender: function () {
 | 
				
			||||||
        let view = this;
 | 
					        let view = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Api.Nginx.ProxyHosts.getAll()
 | 
					        Api.Nginx.ProxyHosts.getAll(['owner', 'access_list'])
 | 
				
			||||||
            .then(response => {
 | 
					            .then(response => {
 | 
				
			||||||
                if (!view.isDestroyed()) {
 | 
					                if (!view.isDestroyed()) {
 | 
				
			||||||
                    if (response && response.length) {
 | 
					                    if (response && response.length) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,8 +9,7 @@ const model = Backbone.Model.extend({
 | 
				
			|||||||
        return {
 | 
					        return {
 | 
				
			||||||
            created_on:      null,
 | 
					            created_on:      null,
 | 
				
			||||||
            modified_on:     null,
 | 
					            modified_on:     null,
 | 
				
			||||||
            owner:           null,
 | 
					            domain_names:    [],
 | 
				
			||||||
            domain_name:     '',
 | 
					 | 
				
			||||||
            forward_ip:      '',
 | 
					            forward_ip:      '',
 | 
				
			||||||
            forward_port:    null,
 | 
					            forward_port:    null,
 | 
				
			||||||
            access_list_id:  null,
 | 
					            access_list_id:  null,
 | 
				
			||||||
@@ -19,7 +18,10 @@ const model = Backbone.Model.extend({
 | 
				
			|||||||
            ssl_forced:      false,
 | 
					            ssl_forced:      false,
 | 
				
			||||||
            caching_enabled: false,
 | 
					            caching_enabled: false,
 | 
				
			||||||
            block_exploits:  false,
 | 
					            block_exploits:  false,
 | 
				
			||||||
            meta:            []
 | 
					            meta:            [],
 | 
				
			||||||
 | 
					            // The following are expansions:
 | 
				
			||||||
 | 
					            owner:           null,
 | 
				
			||||||
 | 
					            access_list:     null
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user