From 8271fb714ccfc82538c873e88b62c8141755ba90 Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Fri, 24 Jan 2025 14:59:36 +0100 Subject: [PATCH 01/23] Add Web of Trust Section --- frontend/src/common/backend.ts | 4 + frontend/src/components/AdminSettings.vue | 162 ++++++++++++++++++++-- frontend/src/i18n/de-DE.json | 7 + frontend/src/i18n/en-US.json | 9 +- 4 files changed, 169 insertions(+), 13 deletions(-) diff --git a/frontend/src/common/backend.ts b/frontend/src/common/backend.ts index 47cbc11f..28413d3f 100644 --- a/frontend/src/common/backend.ts +++ b/frontend/src/common/backend.ts @@ -366,6 +366,10 @@ class SettingsService { public async get(): Promise { return axiosAuth.get('/settings').then(response => response.data); } + + public async put(settings: SettingsDto): Promise { + return axiosAuth.put('/settings', settings); + } } /** diff --git a/frontend/src/components/AdminSettings.vue b/frontend/src/components/AdminSettings.vue index cf264f5f..63ce9f1b 100644 --- a/frontend/src/components/AdminSettings.vue +++ b/frontend/src/components/AdminSettings.vue @@ -121,17 +121,32 @@ {{ t('admin.licenseInfo.expiresAt.description.expired') }}

+ +
+ + +

+ {{ t('admin.webOfTrust.trustLevel.error') }} +

+
+ +
+ + +

+ {{ t('admin.webOfTrust.maxChainLength.error') }} +

+
+ +
+ +
- -
- -
@@ -170,16 +185,66 @@ {{ t('admin.licenseInfo.seats.description.undercutSeats', [numberOfExceededSeats]) }}

+ +
+ +
-
- +
+
+
+

+ {{ t('admin.webOfTrust.title') }} +

+

+ {{ t('admin.webOfTrust.description') }} +

+
+
+
+
+ + +

+ {{ t('admin.webOfTrust.trustLevel.error') }} +

+
+ +
+ + +

+ {{ t('admin.webOfTrust.maxChainLength.error') }} +

+
+ +
+
+

{{ t('common.unexpectedError', [onSaveError.message]) }}

+
+ +
+
+
+
@@ -209,6 +274,13 @@ const now = ref(new Date()); const keycloakAdminRealmURL = ref(); const onFetchError = ref(); const errorOnFetchingUpdates = ref(false); +const trustLevel = ref(0); +const maxChainLength = ref(0); + +// Add validation refs +const trustLevelError = ref(false); +const maxChainLengthError = ref(false); +const showErrors = ref(false); // New ref to control error display const isBeta = computed(() => { if (version.value && semver.valid(version.value.hubVersion)) { @@ -261,6 +333,11 @@ async function fetchData() { admin.value = await backend.billing.get(); version.value = await versionDto; latestVersion.value = await versionAvailable; + + // Get the settings and set the values + const settings = await backend.settings.get(); + trustLevel.value = settings.wotMaxDepth; + maxChainLength.value = settings.wotIdVerifyLen; } catch (error) { if (error instanceof FetchUpdateError) { errorOnFetchingUpdates.value = true; @@ -278,4 +355,65 @@ function manageSubscription() { const languagePathComponent = supportedLanguagePathComponents[(locale.value as string).split('-')[0]] ?? supportedLanguagePathComponents[fallbackLocale.value as string] ?? ''; window.open(`https://cryptomator.org/${languagePathComponent}hub/billing/?hub_id=${admin.value?.hubId}&return_url=${encodeURIComponent(returnUrl)}`, '_self'); } + +// Add validation functions +function validateTrustLevel(value: number) { + return value < 0 || value > 10; +} + +function validateMaxChainLength(value: number) { + return value < 0; +} + +class FormValidationFailedError extends Error { + constructor() { + super('The form is invalid.'); + } +} + +const form = ref(); +const onSaveError = ref(null); +const processing = ref(false); + +async function saveWebOfTrust() { + onSaveError.value = null; + trustLevelError.value = false; + maxChainLengthError.value = false; + + // Validate inputs separately + let hasError = false; + + if (Number(trustLevel.value) < 0 || Number(trustLevel.value) > 10) { + trustLevelError.value = true; + hasError = true; + } + + if (Number(maxChainLength.value) < 0) { + maxChainLengthError.value = true; + hasError = true; + } + + if (hasError) { + return; + } + + try { + processing.value = true; + const settings = { + wotMaxDepth: trustLevel.value, + wotIdVerifyLen: maxChainLength.value, + hubId: '' //TODO: Fix + }; + await backend.settings.put(settings); + } catch (error) { + console.error('Failed to save settings:', error); + onSaveError.value = error instanceof Error ? error : new Error('Unknown reason'); + } finally { + processing.value = false; + } +} + +async function getLicense() { + await manageSubscription(); +} diff --git a/frontend/src/i18n/de-DE.json b/frontend/src/i18n/de-DE.json index 6b0115ba..d6b2b46b 100644 --- a/frontend/src/i18n/de-DE.json +++ b/frontend/src/i18n/de-DE.json @@ -51,6 +51,13 @@ "admin.licenseInfo.getLicense": "Lizenz erhalten", "admin.licenseInfo.selfHostedNoLicense.description": "Vielen Dank, dass du Cryptomator Hub nutzt! Du hast die Community-Lizenz erhalten. Wenn du mehr Sitze benötigst, erweiter deine Lizenz.", "admin.licenseInfo.managedNoLicense.description": "Vielen Dank, dass du Cryptomator Hub nutzt! Du hast aktuell keine aktive Lizenz.", + "admin.webOfTrust.title": "Web of Trust", + "admin.webOfTrust.description": "Konfigurieren Sie die Web of Trust-Einstellungen, um zu verwalten, wie Vertrauen zwischen Benutzern im System aufgebaut wird. Diese Einstellungen beeinflussen die Überprüfung von Benutzeridentitäten und Schlüssel-Signaturen.", + "admin.webOfTrust.trustLevel.error": "Das Vertrauensniveau muss zwischen 0 und 10 liegen.", + "admin.webOfTrust.trustLevel.title": "Vertrauensniveau", + "admin.webOfTrust.maxChainLength.error": "Die maximale Kettenlänge muss größer als 0 sein.", + "admin.webOfTrust.maxChainLength.title": "Maximale Kettenlänge", + "admin.webOfTrust.save": "Speichern", "archiveVaultDialog.title": "Tresor archivieren", "archiveVaultDialog.description": "Das Archivieren eines Tresors macht ihn inaktiv. Dadurch können belegte Sitze frei werden. Ein archivierter Tresor kann später wieder aktiviert werden.", diff --git a/frontend/src/i18n/en-US.json b/frontend/src/i18n/en-US.json index 768294af..009b24a8 100644 --- a/frontend/src/i18n/en-US.json +++ b/frontend/src/i18n/en-US.json @@ -51,7 +51,14 @@ "admin.licenseInfo.getLicense": "Get License", "admin.licenseInfo.selfHostedNoLicense.description": "Thank you for using Cryptomator Hub! You have been granted the Community License. If you need more seats, upgrade your license.", "admin.licenseInfo.managedNoLicense.description": "Thank you for using Cryptomator Hub! You currently have no active license.", - + "admin.webOfTrust.title": "Web of Trust", + "admin.webOfTrust.description": "Configure the Web of Trust settings to manage how trust is established between users in the system. These settings affect the verification of user identities and key signatures.", + "admin.webOfTrust.trustLevel.error": "Trust level must be between 0 and 10.", + "admin.webOfTrust.trustLevel.title": "Trust Level", + "admin.webOfTrust.maxChainLength.error": "Maximum chain length must be greater than 0.", + "admin.webOfTrust.maxChainLength.title": "Maximum Chain Length", + "admin.webOfTrust.save": "Save", + "archiveVaultDialog.title": "Archive Vault", "archiveVaultDialog.description": "Archiving a vault makes it inactive. This may free up occupied seats. An archived vault can be reactivated later.", "archiveVaultDialog.confirm": "Archive", From 209eeb2c59b1a549bfaac55d0d143ddd8ed74d9c Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Sat, 25 Jan 2025 12:43:30 +0100 Subject: [PATCH 02/23] simplify logic for the save button --- frontend/src/components/AdminSettings.vue | 30 +++++------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/AdminSettings.vue b/frontend/src/components/AdminSettings.vue index 63ce9f1b..d80207fb 100644 --- a/frontend/src/components/AdminSettings.vue +++ b/frontend/src/components/AdminSettings.vue @@ -233,12 +233,7 @@

{{ t('common.unexpectedError', [onSaveError.message]) }}

- @@ -377,34 +372,21 @@ const processing = ref(false); async function saveWebOfTrust() { onSaveError.value = null; - trustLevelError.value = false; - maxChainLengthError.value = false; - - // Validate inputs separately - let hasError = false; - - if (Number(trustLevel.value) < 0 || Number(trustLevel.value) > 10) { - trustLevelError.value = true; - hasError = true; - } - - if (Number(maxChainLength.value) < 0) { - maxChainLengthError.value = true; - hasError = true; - } + trustLevelError.value = trustLevel.value < 0 || trustLevel.value > 10; + maxChainLengthError.value = maxChainLength.value < 0; - if (hasError) { + if (trustLevelError.value || maxChainLengthError.value) { return; } - try { processing.value = true; const settings = { wotMaxDepth: trustLevel.value, wotIdVerifyLen: maxChainLength.value, - hubId: '' //TODO: Fix + hubId: admin.value?.hubId ?? '' }; await backend.settings.put(settings); + await new Promise(resolve => setTimeout(resolve, 500)); } catch (error) { console.error('Failed to save settings:', error); onSaveError.value = error instanceof Error ? error : new Error('Unknown reason'); From 475b2e8a3910904770c3512190c91920319aac49 Mon Sep 17 00:00:00 2001 From: Julian Raufelder Date: Mon, 27 Jan 2025 16:57:26 +0100 Subject: [PATCH 03/23] Add Audit event setting WoT added in backend Co-authored-by: iammajid --- .../cryptomator/hub/api/AuditLogResource.java | 6 ++ .../cryptomator/hub/api/SettingsResource.java | 13 ++++ .../hub/entities/events/EventLogger.java | 9 +++ .../events/SettingWotUpdateEvent.java | 63 +++++++++++++++++++ .../V17__Create_Audit_Event_Setting_WoT.sql | 9 +++ 5 files changed, 100 insertions(+) create mode 100644 backend/src/main/java/org/cryptomator/hub/entities/events/SettingWotUpdateEvent.java create mode 100644 backend/src/main/resources/org/cryptomator/hub/flyway/V17__Create_Audit_Event_Setting_WoT.sql diff --git a/backend/src/main/java/org/cryptomator/hub/api/AuditLogResource.java b/backend/src/main/java/org/cryptomator/hub/api/AuditLogResource.java index 0d9afd5c..e8e4c22a 100644 --- a/backend/src/main/java/org/cryptomator/hub/api/AuditLogResource.java +++ b/backend/src/main/java/org/cryptomator/hub/api/AuditLogResource.java @@ -17,6 +17,7 @@ import org.cryptomator.hub.entities.events.AuditEvent; import org.cryptomator.hub.entities.events.DeviceRegisteredEvent; import org.cryptomator.hub.entities.events.DeviceRemovedEvent; +import org.cryptomator.hub.entities.events.SettingWotUpdateEvent; import org.cryptomator.hub.entities.events.SignedWotIdEvent; import org.cryptomator.hub.entities.events.VaultAccessGrantedEvent; import org.cryptomator.hub.entities.events.VaultCreatedEvent; @@ -81,6 +82,7 @@ public List getAllEvents(@QueryParam("startDate") Instant startDa @JsonSubTypes({ // @JsonSubTypes.Type(value = DeviceRegisteredEventDto.class, name = DeviceRegisteredEvent.TYPE), // @JsonSubTypes.Type(value = DeviceRemovedEventDto.class, name = DeviceRemovedEvent.TYPE), // + @JsonSubTypes.Type(value = SettingWotUpdateEvent.class, name = SettingWotUpdateEvent.TYPE), // @JsonSubTypes.Type(value = SignedWotIdEvent.class, name = SignedWotIdEvent.TYPE), // @JsonSubTypes.Type(value = VaultCreatedEventDto.class, name = VaultCreatedEvent.TYPE), // @JsonSubTypes.Type(value = VaultUpdatedEventDto.class, name = VaultUpdatedEvent.TYPE), // @@ -104,6 +106,7 @@ static AuditEventDto fromEntity(AuditEvent entity) { case DeviceRegisteredEvent evt -> new DeviceRegisteredEventDto(evt.getId(), evt.getTimestamp(), DeviceRegisteredEvent.TYPE, evt.getRegisteredBy(), evt.getDeviceId(), evt.getDeviceName(), evt.getDeviceType()); case DeviceRemovedEvent evt -> new DeviceRemovedEventDto(evt.getId(), evt.getTimestamp(), DeviceRemovedEvent.TYPE, evt.getRemovedBy(), evt.getDeviceId()); case SignedWotIdEvent evt -> new SignedWotIdEventDto(evt.getId(), evt.getTimestamp(), SignedWotIdEvent.TYPE, evt.getUserId(), evt.getSignerId(), evt.getSignerKey(), evt.getSignature()); + case SettingWotUpdateEvent evt -> new SettingWotUpdateDto(evt.getId(), evt.getTimestamp(), SettingWotUpdateEvent.TYPE, evt.getUpdatedBy(), evt.getWotMaxDepth(), evt.getWotIdVerifyLen()); case VaultCreatedEvent evt -> new VaultCreatedEventDto(evt.getId(), evt.getTimestamp(), VaultCreatedEvent.TYPE, evt.getCreatedBy(), evt.getVaultId(), evt.getVaultName(), evt.getVaultDescription()); case VaultUpdatedEvent evt -> new VaultUpdatedEventDto(evt.getId(), evt.getTimestamp(), VaultUpdatedEvent.TYPE, evt.getUpdatedBy(), evt.getVaultId(), evt.getVaultName(), evt.getVaultDescription(), evt.isVaultArchived()); case VaultAccessGrantedEvent evt -> new VaultAccessGrantedEventDto(evt.getId(), evt.getTimestamp(), VaultAccessGrantedEvent.TYPE, evt.getGrantedBy(), evt.getVaultId(), evt.getAuthorityId()); @@ -127,6 +130,9 @@ record DeviceRemovedEventDto(long id, Instant timestamp, String type, @JsonPrope record SignedWotIdEventDto(long id, Instant timestamp, String type, @JsonProperty("userId") String userId, @JsonProperty("signerId") String signerId, @JsonProperty("signerKey") String signerKey, @JsonProperty("signature") String signature) implements AuditEventDto { } + record SettingWotUpdateDto(long id, Instant timestamp, String type, @JsonProperty("updatedBy") String updatedBy, @JsonProperty("wotMaxDepth") int wotMaxDepth, @JsonProperty("wotIdVerifyLen") int wotIdVerifyLen) implements AuditEventDto { + } + record VaultCreatedEventDto(long id, Instant timestamp, String type, @JsonProperty("createdBy") String createdBy, @JsonProperty("vaultId") UUID vaultId, @JsonProperty("vaultName") String vaultName, @JsonProperty("vaultDescription") String vaultDescription) implements AuditEventDto { } diff --git a/backend/src/main/java/org/cryptomator/hub/api/SettingsResource.java b/backend/src/main/java/org/cryptomator/hub/api/SettingsResource.java index 2e5735c0..4e728180 100644 --- a/backend/src/main/java/org/cryptomator/hub/api/SettingsResource.java +++ b/backend/src/main/java/org/cryptomator/hub/api/SettingsResource.java @@ -16,15 +16,23 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.cryptomator.hub.entities.Settings; +import org.cryptomator.hub.entities.events.EventLogger; +import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @Path("/settings") public class SettingsResource { + @Inject + EventLogger eventLogger; + @Inject Settings.Repository settingsRepo; + @Inject + JsonWebToken jwt; + @GET @RolesAllowed("user") @Produces(MediaType.APPLICATION_JSON) @@ -45,9 +53,14 @@ public SettingsDto get() { @Transactional public Response put(@NotNull @Valid SettingsDto dto) { var settings = settingsRepo.get(); + var oldWotIdVerifyLen = settings.getWotIdVerifyLen(); + var oldWotMaxDepth = settings.getWotMaxDepth(); settings.setWotMaxDepth(dto.wotMaxDepth); settings.setWotIdVerifyLen(dto.wotIdVerifyLen); settingsRepo.persist(settings); + if (oldWotMaxDepth != dto.wotMaxDepth || oldWotIdVerifyLen != dto.wotIdVerifyLen) { + eventLogger.logWotSettingUpdated(jwt.getSubject(), dto.wotIdVerifyLen, dto.wotMaxDepth); + } return Response.status(Response.Status.NO_CONTENT).build(); } diff --git a/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java b/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java index d4cee866..f0501e9b 100644 --- a/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java +++ b/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java @@ -100,6 +100,15 @@ public void logVaultMemberUpdated(String updatedBy, UUID vaultId, String authori auditEventRepository.persist(event); } + public void logWotSettingUpdated(String userId, int wotIdVerifyLen, int wotMaxDepth) { + var event = new SettingWotUpdateEvent(); + event.setTimestamp(Instant.now()); + event.setWotIdVerifyLen(wotIdVerifyLen); + event.setWotMaxDepth(wotMaxDepth); + event.setUpdatedBy(userId); + auditEventRepository.persist(event); + } + public void logWotIdSigned(String userId, String signerId, String signerKey, String signature) { var event = new SignedWotIdEvent(); event.setTimestamp(Instant.now()); diff --git a/backend/src/main/java/org/cryptomator/hub/entities/events/SettingWotUpdateEvent.java b/backend/src/main/java/org/cryptomator/hub/entities/events/SettingWotUpdateEvent.java new file mode 100644 index 00000000..545fbf88 --- /dev/null +++ b/backend/src/main/java/org/cryptomator/hub/entities/events/SettingWotUpdateEvent.java @@ -0,0 +1,63 @@ +package org.cryptomator.hub.entities.events; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import java.time.Instant; +import java.util.Objects; + +@Entity +@Table(name = "audit_event_setting_wot_update") +@DiscriminatorValue(SettingWotUpdateEvent.TYPE) +public class SettingWotUpdateEvent extends AuditEvent { + + public static final String TYPE = "SETTING_WOT_UPDATE"; + + @Column(name = "updated_by") + private String updatedBy; + + @Column(name = "wot_max_depth") + private int wotMaxDepth; + + @Column(name = "wot_id_verify_len") + private int wotIdVerifyLen; + + public String getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + public int getWotMaxDepth() { + return wotMaxDepth; + } + + public void setWotMaxDepth(int wotMaxDepth) { + this.wotMaxDepth = wotMaxDepth; + } + + public int getWotIdVerifyLen() { + return wotIdVerifyLen; + } + + public void setWotIdVerifyLen(int wotIdVerifyLen) { + this.wotIdVerifyLen = wotIdVerifyLen; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + SettingWotUpdateEvent that = (SettingWotUpdateEvent) o; + return wotMaxDepth == that.wotMaxDepth && wotIdVerifyLen == that.wotIdVerifyLen && Objects.equals(updatedBy, that.updatedBy); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), updatedBy, wotMaxDepth, wotIdVerifyLen); + } +} diff --git a/backend/src/main/resources/org/cryptomator/hub/flyway/V17__Create_Audit_Event_Setting_WoT.sql b/backend/src/main/resources/org/cryptomator/hub/flyway/V17__Create_Audit_Event_Setting_WoT.sql new file mode 100644 index 00000000..de0e1c8e --- /dev/null +++ b/backend/src/main/resources/org/cryptomator/hub/flyway/V17__Create_Audit_Event_Setting_WoT.sql @@ -0,0 +1,9 @@ +CREATE TABLE "audit_event_setting_wot_update" +( + "id" BIGINT NOT NULL, + "updated_by" VARCHAR(255) COLLATE "C" NOT NULL, + "wot_max_depth" INTEGER NOT NULL, + "wot_id_verify_len" INTEGER NOT NULL, + CONSTRAINT "AUDIT_EVENT_SETTING_WOT_UPDATE_PK" PRIMARY KEY ("id"), + CONSTRAINT "AUDIT_EVENT_SETTING_WOT_UPDATE_FK_AUDIT_EVENT" FOREIGN KEY ("id") REFERENCES "audit_event" ("id") ON DELETE CASCADE +); \ No newline at end of file From cf491076818ae65ec9efe492ae126e8268acb46d Mon Sep 17 00:00:00 2001 From: Julian Raufelder Date: Mon, 27 Jan 2025 17:14:36 +0100 Subject: [PATCH 04/23] Correct property name in logWotSettingUpdated method --- .../java/org/cryptomator/hub/entities/events/EventLogger.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java b/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java index f0501e9b..83c153fc 100644 --- a/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java +++ b/backend/src/main/java/org/cryptomator/hub/entities/events/EventLogger.java @@ -100,12 +100,12 @@ public void logVaultMemberUpdated(String updatedBy, UUID vaultId, String authori auditEventRepository.persist(event); } - public void logWotSettingUpdated(String userId, int wotIdVerifyLen, int wotMaxDepth) { + public void logWotSettingUpdated(String updatedBy, int wotIdVerifyLen, int wotMaxDepth) { var event = new SettingWotUpdateEvent(); event.setTimestamp(Instant.now()); event.setWotIdVerifyLen(wotIdVerifyLen); event.setWotMaxDepth(wotMaxDepth); - event.setUpdatedBy(userId); + event.setUpdatedBy(updatedBy); auditEventRepository.persist(event); } From 83be444ae5dd1ebda417ea5347f54c1b1abce37e Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Tue, 28 Jan 2025 11:09:26 +0100 Subject: [PATCH 05/23] refactoring, add tooltips, adjust strings, build WOT audit log --- frontend/src/common/auditlog.ts | 9 +- frontend/src/components/AdminSettings.vue | 97 ++++++++++--------- frontend/src/components/AuditLog.vue | 2 + .../AuditLogDetailsSettingWotUpdate.vue | 53 ++++++++++ frontend/src/i18n/de-DE.json | 15 ++- frontend/src/i18n/en-US.json | 13 ++- 6 files changed, 135 insertions(+), 54 deletions(-) create mode 100644 frontend/src/components/AuditLogDetailsSettingWotUpdate.vue diff --git a/frontend/src/common/auditlog.ts b/frontend/src/common/auditlog.ts index c9531d26..a24171af 100644 --- a/frontend/src/common/auditlog.ts +++ b/frontend/src/common/auditlog.ts @@ -21,6 +21,13 @@ export type AuditEventDeviceRemoveDto = AuditEventDtoBase & { deviceId: string; } +export type AuditEventSettingWotUpdateDto = AuditEventDtoBase & { + type: 'SETTING_WOT_UPDATE', + updatedBy: string; + wotMaxDepth: number; + wotIdVerifyLen: number; +} + export type AuditEventSignedWotIdDto = AuditEventDtoBase & { type: 'SIGN_WOT_ID', userId: string; @@ -89,7 +96,7 @@ export type AuditEventVaultOwnershipClaimDto = AuditEventDtoBase & { vaultId: string; } -export type AuditEventDto = AuditEventDeviceRegisterDto | AuditEventDeviceRemoveDto | AuditEventSignedWotIdDto | AuditEventVaultCreateDto | AuditEventVaultUpdateDto | AuditEventVaultAccessGrantDto | AuditEventVaultKeyRetrieveDto | AuditEventVaultMemberAddDto | AuditEventVaultMemberRemoveDto | AuditEventVaultMemberUpdateDto | AuditEventVaultOwnershipClaimDto; +export type AuditEventDto = AuditEventDeviceRegisterDto | AuditEventDeviceRemoveDto | AuditEventSettingWotUpdateDto | AuditEventSignedWotIdDto | AuditEventVaultCreateDto | AuditEventVaultUpdateDto | AuditEventVaultAccessGrantDto | AuditEventVaultKeyRetrieveDto | AuditEventVaultMemberAddDto | AuditEventVaultMemberRemoveDto | AuditEventVaultMemberUpdateDto | AuditEventVaultOwnershipClaimDto; /* Entity Cache */ diff --git a/frontend/src/components/AdminSettings.vue b/frontend/src/components/AdminSettings.vue index d80207fb..e95146ec 100644 --- a/frontend/src/components/AdminSettings.vue +++ b/frontend/src/components/AdminSettings.vue @@ -120,28 +120,13 @@