get/set solr config

This commit is contained in:
Girish Ramakrishnan
2020-11-19 17:45:16 -08:00
parent cac8659fbd
commit 3125e1b386
5 changed files with 340 additions and 8 deletions

View File

@@ -2240,6 +2240,25 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout
});
};
Client.prototype.getSolrConfig = function (callback) {
var config = {};
get('/api/v1/mailserver/solr_config', config, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null, data);
});
};
Client.prototype.setSolrConfig = function (enabled, callback) {
post('/api/v1/mailserver/solr_config', { enabled: enabled }, null, function (error, data, status) {
if (error) return callback(error);
if (status !== 200) return callback(new ClientError(status, data));
callback(null);
});
};
Client.prototype.getSpamAcl = function (callback) {
var config = {};

View File

@@ -106,7 +106,77 @@
"groups": "Gruppen",
"user": "Benutzer"
},
"newUserAction": "Neuer Benutzer"
"newUserAction": "Neuer Benutzer",
"role": {
"owner": "Superadmin",
"admin": "Administrator",
"usermanager": "User-Manager",
"user": "User"
},
"externalLdapDialog": {
"title": "LDAP konfigurieren"
},
"passwordResetDialog": {
"sendEmailLinkAction": "Link per E-Mail an User senden",
"description": "Link für Passwort wiederherstellen oder {{ username }} erneut einladen:",
"title": "Passwort zurücksetzen oder Einladungslink für {{ username }}"
},
"deleteGroupDialog": {
"deleteAction": "Löschen",
"description": "Diese Gruppe hat immer noch {{ memberCount }} Mitglied(er). Diese Gruppe ist nicht in Verwendung?",
"title": "Gruppe {{ name }} löschen"
},
"editGroupDialog": {
"externalLdapWarning": "Die Gruppe wird in einem externen LDAP-Server verwaltet.",
"title": "Gruppe {{ name }} bearbeiten"
},
"group": {
"addGroupAction": "Gruppe hinzufügen",
"users": "User",
"errorNameTooLong": "Der Name ist zu lang",
"errorNameTooShort": "Der Name ist zu kurz",
"errorNameRequired": "Ein Name ist erforderlich",
"name": "Name"
},
"addGroupDialog": {
"title": "Gruppe hinzufügen"
},
"editUserDialog": {
"externalLdapWarning": "User wird in einem externen LDAP-Server verwaltet.",
"title": "User {{ username }} bearbeiten"
},
"deleteUserDialog": {
"deleteAction": "Löschen",
"description": "Gelöschte User können nicht mehr auf das Dashboard zugreifen und sich nicht in eine der Anwendungen einloggen. Hinweis: Userdaten innerhalb der Anwendungen werden nicht gelöscht.",
"title": "User {{ username }} löschen"
},
"user": {
"activeCheckbox": "User ist aktiv",
"errorDisplayNameRequired": "Der Name ist erforderlich",
"recoveryEmail": "E-Mail-Adresse zur Passwortwiederherstellung",
"primaryEmail": "Primäre E-Mail-Adresse",
"email": "E-Mail-Adresse",
"displayName": "Anzeigename",
"usernamePlaceholder": "Optional. Kann während der Registrierung gewählt werden",
"errorInvalidUsername": "Das ist kein gültiger Username",
"errorInvalidEmail": "Das ist keine gültige E-Mail-Adresse",
"errorEmailRequired": "Eine E-Mail-Adresse ist erforderlich",
"errorNotValidFullName": "Das ist kein gültiger Name",
"noGroups": "Keine Gruppen verfügbar.",
"groups": "Gruppen",
"role": "Rolle",
"username": "Username",
"fullName": "Vollständiger Name"
},
"addUserDialog": {
"addUserAction": "User hinzufügen",
"sendInviteCheckbox": "Einladungsmail jetzt versenden",
"title": "User hinzufügen"
},
"subscriptionDialog": {
"setupAction": "Abonnement einrichten",
"title": "Abonnement notwendig"
}
},
"profile": {
"title": "Profil",
@@ -115,16 +185,90 @@
"useGravatar": "<a target=\"_blank\" href=\"{{ gravatarLink }}\">Gravatar</a> benutzen",
"useCustomPicture": "Eigenes Bild benutzen"
},
"disable2FA": "2FA ausschalten",
"enable2FA": "2FA einschalten",
"disable2FA": {
"disable": "Deaktivieren",
"password": "Passwort",
"title": "Deaktiviere Zwei-Faktor-Authentifizierung"
},
"enable2FA": {
"setup2FA": "Zwei-Faktor-Authentifizierung einrichten",
"enable": "Aktivieren",
"token": "Token",
"authenticatorAppDescription": "Eine der folgenden Tools verwenden, um den Barcode zu scannen: Google Authenticator (<a href=\"{{ googleAuthenticatorPlayStoreLink }}\" target=\"_blank\">Android</a>, <a href=\"{{ googleAuthenticatorITunesLink }}\" target=\"_blank\">iOS</a>), FreeOTP authenticator (<a href=\"{{ freeOTPPlayStoreLink }}\" target=\"_blank\">Android</a>, <a href=\"{{ freeOTPITunesLink }}\" target=\"_blank\">iOS</a>). Vergleichbare TOTP Apps sollten auch funktionieren.",
"description": "Die Benutzung dieser Cloudron-Instanz verlangt von allen Usern eine Zwei-Faktor-Authentifizierung. Hinweis: 2FA aktivieren.",
"title": "Aktiviere Zwei-Faktor-Authentifizierung"
},
"primaryEmail": "Primäre E-Mail-Adresse",
"language": "Sprache",
"changePassword": "Passwort ändern",
"changePassword": {
"errorPasswordInvalid": "Das Passwort muss mindestens 8 und maximal 265 Zeichen haben",
"errorPasswordsDontMatch": "Die Passwörter sind nicht identisch",
"errorPasswordRequired": "Ein Passwort muss angegeben werden",
"newPasswordRepeat": "Neues Passwort wiederholen",
"newPassword": "Neues Passwort",
"currentPassword": "Aktuelles Passwort",
"title": "Passwort ändern"
},
"appPasswords": {
"app": "Applikation",
"name": "Name",
"noPasswordsPlaceholder": "Keine App Passwörter erstellt"
}
"noPasswordsPlaceholder": "Keine App Passwörter erstellt",
"deletePasswordTooltip": "Passwort löschen",
"newPassword": "Neues Passwort",
"description": "App-Passwörter sind eine Sicherheitsmaßnahme zum Schutz des Cloudron-Benutzerkontos. Sobald eingerichtet, kann die Anmeldung (zusätzlich) mit dem Usernamen und dem hier angezeigtem Passwort erfolgen. Hinweis: sinnvoll bei nicht vertrauenswürdigen mobilen Anwendungen oder Desktop-Clients.",
"title": "App-Passworte"
},
"enable2FAAction": "2FA aktivieren",
"disable2FAAction": "2FA deaktivieren",
"changePasswordAction": "Passwort ändern",
"createApiToken": {
"generateToken": "API-Token generieren",
"copyNow": "API-Token kopieren. Hinweis: keine erneute Anzeige des API-Tokens.",
"description": "Neuer API-Token:",
"errorNameRequired": "Ein Name ist erforderlich",
"name": "Name des API-Token",
"title": "API-Token erstellen"
},
"createAppPassword": {
"generatePassword": "Passwort generieren",
"copyNow": "Passwort kopieren. Hinweis: es wird nicht erneut angezeigt.",
"description": "Folgendes Passwort für die App verwenden:",
"app": "App",
"errorNameRequired": "Ein Name ist erforderlich",
"name": "Name des Passwortes",
"title": "App-Passwort erstellen"
},
"changeDisplayName": {
"errorDisplayNameRequired": "Ein gültiger Anzeigename ist erforderlich",
"errorNameInvalid": "Anzeigename ist nicht gültig",
"label": "Anzeigename",
"title": "Anzeigename ändern"
},
"changeFallbackEmail": {
"errorEmailInvalid": "Die E-Mail-Adresse ist nicht gültig",
"errorEmailRequired": "Eine gültige E-Mail-Adresse ist erforderlich",
"title": "E-Mail-Adresse für das Wiederherstellen des Passworts ändern"
},
"changeEmail": {
"errorEmailRequired": "Eine gültige E-Mail-Adresse ist erforderlich",
"errorEmailInvalid": "Die E-Mail-Adresse ist nicht gültig",
"title": "Primäre E-Mail-Adresse ändern"
},
"loginTokens": {
"logoutAll": "Von allen abmelden",
"description": "Es existieren {{ webadminTokenCount}} aktive Web-Token(s) und {{ cliTokenCount }} CLI-Token(s).",
"title": "Anmelde-Tokens"
},
"apiTokens": {
"revokeTokenTooltip": "Token widerrufen",
"noTokensPlaceholder": "Kein API-Token erstellt",
"description": "Persönlichen Zugriffstoken zur Authentifizierung gegenüber der <a target=\"_blank\" href=\"{{ apiDocsLink }}\">Cloudron API</a> verwenden",
"expiresAt": "Verfällt am",
"name": "Name",
"newApiToken": "Neuer API-Token",
"title": "API-Tokens"
},
"passwordRecoveryEmail": "E-Mail-Adresse für Passwort wiederherstellen"
},
"emails": {
"title": "E-Mail"
@@ -145,7 +289,91 @@
"title": "Systeminformationen"
},
"backups": {
"title": "Datensicherung"
"title": "Datensicherung",
"configureBackupStorage": {
"uploadPartSize": "Größe der hochgeladenen Teile",
"memoryLimit": "Speicherlimit",
"advancedSettings": "Erweiterte Einstellungen.",
"encryptionDescription": "Vorsicht: Passphrase an einem sicheren Ort aufbewahren. Cloudron speichert dieses Passwort nicht. Backups können ohne die Passphrase nicht entschlüsselt werden",
"encryptionPassword": "Verschlüsselungspasswort (optional)",
"s3LikeNote": "Alle Regeln für den Ablauf des Lebenszyklus von Objekten entfernen, da dadurch rsync-Backups beschädigt werden.",
"formatChangeNote": "Frühere Backups, die das alte Speicherformat verwenden, müssen manuell entfernt werden.",
"format": "Speicherformat",
"gcsServiceKey": "Service-Kontoschlüssel",
"s3SecretAccessKey": "Geheimer Zugangsschlüssel",
"s3AccessKeyId": "Zugriffsschlüssel-ID",
"region": "Region",
"prefix": "Prefix",
"bucketName": "Name des Bucket",
"acceptSelfSignedCerts": "Selbst signierte Zertifikate akzeptieren",
"s3Endpoint": "Endpunkt",
"hardlinksLabel": "Verwende Hardlinks",
"ext4Label": "Das Backup-Verzeichnis ist eine externe EXT4-Disk",
"localDirectory": "Lokales Backup-Verzeichnis",
"mountPointDescription": "Der Mount-Point muss manuell gesetzt werden. Weitere Informationen in der <a href=\"{{ providerDocsLink }}\" target=\"_blank\">Anleitung</a>.",
"mountPoint": "Mount-Point",
"noopNote": "Diese Option unterbricht die Sicherungs- und Wiederherstellungsfunktionalität von Cloudron und sollte nur zu Testzwecken verwendet werden. Der Server muss in dieser Betriebsart vollständig mit alternativen Mitteln gesichert werden.",
"provider": "Speicher-Anbieter",
"title": "Backup-Speicher konfigurieren"
},
"configureBackupSchedule": {
"retentionPolicy": "Aufbewahrungsrichtlinie",
"hours": "Stunden",
"days": "Tage",
"scheduleDescription": "Tage und Stunden auswählen, an denen Cloudron ein Backup erstellen soll. Der Zeitplan soll sich nicht mit dem <a href=\"/#/settings\">Zeitplan für Aktualisierungen</a> zu überschneiden.",
"schedule": "Zeitplan",
"title": "Sicherungszeitplan und Aufbewahrung konfigurieren"
},
"cleanupBackups": {
"cleanupNow": "Jetzt bereinigen",
"description": "Backups werden täglich automatisch auf der Grundlage der Aufbewahrungsrichtlinie bereinigt. Diese Aktion löst eine sofortige Entfernung der Backups aus.",
"title": "Backups löschen"
},
"backupFailed": {
"title": "Backup erstellen nicht möglich"
},
"backupDetails": {
"list": "Referenz-Backup von {{{ appCount }} Apps",
"format": "Format",
"version": "Version",
"date": "Datum",
"id": "Id",
"title": "Backup-Details"
},
"logs": {
"showLogs": "Logfiles anzeigen",
"description": "Vorsicht: Die Logfiles können sensible Informationen enthalten. Öffentlich erreichbare Webserver sind kein geeigneter Speicherort.",
"title": "Logfiles"
},
"listing": {
"stopTask": "Stop {{ taskType === 'backup' ? 'Backup' : 'Cleanup' }}",
"backupNow": "Backup jetzt erstellen",
"cleanupBackups": "Backups löschen",
"tooltipDownloadBackupConfig": "Backup-Konfiguration herunterladen",
"appCount": "{{ appCount }} Apps",
"noApps": "Keine Apps",
"version": "Version",
"contents": "Inhalt",
"noBackups": "Es wurden noch keine Backups erstellt",
"title": "Liste vorhandener Backups"
},
"schedule": {
"configure": "Konfigurieren",
"retentionPolicy": "Aufbewahrungsrichtlinie",
"schedule": "Zeitplan",
"description": "Cloudron erstellt ein vollständiges Backup des Systems. Es basiert auf dem konfigurierten Intervall und bewahrt die Anzahl der Backups mit der angegebenen Aufbewahrungsrichtlinie auf.",
"title": "Zeitplan und Aufbewahrung"
},
"location": {
"configure": "Konfigurieren",
"format": "Speicherformat",
"endpoint": "Endpunkt",
"location": "Ort",
"provider": "Anbieter",
"disabledList": "Bei folgenden Apps ist das automatische Backup deaktiviert:",
"description": "Cloudron erstellt ein komplettes Systembackup auf dem konfigurierten Standort.",
"title": "Backup-Ort"
}
},
"appstore": {
"title": "App-Store",
@@ -211,5 +439,8 @@
},
"login": {
"password": "Passwort"
},
"welcomeEmail": {
"welcomeTo": "Willkommen auf <%= cloudronName %>!"
}
}

