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 e8e4c22a..96d98725 100644 --- a/backend/src/main/java/org/cryptomator/hub/api/AuditLogResource.java +++ b/backend/src/main/java/org/cryptomator/hub/api/AuditLogResource.java @@ -19,6 +19,9 @@ 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.UserAccountResetEvent; +import org.cryptomator.hub.entities.events.UserKeysChangeEvent; +import org.cryptomator.hub.entities.events.UserSetupCodeChangeEvent; import org.cryptomator.hub.entities.events.VaultAccessGrantedEvent; import org.cryptomator.hub.entities.events.VaultCreatedEvent; import org.cryptomator.hub.entities.events.VaultKeyRetrievedEvent; @@ -82,8 +85,11 @@ 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 = SettingWotUpdateEventDto.class, name = SettingWotUpdateEvent.TYPE), // + @JsonSubTypes.Type(value = SignedWotIdEventDto.class, name = SignedWotIdEvent.TYPE), // + @JsonSubTypes.Type(value = UserAccountResetEventDto.class, name = UserAccountResetEvent.TYPE), // + @JsonSubTypes.Type(value = UserKeysChangeEventDto.class, name = UserKeysChangeEvent.TYPE), // + @JsonSubTypes.Type(value = UserSetupCodeChangeEventDto.class, name = UserSetupCodeChangeEvent.TYPE), // @JsonSubTypes.Type(value = VaultCreatedEventDto.class, name = VaultCreatedEvent.TYPE), // @JsonSubTypes.Type(value = VaultUpdatedEventDto.class, name = VaultUpdatedEvent.TYPE), // @JsonSubTypes.Type(value = VaultAccessGrantedEventDto.class, name = VaultAccessGrantedEvent.TYPE), // @@ -106,7 +112,10 @@ 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 SettingWotUpdateEvent evt -> new SettingWotUpdateEventDto(evt.getId(), evt.getTimestamp(), SettingWotUpdateEvent.TYPE, evt.getUpdatedBy(), evt.getWotMaxDepth(), evt.getWotIdVerifyLen()); + case UserAccountResetEvent evt -> new UserAccountResetEventDto(evt.getId(), evt.getTimestamp(), UserAccountResetEvent.TYPE, evt.getResetBy()); + case UserKeysChangeEvent evt -> new UserKeysChangeEventDto(evt.getId(), evt.getTimestamp(), UserKeysChangeEvent.TYPE, evt.getChangedBy(), evt.getUserName()); + case UserSetupCodeChangeEvent evt -> new UserSetupCodeChangeEventDto(evt.getId(), evt.getTimestamp(), UserSetupCodeChangeEvent.TYPE, evt.getChangedBy()); 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,10 +136,21 @@ record DeviceRegisteredEventDto(long id, Instant timestamp, String type, @JsonPr record DeviceRemovedEventDto(long id, Instant timestamp, String type, @JsonProperty("removedBy") String removedBy, @JsonProperty("deviceId") String deviceId) implements AuditEventDto { } - 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 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 SettingWotUpdateEventDto(long id, Instant timestamp, String type, @JsonProperty("updatedBy") String updatedBy, @JsonProperty("wotMaxDepth") int wotMaxDepth, + @JsonProperty("wotIdVerifyLen") int wotIdVerifyLen) implements AuditEventDto { + } + + record UserAccountResetEventDto(long id, Instant timestamp, String type, @JsonProperty("resetBy") String resetBy) implements AuditEventDto { + } + + record UserKeysChangeEventDto(long id, Instant timestamp, String type, @JsonProperty("changedBy") String changedBy, @JsonProperty("userName") String userName) implements AuditEventDto { + } + + record UserSetupCodeChangeEventDto(long id, Instant timestamp, String type, @JsonProperty("changedBy") String changedBy) implements AuditEventDto { } record VaultCreatedEventDto(long id, Instant timestamp, String type, @JsonProperty("createdBy") String createdBy, @JsonProperty("vaultId") UUID vaultId, @JsonProperty("vaultName") String vaultName, diff --git a/backend/src/main/java/org/cryptomator/hub/api/UsersResource.java b/backend/src/main/java/org/cryptomator/hub/api/UsersResource.java index d42e73c3..89f2c436 100644 --- a/backend/src/main/java/org/cryptomator/hub/api/UsersResource.java +++ b/backend/src/main/java/org/cryptomator/hub/api/UsersResource.java @@ -34,6 +34,7 @@ import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -79,10 +80,16 @@ public Response putMe(@Nullable @Valid UserDto dto) { user.setPictureUrl(jwt.getClaim("picture")); user.setEmail(jwt.getClaim("email")); if (dto != null) { - user.setEcdhPublicKey(dto.ecdhPublicKey); - user.setEcdsaPublicKey(dto.ecdsaPublicKey); - user.setPrivateKeys(dto.privateKeys); - user.setSetupCode(dto.setupCode); + if (!Objects.equals(user.getSetupCode(), dto.setupCode)) { + user.setSetupCode(dto.setupCode); + eventLogger.logUserSetupCodeChanged(jwt.getSubject()); + } + if (!Objects.equals(user.getEcdhPublicKey(), dto.ecdhPublicKey) || !Objects.equals(user.getEcdsaPublicKey(), dto.ecdsaPublicKey) || !Objects.equals(user.getPrivateKeys(), dto.privateKeys)) { + user.setEcdhPublicKey(dto.ecdhPublicKey); + user.setEcdsaPublicKey(dto.ecdsaPublicKey); + user.setPrivateKeys(dto.privateKeys); + eventLogger.logUserKeysChanged(jwt.getSubject(), jwt.getName()); + } updateDevices(user, dto); } userRepo.persist(user); @@ -163,11 +170,13 @@ public UserDto getMe(@QueryParam("withDevices") boolean withDevices) { public Response resetMe() { User user = userRepo.findById(jwt.getSubject()); user.setEcdhPublicKey(null); + user.setEcdsaPublicKey(null); user.setPrivateKeys(null); user.setSetupCode(null); userRepo.persist(user); deviceRepo.deleteByOwner(user.getId()); accessTokenRepo.deleteByUser(user.getId()); + eventLogger.logUserAccountReset(jwt.getSubject()); return Response.noContent().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 83c153fc..779ba2b4 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 @@ -53,6 +53,28 @@ public void logDeviceRemoved(String removedBy, String deviceId) { auditEventRepository.persist(event); } + public void logUserAccountReset(String resetBy) { + var event = new UserAccountResetEvent(); + event.setTimestamp(Instant.now()); + event.setResetBy(resetBy); + auditEventRepository.persist(event); + } + + public void logUserKeysChanged(String changedBy, String userName) { + var event = new UserKeysChangeEvent(); + event.setTimestamp(Instant.now()); + event.setChangedBy(changedBy); + event.setUserName(userName); + auditEventRepository.persist(event); + } + + public void logUserSetupCodeChanged(String changedBy) { + var event = new UserSetupCodeChangeEvent(); + event.setTimestamp(Instant.now()); + event.setChangedBy(changedBy); + auditEventRepository.persist(event); + } + public void logVaultAccessGranted(String grantedBy, UUID vaultId, String authorityId) { var event = new VaultAccessGrantedEvent(); event.setTimestamp(Instant.now()); diff --git a/backend/src/main/java/org/cryptomator/hub/entities/events/UserAccountResetEvent.java b/backend/src/main/java/org/cryptomator/hub/entities/events/UserAccountResetEvent.java new file mode 100644 index 00000000..47e733f0 --- /dev/null +++ b/backend/src/main/java/org/cryptomator/hub/entities/events/UserAccountResetEvent.java @@ -0,0 +1,40 @@ +package org.cryptomator.hub.entities.events; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import java.util.Objects; + +@Entity +@Table(name = "audit_event_user_account_reset") +@DiscriminatorValue(UserAccountResetEvent.TYPE) +public class UserAccountResetEvent extends AuditEvent { + + public static final String TYPE = "USER_ACCOUNT_RESET"; + + @Column(name = "reset_by") + private String resetBy; + + public String getResetBy() { + return resetBy; + } + + public void setResetBy(String resetBy) { + this.resetBy = resetBy; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + UserAccountResetEvent that = (UserAccountResetEvent) o; + return Objects.equals(resetBy, that.resetBy); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), resetBy); + } +} diff --git a/backend/src/main/java/org/cryptomator/hub/entities/events/UserKeysChangeEvent.java b/backend/src/main/java/org/cryptomator/hub/entities/events/UserKeysChangeEvent.java new file mode 100644 index 00000000..24ad18f3 --- /dev/null +++ b/backend/src/main/java/org/cryptomator/hub/entities/events/UserKeysChangeEvent.java @@ -0,0 +1,52 @@ +package org.cryptomator.hub.entities.events; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import java.util.Objects; + +@Entity +@Table(name = "audit_event_user_keys_change") +@DiscriminatorValue(UserKeysChangeEvent.TYPE) +public class UserKeysChangeEvent extends AuditEvent { + + public static final String TYPE = "USER_KEYS_CHANGE"; + + @Column(name = "changed_by") + private String changedBy; + + @Column(name = "user_name") + private String userName; + + public String getChangedBy() { + return changedBy; + } + + public void setChangedBy(String changedBy) { + this.changedBy = changedBy; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + UserKeysChangeEvent that = (UserKeysChangeEvent) o; + return Objects.equals(changedBy, that.changedBy) && Objects.equals(userName, that.userName); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), changedBy, userName); + } + +} diff --git a/backend/src/main/java/org/cryptomator/hub/entities/events/UserSetupCodeChangeEvent.java b/backend/src/main/java/org/cryptomator/hub/entities/events/UserSetupCodeChangeEvent.java new file mode 100644 index 00000000..b846bb5f --- /dev/null +++ b/backend/src/main/java/org/cryptomator/hub/entities/events/UserSetupCodeChangeEvent.java @@ -0,0 +1,40 @@ +package org.cryptomator.hub.entities.events; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +import java.util.Objects; + +@Entity +@Table(name = "audit_event_user_setupcode_change") +@DiscriminatorValue(UserSetupCodeChangeEvent.TYPE) +public class UserSetupCodeChangeEvent extends AuditEvent { + + public static final String TYPE = "USER_SETUP_CODE_CHANGE"; + + @Column(name = "changed_by") + private String changedBy; + + public String getChangedBy() { + return changedBy; + } + + public void setChangedBy(String changedBy) { + this.changedBy = changedBy; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + UserSetupCodeChangeEvent that = (UserSetupCodeChangeEvent) o; + return Objects.equals(changedBy, that.changedBy); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), changedBy); + } +} diff --git a/backend/src/main/resources/org/cryptomator/hub/flyway/V18__Create_Further_User_Audit_Events.sql b/backend/src/main/resources/org/cryptomator/hub/flyway/V18__Create_Further_User_Audit_Events.sql new file mode 100644 index 00000000..f9d54fc5 --- /dev/null +++ b/backend/src/main/resources/org/cryptomator/hub/flyway/V18__Create_Further_User_Audit_Events.sql @@ -0,0 +1,24 @@ +CREATE TABLE "audit_event_user_keys_change" +( + "id" BIGINT NOT NULL, + "changed_by" VARCHAR(255) COLLATE "C" NOT NULL, + "user_name" VARCHAR NOT NULL, + CONSTRAINT "AUDIT_EVENT_USER_ACCOUNT_SETUP_COMPLETE_PK" PRIMARY KEY ("id"), + CONSTRAINT "AUDIT_EVENT_USER_ACCOUNT_SETUP_COMPLETE_FK_AUDIT_EVENT" FOREIGN KEY ("id") REFERENCES "audit_event" ("id") ON DELETE CASCADE +); + +CREATE TABLE "audit_event_user_account_reset" +( + "id" BIGINT NOT NULL, + "reset_by" VARCHAR(255) COLLATE "C" NOT NULL, + CONSTRAINT "AUDIT_EVENT_USER_ACCOUNT_RESET_PK" PRIMARY KEY ("id"), + CONSTRAINT "AUDIT_EVENT_USER_ACCOUNT_RESET_FK_AUDIT_EVENT" FOREIGN KEY ("id") REFERENCES "audit_event" ("id") ON DELETE CASCADE +); + +CREATE TABLE "audit_event_user_setupcode_change" +( + "id" BIGINT NOT NULL, + "changed_by" VARCHAR(255) COLLATE "C" NOT NULL, + CONSTRAINT "AUDIT_EVENT_USER_SETUPCODE_CHANGE_PK" PRIMARY KEY ("id"), + CONSTRAINT "AUDIT_EVENT_USER_ACCOUNT_SETUPCODE_CHANGE_EVENT" FOREIGN KEY ("id") REFERENCES "audit_event" ("id") ON DELETE CASCADE +); \ No newline at end of file diff --git a/frontend/src/common/auditlog.ts b/frontend/src/common/auditlog.ts index a24171af..bd72fc65 100644 --- a/frontend/src/common/auditlog.ts +++ b/frontend/src/common/auditlog.ts @@ -36,6 +36,22 @@ export type AuditEventSignedWotIdDto = AuditEventDtoBase & { signature: string; } +export type AuditEventUserAccountResetDto = AuditEventDtoBase & { + type: 'USER_ACCOUNT_RESET', + resetBy: string; +} + +export type AuditEventUserKeysChangeDto = AuditEventDtoBase & { + type: 'USER_KEYS_CHANGE', + changedBy: string, + userName: string; +} + +export type AuditEventUserSetupCodeChangeDto = AuditEventDtoBase & { + type: 'USER_SETUP_CODE_CHANGE', + changedBy: string; +} + export type AuditEventVaultCreateDto = AuditEventDtoBase & { type: 'VAULT_CREATE', createdBy: string; @@ -96,7 +112,7 @@ export type AuditEventVaultOwnershipClaimDto = AuditEventDtoBase & { vaultId: string; } -export type AuditEventDto = AuditEventDeviceRegisterDto | AuditEventDeviceRemoveDto | AuditEventSettingWotUpdateDto | AuditEventSignedWotIdDto | AuditEventVaultCreateDto | AuditEventVaultUpdateDto | AuditEventVaultAccessGrantDto | AuditEventVaultKeyRetrieveDto | AuditEventVaultMemberAddDto | AuditEventVaultMemberRemoveDto | AuditEventVaultMemberUpdateDto | AuditEventVaultOwnershipClaimDto; +export type AuditEventDto = AuditEventDeviceRegisterDto | AuditEventDeviceRemoveDto | AuditEventSettingWotUpdateDto | AuditEventSignedWotIdDto | AuditEventUserAccountResetDto | AuditEventUserKeysChangeDto | AuditEventUserSetupCodeChangeDto | AuditEventVaultCreateDto | AuditEventVaultUpdateDto | AuditEventVaultAccessGrantDto | AuditEventVaultKeyRetrieveDto | AuditEventVaultMemberAddDto | AuditEventVaultMemberRemoveDto | AuditEventVaultMemberUpdateDto | AuditEventVaultOwnershipClaimDto; /* Entity Cache */ diff --git a/frontend/src/components/AuditLog.vue b/frontend/src/components/AuditLog.vue index 4aa83121..af6ed487 100644 --- a/frontend/src/components/AuditLog.vue +++ b/frontend/src/components/AuditLog.vue @@ -105,6 +105,9 @@ + + + @@ -172,6 +175,7 @@ import AuditLogDetailsDeviceRegister from './AuditLogDetailsDeviceRegister.vue'; import AuditLogDetailsDeviceRemove from './AuditLogDetailsDeviceRemove.vue'; import AuditLogDetailsSettingWotUpdate from './AuditLogDetailsSettingWotUpdate.vue'; import AuditLogDetailsSignedWotId from './AuditLogDetailsSignedWotId.vue'; +import AuditLogDetailsUserAccountReset from './AuditLogDetailsUserAccountReset.vue'; import AuditLogDetailsVaultAccessGrant from './AuditLogDetailsVaultAccessGrant.vue'; import AuditLogDetailsVaultCreate from './AuditLogDetailsVaultCreate.vue'; import AuditLogDetailsVaultKeyRetrieve from './AuditLogDetailsVaultKeyRetrieve.vue'; @@ -180,6 +184,8 @@ import AuditLogDetailsVaultMemberRemove from './AuditLogDetailsVaultMemberRemove import AuditLogDetailsVaultMemberUpdate from './AuditLogDetailsVaultMemberUpdate.vue'; import AuditLogDetailsVaultOwnershipClaim from './AuditLogDetailsVaultOwnershipClaim.vue'; import AuditLogDetailsVaultUpdate from './AuditLogDetailsVaultUpdate.vue'; +import AuditLogUserKeysChange from './AuditLogUserKeysChange.vue'; +import AuditLogUserSetupCodeChanged from './AuditLogUserSetupCodeChanged.vue'; import FetchError from './FetchError.vue'; enum State { diff --git a/frontend/src/components/AuditLogDetailsUserAccountReset.vue b/frontend/src/components/AuditLogDetailsUserAccountReset.vue new file mode 100644 index 00000000..78f57564 --- /dev/null +++ b/frontend/src/components/AuditLogDetailsUserAccountReset.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/components/AuditLogUserKeysChange.vue b/frontend/src/components/AuditLogUserKeysChange.vue new file mode 100644 index 00000000..e9750e6f --- /dev/null +++ b/frontend/src/components/AuditLogUserKeysChange.vue @@ -0,0 +1,45 @@ + + + diff --git a/frontend/src/components/AuditLogUserSetupCodeChanged.vue b/frontend/src/components/AuditLogUserSetupCodeChanged.vue new file mode 100644 index 00000000..ab743f3c --- /dev/null +++ b/frontend/src/components/AuditLogUserSetupCodeChanged.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/components/InitialSetup.vue b/frontend/src/components/InitialSetup.vue index cda8cebf..f337fc03 100644 --- a/frontend/src/components/InitialSetup.vue +++ b/frontend/src/components/InitialSetup.vue @@ -297,6 +297,7 @@ async function recoverUserKey() { } async function submitBrowserKeys(browserKeys: BrowserKeys, me: UserDto, userKeys: UserKeys) { + await backend.users.putMe(me); const jwe = await userKeys.encryptForDevice(browserKeys.keyPair.publicKey); await backend.devices.putDevice({ id: await browserKeys.id(), @@ -306,7 +307,6 @@ async function submitBrowserKeys(browserKeys: BrowserKeys, me: UserDto, userKeys userPrivateKey: jwe, creationTime: new Date() }); - await backend.users.putMe(me); userdata.reload(); } diff --git a/frontend/src/i18n/de-DE.json b/frontend/src/i18n/de-DE.json index bd2cf992..7633c648 100644 --- a/frontend/src/i18n/de-DE.json +++ b/frontend/src/i18n/de-DE.json @@ -81,7 +81,9 @@ "auditLog.details.device.register": "Gerät registrieren", "auditLog.details.device.remove": "Gerät entfernen", "auditLog.details.setting.wot.update": "WoT-Einstellung aktualisieren", - "auditLog.details.wot.signedIdentity": "Identität beglaubigt", + "auditLog.details.user.account.reset": "Account zurücksetzen", + "auditLog.details.user.keys.change": "Nutzer-Schlüssel geändert", + "auditLog.details.user.setupCode.change": "Account Key geänert", "auditLog.details.vault.create": "Tresor erstellen", "auditLog.details.vault.update": "Tresor aktualisieren", "auditLog.details.vaultAccess.grant": "Tresor-Zugriff gewähren", @@ -90,6 +92,7 @@ "auditLog.details.vaultMember.remove": "Tresor-Mitglied entfernen", "auditLog.details.vaultMember.update": "Tresor-Mitglied aktualisieren", "auditLog.details.vaultOwnership.claim": "Tresor-Eigentümer werden", + "auditLog.details.wot.signedIdentity": "Identität beglaubigt", "auditLog.pagination.showing": "Zeige Einträge {0} bis {1}", "auditLog.paymentRequired.message": "Lizenz erforderlich", "auditLog.paymentRequired.description": "Audit-Logs sind nur mit einer kostenpflichtigen Lizenz verfügbar. Du kannst eine im Admin-Bereich erhalten.", diff --git a/frontend/src/i18n/en-US.json b/frontend/src/i18n/en-US.json index 2d9a1eef..aea18761 100644 --- a/frontend/src/i18n/en-US.json +++ b/frontend/src/i18n/en-US.json @@ -81,7 +81,9 @@ "auditLog.details.device.register": "Register Device", "auditLog.details.device.remove": "Remove Device", "auditLog.details.setting.wot.update": "Update Wot Settings", - "auditLog.details.wot.signedIdentity": "Signed Identity", + "auditLog.details.user.account.reset": "Reset User Account", + "auditLog.details.user.keys.change": "User Keys Change", + "auditLog.details.user.setupCode.change": "Account Key Change", "auditLog.details.vault.create": "Create Vault", "auditLog.details.vault.update": "Update Vault", "auditLog.details.vaultAccess.grant": "Grant Vault Access", @@ -90,6 +92,7 @@ "auditLog.details.vaultMember.remove": "Remove Vault Member", "auditLog.details.vaultMember.update": "Update Vault Member", "auditLog.details.vaultOwnership.claim": "Claim Vault Ownership", + "auditLog.details.wot.signedIdentity": "Signed Identity", "auditLog.pagination.showing": "Showing entries {0} to {1}", "auditLog.paymentRequired.message": "License Required", "auditLog.paymentRequired.description": "Audit Logs are only available with a paid license. You can get one in the admin section.",