mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-30 23:33:34 +00:00 
			
		
		
		
	Added user permissions, delete user
This commit is contained in:
		| @@ -1,11 +1,12 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| const _             = require('lodash'); | const _                   = require('lodash'); | ||||||
| const error         = require('../lib/error'); | const error               = require('../lib/error'); | ||||||
| const userModel     = require('../models/user'); | const userModel           = require('../models/user'); | ||||||
| const authModel     = require('../models/auth'); | const userPermissionModel = require('../models/user_permission'); | ||||||
| const gravatar      = require('gravatar'); | const authModel           = require('../models/auth'); | ||||||
| const internalToken = require('./token'); | const gravatar            = require('gravatar'); | ||||||
|  | const internalToken       = require('./token'); | ||||||
|  |  | ||||||
| function omissions () { | function omissions () { | ||||||
|     return ['is_deleted']; |     return ['is_deleted']; | ||||||
| @@ -56,7 +57,23 @@ const internalUser = { | |||||||
|                 } |                 } | ||||||
|             }) |             }) | ||||||
|             .then(user => { |             .then(user => { | ||||||
|                 return internalUser.get(access, {id: user.id}); |                 // 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 internalUser.get(access, {id: user.id, expand: ['permissions']}); | ||||||
|  |                     }); | ||||||
|             }); |             }); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| @@ -145,6 +162,7 @@ const internalUser = { | |||||||
|                     .query() |                     .query() | ||||||
|                     .where('is_deleted', 0) |                     .where('is_deleted', 0) | ||||||
|                     .andWhere('id', data.id) |                     .andWhere('id', data.id) | ||||||
|  |                     .allowEager('[permissions]') | ||||||
|                     .first(); |                     .first(); | ||||||
|  |  | ||||||
|                 // Custom omissions |                 // Custom omissions | ||||||
| @@ -377,6 +395,50 @@ const internalUser = { | |||||||
|             }); |             }); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @param  {Access}  access | ||||||
|  |      * @param  {Object}  data | ||||||
|  |      * @return {Promise} | ||||||
|  |      */ | ||||||
|  |     setPermissions: (access, data) => { | ||||||
|  |         return access.can('users:permissions', data.id) | ||||||
|  |             .then(() => { | ||||||
|  |                 return internalUser.get(access, {id: data.id}); | ||||||
|  |             }) | ||||||
|  |             .then(user => { | ||||||
|  |                 if (user.id !== data.id) { | ||||||
|  |                     // Sanity check that something crazy hasn't happened | ||||||
|  |                     throw new error.InternalValidationError('User could not be updated, IDs do not match: ' + user.id + ' !== ' + data.id); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 return user; | ||||||
|  |             }) | ||||||
|  |             .then(user => { | ||||||
|  |                 // Get perms row, patch if it exists | ||||||
|  |                 return userPermissionModel | ||||||
|  |                     .query() | ||||||
|  |                     .where('user_id', user.id) | ||||||
|  |                     .first() | ||||||
|  |                     .then(existing_auth => { | ||||||
|  |                         if (existing_auth) { | ||||||
|  |                             // patch | ||||||
|  |                             return userPermissionModel | ||||||
|  |                                 .query() | ||||||
|  |                                 .where('user_id', user.id) | ||||||
|  |                                 .patchAndFetchById(existing_auth.id, _.assign({user_id: user.id}, data)); | ||||||
|  |                         } else { | ||||||
|  |                             // insert | ||||||
|  |                             return userPermissionModel | ||||||
|  |                                 .query() | ||||||
|  |                                 .insertAndFetch(_.assign({user_id: user.id}, data)); | ||||||
|  |                         } | ||||||
|  |                     }) | ||||||
|  |                     .then(permissions => { | ||||||
|  |                         return true; | ||||||
|  |                     }); | ||||||
|  |             }); | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @param {Access}   access |      * @param {Access}   access | ||||||
|      * @param {Object}   data |      * @param {Object}   data | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								src/backend/lib/access/users-permissions.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/backend/lib/access/users-permissions.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | { | ||||||
|  |   "anyOf": [ | ||||||
|  |     { | ||||||
|  |       "$ref": "roles#/definitions/admin" | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
| @@ -43,6 +43,124 @@ exports.up = function (knex/*, Promise*/) { | |||||||
|         }) |         }) | ||||||
|         .then(() => { |         .then(() => { | ||||||
|             logger.info('[' + migrate_name + '] user Table created'); |             logger.info('[' + migrate_name + '] user Table created'); | ||||||
|  |  | ||||||
|  |             return knex.schema.createTable('user_permission', table => { | ||||||
|  |                 table.increments().primary(); | ||||||
|  |                 table.dateTime('created_on').notNull(); | ||||||
|  |                 table.dateTime('modified_on').notNull(); | ||||||
|  |                 table.integer('user_id').notNull().unsigned(); | ||||||
|  |                 table.string('visibility').notNull(); | ||||||
|  |                 table.string('proxy_hosts').notNull(); | ||||||
|  |                 table.string('redirection_hosts').notNull(); | ||||||
|  |                 table.string('dead_hosts').notNull(); | ||||||
|  |                 table.string('streams').notNull(); | ||||||
|  |                 table.string('access_lists').notNull(); | ||||||
|  |                 table.unique('user_id'); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |             logger.info('[' + migrate_name + '] user_permission Table created'); | ||||||
|  |  | ||||||
|  |             return knex.schema.createTable('proxy_host', table => { | ||||||
|  |                 table.increments().primary(); | ||||||
|  |                 table.dateTime('created_on').notNull(); | ||||||
|  |                 table.dateTime('modified_on').notNull(); | ||||||
|  |                 table.integer('owner_user_id').notNull().unsigned(); | ||||||
|  |                 table.integer('is_deleted').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.string('domain_name').notNull(); | ||||||
|  |                 table.string('forward_ip').notNull(); | ||||||
|  |                 table.integer('forward_port').notNull().unsigned(); | ||||||
|  |                 table.integer('access_list_id').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.integer('ssl_enabled').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.string('ssl_provider').notNull().defaultTo(''); | ||||||
|  |                 table.integer('ssl_forced').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.integer('caching_enabled').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.integer('block_exploits').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.json('meta').notNull(); | ||||||
|  |                 table.unique(['domain_name', 'is_deleted']); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |             logger.info('[' + migrate_name + '] proxy_host Table created'); | ||||||
|  |  | ||||||
|  |             return knex.schema.createTable('redirection_host', table => { | ||||||
|  |                 table.increments().primary(); | ||||||
|  |                 table.dateTime('created_on').notNull(); | ||||||
|  |                 table.dateTime('modified_on').notNull(); | ||||||
|  |                 table.integer('owner_user_id').notNull().unsigned(); | ||||||
|  |                 table.integer('is_deleted').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.string('domain_name').notNull(); | ||||||
|  |                 table.string('forward_domain_name').notNull(); | ||||||
|  |                 table.integer('preserve_path').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.integer('ssl_enabled').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.string('ssl_provider').notNull().defaultTo(''); | ||||||
|  |                 table.integer('block_exploits').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.json('meta').notNull(); | ||||||
|  |                 table.unique(['domain_name', 'is_deleted']); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |                 logger.info('[' + migrate_name + '] redirection_host Table created'); | ||||||
|  |  | ||||||
|  |                 return knex.schema.createTable('dead_host', table => { | ||||||
|  |                     table.increments().primary(); | ||||||
|  |                     table.dateTime('created_on').notNull(); | ||||||
|  |                     table.dateTime('modified_on').notNull(); | ||||||
|  |                     table.integer('owner_user_id').notNull().unsigned(); | ||||||
|  |                     table.integer('is_deleted').notNull().unsigned().defaultTo(0); | ||||||
|  |                     table.string('domain_name').notNull(); | ||||||
|  |                     table.integer('ssl_enabled').notNull().unsigned().defaultTo(0); | ||||||
|  |                     table.string('ssl_provider').notNull().defaultTo(''); | ||||||
|  |                     table.json('meta').notNull(); | ||||||
|  |                     table.unique(['domain_name', 'is_deleted']); | ||||||
|  |                 }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |             logger.info('[' + migrate_name + '] dead_host Table created'); | ||||||
|  |  | ||||||
|  |             return knex.schema.createTable('stream', table => { | ||||||
|  |                 table.increments().primary(); | ||||||
|  |                 table.dateTime('created_on').notNull(); | ||||||
|  |                 table.dateTime('modified_on').notNull(); | ||||||
|  |                 table.integer('owner_user_id').notNull().unsigned(); | ||||||
|  |                 table.integer('is_deleted').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.integer('incoming_port').notNull().unsigned(); | ||||||
|  |                 table.string('forward_ip').notNull(); | ||||||
|  |                 table.integer('forwarding_port').notNull().unsigned(); | ||||||
|  |                 table.integer('tcp_forwarding').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.integer('udp_forwarding').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.json('meta').notNull(); | ||||||
|  |                 table.unique(['incoming_port', 'is_deleted']); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |             logger.info('[' + migrate_name + '] stream Table created'); | ||||||
|  |  | ||||||
|  |             return knex.schema.createTable('access_list', table => { | ||||||
|  |                 table.increments().primary(); | ||||||
|  |                 table.dateTime('created_on').notNull(); | ||||||
|  |                 table.dateTime('modified_on').notNull(); | ||||||
|  |                 table.integer('owner_user_id').notNull().unsigned(); | ||||||
|  |                 table.integer('is_deleted').notNull().unsigned().defaultTo(0); | ||||||
|  |                 table.string('name').notNull(); | ||||||
|  |                 table.json('meta').notNull(); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |             logger.info('[' + migrate_name + '] access_list Table created'); | ||||||
|  |  | ||||||
|  |             return knex.schema.createTable('access_list_auth', table => { | ||||||
|  |                 table.increments().primary(); | ||||||
|  |                 table.dateTime('created_on').notNull(); | ||||||
|  |                 table.dateTime('modified_on').notNull(); | ||||||
|  |                 table.integer('access_list_id').notNull().unsigned(); | ||||||
|  |                 table.string('username').notNull(); | ||||||
|  |                 table.string('password').notNull(); | ||||||
|  |                 table.json('meta').notNull(); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |             logger.info('[' + migrate_name + '] access_list_auth Table created'); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -3,8 +3,9 @@ | |||||||
|  |  | ||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| const db    = require('../db'); | const db             = require('../db'); | ||||||
| const Model = require('objection').Model; | const Model          = require('objection').Model; | ||||||
|  | const UserPermission = require('./user_permission'); | ||||||
|  |  | ||||||
| Model.knex(db); | Model.knex(db); | ||||||
|  |  | ||||||
| @@ -30,6 +31,22 @@ class User extends Model { | |||||||
|         return ['roles']; |         return ['roles']; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     static get relationMappings () { | ||||||
|  |         return { | ||||||
|  |             permissions: { | ||||||
|  |                 relation:   Model.HasOneRelation, | ||||||
|  |                 modelClass: UserPermission, | ||||||
|  |                 join:       { | ||||||
|  |                     from: 'user.id', | ||||||
|  |                     to:   'user_permission.user_id' | ||||||
|  |                 }, | ||||||
|  |                 modify:     function (qb) { | ||||||
|  |                     qb.omit(['id', 'created_on', 'modified_on', 'user_id']); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = User; | module.exports = User; | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								src/backend/models/user_permission.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/backend/models/user_permission.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // Objection Docs: | ||||||
|  | // http://vincit.github.io/objection.js/ | ||||||
|  |  | ||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | const db    = require('../db'); | ||||||
|  | const Model = require('objection').Model; | ||||||
|  |  | ||||||
|  | Model.knex(db); | ||||||
|  |  | ||||||
|  | class UserPermission 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 'UserPermission'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     static get tableName () { | ||||||
|  |         return 'user_permission'; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = UserPermission; | ||||||
| @@ -183,12 +183,12 @@ router | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Specific user service settings |  * Specific user permissions | ||||||
|  * |  * | ||||||
|  * /api/users/123/services |  * /api/users/123/permissions | ||||||
|  */ |  */ | ||||||
| router | router | ||||||
|     .route('/:user_id/services') |     .route('/:user_id/permissions') | ||||||
|     .options((req, res) => { |     .options((req, res) => { | ||||||
|         res.sendStatus(204); |         res.sendStatus(204); | ||||||
|     }) |     }) | ||||||
| @@ -196,18 +196,18 @@ router | |||||||
|     .all(userIdFromMe) |     .all(userIdFromMe) | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * POST /api/users/123/services |      * PUT /api/users/123/permissions | ||||||
|      * |      * | ||||||
|      * Sets Service Settings for a user |      * Set some or all permissions for a user | ||||||
|      */ |      */ | ||||||
|     .post((req, res, next) => { |     .put((req, res, next) => { | ||||||
|         apiValidator({$ref: 'endpoints/users#/links/5/schema'}, req.body) |         apiValidator({$ref: 'endpoints/users#/links/5/schema'}, req.body) | ||||||
|             .then(payload => { |             .then(payload => { | ||||||
|                 payload.id = req.params.user_id; |                 payload.id = req.params.user_id; | ||||||
|                 return internalUser.setServiceSettings(res.locals.access, payload); |                 return internalUser.setPermissions(res.locals.access, payload); | ||||||
|             }) |             }) | ||||||
|             .then(result => { |             .then(result => { | ||||||
|                 res.status(200) |                 res.status(201) | ||||||
|                     .send(result); |                     .send(result); | ||||||
|             }) |             }) | ||||||
|             .catch(next); |             .catch(next); | ||||||
|   | |||||||
| @@ -206,6 +206,49 @@ | |||||||
|       "targetSchema": { |       "targetSchema": { | ||||||
|         "type": "boolean" |         "type": "boolean" | ||||||
|       } |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "title": "Set Permissions", | ||||||
|  |       "description": "Sets Permissions for a User", | ||||||
|  |       "href": "/users/{definitions.identity.example}/permissions", | ||||||
|  |       "access": "private", | ||||||
|  |       "method": "PUT", | ||||||
|  |       "rel": "update", | ||||||
|  |       "http_header": { | ||||||
|  |         "$ref": "../examples.json#/definitions/auth_header" | ||||||
|  |       }, | ||||||
|  |       "schema": { | ||||||
|  |         "type": "object", | ||||||
|  |         "properties": { | ||||||
|  |           "visibility": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(all|user)$" | ||||||
|  |           }, | ||||||
|  |           "access_lists": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(hidden|view|manage)$" | ||||||
|  |           }, | ||||||
|  |           "dead_hosts": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(hidden|view|manage)$" | ||||||
|  |           }, | ||||||
|  |           "proxy_hosts": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(hidden|view|manage)$" | ||||||
|  |           }, | ||||||
|  |           "redirection_hosts": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(hidden|view|manage)$" | ||||||
|  |           }, | ||||||
|  |           "streams": { | ||||||
|  |             "type": "string", | ||||||
|  |             "pattern": "^(hidden|view|manage)$" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "targetSchema": { | ||||||
|  |         "type": "boolean" | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "properties": { |   "properties": { | ||||||
|   | |||||||
| @@ -1,11 +1,12 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| const fs        = require('fs'); | const fs                  = require('fs'); | ||||||
| const NodeRSA   = require('node-rsa'); | const NodeRSA             = require('node-rsa'); | ||||||
| const config    = require('config'); | const config              = require('config'); | ||||||
| const logger    = require('./logger').global; | const logger              = require('./logger').global; | ||||||
| const userModel = require('./models/user'); | const userModel           = require('./models/user'); | ||||||
| const authModel = require('./models/auth'); | const userPermissionModel = require('./models/user_permission'); | ||||||
|  | const authModel           = require('./models/auth'); | ||||||
|  |  | ||||||
| module.exports = function () { | module.exports = function () { | ||||||
|     return new Promise((resolve, reject) => { |     return new Promise((resolve, reject) => { | ||||||
| @@ -54,7 +55,7 @@ module.exports = function () { | |||||||
|                 .select(userModel.raw('COUNT(`id`) as `count`')) |                 .select(userModel.raw('COUNT(`id`) as `count`')) | ||||||
|                 .where('is_deleted', 0) |                 .where('is_deleted', 0) | ||||||
|                 .first('count') |                 .first('count') | ||||||
|                 .then((row) => { |                 .then(row => { | ||||||
|                     if (!row.count) { |                     if (!row.count) { | ||||||
|                         // Create a new user and set password |                         // Create a new user and set password | ||||||
|                         logger.info('Creating a new user: admin@example.com with password: changeme'); |                         logger.info('Creating a new user: admin@example.com with password: changeme'); | ||||||
| @@ -79,6 +80,19 @@ module.exports = function () { | |||||||
|                                         type:    'password', |                                         type:    'password', | ||||||
|                                         secret:  'changeme', |                                         secret:  'changeme', | ||||||
|                                         meta:    {} |                                         meta:    {} | ||||||
|  |                                     }) | ||||||
|  |                                     .then(() => { | ||||||
|  |                                         return userPermissionModel | ||||||
|  |                                             .query() | ||||||
|  |                                             .insert({ | ||||||
|  |                                                 user_id:           user.id, | ||||||
|  |                                                 visibility:        'all', | ||||||
|  |                                                 proxy_hosts:       'manage', | ||||||
|  |                                                 redirection_hosts: 'manage', | ||||||
|  |                                                 dead_hosts:        'manage', | ||||||
|  |                                                 streams:           'manage', | ||||||
|  |                                                 access_lists:      'manage' | ||||||
|  |                                             }); | ||||||
|                                     }); |                                     }); | ||||||
|                             }); |                             }); | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -224,6 +224,16 @@ module.exports = { | |||||||
|          */ |          */ | ||||||
|         loginAs: function (id) { |         loginAs: function (id) { | ||||||
|             return fetch('post', 'users/' + id + '/login'); |             return fetch('post', 'users/' + id + '/login'); | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * | ||||||
|  |          * @param   {Integer}  id | ||||||
|  |          * @param   {Object}   perms | ||||||
|  |          * @returns {Promise} | ||||||
|  |          */ | ||||||
|  |         setPermissions: function (id, perms) { | ||||||
|  |             return fetch('put', 'users/' + id + '/permissions', perms); | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,6 +52,19 @@ module.exports = { | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * User Permissions Form | ||||||
|  |      * | ||||||
|  |      * @param model | ||||||
|  |      */ | ||||||
|  |     showUserPermissions: function (model) { | ||||||
|  |         if (Cache.User.isAdmin()) { | ||||||
|  |             require(['./main', './user/permissions'], function (App, View) { | ||||||
|  |                 App.UI.showModalDialog(new View({model: model})); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * User Password Form |      * User Password Form | ||||||
|      * |      * | ||||||
| @@ -65,6 +78,19 @@ module.exports = { | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * User Delete Confirm | ||||||
|  |      * | ||||||
|  |      * @param model | ||||||
|  |      */ | ||||||
|  |     showUserDeleteConfirm: function (model) { | ||||||
|  |         if (Cache.User.isAdmin() && model.get('id') !== Cache.User.get('id')) { | ||||||
|  |             require(['./main', './user/delete'], function (App, View) { | ||||||
|  |                 App.UI.showModalDialog(new View({model: model})); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Error |      * Error | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ const App = Mn.Application.extend({ | |||||||
|      * @returns {Promise} |      * @returns {Promise} | ||||||
|      */ |      */ | ||||||
|     bootstrap: function () { |     bootstrap: function () { | ||||||
|         return Api.Users.getById('me') |         return Api.Users.getById('me', ['permissions']) | ||||||
|             .then(response => { |             .then(response => { | ||||||
|                 Cache.User.set(response); |                 Cache.User.set(response); | ||||||
|                 Tokens.setCurrentName(response.nickname || response.name); |                 Tokens.setCurrentName(response.nickname || response.name); | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								src/frontend/js/app/user/delete.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/frontend/js/app/user/delete.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | <div class="modal-content"> | ||||||
|  |     <div class="modal-header"> | ||||||
|  |         <h5 class="modal-title">Delete <%- name %></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 <strong><%- name %></strong>? | ||||||
|  |                 </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/user/delete.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/frontend/js/app/user/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.Users.delete(this.model.get('id')) | ||||||
|  |                 .then(() => { | ||||||
|  |                     Controller.showUsers(); | ||||||
|  |                     App.UI.closeModal(); | ||||||
|  |                 }) | ||||||
|  |                 .catch(err => { | ||||||
|  |                     alert(err.message); | ||||||
|  |                     this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); | ||||||
|  |                 }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }); | ||||||
| @@ -25,25 +25,27 @@ | |||||||
|                         <div class="invalid-feedback secret-error"></div> |                         <div class="invalid-feedback secret-error"></div> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|                 <% if (!isSelf()) { %> |  | ||||||
|                 <div class="col-sm-12 col-md-12"> |                 <div class="col-sm-12 col-md-12"> | ||||||
|  |                     <div class="form-label">Roles</div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="col-sm-6 col-md-6"> | ||||||
|                     <div class="form-group"> |                     <div class="form-group"> | ||||||
|                         <div class="form-label">Switches</div> |                         <label class="custom-switch"> | ||||||
|                         <div class="custom-switches-stacked"> |                             <input type="checkbox" class="custom-switch-input" name="is_admin" value="1"<%- isAdmin() ? ' checked' : '' %><%- isSelf() ? ' disabled' : '' %>> | ||||||
|                             <label class="custom-switch"> |                             <span class="custom-switch-indicator"></span> | ||||||
|                                 <input type="checkbox" class="custom-switch-input" name="is_admin" value="1"<%- isAdmin() ? ' checked' : '' %>> |                             <span class="custom-switch-description">Administrator</span> | ||||||
|                                 <span class="custom-switch-indicator"></span> |                         </label> | ||||||
|                                 <span class="custom-switch-description">Administrator</span> |                     </div> | ||||||
|                             </label> |                 </div> | ||||||
|                             <label class="custom-switch"> |                 <div class="col-sm-6 col-md-6"> | ||||||
|                                 <input type="checkbox" class="custom-switch-input" name="is_disabled" value="1"<%- is_disabled ? ' checked' : '' %>> |                     <div class="form-group"> | ||||||
|                                 <span class="custom-switch-indicator"></span> |                         <label class="custom-switch"> | ||||||
|                                 <span class="custom-switch-description">Disabled</span> |                             <input type="checkbox" class="custom-switch-input" name="is_disabled" value="1"<%- is_disabled ? ' checked' : '' %><%- isSelf() ? ' disabled' : '' %>> | ||||||
|                             </label> |                             <span class="custom-switch-indicator"></span> | ||||||
|                         </div> |                             <span class="custom-switch-description">Disabled</span> | ||||||
|  |                         </label> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|                 <% } %> |  | ||||||
|             </div> |             </div> | ||||||
|         </form> |         </form> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -58,7 +58,12 @@ module.exports = Mn.View.extend({ | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     view.model.set(result); |                     view.model.set(result); | ||||||
|                     App.UI.closeModal(); |                     App.UI.closeModal(function () { | ||||||
|  |                         if (method === Api.Users.create) { | ||||||
|  |                             // Show permissions dialog immediately | ||||||
|  |                             Controller.showUserPermissions(view.model); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|                 }) |                 }) | ||||||
|                 .catch(err => { |                 .catch(err => { | ||||||
|                     this.ui.error.text(err.message).show(); |                     this.ui.error.text(err.message).show(); | ||||||
|   | |||||||
							
								
								
									
										140
									
								
								src/frontend/js/app/user/permissions.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/frontend/js/app/user/permissions.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | <div class="modal-content"> | ||||||
|  |     <div class="modal-header"> | ||||||
|  |         <h5 class="modal-title">Permissions for <%- name %></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"> | ||||||
|  |  | ||||||
|  |                     <% if (isAdmin()) { %> | ||||||
|  |                     <div class="alert alert-icon alert-secondary" role="alert"> | ||||||
|  |                         <i class="fe fe-alert-triangle mr-2" aria-hidden="true"></i> | ||||||
|  |                         This user is an Administrator and some items cannot be altered | ||||||
|  |                     </div> | ||||||
|  |                     <% } %> | ||||||
|  |  | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <label class="form-label">Item Visibility</label> | ||||||
|  |                         <div class="selectgroup w-100"> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="visibility" value="user" class="selectgroup-input"<%- getPerm('visibility') !== 'all' ? ' checked' : '' %>> | ||||||
|  |                                 <span class="selectgroup-button">Created Items Only</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="visibility" value="all" class="selectgroup-input"<%- getPerm('visibility') === 'all' ? ' checked' : '' %>> | ||||||
|  |                                 <span class="selectgroup-button">All Items</span> | ||||||
|  |                             </label> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="col-sm-12 col-md-12"> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <label class="form-label">Proxy Hosts</label> | ||||||
|  |                         <div class="selectgroup w-100"> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="proxy_hosts" value="manage" class="selectgroup-input" <%- getPermProps('proxy_hosts', 'manage', true) %>> | ||||||
|  |                                 <span class="selectgroup-button">Manage</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="proxy_hosts" value="view" class="selectgroup-input" <%- getPermProps('proxy_hosts', 'view') %>> | ||||||
|  |                                 <span class="selectgroup-button">View Only</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="proxy_hosts" value="hidden" class="selectgroup-input" <%- getPermProps('proxy_hosts', 'hidden') %>> | ||||||
|  |                                 <span class="selectgroup-button">Hidden</span> | ||||||
|  |                             </label> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="col-sm-12 col-md-12"> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <label class="form-label">Redirection Hosts</label> | ||||||
|  |                         <div class="selectgroup w-100"> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="redirection_hosts" value="manage" class="selectgroup-input" <%- getPermProps('redirection_hosts', 'manage', true) %>> | ||||||
|  |                                 <span class="selectgroup-button">Manage</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="redirection_hosts" value="view" class="selectgroup-input" <%- getPermProps('redirection_hosts', 'view') %>> | ||||||
|  |                                 <span class="selectgroup-button">View Only</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="redirection_hosts" value="hidden" class="selectgroup-input" <%- getPermProps('redirection_hosts', 'hidden') %>> | ||||||
|  |                                 <span class="selectgroup-button">Hidden</span> | ||||||
|  |                             </label> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="col-sm-12 col-md-12"> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <label class="form-label">404 Hosts</label> | ||||||
|  |                         <div class="selectgroup w-100"> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="dead_hosts" value="manage" class="selectgroup-input" <%- getPermProps('dead_hosts', 'manage', true) %>> | ||||||
|  |                                 <span class="selectgroup-button">Manage</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="dead_hosts" value="view" class="selectgroup-input" <%- getPermProps('dead_hosts', 'view') %>> | ||||||
|  |                                 <span class="selectgroup-button">View Only</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="dead_hosts" value="hidden" class="selectgroup-input" <%- getPermProps('dead_hosts', 'hidden') %>> | ||||||
|  |                                 <span class="selectgroup-button">Hidden</span> | ||||||
|  |                             </label> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="col-sm-12 col-md-12"> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <label class="form-label">Streams</label> | ||||||
|  |                         <div class="selectgroup w-100"> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="streams" value="manage" class="selectgroup-input" <%- getPermProps('streams', 'manage', true) %>> | ||||||
|  |                                 <span class="selectgroup-button">Manage</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="streams" value="view" class="selectgroup-input" <%- getPermProps('streams', 'view') %>> | ||||||
|  |                                 <span class="selectgroup-button">View Only</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="streams" value="hidden" class="selectgroup-input" <%- getPermProps('streams', 'hidden') %>> | ||||||
|  |                                 <span class="selectgroup-button">Hidden</span> | ||||||
|  |                             </label> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |  | ||||||
|  |                 <div class="col-sm-12 col-md-12"> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <label class="form-label">Access Lists</label> | ||||||
|  |                         <div class="selectgroup w-100"> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="access_lists" value="manage" class="selectgroup-input" <%- getPermProps('access_lists', 'manage', true) %>> | ||||||
|  |                                 <span class="selectgroup-button">Manage</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="access_lists" value="view" class="selectgroup-input" <%- getPermProps('access_lists', 'view') %>> | ||||||
|  |                                 <span class="selectgroup-button">View Only</span> | ||||||
|  |                             </label> | ||||||
|  |                             <label class="selectgroup-item"> | ||||||
|  |                                 <input type="radio" name="access_lists" value="hidden" class="selectgroup-input" <%- getPermProps('access_lists', 'hidden') %>> | ||||||
|  |                                 <span class="selectgroup-button">Hidden</span> | ||||||
|  |                             </label> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </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-teal save">Save</button> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
							
								
								
									
										99
									
								
								src/frontend/js/app/user/permissions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/frontend/js/app/user/permissions.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | const Mn         = require('backbone.marionette'); | ||||||
|  | const template   = require('./permissions.ejs'); | ||||||
|  | const Controller = require('../controller'); | ||||||
|  | const Cache      = require('../cache'); | ||||||
|  | const Api        = require('../api'); | ||||||
|  | const App        = require('../main'); | ||||||
|  | const UserModel  = require('../../models/user'); | ||||||
|  |  | ||||||
|  | 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', | ||||||
|  |         error:   '.secret-error' | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     events: { | ||||||
|  |  | ||||||
|  |         'click @ui.save': function (e) { | ||||||
|  |             e.preventDefault(); | ||||||
|  |  | ||||||
|  |             let view = this; | ||||||
|  |             let data = this.ui.form.serializeJSON(); | ||||||
|  |  | ||||||
|  |             // Manipulate | ||||||
|  |             if (view.model.isAdmin()) { | ||||||
|  |                 // Force some attributes for admin | ||||||
|  |                 data = _.assign({}, data, { | ||||||
|  |                     access_lists:      'manage', | ||||||
|  |                     dead_hosts:        'manage', | ||||||
|  |                     proxy_hosts:       'manage', | ||||||
|  |                     redirection_hosts: 'manage', | ||||||
|  |                     streams:           'manage' | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); | ||||||
|  |  | ||||||
|  |             Api.Users.setPermissions(view.model.get('id'), data) | ||||||
|  |                 .then(() => { | ||||||
|  |                     if (view.model.get('id') === Cache.User.get('id')) { | ||||||
|  |                         Cache.User.set({permissions: data}); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     view.model.set({permissions: data}); | ||||||
|  |                     App.UI.closeModal(); | ||||||
|  |                 }) | ||||||
|  |                 .catch(err => { | ||||||
|  |                     this.ui.error.text(err.message).show(); | ||||||
|  |                     this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); | ||||||
|  |                 }); | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     templateContext: function () { | ||||||
|  |         let perms    = this.model.get('permissions'); | ||||||
|  |         let is_admin = this.model.isAdmin(); | ||||||
|  |  | ||||||
|  |         return { | ||||||
|  |             getPerm: function (key) { | ||||||
|  |                 if (perms !== null && typeof perms[key] !== 'undefined') { | ||||||
|  |                     return perms[key]; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 return null; | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             getPermProps: function (key, item, forced_admin) { | ||||||
|  |                 if (forced_admin && is_admin) { | ||||||
|  |                     return 'checked disabled'; | ||||||
|  |                 } else if (is_admin) { | ||||||
|  |                     return 'disabled'; | ||||||
|  |                 } else if (perms !== null && typeof perms[key] !== 'undefined' && perms[key] === item) { | ||||||
|  |                     return 'checked'; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 return ''; | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             isAdmin: function () { | ||||||
|  |                 return is_admin; | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     initialize: function (options) { | ||||||
|  |         if (typeof options.model === 'undefined' || !options.model) { | ||||||
|  |             this.model = new UserModel.Model(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }); | ||||||
| @@ -19,8 +19,9 @@ | |||||||
|     <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 User</a> |             <a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit Details</a> | ||||||
|             <a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Set Password</a> |             <a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a> | ||||||
|  |             <a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> Set Password</a> | ||||||
|             <% if (!isSelf()) { %> |             <% if (!isSelf()) { %> | ||||||
|             <a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> Sign in as User</a> |             <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> | ||||||
|   | |||||||
| @@ -12,10 +12,11 @@ module.exports = Mn.View.extend({ | |||||||
|     tagName:  'tr', |     tagName:  'tr', | ||||||
|  |  | ||||||
|     ui: { |     ui: { | ||||||
|         edit:             'a.edit-user', |         edit:        'a.edit-user', | ||||||
|         password:         'a.set-password', |         permissions: 'a.edit-permissions', | ||||||
|         login:            'a.login', |         password:    'a.set-password', | ||||||
|         delete:           'a.delete-user' |         login:       'a.login', | ||||||
|  |         delete:      'a.delete-user' | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     events: { |     events: { | ||||||
| @@ -24,6 +25,11 @@ module.exports = Mn.View.extend({ | |||||||
|             Controller.showUserForm(this.model); |             Controller.showUserForm(this.model); | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|  |         'click @ui.permissions': function (e) { | ||||||
|  |             e.preventDefault(); | ||||||
|  |             Controller.showUserPermissions(this.model); | ||||||
|  |         }, | ||||||
|  |  | ||||||
|         'click @ui.password': function (e) { |         'click @ui.password': function (e) { | ||||||
|             e.preventDefault(); |             e.preventDefault(); | ||||||
|             Controller.showUserPasswordForm(this.model); |             Controller.showUserPasswordForm(this.model); | ||||||
| @@ -31,7 +37,7 @@ module.exports = Mn.View.extend({ | |||||||
|  |  | ||||||
|         'click @ui.delete': function (e) { |         'click @ui.delete': function (e) { | ||||||
|             e.preventDefault(); |             e.preventDefault(); | ||||||
|             //Controller.showUserDeleteConfirm(this.model); |             Controller.showUserDeleteConfirm(this.model); | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         'click @ui.login': function (e) { |         'click @ui.login': function (e) { | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ module.exports = Mn.View.extend({ | |||||||
|     onRender: function () { |     onRender: function () { | ||||||
|         let view = this; |         let view = this; | ||||||
|  |  | ||||||
|         Api.Users.getAll() |         Api.Users.getAll(['permissions']) | ||||||
|             .then(response => { |             .then(response => { | ||||||
|                 if (!view.isDestroyed() && response && response.length) { |                 if (!view.isDestroyed() && response && response.length) { | ||||||
|                     view.showChildView('list_region', new ListView({ |                     view.showChildView('list_region', new ListView({ | ||||||
|   | |||||||
| @@ -12,7 +12,8 @@ const model = Backbone.Model.extend({ | |||||||
|             nickname:    '', |             nickname:    '', | ||||||
|             email:       '', |             email:       '', | ||||||
|             is_disabled: false, |             is_disabled: false, | ||||||
|             roles:       [] |             roles:       [], | ||||||
|  |             permissions: null | ||||||
|         }; |         }; | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,8 @@ module.exports = { | |||||||
|             'vector-map':       'tabler-ui/dist/assets/js/vendors/jquery-jvectormap-2.0.3.min', |             'vector-map':       'tabler-ui/dist/assets/js/vendors/jquery-jvectormap-2.0.3.min', | ||||||
|             'vector-map-de':    'tabler-ui/dist/assets/js/vendors/jquery-jvectormap-de-merc', |             'vector-map-de':    'tabler-ui/dist/assets/js/vendors/jquery-jvectormap-de-merc', | ||||||
|             'vector-map-world': 'tabler-ui/dist/assets/js/vendors/jquery-jvectormap-world-mill', |             'vector-map-world': 'tabler-ui/dist/assets/js/vendors/jquery-jvectormap-world-mill', | ||||||
|             'circle-progress':  'tabler-ui/dist/assets/js/vendors/circle-progress.min' |             'circle-progress':  'tabler-ui/dist/assets/js/vendors/circle-progress.min', | ||||||
|  |             'c3':               'tabler-ui/dist/assets/js/vendors/chart.bundle.min' | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     module:    { |     module:    { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user