View File

@@ -448,7 +448,10 @@
"maxMailSize": "Maximum email size",
"spamFilter": "Spam filtering",
"spamFilterOverview": "{{ blacklistCount }} address(es) blacklisted.",
"changeDomainProgress": "Changing Email domain:"
"changeDomainProgress": "Changing Email domain:",
"solrFts": "Full Text Search (Solr)",
"solrEnabled": "Enabled",
"solrDisabled": "Disabled"
},
"eventlog": {
"title": "Event Log",
@@ -501,6 +504,11 @@
"mailTo": "Email to",
"mailToPlaceholder": "Email address",
"sendAction": "Send"
},
"solrConfig": {
"title": "Full Text Search (Solr)",
"description": "Solr can be used to provide full-text search in Dovecot. Solr requires a lot of RAM and as such should only be enabled if your server has more than 3GB RAM.",
"enableSolrCheckbox": "Enable Full Text Search using Solr"
}
},
"network": {
@@ -1314,5 +1322,8 @@
"title": "Your Account is ready",
"openDashboardAction": "Open Dashboard"
}
},
"welcomeEmail": {
"welcomeTo": "Welcome to <%= cloudronName %>!"
}
}

View File

@@ -71,6 +71,30 @@
</div>
</div>
<!-- Modal solr config -->
<div class="modal fade" id="solrConfigModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">{{ 'emails.solrConfig.title' | tr }}</h4>
</div>
<div class="modal-body">
<div ng-bind-html=" 'emails.solrConfig.description' | tr "></div>
<br>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="solrConfig.enabled">{{ 'emails.solrConfig.enableSolrCheckbox' | tr }}</input>
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
<button type="button" class="btn btn-success" ng-click="solrConfig.submit()" ng-disabled="solrConfig.enabled === solrConfig.currentConfig.enabled"><i class="fa fa-circle-notch fa-spin" ng-show="maxEmailSize.busy"></i> {{ 'main.dialog.save' | tr }}</button>
</div>
</div>
</div>
</div>
<!-- Modal change spam config -->
<div class="modal fade" id="spamConfigChangeModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
@@ -215,6 +239,14 @@
<div class="col-xs-6 text-right">
<span>{{ 'emails.settings.spamFilterOverview' | tr:{ blacklistCount: spamConfig.acl.blacklist.length } }} <a href="" ng-click="spamConfig.show()"><i class="fa fa-edit text-small"></i></a></span>
</div>
<div class="col-xs-6">
<span class="text-muted">{{ 'emails.settings.solrFts' | tr }}</span>
</div>
<div class="col-xs-6 text-right">
<span ng-show="solrConfig.currentConfig.enabled">{{ 'emails.settings.solrEnabled' | tr }}</span>
<span ng-hide="solrConfig.currentConfig.enabled">{{ 'emails.settings.solrDisabled' | tr }}</span>
<a href="" ng-click="solrConfig.show()"><i class="fa fa-edit text-small"></i></a>
</div>
</div>
<div class="row" ng-show="mailLocation.busy">

View File

@@ -213,6 +213,44 @@ angular.module('Application').controller('EmailsController', ['$scope', '$locati
}
};
$scope.solrConfig = {
busy: false,
error: {},
currentConfig: {},
enabled: false,
refresh: function () {
Client.getSolrConfig(function (error, config) {
if (error) return console.error('Failed to get solr config', error);
$scope.solrConfig.currentConfig = config;
});
},
show: function() {
$scope.solrConfig.busy = false;
$scope.solrConfig.error = null;
$scope.solrConfig.enabled = $scope.solrConfig.currentConfig.enabled;
$('#solrConfigModal').modal('show');
},
submit: function () {
$scope.solrConfig.busy = true;
Client.setSolrConfig($scope.solrConfig.enabled, function (error) {
$scope.solrConfig.busy = false;
if (error) return console.error(error);
$scope.solrConfig.refresh();
$('#solrConfigModal').modal('hide');
});
}
};
$scope.spamConfig = {
busy: false,
error: {},
@@ -361,6 +399,7 @@ angular.module('Application').controller('EmailsController', ['$scope', '$locati
$scope.maxEmailSize.refresh();
$scope.spamConfig.refresh();
$scope.solrConfig.refresh();
});
}