Implement syncplay permissions for a user

This commit is contained in:
gion 2020-04-04 18:20:39 +02:00
parent 56ee678fc2
commit a18bca9d8c
6 changed files with 64 additions and 23 deletions

View file

@ -27,18 +27,17 @@ function emptyCallback() {
/** /**
* Used when user needs to join a group. * Used when user needs to join a group.
* @param {HTMLElement} button - Element where to place the menu. * @param {HTMLElement} button - Element where to place the menu.
* @param {Object} user - Current user.
* @param {Object} apiClient - ApiClient.
*/ */
function showNewJoinGroupSelection(button) { function showNewJoinGroupSelection(button, user, apiClient) {
var apiClient = connectionManager.currentApiClient(); let sessionId = getActivePlayerId();
var sessionId = getActivePlayerId();
sessionId = sessionId ? sessionId : "none"; sessionId = sessionId ? sessionId : "none";
const inSession = sessionId !== "none";
loading.show(); const policy = user.localUser ? user.localUser.Policy : {};
apiClient.sendSyncplayCommand(sessionId, "ListGroups").then(function (response) { apiClient.sendSyncplayCommand(sessionId, "ListGroups").then(function (response) {
response.json().then(function (groups) { response.json().then(function (groups) {
var inSession = sessionId !== "none";
var menuItems = groups.map(function (group) { var menuItems = groups.map(function (group) {
var name = datetime.getDisplayRunningTime(group.PositionTicks); var name = datetime.getDisplayRunningTime(group.PositionTicks);
if (!inSession) { if (!inSession) {
@ -53,7 +52,7 @@ function showNewJoinGroupSelection(button) {
}; };
}); });
if (inSession) { if (inSession && policy.SyncplayAccess === "CreateAndJoinGroups") {
menuItems.push({ menuItems.push({
name: globalize.translate('LabelSyncplayNewGroup'), name: globalize.translate('LabelSyncplayNewGroup'),
icon: "add", icon: "add",
@ -64,9 +63,15 @@ function showNewJoinGroupSelection(button) {
} }
if (menuItems.length === 0) { if (menuItems.length === 0) {
if (inSession && policy.SyncplayAccess === "JoinGroups") {
toast({
text: globalize.translate('MessageSyncplayPermissionRequired')
});
} else {
toast({ toast({
text: globalize.translate('MessageSyncplayNoGroupsAvailable') text: globalize.translate('MessageSyncplayNoGroupsAvailable')
}); });
}
loading.hide(); loading.hide();
return; return;
} }
@ -92,20 +97,23 @@ function showNewJoinGroupSelection(button) {
loading.hide(); loading.hide();
}); });
}).catch(function (error) { }).catch(function (error) {
loading.hide();
console.error(error); console.error(error);
loading.hide();
toast({
text: globalize.translate('MessageSyncplayNoGroupsAvailable')
});
}); });
} }
/** /**
* Used when user has joined a group. * Used when user has joined a group.
* @param {HTMLElement} button - Element where to place the menu. * @param {HTMLElement} button - Element where to place the menu.
* @param {Object} user - Current user.
* @param {Object} apiClient - ApiClient.
*/ */
function showLeaveGroupSelection(button) { function showLeaveGroupSelection(button, user, apiClient) {
const apiClient = connectionManager.currentApiClient();
const sessionId = getActivePlayerId(); const sessionId = getActivePlayerId();
loading.show();
const menuItems = [{ const menuItems = [{
name: globalize.translate('LabelSyncplayLeaveGroup'), name: globalize.translate('LabelSyncplayLeaveGroup'),
@ -143,9 +151,20 @@ events.on(syncplayManager, 'SyncplayEnabled', function (e, enabled) {
* @param {HTMLElement} button - Element where to place the menu. * @param {HTMLElement} button - Element where to place the menu.
*/ */
export function show(button) { export function show(button) {
if (syncplayEnabled) { loading.show();
showLeaveGroupSelection(button);
} else { const apiClient = connectionManager.currentApiClient();
showNewJoinGroupSelection(button); connectionManager.user(apiClient).then((user) => {
} if (syncplayEnabled) {
showLeaveGroupSelection(button, user, apiClient);
} else {
showNewJoinGroupSelection(button, user, apiClient);
}
}).catch((error) => {
console.error(error);
loading.hide();
toast({
text: globalize.translate('MessageSyncplayNoGroupsAvailable')
});
});
} }

View file

@ -645,7 +645,7 @@ class SyncplayManager {
/** /**
* Converts server time to local time. * Converts server time to local time.
* @param {Date} server * @param {Date} server The time to convert.
* @returns {Date} Local time. * @returns {Date} Local time.
*/ */
serverDateToLocal (server) { serverDateToLocal (server) {
@ -655,7 +655,7 @@ class SyncplayManager {
/** /**
* Converts local time to server time. * Converts local time to server time.
* @param {Date} local * @param {Date} local The time to convert.
* @returns {Date} Server time. * @returns {Date} Server time.
*/ */
localDateToServer (local) { localDateToServer (local) {
@ -665,7 +665,7 @@ class SyncplayManager {
/** /**
* Gets Syncplay status. * Gets Syncplay status.
* @returns {boolean} _true_ is user joined a group, _false_ otherwise. * @returns {boolean} _true_ if user joined a group, _false_ otherwise.
*/ */
isSyncplayEnabled () { isSyncplayEnabled () {
return this.syncplayEnabledAt !== null ? true : false; return this.syncplayEnabledAt !== null ? true : false;

View file

@ -104,6 +104,7 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize', 'fnchecked'], function
$('#chkEnableSharing', page).checked(user.Policy.EnablePublicSharing); $('#chkEnableSharing', page).checked(user.Policy.EnablePublicSharing);
$('#txtRemoteClientBitrateLimit', page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || ''); $('#txtRemoteClientBitrateLimit', page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || '');
$('#txtLoginAttemptsBeforeLockout', page).val(user.Policy.LoginAttemptsBeforeLockout || '0'); $('#txtLoginAttemptsBeforeLockout', page).val(user.Policy.LoginAttemptsBeforeLockout || '0');
$('#selectSyncplayAccess').val(user.Policy.SyncplayAccess);
loading.hide(); loading.hide();
} }
@ -145,6 +146,7 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize', 'fnchecked'], function
}).map(function (c) { }).map(function (c) {
return c.getAttribute('data-id'); return c.getAttribute('data-id');
}); });
user.Policy.SyncplayAccess = page.querySelector('#selectSyncplayAccess').value;
ApiClient.updateUser(user).then(function () { ApiClient.updateUser(user).then(function () {
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
onSaveComplete(page, user); onSaveComplete(page, user);

View file

@ -86,6 +86,12 @@ define(['dom', 'layoutManager', 'inputManager', 'connectionManager', 'events', '
if (!layoutManager.tv) { if (!layoutManager.tv) {
headerCastButton.classList.remove('hide'); headerCastButton.classList.remove('hide');
} }
var policy = user.Policy ? user.Policy : user.localUser.Policy;
if (headerSyncButton && policy && policy.SyncplayAccess !== "None") {
headerSyncButton.classList.remove("hide");
}
} else { } else {
headerHomeButton.classList.add('hide'); headerHomeButton.classList.add('hide');
headerCastButton.classList.add('hide'); headerCastButton.classList.add('hide');
@ -95,8 +101,6 @@ define(['dom', 'layoutManager', 'inputManager', 'connectionManager', 'events', '
} }
} }
headerSyncButton.classList.remove("hide");
requiresUserRefresh = false; requiresUserRefresh = false;
} }

View file

@ -862,6 +862,10 @@
"LabelSyncplayNewGroupDescription": "Create a new group", "LabelSyncplayNewGroupDescription": "Create a new group",
"LabelSyncplayLeaveGroup": "Leave group", "LabelSyncplayLeaveGroup": "Leave group",
"LabelSyncplayLeaveGroupDescription": "Disable Syncplay", "LabelSyncplayLeaveGroupDescription": "Disable Syncplay",
"LabelSyncplayAccessCreateAndJoinGroups": "Allow user to create and join groups",
"LabelSyncplayAccessJoinGroups": "Allow user to join groups",
"LabelSyncplayAccessNone": "Disabled for this user",
"LabelSyncplayAccess": "Syncplay access",
"LabelTVHomeScreen": "TV mode home screen:", "LabelTVHomeScreen": "TV mode home screen:",
"LabelTag": "Tag:", "LabelTag": "Tag:",
"LabelTagline": "Tagline:", "LabelTagline": "Tagline:",
@ -1031,6 +1035,7 @@
"MessageSyncplayUserLeft": "<b>{0}</b> left group.", "MessageSyncplayUserLeft": "<b>{0}</b> left group.",
"MessageSyncplayGroupWait": "<b>{0}</b> is buffering...", "MessageSyncplayGroupWait": "<b>{0}</b> is buffering...",
"MessageSyncplayNoGroupsAvailable": "No groups available.", "MessageSyncplayNoGroupsAvailable": "No groups available.",
"MessageSyncplayPermissionRequired": "Permission required to create a group.",
"Metadata": "Metadata", "Metadata": "Metadata",
"MetadataManager": "Metadata Manager", "MetadataManager": "Metadata Manager",
"MetadataSettingChangeHelp": "Changing metadata settings will affect new content that is added going forward. To refresh existing content, open the detail screen and click the refresh button, or perform bulk refreshes using the metadata manager.", "MetadataSettingChangeHelp": "Changing metadata settings will affect new content that is added going forward. To refresh existing content, open the detail screen and click the refresh button, or perform bulk refreshes using the metadata manager.",
@ -1379,6 +1384,7 @@
"Suggestions": "Suggestions", "Suggestions": "Suggestions",
"Sunday": "Sunday", "Sunday": "Sunday",
"Sync": "Sync", "Sync": "Sync",
"SyncplayAccessHelp": "Select the level of access this user has to the Syncplay feature. Syncplay enables to sync playback with other users.",
"SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
"TV": "TV", "TV": "TV",
"TabAccess": "Access", "TabAccess": "Access",

View file

@ -104,6 +104,16 @@
<div class="fieldDescription">${LabelUserRemoteClientBitrateLimitHelp}</div> <div class="fieldDescription">${LabelUserRemoteClientBitrateLimitHelp}</div>
</div> </div>
</div> </div>
<div class="verticalSection">
<div class="selectContainer fldSelectSyncplayAccess">
<select class="selectSyncplayAccess" is="emby-select" id="selectSyncplayAccess" label="${LabelSyncplayAccess}">
<option value="CreateAndJoinGroups">${LabelSyncplayAccessCreateAndJoinGroups}</option>
<option value="JoinGroups">${LabelSyncplayAccessJoinGroups}</option>
<option value="None">${LabelSyncplayAccessNone}</option>
</select>
<div class="fieldDescription">${SyncplayAccessHelp}</div>
</div>
</div>
<div class="verticalSection"> <div class="verticalSection">
<h2 class="checkboxListLabel" style="margin-bottom:1em;">${HeaderAllowMediaDeletionFrom}</h2> <h2 class="checkboxListLabel" style="margin-bottom:1em;">${HeaderAllowMediaDeletionFrom}</h2>
<div class="checkboxList paperList checkboxList-paperList"> <div class="checkboxList paperList checkboxList-paperList">