jellyfin-plugin-keycloak-auth/Jellyfin.Plugin.Keycloak/Configuration/configPage.html
2025-03-31 00:08:54 +02:00

198 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Keycloak</title>
</head>
<body>
<div id="TemplateConfigPage" data-role="page" class="page type-interior pluginConfigurationPage" data-require="emby-input,emby-button,emby-select,emby-checkbox">
<div data-role="content">
<div class="content-primary">
<h1>Keycloak Authentication</h1>
<form id="TemplateConfigForm">
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="Enabled" name="TrueFalseCheckBox" type="checkbox" is="emby-checkbox"/>
<span>Enable Keycloak authentication</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="CreateUser" name="TrueFalseCheckBox" type="checkbox" is="emby-checkbox"/>
<span>Create Keycloak user if it does not exist</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="Enable2Fa" name="TrueFalseCheckBox" type="checkbox" is="emby-checkbox"/>
<span>Enable Two-factor authentication</span>
</label>
<div class="fieldDescription">You need to add the TOTP (6 digits) to the password when logging in</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="AuthServerUrl">Keycloak server URL</label>
<input id="AuthServerUrl" name="AuthServerUrl" type="text" is="emby-input"/>
</div>
<div class="inputContainer">
<label class="inputeLabel inputLabelUnfocused" for="Realm">Keycloak Realm</label>
<input id="Realm" name="AString" type="text" is="emby-input"/>
</div>
<div class="inputContainer">
<label class="inputeLabel inputLabelUnfocused" for="ClientId">Client ID</label>
<input id="ClientId" name="AString" type="text" is="emby-input"/>
</div>
<div class="inputContainer">
<label class="inputeLabel inputLabelUnfocused" for="ClientSecret">Client Secret</label>
<input id="ClientSecret" name="AString" type="text" is="emby-input"/>
</div>
<div class="inputContainer">
<label class="inputeLabel inputLabelUnfocused" for="OAuthScope"> OAuth Scope</label>
<input id="OAuthScope" name="AString" type="text" is="emby-input"/>
</div>
<div class="inputContainer">
<label class="inputeLabel inputLabelUnfocused" for="RolesTokenAttribute"> Roles token attribute</label>
<input id="RolesTokenAttribute" name="AString" type="text" is="emby-input"/>
<div class="fieldDescription">Access token attribute with the list of roles. Seperate keys with a '.' if the role list is part of a nested object.</div>
</div>
<div class="inputContainer">
<label class="inputeLabel inputLabelUnfocused" for="UsernameTokenAttribute"> Username token attribute</label>
<input id="UsernameTokenAttribute" name="AString" type="text" is="emby-input"/>
<div class="fieldDescription">Access token attribute with the username</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="AllowUsersWithoutRole" name="TrueFalseCheckBox" type="checkbox" is="emby-checkbox"/>
<span>Allow users without a role to log in</span>
</label>
</div>
<label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" id="EnableAllFolders" />
<span>Enable access to all libraries</span>
</label>
<div class="folderAccessListContainer">
<div id="FolderAccessList"></div>
<div class="fieldDescription">Enable access to certain libraries by default</div>
<div class="fieldDescription">Add library access to certain users by giving them the 'lib-&lt;ID&gt;' role</div>
<p class="fieldDescription" id="LibraryIdTable"></p>
</div>
<div>
<button is="emby-button" type="submit" class="raised button-submit block emby-button">
<span>Save</span>
</button>
</div>
</form>
</div>
</div>
<script type="text/javascript">
var KeycloakPluginConfig = {
pluginUniqueId: '40886866-b3dd-4d6a-bf9b-25c83e6c3d10',
chkEnabled: document.querySelector('#Enabled'),
chkCreateUser: document.querySelector('#CreateUser'),
txtAuthServerUrl: document.querySelector('#AuthServerUrl'),
txtRealm: document.querySelector('#Realm'),
txtClientId: document.querySelector('#ClientId'),
txtClientSecret: document.querySelector('#ClientSecret'),
txtOAuthScope: document.querySelector('#OAuthScope'),
txtRolesTokenAttribute: document.querySelector('#RolesTokenAttribute'),
txtUsernameTokenAttribute: document.querySelector('#UsernameTokenAttribute'),
chkEnable2Fa: document.querySelector('#Enable2Fa'),
chkAllowUsersWithoutRole: document.querySelector('#AllowUsersWithoutRole'),
chkEnableAllFolders: document.querySelector('#EnableAllFolders'),
libraryIdTable: document.querySelector("#LibraryIdTable"),
folderAccessList: document.querySelector("#FolderAccessList"),
};
document.querySelector('#TemplateConfigPage')
.addEventListener('pageshow', function () {
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(KeycloakPluginConfig.pluginUniqueId).then(function (config) {
KeycloakPluginConfig.chkEnabled.checked = config.Enabled;
KeycloakPluginConfig.chkCreateUser.checked = config.CreateUser;
KeycloakPluginConfig.txtAuthServerUrl.value = config.AuthServerUrl;
KeycloakPluginConfig.txtRealm.value = config.Realm;
KeycloakPluginConfig.txtClientId.value = config.ClientId;
KeycloakPluginConfig.txtClientSecret.value = config.ClientSecret;
KeycloakPluginConfig.txtOAuthScope.value = config.OAuthScope;
KeycloakPluginConfig.txtRolesTokenAttribute.value = config.RolesTokenAttribute;
KeycloakPluginConfig.txtUsernameTokenAttribute.value = config.UsernameTokenAttribute;
KeycloakPluginConfig.chkEnable2Fa.checked = config.Enable2Fa;
KeycloakPluginConfig.chkEnableAllFolders.checked = config.EnableAllFolders;
KeycloakPluginConfig.chkAllowUsersWithoutRole.checked = config.AllowUsersWithoutRole;
loadMediaFolders(config).then(() => {
Dashboard.hideLoadingMsg();
});
});
});
document.querySelector('#TemplateConfigForm')
.addEventListener('submit', function (e) {
e.preventDefault();
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(KeycloakPluginConfig.pluginUniqueId).then(function (config) {
config.Enabled = KeycloakPluginConfig.chkEnabled.checked;
config.CreateUser = KeycloakPluginConfig.chkCreateUser.checked;
config.AuthServerUrl = KeycloakPluginConfig.txtAuthServerUrl.value;
config.Realm = KeycloakPluginConfig.txtRealm.value;
config.ClientId = KeycloakPluginConfig.txtClientId.value;
config.ClientSecret = KeycloakPluginConfig.txtClientSecret.value;
config.OAuthScope = KeycloakPluginConfig.txtOAuthScope.value;
config.RolesTokenAttribute = KeycloakPluginConfig.txtRolesTokenAttribute.value;
config.UsernameTokenAttribute = KeycloakPluginConfig.txtUsernameTokenAttribute.value;
config.Enable2Fa = KeycloakPluginConfig.chkEnable2Fa.checked;
config.EnableAllFolders = KeycloakPluginConfig.chkEnableAllFolders.checked;
config.AllowUsersWithoutRole = KeycloakPluginConfig.chkAllowUsersWithoutRole.checked;
let folders = document.querySelectorAll('#folderList input');
folders = Array.prototype.filter.call(folders, folder => folder.checked)
.map(folder => folder.getAttribute("data-id"));
config.EnabledFolders = folders;
ApiClient.updatePluginConfiguration(KeycloakPluginConfig.pluginUniqueId, config).then(function (result) {
Dashboard.processPluginConfigurationUpdateResult(result);
});
});
return false;
});
function escapeHTML(str){
return new Option(str).innerHTML;
}
function loadMediaFolders(config) {
return ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { IsHidden: false })).then((mediaFolders) => {
let html = "";
html += '<h3 class="checkboxListLabel">${HeaderLibraries}</h3>';
html +=
'<div id="folderList" class="checkboxList paperList checkboxList-paperList">';
let tableHtml = "<table><tbody>\n";
if (Array.isArray(mediaFolders.Items)) {
mediaFolders.Items.forEach((folder) => {
const isChecked =
config.EnableAllFolders ||
config.EnabledFolders.indexOf(folder.Id) != -1;
const checkedAttribute = isChecked ? " checked" : "";
html +=
'<label class="emby-checkbox-label"><input type="checkbox" is="emby-checkbox" class="chkFolder emby-checkbox" data-id="' +
folder.Id +
'" ' +
checkedAttribute +
"><span>" +
escapeHTML(folder.Name) +
"</span></label>";
tableHtml += "<tr><td><b>" + escapeHTML(folder.Name) + "</b></td><td><code>lib-" + folder.Id + "</code></td></tr>\n";
});
}
html += "</div>";
tableHtml += "</tbody></table>";
KeycloakPluginConfig.folderAccessList.innerHTML = html;
KeycloakPluginConfig.libraryIdTable.innerHTML = tableHtml;
});
}
</script>
</div>
</body>
</html>