1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Add confirmation for 3rd party repos

Adds a confirmation similar to the one performed during plugin
installation, when adding a 3rd party repository.

The safe domain is hardcoded to be "repo.jellyfin.org" as this is very
stable and we have no plans to change it. Individual mirrors don't need
to be specified since this is user-input content and they should be
using the main URL not the URL of a specific mirror.

The confirmation message makes explicit mention of the possibility of
malicious code from 3rd party repositories as well as updates that may
bring it in, and suggests only adding 3rd parties from trusted people.

The plugin install confirmation is also modified to use the same
conditional and an altered message similar to the above, again to
emphasize the potential security risks of 3rd party plugins.

Finally, some additional information is added to the Developer Info
section of the plugin page; specifically, the name of the repository the
plugin is sourced from as well as its URL. How this is obtained is a
hack, since these should probably be part of the main information about
the plugin and not each specific version, but this is worked around by
only showing the information from the first (i.e. newest) version.
This commit is contained in:
Joshua M. Boniface 2023-05-29 10:57:17 -04:00
parent 62246fe0a9
commit 509cbabedb
4 changed files with 48 additions and 10 deletions

View file

@ -34,7 +34,9 @@
<div class="readOnlyContent">
<div is="emby-collapse" title="${HeaderDeveloperInfo}">
<div class="collapseContent">
<p id="developer"></p>
<p>Developer: <span id="developer"></span></p>
<p>Repository Name: <span id="repositoryName"></span></p>
<p>Repository URL: <span id="repositoryUrl"</span></p>
</div>
</div>

View file

@ -50,6 +50,8 @@ function renderPackage(pkg, installedPlugins, page) {
return ip.Name == pkg.name;
})[0];
console.log(pkg)
populateVersions(pkg, page, installedPlugin);
populateHistory(pkg, page);
@ -65,6 +67,11 @@ function renderPackage(pkg, installedPlugins, page) {
$('#description', page).text(pkg.description);
$('#developer', page).text(pkg.owner);
// This is a hack; the repository name and URL should be part of the global values
// for the plugin, not each individual version. So we just use the top (latest)
// version to get this information.
$('#repositoryName', page).text(pkg.versions[0].repositoryName);
$('#repositoryUrl', page).text(pkg.versions[0].repositoryUrl);
if (installedPlugin) {
const currentVersionText = globalize.translate('MessageYouHaveVersionInstalled', '<strong>' + installedPlugin.Version + '</strong>');
@ -82,6 +89,7 @@ function alertText(options) {
function performInstallation(page, name, guid, version) {
const developer = $('#developer', page).html().toLowerCase();
const repository_url = $('#repositoryUrl', page).html().toLowerCase();
const alertCallback = function () {
loading.show();
@ -94,7 +102,9 @@ function performInstallation(page, name, guid, version) {
});
};
if (developer !== 'jellyfin') {
// Check the repository URL for the official Jellyfin repository domain, or
// present the warning for 3rd party plugins.
if (!repository_url.startsWith("https://repo.jellyfin.org/")) {
loading.hide();
let msg = globalize.translate('MessagePluginInstallDisclaimer');
msg += '<br/>';

View file

@ -2,6 +2,7 @@ import loading from '../../../../components/loading/loading';
import libraryMenu from '../../../../scripts/libraryMenu';
import globalize from '../../../../scripts/globalize';
import dialogHelper from '../../../../components/dialogHelper/dialogHelper';
import confirm from '../../../../components/confirm/confirm';
import '../../../../elements/emby-button/emby-button';
import '../../../../elements/emby-checkbox/emby-checkbox';
@ -166,14 +167,36 @@ export default function(view) {
dialog.querySelector('.newPluginForm').addEventListener('submit', e => {
e.preventDefault();
repositories.push({
Name: dialog.querySelector('#txtRepositoryName').value,
Url: dialog.querySelector('#txtRepositoryUrl').value,
Enabled: true
});
const repository_url = dialog.querySelector('#txtRepositoryUrl').value.toLowerCase();
const alertCallback = function () {
repositories.push({
Name: dialog.querySelector('#txtRepositoryName').value,
Url: dialog.querySelector('#txtRepositoryUrl').value,
Enabled: true
});
saveList(view);
dialogHelper.close(dialog);
};
// Check the repository URL for the official Jellyfin repository domain, or
// present the warning for 3rd party plugins.
if (!repository_url.startsWith("https://repo.jellyfin.org/")) {
let msg = globalize.translate('MessageRepositoryInstallDisclaimer');
msg += '<br/>';
msg += '<br/>';
msg += globalize.translate('PleaseConfirmRepositoryInstallation');
confirm(msg, globalize.translate('HeaderConfirmRepositoryInstallation')).then(function () {
alertCallback();
}).catch(() => {
console.debug('repository not installed');
dialogHelper.close(dialog);
});
} else {
alertCallback();
}
saveList(view);
dialogHelper.close(dialog);
return false;
});

View file

@ -333,6 +333,7 @@
"HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct playback.",
"HeaderConfigureRemoteAccess": "Set up Remote Access",
"HeaderConfirmPluginInstallation": "Confirm Plugin Installation",
"HeaderConfirmRepositoryInstallation": "Confirm Plugin Repository Installation",
"HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
"HeaderConfirmRevokeApiKey": "Revoke API Key",
"HeaderConnectionFailure": "Connection Failure",
@ -1078,10 +1079,11 @@
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"MessagePleaseWait": "Please wait. This may take a minute.",
"MessagePluginConfigurationRequiresLocalAccess": "To set up this plugin please sign in to your local server directly.",
"MessagePluginInstallDisclaimer": "Plugins built by community members are a great way to enhance your experience with additional features and benefits. Before installing, please be aware of the effects they may have on your server, such as longer library scans, additional background processing, and decreased system stability.",
"MessagePluginInstallDisclaimer": "WARNING: Installing a third party plugin carries risks. It may contain unstable or malicious code, and may change at any time. Only install plugins from authors that you trust, and please be aware of the potential effects it may have, including external service queries, longer library scans, or additional background processing.",
"MessagePluginInstalled": "The plugin has been successfully installed. The server will need to be restarted for changes to take effect.",
"MessagePluginInstallError": "An error occurred while installing the plugin.",
"MessageReenableUser": "See below to reenable",
"MessageRepositoryInstallDisclaimer": "WARNING: Installing a third party plugin repository carries risks. It may contain unstable or malicious code, and may change at any time. Only install repositories from authors that you trust.",
"MessageSent": "Message sent.",
"MessageSyncPlayCreateGroupDenied": "Permission required to create a group.",
"MessageSyncPlayDisabled": "SyncPlay disabled.",
@ -1296,6 +1298,7 @@
"PlayNextEpisodeAutomatically": "Play next episode automatically",
"PleaseAddAtLeastOneFolder": "Please add at least one folder to this library by clicking the '+' button in 'Folders' section.",
"PleaseConfirmPluginInstallation": "Please click OK to confirm you've read the above and wish to proceed with the plugin installation.",
"PleaseConfirmRepositoryInstallation": "Please click OK to confirm you've read the above and wish to proceed with the plugin repository installation.",
"PleaseEnterNameOrId": "Please enter a name or an external ID.",
"PleaseRestartServerName": "Please restart Jellyfin on {0}.",
"PleaseSelectTwoItems": "Please select at least two items.",