mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
Merge pull request #297 from YunoHost/permission_protection
Extends permission feature
This commit is contained in:
commit
df51c42fb0
8 changed files with 124 additions and 80 deletions
|
@ -12,6 +12,11 @@
|
||||||
app.get('#/apps', function (c) {
|
app.get('#/apps', function (c) {
|
||||||
c.api('GET', '/apps?full', {}, function(data) {
|
c.api('GET', '/apps?full', {}, function(data) {
|
||||||
var apps = data['apps'];
|
var apps = data['apps'];
|
||||||
|
for (var a in apps)
|
||||||
|
{
|
||||||
|
var app = apps[a]
|
||||||
|
app['label'] = app['permissions'][app['id'] + ".main"]['label']
|
||||||
|
}
|
||||||
c.arraySortById(apps);
|
c.arraySortById(apps);
|
||||||
c.view('app/app_list', {apps: apps});
|
c.view('app/app_list', {apps: apps});
|
||||||
});
|
});
|
||||||
|
@ -262,10 +267,9 @@
|
||||||
// Get app information
|
// Get app information
|
||||||
app.get('#/apps/:app', function (c) {
|
app.get('#/apps/:app', function (c) {
|
||||||
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(data) {
|
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(data) {
|
||||||
c.api('GET', '/users/permissions', {}, function(data_permissions) {
|
data.label = data.permissions[c.params['app']+".main"]['label']
|
||||||
|
|
||||||
// Permissions
|
data.permissions = data.permissions[c.params['app']+".main"]["allowed"];
|
||||||
data.permissions = data_permissions.permissions[c.params['app']+".main"]["allowed"];
|
|
||||||
|
|
||||||
// Multilingual description
|
// Multilingual description
|
||||||
data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ?
|
data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ?
|
||||||
|
@ -305,7 +309,6 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// App actions
|
// App actions
|
||||||
|
@ -677,12 +680,48 @@
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// A small utility to convert a string to title case
|
||||||
|
// e.g. "hAvE a NicE dAy" --> "Have A Nice Day"
|
||||||
|
// Savagely stolen from https://stackoverflow.com/a/196991
|
||||||
|
function toFriendlyName(str) {
|
||||||
|
return str.split('.')[1].replace(/_/g, " ").replace(
|
||||||
|
/\w\S*/g,
|
||||||
|
function(txt) {
|
||||||
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Get app change label page
|
// Get app change label page
|
||||||
app.get('#/apps/:app/changelabel', function (c) {
|
app.get('#/apps/:app/changelabel', function (c) {
|
||||||
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(app_data) {
|
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(app_data) {
|
||||||
|
var permissions_dict = app_data.permissions;
|
||||||
|
var permissions = [
|
||||||
|
permissions_dict[c.params['app'] + '.main']
|
||||||
|
];
|
||||||
|
permissions[0].name = c.params['app'] + '.main';
|
||||||
|
permissions[0].title = y18n.t('permission_main');
|
||||||
|
permissions[0].tile_available = permissions[0].url != null && ! permissions[0].url.startsWith('re:');
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
for (var permission in permissions_dict) {
|
||||||
|
if (! permission.endsWith('.main')) {
|
||||||
|
permissions[i] = permissions_dict[permission];
|
||||||
|
permissions[i].name = permission;
|
||||||
|
permissions[i].label = permissions[i].sublabel;
|
||||||
|
permissions[i].title = toFriendlyName(permission);
|
||||||
|
permissions[i].tile_available = permissions_dict[permission].url != null && ! permissions_dict[permission].url.startsWith('re:');
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
id: c.params['app'],
|
'id': c.params['app'],
|
||||||
label: app_data.settings.label,
|
'label': permissions[0].label,
|
||||||
|
'permissions': permissions,
|
||||||
|
'show_tile': function(permission_name) {
|
||||||
|
return permissions_dict[permission_name].show_tile;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
c.view('app/app_changelabel', data);
|
c.view('app/app_changelabel', data);
|
||||||
});
|
});
|
||||||
|
@ -690,10 +729,19 @@
|
||||||
|
|
||||||
// Change app label
|
// Change app label
|
||||||
app.post('#/apps/:app/changelabel', function (c) {
|
app.post('#/apps/:app/changelabel', function (c) {
|
||||||
params = {'new_label': c.params['label']};
|
|
||||||
c.api('PUT', '/apps/' + c.params['app'] + '/label', params, function(data) {
|
$.each($(".permission-row", c.target), function() {
|
||||||
c.redirect_to('#/apps/'+ c.params['app']);
|
var perm = $(this).data('permission');
|
||||||
|
if ('show_tile_' + perm in c.params) {
|
||||||
|
show_tile = "True";
|
||||||
|
} else {
|
||||||
|
show_tile = "False";
|
||||||
|
}
|
||||||
|
new_label = c.params["label_" + perm]
|
||||||
|
c.api('PUT', '/users/permissions/' + perm, {show_tile: show_tile, label: new_label}, function(data) {});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
c.redirect_to('#/apps/'+ c.params['app']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get app change URL page
|
// Get app change URL page
|
||||||
|
|
|
@ -5,18 +5,6 @@
|
||||||
|
|
||||||
var PASSWORD_MIN_LENGTH = 4;
|
var PASSWORD_MIN_LENGTH = 4;
|
||||||
|
|
||||||
// A small utility to convert a string to title case
|
|
||||||
// e.g. "hAvE a NicE dAy" --> "Have A Nice Day"
|
|
||||||
// Savagely stolen from https://stackoverflow.com/a/196991
|
|
||||||
function toTitleCase(str) {
|
|
||||||
return str.replace(
|
|
||||||
/\w\S*/g,
|
|
||||||
function(txt) {
|
|
||||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups and permissions
|
* Groups and permissions
|
||||||
*
|
*
|
||||||
|
@ -119,7 +107,7 @@
|
||||||
app.get('#/groups', function (c) {
|
app.get('#/groups', function (c) {
|
||||||
c.api('GET', '/users/groups?full&include_primary_groups', {}, function(data_groups) {
|
c.api('GET', '/users/groups?full&include_primary_groups', {}, function(data_groups) {
|
||||||
c.api('GET', '/users', {}, function(data_users) {
|
c.api('GET', '/users', {}, function(data_users) {
|
||||||
c.api('GET', '/users/permissions?short', {}, function(data_permissions) {
|
c.api('GET', '/users/permissions?full', {}, function(data_permissions) {
|
||||||
//var perms = data_permissions.permissions;
|
//var perms = data_permissions.permissions;
|
||||||
var specific_perms = {};
|
var specific_perms = {};
|
||||||
var all_perms = data_permissions.permissions;
|
var all_perms = data_permissions.permissions;
|
||||||
|
@ -128,10 +116,11 @@
|
||||||
// Enrich groups data with primary group indicator and inversed items list
|
// Enrich groups data with primary group indicator and inversed items list
|
||||||
for (var group in data_groups.groups) {
|
for (var group in data_groups.groups) {
|
||||||
data_groups.groups[group].primary = users.indexOf(group) !== -1;
|
data_groups.groups[group].primary = users.indexOf(group) !== -1;
|
||||||
data_groups.groups[group].permissionsInv = all_perms.filter(function(item) {
|
data_groups.groups[group].permissionsInv = Object.keys(all_perms).filter(function(item) {
|
||||||
return data_groups.groups[group].permissions.indexOf(item) === -1;
|
return data_groups.groups[group].permissions.indexOf(item) === -1;
|
||||||
}).filter(function(item) {
|
}).filter(function(item) {
|
||||||
return group != "visitors" || (item != "mail.main" && item != "xmpp.main"); // Remove 'email' and 'xmpp' in visitors's permission choice list
|
// Remove 'email', 'xmpp' and protected permission in visitors's permission choice list
|
||||||
|
return group != "visitors" || (item != "mail.main" && item != "xmpp.main" && ! all_perms[item].protected == true);
|
||||||
});
|
});
|
||||||
data_groups.groups[group].membersInv = users.filter(function(item) {
|
data_groups.groups[group].membersInv = users.filter(function(item) {
|
||||||
return data_groups.groups[group].members.indexOf(item) === -1;
|
return data_groups.groups[group].members.indexOf(item) === -1;
|
||||||
|
@ -147,23 +136,18 @@
|
||||||
data = {
|
data = {
|
||||||
'groups':data_groups.groups,
|
'groups':data_groups.groups,
|
||||||
'displayPermission': function (text) {
|
'displayPermission': function (text) {
|
||||||
// Display a permission correctly for a human
|
return all_perms[text].label;
|
||||||
text = text.replace('.main', '');
|
|
||||||
if (text.indexOf('.') > -1)
|
|
||||||
text = text.replace('.', ' (') + ')';
|
|
||||||
|
|
||||||
if (text == "mail")
|
|
||||||
text = "E-mail";
|
|
||||||
else if (text == "xmpp")
|
|
||||||
text = "XMPP";
|
|
||||||
else
|
|
||||||
text = toTitleCase(text);
|
|
||||||
|
|
||||||
return text;
|
|
||||||
},
|
},
|
||||||
'displayUser': function (text) {
|
'displayUser': function (text) {
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
|
'is_protected': function (item, type, group) {
|
||||||
|
if (type == 'permission' && group == 'visitors') {
|
||||||
|
return all_perms[item].protected;
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
updateView(data);
|
updateView(data);
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,17 +6,18 @@
|
||||||
"administration_password": "Administration password",
|
"administration_password": "Administration password",
|
||||||
"all": "All",
|
"all": "All",
|
||||||
"all_apps": "All apps",
|
"all_apps": "All apps",
|
||||||
|
"apply": "Apply",
|
||||||
"api_not_responding": "The YunoHost API is not responding. Maybe 'yunohost-api' is down or got restarted?",
|
"api_not_responding": "The YunoHost API is not responding. Maybe 'yunohost-api' is down or got restarted?",
|
||||||
"app_change_label": "Change Label",
|
|
||||||
"app_change_url": "Change URL",
|
"app_change_url": "Change URL",
|
||||||
"app_info_access_desc": "Groups / users currently allowed to access this app:",
|
"app_info_access_desc": "Groups / users currently allowed to access this app:",
|
||||||
"app_info_changelabel_desc": "Change app label in the portal.",
|
"app_info_managelabel_desc": "Manage permissions labels in the portal.",
|
||||||
"app_info_default_desc": "Redirect domain root to this application (%s).",
|
"app_info_default_desc": "Redirect domain root to this application (%s).",
|
||||||
"app_info_changeurl_desc": "Change the access URL of this application (domain and/or path).",
|
"app_info_changeurl_desc": "Change the access URL of this application (domain and/or path).",
|
||||||
"app_info_change_url_disabled_tooltip": "This feature hasn't been implemented in this app yet",
|
"app_info_change_url_disabled_tooltip": "This feature hasn't been implemented in this app yet",
|
||||||
"app_info_uninstall_desc": "Remove this application.",
|
"app_info_uninstall_desc": "Remove this application.",
|
||||||
"app_install_cancel": "Installation cancelled.",
|
"app_install_cancel": "Installation cancelled.",
|
||||||
"app_install_custom_no_manifest": "No manifest.json file",
|
"app_install_custom_no_manifest": "No manifest.json file",
|
||||||
|
"app_manage_label_and_tiles": "Manage label and tiles",
|
||||||
"app_make_default": "Make default",
|
"app_make_default": "Make default",
|
||||||
"app_no_actions": "This application doesn't have any actions",
|
"app_no_actions": "This application doesn't have any actions",
|
||||||
"app_state_inprogress": "not yet working",
|
"app_state_inprogress": "not yet working",
|
||||||
|
@ -230,6 +231,9 @@
|
||||||
"logs_more": "Display more lines",
|
"logs_more": "Display more lines",
|
||||||
"path_url": "Path",
|
"path_url": "Path",
|
||||||
"pending_migrations": "There are some pending migrations waiting to be ran. Please go to the <a href='#/tools/migrations'>Tools > Migrations</a> view to run them.",
|
"pending_migrations": "There are some pending migrations waiting to be ran. Please go to the <a href='#/tools/migrations'>Tools > Migrations</a> view to run them.",
|
||||||
|
"permission_corresponding_url": "Corresponding URL",
|
||||||
|
"permission_main": "Main permission",
|
||||||
|
"permission_show_tile_enabled": "Show the tile in the user portal",
|
||||||
"port": "Port",
|
"port": "Port",
|
||||||
"ports": "Ports",
|
"ports": "Ports",
|
||||||
"postinstall": "Post-installation",
|
"postinstall": "Post-installation",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<a href="#/apps" class="hidden-xs">{{t 'applications'}}</a>
|
<a href="#/apps" class="hidden-xs">{{t 'applications'}}</a>
|
||||||
<a href="#/apps" class="visible-xs">…</a>
|
<a href="#/apps" class="visible-xs">…</a>
|
||||||
<a href="#/apps/{{id}}">{{label}}</a>
|
<a href="#/apps/{{id}}">{{label}}</a>
|
||||||
<a href="#/apps/{{id}}/changelabel">{{t 'app_change_label'}}</a>
|
<a href="#/apps/{{id}}/changelabel">{{t 'app_manage_label_and_tiles'}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
|
@ -11,19 +11,25 @@
|
||||||
<form action="#/apps/{{id}}/changelabel" method="POST" class="form-horizontal form-app-install">
|
<form action="#/apps/{{id}}/changelabel" method="POST" class="form-horizontal form-app-install">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title"><span class="fa-fw fa-tag"></span> {{t 'app_change_label'}}</h2>
|
<h2 class="panel-title"><span class="fa-fw fa-tag"></span> {{t 'app_manage_label_and_tiles'}}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="form-group">
|
{{#each permissions}}
|
||||||
<label for="label" class="col-sm-12">{{t 'label'}}</label>
|
<div class="permission-row" data-permission="{{name}}">
|
||||||
<div class="col-sm-12">
|
<h3>{{title}}</h3>
|
||||||
<input class="col-sm-12" type="text" id="label" name="label" class="form-control" value="{{label}}" required="required">
|
{{#if tile_available}}
|
||||||
|
<p>{{t 'permission_corresponding_url'}}: <a href=https://{{url}}>https://{{url}}</a></p>
|
||||||
|
{{/if}}
|
||||||
|
<input type="text" id="label" name="label_{{name}}" class="form-control" value="{{label}}" required="required">
|
||||||
|
{{#if tile_available}}
|
||||||
|
<input type="checkbox" id="show_tile_{{name}}" name="show_tile_{{name}}" value="{{name}}" {{#if show_tile}} checked {{/if}}>
|
||||||
|
<label for="show_tile_{{name}}" style="font-weight:normal;"> {{t 'permission_show_tile_enabled'}}</label>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<hr />
|
||||||
<hr>
|
{{/each}}
|
||||||
<input type="hidden" name="app" value="{{id}}">
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<input type="submit" role="button" class="btn btn-success slide back" value="{{t 'app_change_label'}}">
|
<input type="submit" role="button" class="btn btn-success slide back" value="{{t 'apply'}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<dt>{{t 'id'}}</dt>
|
<dt>{{t 'id'}}</dt>
|
||||||
<dd>{{settings.id}}</dd>
|
<dd>{{settings.id}}</dd>
|
||||||
<dt>{{t 'label'}}</dt>
|
<dt>{{t 'label'}}</dt>
|
||||||
<dd>{{settings.label}}</dd>
|
<dd>{{label}}</dd>
|
||||||
<dt>{{t 'description'}}</dt>
|
<dt>{{t 'description'}}</dt>
|
||||||
<dd>{{description}}</dd>
|
<dd>{{description}}</dd>
|
||||||
<dt>{{t 'version'}}</dt>
|
<dt>{{t 'version'}}</dt>
|
||||||
|
@ -41,9 +41,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p>{{t 'app_info_changelabel_desc' settings.label}}</p>
|
<p>{{t 'app_info_managelabel_desc' settings.label}}</p>
|
||||||
<a role="button" href="#/apps/{{settings.id}}/changelabel" class="btn btn-info slide">
|
<a role="button" href="#/apps/{{settings.id}}/changelabel" class="btn btn-info slide">
|
||||||
<span class="fa-tag"></span> {{t 'app_change_label'}}
|
<span class="fa-tag"></span> {{t 'app_manage_label_and_tiles'}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<a href="#/apps/{{id}}" class="list-group-item slide" title="{{t 'infos'}}">
|
<a href="#/apps/{{id}}" class="list-group-item slide" title="{{t 'infos'}}">
|
||||||
<span class="fa-chevron-right pull-right"></span>
|
<span class="fa-chevron-right pull-right"></span>
|
||||||
<h2 class="list-group-item-heading">
|
<h2 class="list-group-item-heading">
|
||||||
{{settings.label}} <small>{{name}}</small>
|
{{label}} <small>{{name}}</small>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="list-group-item-text">{{description}}</p>
|
<p class="list-group-item-text">{{description}}</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
{{#each apps}}
|
{{#each apps}}
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<input type="checkbox" id="{{id}}" name="apps" value="{{id}}" checked class="nice-checkbox">
|
<input type="checkbox" id="{{id}}" name="apps" value="1" checked class="nice-checkbox">
|
||||||
<label for="{{id}}" class="pull-right"><span class="sr-only">{{t 'check'}}</span></label>
|
<label for="{{id}}" class="pull-right"><span class="sr-only">{{t 'check'}}</span></label>
|
||||||
<h2 class="list-group-item-heading">{{label}} <small>{{id}}</small></h2>
|
<h2 class="list-group-item-heading">{{label}} <small>{{id}}</small></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,15 +18,17 @@
|
||||||
<span class="fa-fw fa-{{icon}}"></span>
|
<span class="fa-fw fa-{{icon}}"></span>
|
||||||
{{text}}
|
{{text}}
|
||||||
<button data-type="{{type}}s" data-action="remove" data-item="{{value}}" data-group="{{group}}">
|
<button data-type="{{type}}s" data-action="remove" data-item="{{value}}" data-group="{{group}}">
|
||||||
|
{{#unless protected}}
|
||||||
<span class="fa-close" style="margin-left:5px"></span>
|
<span class="fa-close" style="margin-left:5px"></span>
|
||||||
<span class="sr-only">{{t 'delete'}}</span>
|
<span class="sr-only">{{t 'delete'}}</span>
|
||||||
|
{{/unless}}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
{{/inline}}
|
{{/inline}}
|
||||||
|
|
||||||
{{#*inline "labelsLine"}}
|
{{#*inline "labelsLine"}}
|
||||||
{{#each items}}
|
{{#each items}}
|
||||||
{{> label text=(call ../display .) value=. icon=../icon type=../type item=. group=../group}}
|
{{> label text=(call ../display .) value=. icon=../icon type=../type item=. group=../group protected=(call ../is_protected . ../type ../group)}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#if inv}}
|
{{#if inv}}
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
@ -73,7 +75,7 @@
|
||||||
<div style="font-style:italic">{{t 'group_explain_visitors_needed_for_external_client'}}</div>
|
<div style="font-style:italic">{{t 'group_explain_visitors_needed_for_external_client'}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{> labelsLine display=../displayUser icon="user" type="member" items=members inv=membersInv group=@key}}
|
{{> labelsLine display=../displayUser icon="user" type="member" items=members inv=membersInv group=@key is_protected=../is_protected}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,7 +85,7 @@
|
||||||
<h3>{{t 'permissions'}}</h3>
|
<h3>{{t 'permissions'}}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
{{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key}}
|
{{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key is_protected=../is_protected}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,7 +113,7 @@
|
||||||
<h3><span class="fa-fw fa-user"></span> {{@key}}</h3>
|
<h3><span class="fa-fw fa-user"></span> {{@key}}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
{{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key}}
|
{{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key is_protected=../is_protected}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
Loading…
Add table
Reference in a new issue