TeaWeb/shared/js/ui/modal/ModalPermissionEdit.ts
2019-04-04 21:47:52 +02:00

1296 lines
No EOL
62 KiB
TypeScript

/// <reference path="../../ui/elements/modal.ts" />
/// <reference path="../../ConnectionHandler.ts" />
/// <reference path="../../proto.ts" />
/*
TODO: Check needed permissions and may not even try to request, because we dont have the permission. Permissions:
b_virtualserver_servergroup_permission_list
b_virtualserver_channel_permission_list
b_virtualserver_client_permission_list
b_virtualserver_channelgroup_permission_list
b_virtualserver_channelclient_permission_list
b_virtualserver_playlist_permission_list
*/
interface JQuery<TElement = HTMLElement> {
dropdown: any;
}
namespace Modals {
namespace PermissionEditor {
export interface PermissionEntry {
tag: JQuery;
tag_value: JQuery;
tag_grant: JQuery;
tag_flag_negate: JQuery;
tag_flag_skip: JQuery;
id: number;
filter: string;
is_bool: boolean;
}
export interface PermissionValue {
remove: boolean; /* if set remove the set permission (value or granted) */
granted?: number;
value?: number;
flag_skip?: boolean;
flag_negate?: boolean;
}
export type change_listener_t = (permission: PermissionInfo, value?: PermissionEditor.PermissionValue) => Promise<any>;
}
enum PermissionEditorMode {
VISIBLE,
NO_PERMISSION,
UNSET
}
class PermissionEditor {
readonly permissions: GroupedPermissions[];
container: JQuery;
private mode_container_permissions: JQuery;
private mode_container_error_permission: JQuery;
private mode_container_unset: JQuery;
/* references within the container tag */
private permission_value_map: {[key:number]:PermissionValue} = {};
private permission_map: {[key:number]: PermissionEditor.PermissionEntry};
private listener_change: PermissionEditor.change_listener_t = () => Promise.resolve();
private listener_update: () => any;
constructor(permissions: GroupedPermissions[]) {
this.permissions = permissions;
}
build_tag() {
this.permission_map = {};
this.container = $("#tmpl_permission_editor").renderTag();
/* search for that as long we've not that much nodes */
this.mode_container_permissions = this.container.find(".container-mode-permissions");
this.mode_container_error_permission = this.container.find(".container-mode-no-permissions");
this.mode_container_unset = this.container.find(".container-mode-unset");
this.set_mode(PermissionEditorMode.UNSET);
/* the filter */
{
const tag_filter_input = this.container.find(".filter-input");
const tag_filter_granted = this.container.find(".filter-granted");
tag_filter_granted.on('change', event => tag_filter_input.trigger('change'));
tag_filter_input.on('keyup change', event => {
let filter_mask = tag_filter_input.val() as string;
let req_granted = tag_filter_granted.prop("checked");
/* we've to disable this function because its sometimes laggy */
const org_fn = $.fn.dropdown && $.fn.dropdown.Constructor ? $.fn.dropdown.Constructor._clearMenus : undefined;
if(org_fn)
$.fn.dropdown.Constructor._clearMenus = () => {};
/* update each permission */
{
const start = Date.now();
for(const permission_id of Object.keys(this.permission_map)) {
const permission: PermissionEditor.PermissionEntry = this.permission_map[permission_id];
let shown = filter_mask.length == 0 || permission.filter.indexOf(filter_mask) != -1;
if(shown && req_granted) {
const value: PermissionValue = this.permission_value_map[permission_id];
shown = value && (value.hasValue() || value.hasGrant());
}
permission.tag.attr("match", shown ? 1 : 0);
/* this is faster then .hide() or .show() */
if(shown)
permission.tag.css('display', 'flex');
else
permission.tag.css('display', 'none');
}
const end = Date.now();
console.error("Filter update required %oms", end - start);
}
/* update group visibility (hide empty groups) */
{
const start = Date.now();
this.container.find(".group").each((idx, _entry) => {
let entry = $(_entry);
let target = entry.find(".entry:not(.group)[match=\"1\"]").length > 0;
/* this is faster then .hide() or .show() */
if(target)
entry.css('display', 'flex');
else
entry.css('display', 'none');
});
const end = Date.now();
console.error("Group update required %oms", end - start);
}
if(org_fn)
$.fn.dropdown.Constructor._clearMenus = org_fn;
});
}
/* update button */
{
this.container.find(".button-update").on('click', this.trigger_update.bind(this));
}
/* global context menu listener */
{
this.container.on('contextmenu', event => {
if(event.isDefaultPrevented()) return;
event.preventDefault();
/* TODO allow collapse and expend all */
});
}
/* actual permissions */
{
const tag_entries = this.container.find(".entries");
const template_entry = $("#tmpl_permission_entry");
const build_group = (group: GroupedPermissions) : JQuery => {
const tag_group = template_entry.renderTag({
type: "group",
name: group.group.name
});
const tag_group_entries = tag_group.find(".group-entries");
const update_collapse_status = (status: boolean, recursive: boolean) => {
const tag = recursive ? this.container.find(".entry.group") : tag_group;
/* this is faster then .hide() or .show() */
if(status) {
tag.find("> .group-entries").css('display', 'block');
} else {
tag.find("> .group-entries").css('display', 'none');
}
tag.find("> .title .arrow").toggleClass("down", status).toggleClass("right", !status);
};
/* register collapse and context listener */
{
const tag_arrow = tag_group.find(".arrow");
tag_arrow.on('click', event => {
if(event.isDefaultPrevented()) return;
event.preventDefault();
update_collapse_status(tag_arrow.hasClass("right"), false);
});
const tag_title = tag_group.find(".title");
tag_title.on('contextmenu', event => {
if(event.isDefaultPrevented()) return;
event.preventDefault();
spawn_context_menu(event.pageX, event.pageY, {
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Expend group"),
callback: () => update_collapse_status(true, false)
}, {
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Expend all"),
callback: () => update_collapse_status(true, true)
}, {
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Collapse group"),
callback: () => update_collapse_status(false, false)
}, {
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Collapse all"),
callback: () => update_collapse_status(false, true)
});
});
}
/* build the permissions */
{
for(const permission of group.permissions) {
const tag_permission = template_entry.renderTag({
type: "permission",
permission_name: permission.name,
permission_id: permission.id,
permission_description: permission.description,
});
const tag_value = tag_permission.find(".column-value input");
const tag_granted = tag_permission.find(".column-granted input");
const tag_flag_skip = tag_permission.find(".column-skip input");
const tag_flag_negate = tag_permission.find(".column-negate input");
/* double click listener */
{
tag_permission.on('dblclick', event => {
if(event.isDefaultPrevented()) return;
event.preventDefault();
if(tag_permission.hasClass("value-unset")) {
tag_flag_skip.prop("checked", false);
tag_flag_negate.prop("checked", false);
tag_permission.removeClass("value-unset");
if(permission.name.startsWith("b_")) {
tag_permission.find(".column-value input")
.prop("checked", true)
.trigger('change');
} else {
/* TODO auto value */
tag_value.val('').focus();
}
} else if(!permission.name.startsWith("b_")) {
tag_value.focus();
}
});
tag_permission.find(".column-granted").on('dblclick', event => {
if(event.isDefaultPrevented()) return;
event.preventDefault();
if(tag_permission.hasClass("grant-unset")) {
tag_permission.removeClass("grant-unset");
tag_granted.focus();
}
});
}
/* focus out listener */
{
tag_granted.on('focusout', event => {
try {
const value = tag_granted.val() as string;
if(isNaN(parseInt(value)))
throw "";
} catch(_) {
tag_granted.val("");
tag_permission.addClass("grant-unset");
const element = this.permission_value_map[permission.id];
if(element && element.hasGrant()) {
this.listener_change(permission, {
remove: true,
granted: -2
}).then(() => {
element.granted_value = undefined;
}).catch(() => {
tag_granted.val(element.granted_value);
});
}
}
});
tag_value.on('focusout', event => {
try {
if(isNaN(parseInt(tag_value.val() as string)))
throw "";
} catch(_) {
const element = this.permission_value_map[permission.id];
if(element && element.hasValue()) {
tag_value.val(element.value);
} else {
tag_value.val("");
tag_permission.addClass("value-unset");
}
}
})
}
/* change listener */
{
tag_flag_negate.on('change', () => tag_value.trigger('change'));
tag_flag_skip.on('change', () => tag_value.trigger('change'));
tag_granted.on('change', event => {
const value = parseInt(tag_granted.val() as string);
if(isNaN(value)) return;
this.listener_change(permission, {
remove: false,
granted: value,
}).then(() => {
const element = this.permission_value_map[permission.id] || (this.permission_value_map[permission.id] = new PermissionValue(permission));
element.granted_value = value;
}).catch(() => {
const element = this.permission_value_map[permission.id];
tag_granted.val(element && element.hasGrant() ? element.granted_value : "");
tag_permission.toggleClass("grant-unset", !element || !element.hasGrant());
});
});
tag_value.on('change', event => {
const value = permission.is_boolean() ? tag_value.prop("checked") ? 1 : 0 : parseInt(tag_value.val() as string);
if(isNaN(value)) return;
const flag_negate = tag_flag_negate.prop("checked");
const flag_skip = tag_flag_skip.prop("checked");
this.listener_change(permission, {
remove: false,
value: value,
flag_negate: flag_negate,
flag_skip: flag_skip
}).then(() => {
const element = this.permission_value_map[permission.id] || (this.permission_value_map[permission.id] = new PermissionValue(permission));
element.value = value;
element.flag_skip = flag_skip;
element.flag_negate = flag_negate;
}).catch(error => {
const element = this.permission_value_map[permission.id];
/* reset or set the fields */
if(permission.is_boolean())
tag_value.prop('checked', element && element.hasValue() && element.value > 0);
else
tag_value.val(element && element.hasValue() ? element.value : "");
tag_flag_negate.prop("checked", element && element.flag_negate);
tag_flag_skip.prop("checked", element && element.flag_skip);
tag_permission.toggleClass("value-unset", !element || !element.hasValue());
});
});
}
/* context menu */
{
tag_permission.on('contextmenu', event => {
if(event.isDefaultPrevented()) return;
event.preventDefault();
let entries: ContextMenuEntry[] = [];
if(tag_permission.hasClass("value-unset")) {
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Add permission"),
callback: () => tag_permission.trigger('dblclick')
});
} else {
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Remove permission"),
callback: () => {
this.listener_change(permission, {
remove: true,
value: -2
}).then(() => {
const element = this.permission_value_map[permission.id];
if(!element) return; /* This should never happen, if so how are we displaying this permission?! */
element.value = undefined;
element.flag_negate = false;
element.flag_skip = false;
tag_permission.toggleClass("value-unset", true);
}).catch(() => {
const element = this.permission_value_map[permission.id];
/* reset or set the fields */
tag_value.val(element && element.hasValue() ? element.value : "");
tag_flag_negate.prop("checked", element && element.flag_negate);
tag_flag_skip.prop("checked", element && element.flag_skip);
tag_permission.toggleClass("value-unset", !element || !element.hasValue());
});
}
});
}
if(tag_permission.hasClass("grant-unset")) {
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Add grant permission"),
callback: () => tag_permission.find(".column-granted").trigger('dblclick')
});
} else {
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Remove grant permission"),
callback: () =>
tag_granted.val('').trigger('focusout') /* empty values are handled within focus out */
});
}
entries.push(MenuEntry.HR());
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Expend all"),
callback: () => update_collapse_status(true, true)
});
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Collapse all"),
callback: () => update_collapse_status(false, true)
});
entries.push(MenuEntry.HR());
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Show permission description"),
callback: () => {
createInfoModal(
tr("Permission description"),
tr("Permission description for permission ") + permission.name + ": <br>" + permission.description
).open();
}
});
entries.push({
type: MenuEntryType.ENTRY,
icon: "",
name: tr("Copy permission name"),
callback: () => {
copy_to_clipboard(permission.name);
}
});
spawn_context_menu(event.pageX, event.pageY, ...entries);
});
}
this.permission_map[permission.id] = {
tag: tag_permission,
id: permission.id,
filter: permission.name,
tag_flag_negate: tag_flag_negate,
tag_flag_skip: tag_flag_skip,
tag_grant: tag_granted,
tag_value: tag_value,
is_bool: permission.is_boolean()
};
tag_group_entries.append(tag_permission);
}
}
/* append the subgroups */
for(const child of group.children) {
tag_group_entries.append(build_group(child));
}
return tag_group;
};
/* build the groups */
for(const group of this.permissions)
tag_entries.append(build_group(group));
}
}
set_permissions(permissions?: PermissionValue[]) {
permissions = permissions || [];
this.permission_value_map = {};
for(const permission of permissions)
this.permission_value_map[permission.type.id] = permission;
for(const permission_id of Object.keys(this.permission_map)) {
const permission: PermissionEditor.PermissionEntry = this.permission_map[permission_id];
const value: PermissionValue = this.permission_value_map[permission_id];
permission.tag
.toggleClass("value-unset", !value || !value.hasValue())
.toggleClass("grant-unset", !value || !value.hasGrant());
if(value && value.hasValue()) {
if(value.type.is_boolean())
permission.tag_value.prop("checked", value.value);
else
permission.tag_value.val(value.value);
permission.tag_flag_skip.prop("checked", value.flag_skip);
permission.tag_flag_negate.prop("checked", value.flag_negate);
}
if(value && value.hasGrant()) {
permission.tag_grant.val(value.granted_value);
}
}
}
set_listener(listener?: PermissionEditor.change_listener_t) {
this.listener_change = listener || (() => Promise.resolve());
}
set_listener_update(listener?: () => any) {
this.listener_update = listener;
}
trigger_update() {
if(this.listener_update)
this.listener_update();
}
set_mode(mode: PermissionEditorMode) {
this.mode_container_permissions.css('display', mode == PermissionEditorMode.VISIBLE ? 'flex' : 'none');
this.mode_container_error_permission.css('display', mode == PermissionEditorMode.NO_PERMISSION ? 'flex' : 'none');
this.mode_container_unset.css('display', mode == PermissionEditorMode.UNSET ? 'block' : 'none');
}
}
export function spawnPermissionEdit(connection: ConnectionHandler) : Modal {
const connectModal = createModal({
header: function() {
return tr("Server Permissions");
},
body: function () {
let properties: any = {};
let tag = $("#tmpl_server_permissions").renderTag(properties);
const pe = new PermissionEditor(connection.permissions.groupedPermissions());
pe.build_tag();
/* initialisation */
{
const pe_server = tag.find("permission-editor.group-server");
pe_server.append(pe.container); /* fuck off workaround to initialize form listener */
}
apply_server_groups(connection, pe, tag.find(".tab-group-server"));
apply_channel_groups(connection, pe, tag.find(".tab-group-channel"));
apply_channel_permission(connection, pe, tag.find(".tab-channel"));
apply_client_permission(connection, pe, tag.find(".tab-client"));
apply_client_channel_permission(connection, pe, tag.find(".tab-client-channel"));
return tag.tabify(false);
},
footer: undefined,
width: "90%",
height: "80%",
trigger_tab: false,
full_size: true
});
const tag = connectModal.htmlTag;
tag.find(".btn_close").on('click', () => {
connectModal.close();
});
return connectModal;
}
function build_channel_tree(connection: ConnectionHandler, channel_list: JQuery, select_callback: (channel: ChannelEntry) => any) {
const root = connection.channelTree.get_first_channel();
if(!root) return;
const build_channel = (channel: ChannelEntry) => {
let tag = $.spawn("div").addClass("channel").attr("channel-id", channel.channelId);
connection.fileManager.icons.generateTag(channel.properties.channel_icon_id).appendTo(tag);
{
let name = $.spawn("a").text(channel.channelName() + " (" + channel.channelId + ")").addClass("name");
//if(connection.channelTree.server.properties. == group.id)
// name.addClass("default");
name.appendTo(tag);
}
tag.on('click', event => {
channel_list.find(".selected").removeClass("selected");
tag.addClass("selected");
select_callback(channel);
});
return tag;
};
const build_channels = (root: ChannelEntry) => {
build_channel(root).appendTo(channel_list);
for(const child of root.children())
build_channels(child);
while(root.channel_next) {
root = root.channel_next;
build_channel(root).appendTo(channel_list);
}
};
build_channels(root);
setTimeout(() => channel_list.find('.channel').first().trigger('click'), 0);
}
function apply_client_channel_permission(connection: ConnectionHandler, editor: PermissionEditor, tab_tag: JQuery) {
let current_cldbid: number = 0;
let current_channel: ChannelEntry;
/* the editor */
{
const pe_client = tab_tag.find("permission-editor.client-channel");
tab_tag.on('show', event => {
console.error("Channel tab show");
pe_client.append(editor.container);
if(connection.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CLIENT_PERMISSION_LIST).granted(1)) {
if(current_cldbid && current_channel)
editor.set_mode(PermissionEditorMode.VISIBLE);
else
editor.set_mode(PermissionEditorMode.UNSET);
} else {
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
return;
}
editor.set_listener_update(() => {
if(!current_cldbid || !current_channel) return;
connection.permissions.requestClientChannelPermissions(current_cldbid, current_channel.channelId).then(result => {
editor.set_permissions(result);
editor.set_mode(PermissionEditorMode.VISIBLE);
}).catch(error => {
console.log(error); //TODO handling?
});
});
editor.set_listener((permission, value) => {
if (!current_cldbid)
return Promise.reject("unset client");
if (!current_channel)
return Promise.reject("unset channel");
if (value.remove) {
/* remove the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Removing client channel permission %s. permission.id: %o"),
permission.name,
permission.id,
);
return connection.serverConnection.send_command("channelclientdelperm", {
cldbid: current_cldbid,
cid: current_channel.channelId,
permid: permission.id,
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Removing client channel grant permission %s. permission.id: %o"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("channelclientdelperm", {
cldbid: current_cldbid,
cid: current_channel.channelId,
permid: permission.id_grant(),
});
}
} else {
/* add the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating client channel permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}"),
permission.name,
permission.id,
value.value,
value.flag_skip,
value.flag_negate
);
return connection.serverConnection.send_command("channelclientaddperm", {
cldbid: current_cldbid,
cid: current_channel.channelId,
permid: permission.id,
permvalue: value.value,
permskip: value.flag_skip,
permnegate: value.flag_negate
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating client channel grant permission %s. permission.{id: %o, value: %o}"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("channelclientaddperm", {
cldbid: current_cldbid,
cid: current_channel.channelId,
permid: permission.id_grant(),
permvalue: value.granted,
permskip: false,
permnegate: false
});
}
}
});
/* FIXME: Use cached permissions */
editor.trigger_update();
});
}
build_channel_tree(connection, tab_tag.find(".list-channel .entries"), channel => {
if(current_channel == channel) return;
current_channel = channel;
/* TODO: Test for visibility */
editor.trigger_update();
});
{
const tag_select_uid = tab_tag.find(".client-select input");
const tag_select_error = tab_tag.find(".client-select .invalid-feedback");
const tag_client_name = tab_tag.find(".client-name");
const tag_client_uid = tab_tag.find(".client-uid");
const tag_client_dbid = tab_tag.find(".client-dbid");
const resolve_client = () => {
let client_uid = tag_select_uid.val() as string;
connection.serverConnection.command_helper.info_from_uid(client_uid).then(result => {
if(!result || result.length == 0) return Promise.reject("invalid data");
tag_select_uid.attr('pattern', null).removeClass('is-invalid');
tag_client_name.val(result[0].client_nickname );
tag_client_uid.val(result[0].client_unique_id);
tag_client_dbid.val(result[0].client_database_id);
current_cldbid = result[0].client_database_id;
editor.trigger_update();
}).catch(error => {
console.log(error);
if(error instanceof CommandResult) {
if(error.id == ErrorID.EMPTY_RESULT)
error = "unknown client";
else
error = error.extra_message || error.message;
}
tag_client_name.val("");
tag_client_uid.val("");
tag_client_dbid.val("");
tag_select_error.text(error);
tag_select_uid.attr('pattern', '^[a]{1000}$').addClass('is-invalid');
editor.set_mode(PermissionEditorMode.UNSET);
});
};
tab_tag.find(".client-select-uid").on('change', event => resolve_client());
}
}
function apply_client_permission(connection: ConnectionHandler, editor: PermissionEditor, tab_tag: JQuery) {
let current_cldbid: number = 0;
/* the editor */
{
const pe_client = tab_tag.find("permission-editor.client");
tab_tag.on('show', event => {
console.error("Channel tab show");
pe_client.append(editor.container);
if(connection.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CLIENT_PERMISSION_LIST).granted(1)) {
if(current_cldbid)
editor.set_mode(PermissionEditorMode.VISIBLE);
else
editor.set_mode(PermissionEditorMode.UNSET);
} else {
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
return;
}
editor.set_listener_update(() => {
if(!current_cldbid) return;
connection.permissions.requestClientPermissions(current_cldbid).then(result => {
editor.set_permissions(result);
editor.set_mode(PermissionEditorMode.VISIBLE);
}).catch(error => {
console.log(error); //TODO handling?
});
});
editor.set_listener((permission, value) => {
if (!current_cldbid)
return Promise.reject("unset client");
if (value.remove) {
/* remove the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Removing client permission %s. permission.id: %o"),
permission.name,
permission.id,
);
return connection.serverConnection.send_command("clientaddperm", {
cldbid: current_cldbid,
permid: permission.id,
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Removing client grant permission %s. permission.id: %o"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("clientaddperm", {
cldbid: current_cldbid,
permid: permission.id_grant(),
});
}
} else {
/* add the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating client permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}"),
permission.name,
permission.id,
value.value,
value.flag_skip,
value.flag_negate
);
return connection.serverConnection.send_command("clientaddperm", {
cldbid: current_cldbid,
permid: permission.id,
permvalue: value.value,
permskip: value.flag_skip,
permnegate: value.flag_negate
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating client grant permission %s. permission.{id: %o, value: %o}"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("clientaddperm", {
cldbid: current_cldbid,
permid: permission.id_grant(),
permvalue: value.granted,
permskip: false,
permnegate: false
});
}
}
});
/* FIXME: Use cached permissions */
editor.trigger_update();
});
}
const tag_select_uid = tab_tag.find(".client-select input");
const tag_select_error = tab_tag.find(".client-select .invalid-feedback");
const tag_client_name = tab_tag.find(".client-name");
const tag_client_uid = tab_tag.find(".client-uid");
const tag_client_dbid = tab_tag.find(".client-dbid");
const resolve_client = () => {
let client_uid = tag_select_uid.val() as string;
connection.serverConnection.command_helper.info_from_uid(client_uid).then(result => {
if(!result || result.length == 0) return Promise.reject("invalid data");
tag_select_uid.attr('pattern', null).removeClass('is-invalid');
tag_client_name.val(result[0].client_nickname );
tag_client_uid.val(result[0].client_unique_id);
tag_client_dbid.val(result[0].client_database_id);
current_cldbid = result[0].client_database_id;
editor.trigger_update();
}).catch(error => {
console.log(error);
if(error instanceof CommandResult) {
if(error.id == ErrorID.EMPTY_RESULT)
error = "unknown client";
else
error = error.extra_message || error.message;
}
tag_client_name.val("");
tag_client_uid.val("");
tag_client_dbid.val("");
tag_select_error.text(error);
tag_select_uid.attr('pattern', '^[a]{1000}$').addClass('is-invalid');
editor.set_mode(PermissionEditorMode.UNSET);
});
};
tab_tag.find(".client-select-uid").on('change', event => resolve_client());
}
function apply_channel_permission(connection: ConnectionHandler, editor: PermissionEditor, tab_tag: JQuery) {
let current_channel: ChannelEntry | undefined;
/* the editor */
{
const pe_channel = tab_tag.find("permission-editor.channel");
tab_tag.on('show', event => {
console.error("Channel tab show");
pe_channel.append(editor.container);
if(connection.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CHANNEL_PERMISSION_LIST).granted(1))
editor.set_mode(PermissionEditorMode.VISIBLE);
else {
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
return;
}
editor.set_listener_update(() => {
if(!current_channel) return;
connection.permissions.requestChannelPermissions(current_channel.channelId).then(result => editor.set_permissions(result)).catch(error => {
console.log(error); //TODO handling?
});
});
editor.set_listener((permission, value) => {
if (!current_channel)
return Promise.reject("unset channel");
if (value.remove) {
/* remove the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Removing channel permission %s. permission.id: %o"),
permission.name,
permission.id,
);
return connection.serverConnection.send_command("channeldelperm", {
cid: current_channel.channelId,
permid: permission.id,
});
} else {
/* TODO Remove this because its totally useless. Remove this from the UI as well */
log.info(LogCategory.PERMISSIONS, tr("Removing channel grant permission %s. permission.id: %o"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("channeldelperm", {
cid: current_channel.channelId,
permid: permission.id_grant(),
});
}
} else {
/* add the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating channel permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}"),
permission.name,
permission.id,
value.value,
value.flag_skip,
value.flag_negate
);
return connection.serverConnection.send_command("channeladdperm", {
cid: current_channel.channelId,
permid: permission.id,
permvalue: value.value,
permskip: value.flag_skip,
permnegate: value.flag_negate
});
} else {
/* TODO Remove this because its totally useless. Remove this from the UI as well */
log.info(LogCategory.PERMISSIONS, tr("Adding or updating channel grant permission %s. permission.{id: %o, value: %o}"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("channeladdperm", {
cid: current_channel.channelId,
permid: permission.id_grant(),
permvalue: value.granted,
permskip: false,
permnegate: false
});
}
}
});
/* FIXME: Use cached permissions */
editor.trigger_update();
});
}
let channel_list = tab_tag.find(".list-channel .entries");
build_channel_tree(connection, channel_list, channel => {
current_channel = channel;
editor.trigger_update();
});
}
function apply_channel_groups(connection: ConnectionHandler, editor: PermissionEditor, tab_tag: JQuery) {
let current_group;
/* the editor */
{
const pe_server = tab_tag.find("permission-editor.group-channel");
tab_tag.on('show', event => {
console.error("Channel group tab show");
pe_server.append(editor.container);
if(connection.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CHANNELGROUP_PERMISSION_LIST).granted(1))
editor.set_mode(PermissionEditorMode.VISIBLE);
else {
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
return;
}
editor.set_listener_update(() => {
if(!current_group) return;
connection.groups.request_permissions(current_group).then(result => editor.set_permissions(result)).catch(error => {
console.log(error); //TODO handling?
});
});
editor.set_listener((permission, value) => {
if (!current_group)
return Promise.reject("unset channel group");
if (value.remove) {
/* remove the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Removing channel group permission %s. permission.id: %o"),
permission.name,
permission.id,
);
return connection.serverConnection.send_command("channelgroupdelperm", {
cgid: current_group.id,
permid: permission.id,
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Removing channel group grant permission %s. permission.id: %o"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("channelgroupdelperm", {
cgid: current_group.id,
permid: permission.id_grant(),
});
}
} else {
/* add the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating channel group permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}"),
permission.name,
permission.id,
value.value,
value.flag_skip,
value.flag_negate
);
return connection.serverConnection.send_command("channelgroupaddperm", {
cgid: current_group.id,
permid: permission.id,
permvalue: value.value,
permskip: value.flag_skip,
permnegate: value.flag_negate
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating channel group grant permission %s. permission.{id: %o, value: %o}"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("channelgroupaddperm", {
cgid: current_group.id,
permid: permission.id_grant(),
permvalue: value.granted,
permskip: false,
permnegate: false
});
}
}
});
/* FIXME: Use cached permissions */
editor.trigger_update();
});
}
/* list all channel groups */
{
let group_list = tab_tag.find(".list-group-channel .entries");
const allow_query_groups = connection.permissions.neededPermission(PermissionType.B_SERVERINSTANCE_MODIFY_QUERYGROUP).granted(1);
const allow_template_groups = connection.permissions.neededPermission(PermissionType.B_SERVERINSTANCE_MODIFY_TEMPLATES).granted(1);
for(let group of connection.groups.channelGroups.sort(GroupManager.sorter())) {
if(group.type == GroupType.QUERY) {
if(!allow_query_groups)
continue;
} else if(group.type == GroupType.TEMPLATE) {
if(!allow_template_groups)
continue;
}
let tag = $.spawn("div").addClass("group").attr("group-id", group.id);
connection.fileManager.icons.generateTag(group.properties.iconid).appendTo(tag);
{
let name = $.spawn("a").text(group.name + " (" + group.id + ")").addClass("name");
if(group.properties.savedb)
name.addClass("savedb");
if(connection.channelTree.server.properties.virtualserver_default_channel_group == group.id)
name.addClass("default");
name.appendTo(tag);
}
tag.appendTo(group_list);
tag.on('click', event => {
current_group = group;
group_list.find(".selected").removeClass("selected");
tag.addClass("selected");
//TODO trigger only if the editor is in channel group mode!
editor.trigger_update();
});
}
/* because the server menu is the first which will be shown */
setTimeout(() => group_list.find('.group').first().trigger('click'), 0);
}
}
/*
b_virtualserver_servergroup_permission_list
b_virtualserver_channel_permission_list
b_virtualserver_client_permission_list
b_virtualserver_channelgroup_permission_list
b_virtualserver_channelclient_permission_list
b_virtualserver_playlist_permission_list
*/
function apply_server_groups(connection: ConnectionHandler, editor: PermissionEditor, tab_tag: JQuery) {
let current_group;
/* list all groups */
{
let group_list = tab_tag.find(".list-group-server .entries");
const allow_query_groups = connection.permissions.neededPermission(PermissionType.B_SERVERINSTANCE_MODIFY_QUERYGROUP).granted(1);
const allow_template_groups = connection.permissions.neededPermission(PermissionType.B_SERVERINSTANCE_MODIFY_TEMPLATES).granted(1);
for(const group of connection.groups.serverGroups.sort(GroupManager.sorter())) {
if(group.type == GroupType.QUERY) {
if(!allow_query_groups)
continue;
} else if(group.type == GroupType.TEMPLATE) {
if(!allow_template_groups)
continue;
}
let tag = $.spawn("div").addClass("group").attr("group-id", group.id);
connection.fileManager.icons.generateTag(group.properties.iconid).appendTo(tag);
{
let name = $.spawn("a").text(group.name + " (" + group.id + ")").addClass("name");
if(group.properties.savedb)
name.addClass("savedb");
if(connection.channelTree.server.properties.virtualserver_default_server_group == group.id)
name.addClass("default");
name.appendTo(tag);
}
tag.appendTo(group_list);
tag.on('click', event => {
current_group = group;
group_list.find(".selected").removeClass("selected");
tag.addClass("selected");
editor.trigger_update();
});
}
/* because the server menu is the first which will be shown */
setTimeout(() => group_list.find('.group').first().trigger('click'), 0);
}
/* the editor */
{
const pe_server = tab_tag.find("permission-editor.group-server");
tab_tag.on('show', event => {
console.error("Server tab show");
pe_server.append(editor.container);
if(connection.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_SERVERGROUP_PERMISSION_LIST).granted(1))
editor.set_mode(PermissionEditorMode.VISIBLE);
else {
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
return;
}
editor.set_listener_update(() => {
connection.groups.request_permissions(current_group).then(result => editor.set_permissions(result)).catch(error => {
console.log(error); //TODO handling?
});
});
editor.set_listener((permission, value) => {
if (!current_group)
return Promise.reject("unset server group");
if (value.remove) {
/* remove the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Removing server group permission %s. permission.id: %o"),
permission.name,
permission.id,
);
return connection.serverConnection.send_command("servergroupdelperm", {
sgid: current_group.id,
permid: permission.id,
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Removing server group grant permission %s. permission.id: %o"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("servergroupdelperm", {
sgid: current_group.id,
permid: permission.id_grant(),
});
}
} else {
/* add the permission */
if (typeof (value.value) !== "undefined") {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating server group permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}"),
permission.name,
permission.id,
value.value,
value.flag_skip,
value.flag_negate
);
return connection.serverConnection.send_command("servergroupaddperm", {
sgid: current_group.id,
permid: permission.id,
permvalue: value.value,
permskip: value.flag_skip,
permnegate: value.flag_negate
});
} else {
log.info(LogCategory.PERMISSIONS, tr("Adding or updating server group grant permission %s. permission.{id: %o, value: %o}"),
permission.name,
permission.id_grant(),
value.granted,
);
return connection.serverConnection.send_command("servergroupaddperm", {
sgid: current_group.id,
permid: permission.id_grant(),
permvalue: value.granted,
permskip: false,
permnegate: false
});
}
}
});
editor.trigger_update();
});
}
}
}