Skip to content
Draft
Show file tree
Hide file tree
Changes from 127 commits
Commits
Show all changes
155 commits
Select commit Hold shift + click to select a range
2d080ea
add `"alg": "A256KW"` support for JWEs
overheadhunter Mar 2, 2024
d109cff
uvf metadata (WiP).
chenkins Feb 28, 2024
55633f1
remove dead code from `backend.ts` for now
overheadhunter Apr 13, 2024
fe7ff3d
disentangle v8 and uvf based vaults
overheadhunter Apr 13, 2024
be8803c
move vault format 8 code to separate file
overheadhunter Apr 13, 2024
b51cc59
move UVF code to separate file
overheadhunter Apr 13, 2024
a9f12d4
adjust UVF payload to latest spec
overheadhunter Apr 13, 2024
cdf5571
Merge branch 'develop' into feature/uvf
overheadhunter Apr 20, 2024
3f77d16
new JWE API supporting compact and JSON format
overheadhunter Apr 25, 2024
3646379
use correct `AlgorithmID` for Concat KDF
overheadhunter Apr 26, 2024
f1c14fd
added tests
overheadhunter Apr 26, 2024
e0a7ab1
Merge branch 'develop' into feature/uvf
overheadhunter Apr 28, 2024
aa1690f
type cleanup
overheadhunter Apr 28, 2024
e6e028a
include recovery key in UVF metadata
overheadhunter Apr 28, 2024
a85cf3c
create UVF-based vault
overheadhunter Apr 28, 2024
32f2743
store uvf metadata and recovery key in vault table
overheadhunter May 2, 2024
a63ef34
adjusted to DTO model
overheadhunter May 2, 2024
6ce1569
Merge branch 'develop' into feature/uvf
overheadhunter May 2, 2024
01c8a06
grant permission to UVF vault
overheadhunter May 2, 2024
36eb79c
fix autocompletion mistake
overheadhunter May 2, 2024
3cf9c8e
use common interfaces for VF8 and UVF
overheadhunter May 2, 2024
69f0360
fix linter errors
overheadhunter May 2, 2024
7bddc62
experimental implementation of `serializePrivateKey()`
overheadhunter May 2, 2024
ba05d8b
make config.ts usable during tests
overheadhunter May 2, 2024
3d1db01
deduplicate "encrypt for user"
overheadhunter May 3, 2024
6b46862
store recovery key among vault key in access token
overheadhunter May 3, 2024
cb4e53a
reordered fields
overheadhunter May 3, 2024
b294f55
store recovery key as PKCS8 instead of words
overheadhunter May 9, 2024
a3fc184
adjusted parameter order
overheadhunter May 9, 2024
aeafffe
fix mocha test explorer: `document is not defined`
overheadhunter May 9, 2024
17c7099
fix method signature
overheadhunter May 9, 2024
f3f3e02
relax linter
overheadhunter May 9, 2024
aa49371
add tests
overheadhunter May 9, 2024
eda2621
add tests
overheadhunter May 9, 2024
815199f
reduce public API surface
overheadhunter May 9, 2024
037157f
add tests
overheadhunter May 9, 2024
2a40d01
speed up tests by reducing KDF iteration count
overheadhunter May 9, 2024
5118876
Merge branch 'develop' into feature/uvf
overheadhunter May 9, 2024
e4f9865
renamed files
overheadhunter May 10, 2024
e27d20a
clean up tests
overheadhunter May 10, 2024
657598a
fix uneffective test
overheadhunter May 10, 2024
88a95eb
clean up test
overheadhunter May 10, 2024
c229fdd
remove outdated TODOs
overheadhunter May 10, 2024
b46f55e
restore recovery key from human-readable form
overheadhunter May 10, 2024
b0790aa
store JWK Set in backend
overheadhunter May 10, 2024
98cd173
expose `jwks.json` and `vault.uvf` endpoints
overheadhunter May 10, 2024
00641e4
switch to MemberDto
overheadhunter May 16, 2024
4f3e969
cleanup
overheadhunter May 16, 2024
8320786
include role-depending data in access token
overheadhunter May 16, 2024
458e98a
Merge branch 'develop' into feature/uvf
overheadhunter May 16, 2024
8cb9af6
add `UniversalVaultFormat.recover(...)`
overheadhunter May 16, 2024
aad13fa
Merge branch 'develop' into feature/uvf
overheadhunter May 17, 2024
686713b
Merge branch 'develop' into feature/uvf
overheadhunter May 17, 2024
994d7b3
Merge branch 'develop' into feature/uvf
overheadhunter May 17, 2024
155d640
remove unnecessary guard
overheadhunter May 17, 2024
9b4f5ba
fix weird error message in unit tests
overheadhunter May 21, 2024
388426f
pass in URL during vault template generation
overheadhunter May 21, 2024
52b97b5
improve test
overheadhunter May 21, 2024
7224b46
add root directory to vault template
overheadhunter May 21, 2024
81e9ab4
split up `computeDirId` and `computeDirIdHash`
overheadhunter May 21, 2024
9c3ab12
add `dir.uvf` file to vault template
overheadhunter May 21, 2024
ec4415d
refine test
overheadhunter May 22, 2024
2947b80
show also uvf recovery key in vault details
infeo May 22, 2024
2d03e39
fix linter hints
infeo May 22, 2024
bf85c2a
(unfinished) rework recover Vault dialog
infeo May 27, 2024
8d86446
Do not erase uploaded file on failed upload
infeo May 28, 2024
57cfd0a
improve error handling
infeo May 28, 2024
b1f9fc4
define event listeners as functions
infeo May 28, 2024
a667e0d
remove unused Error class
infeo May 28, 2024
871b6de
set vault type during recovery
infeo May 28, 2024
3368768
minor adjustments
infeo May 28, 2024
b43a946
add additional verification to vaultformat 8 module
infeo May 29, 2024
ea77daf
Add negative test for vaultFormat8 verfiy and recover
infeo May 30, 2024
c2fe768
reduce diff
infeo May 30, 2024
b2cb75d
add doc string
infeo Jun 3, 2024
64d8ff6
add tests for simple jwt parsing
infeo Jun 3, 2024
eaaad24
improve error handling
infeo Jun 3, 2024
597b2cc
add error translations
infeo Jun 3, 2024
b7a0687
more wording/translations
infeo Jun 5, 2024
afd370f
fix display bug
infeo Jun 5, 2024
0de22c9
Merge branch 'develop' into feature/uvf
overheadhunter Jun 6, 2024
917fedc
use new JWE parser in `userdata.ts`
overheadhunter Jun 6, 2024
847ecc4
dedup
overheadhunter Jun 6, 2024
26369a5
adjust DTO to carry both EC keys
overheadhunter Jun 6, 2024
e77ca7a
Merge branch 'develop' into feature/uvf
overheadhunter Jul 12, 2024
3e30a00
Merge branch 'develop' into feature/uvf
overheadhunter Nov 3, 2024
fd0add4
fixed test
overheadhunter Nov 3, 2024
68eb5d9
fixed linter warnings
overheadhunter Nov 3, 2024
ebd5f7d
Merge branch 'develop' into feature/uvf
overheadhunter Jan 17, 2025
4268484
make tests run from IDE again
overheadhunter Jan 17, 2025
3ca8f78
linter error
overheadhunter Jan 17, 2025
a0ce488
spec is final now
overheadhunter Jan 17, 2025
da7fe40
encode keys with base64url; values with base64
overheadhunter Jan 17, 2025
3cc7d27
use corrected test vectors confirmed in java
overheadhunter Jan 17, 2025
f684a58
fix incorrect hkdf output size
overheadhunter Jan 17, 2025
12106cc
Merge branch 'develop' into feature/uvf
overheadhunter Jan 31, 2025
c1d6c29
reordered flyway migrations
overheadhunter Jan 31, 2025
5a38a4d
Merge branch 'develop' into feature/uvf
overheadhunter Feb 7, 2025
fd6db88
reordered migrations
overheadhunter Feb 7, 2025
1f0b7c6
Merge branch 'develop' into feature/uvf
overheadhunter Feb 24, 2025
cd68e29
Merge branch 'develop' into feature/uvf
overheadhunter Mar 22, 2025
3a65446
Merge branch 'develop' into feature/uvf
overheadhunter Apr 24, 2025
b5a94a9
use base64url in `vault.uvf`
overheadhunter Apr 24, 2025
7e285ea
fix base64url encoding and tests
overheadhunter Apr 24, 2025
6efd702
fix test broken during merge cd68e29
overheadhunter Apr 24, 2025
ce36aa1
run linter
overheadhunter Apr 24, 2025
928b613
Merge branch 'develop' into feature/uvf
overheadhunter May 2, 2025
9fb01db
Merge branch 'develop' into feature/uvf
overheadhunter Jul 8, 2025
27a944d
use 512 bit keys for HMAC-SHA256 as per spec
overheadhunter Jul 8, 2025
b882d6b
Merge branch 'develop' into feature/uvf
tobihagemann Jul 18, 2025
6318fb6
Merge branch 'develop' into feature/uvf
overheadhunter Aug 28, 2025
85f4d30
force big-endian seed IDs
overheadhunter Sep 2, 2025
e7dceec
use `Uint8Array<ArrayBuffer>` (TS 5.7 adjustments)
overheadhunter Sep 2, 2025
703d092
use `Uint8Array<ArrayBuffer>` (TS 5.7 adjustments)
overheadhunter Nov 5, 2025
ce24d91
add missing protected header params
overheadhunter Nov 5, 2025
6bac061
Merge branch 'develop' into feature/uvf
overheadhunter Nov 12, 2025
008b3cd
Merge branch 'develop' into feature/uvf
overheadhunter Nov 13, 2025
7272005
Merge branch 'develop' into feature/uvf
overheadhunter Dec 12, 2025
5ac0762
Merge branch 'develop' into feature/uvf
overheadhunter Jan 9, 2026
04a88c2
Merge branch 'develop' into feature/uvf
overheadhunter Mar 10, 2026
b92e7d3
fix build
overheadhunter Mar 11, 2026
236e9cf
Merge branch 'develop' into feature/uvf
overheadhunter Apr 2, 2026
7e7bd3c
fix frontend build
overheadhunter Apr 2, 2026
e2e0561
fix test
overheadhunter Apr 2, 2026
15f79b5
Merge branch 'develop' into feature/uvf
overheadhunter Apr 14, 2026
9a0f8df
fix test
overheadhunter Apr 14, 2026
4b86f36
Merge branch 'develop' into feature/uvf
overheadhunter Apr 14, 2026
a8135f1
Read `maxWotDepth` from `/api/settings`
overheadhunter May 13, 2026
f5acdcc
Adjust wotMaxDepth constraint: allow -1 to Integer.MAX_VALUE
Copilot May 13, 2026
66d326f
Restore @Max(9) on wotMaxDepth, keep @Min(-1)
Copilot May 13, 2026
aae0e59
Merge pull request #447 from cryptomator/copilot/adjust-settings-dto-…
overheadhunter May 13, 2026
e7a210d
undo #447
overheadhunter May 14, 2026
d0f40df
add `automatic access grant` settings
overheadhunter May 19, 2026
c4ae29f
add `GET /vaults/users-requiring-access-grant`
overheadhunter May 19, 2026
5b7a148
fix test
overheadhunter May 19, 2026
431fa68
Merge branch 'develop' into feature/uvf
overheadhunter May 21, 2026
87cf1c7
Merge branch 'uvf' into `automatic-access-grant`
overheadhunter May 21, 2026
29aaa77
change migration order
overheadhunter May 21, 2026
705f2de
add "automatic" to audit log event
overheadhunter May 21, 2026
da97a13
add `POST /{vaultId}/access-tokens/auto`
overheadhunter May 21, 2026
b7461b3
refine settings UI
overheadhunter May 22, 2026
cd1bf5c
Implement client-side automatic access grant agent
overheadhunter May 22, 2026
8a761db
simplify backoff strategy
overheadhunter May 25, 2026
3c26751
Merge branch 'develop' into feature/uvf
overheadhunter May 26, 2026
6f7b109
Apply suggestions from code review
overheadhunter May 27, 2026
8daa49b
renamed event to avoid confusion
overheadhunter May 27, 2026
cebef13
update event DTOs
overheadhunter May 27, 2026
555a192
remove support for `maxWotDepth: -1`
overheadhunter May 27, 2026
fc820fa
Merge pull request #457 from cryptomator/feature/automatic-access-grant
overheadhunter May 28, 2026
b27700c
Merge branch 'develop' into feature/uvf
overheadhunter May 28, 2026
bf8b70e
Merge branch 'develop' into feature/uvf
overheadhunter Jun 26, 2026
6c8835d
Merge branch 'develop' into feature/uvf
overheadhunter Jun 26, 2026
b81da19
constructor injection
overheadhunter Jun 26, 2026
35b6dcd
Merge branch 'develop' into feature/uvf
overheadhunter Jul 3, 2026
030d106
Merge branch 'develop' into feature/uvf
overheadhunter Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 55 additions & 7 deletions backend/src/main/java/org/cryptomator/hub/api/VaultResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,18 @@ public Response removeAuthority(@PathParam("vaultId") UUID vaultId, @PathParam("
@VaultRole(value = VaultAccess.Role.OWNER, bypassForEmergencyAccess = true) // may throw 403
@Transactional
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "list users requiring access rights", description = "lists all users, who don't have a user-specific vault key yet")
@Operation(summary = "list members requiring access tokens", description = "lists all members, that have permissions but lack an access token")
@APIResponse(responseCode = "200")
@APIResponse(responseCode = "403", description = "not a vault owner")
public List<UserDto> getUsersRequiringAccessGrant(@PathParam("vaultId") UUID vaultId) {
return userRepo.findRequiringAccessGrant(vaultId).map(UserDto::justPublicInfo).toList();
public List<MemberDto> getUsersRequiringAccessGrant(@PathParam("vaultId") UUID vaultId) {
return effectiveVaultAccessRepo.findMembersWithoutAccessTokens(vaultId).map(access -> {
if (access.getAuthority() instanceof User u) {
return MemberDto.fromEntity(u, access.getRole());
} else {
// findMembersWithoutAccessTokens() should only return users, not groups.
throw new IllegalStateException();
}
}).toList();
}

/**
Expand Down Expand Up @@ -461,6 +468,38 @@ public Response unlock(@PathParam("vaultId") UUID vaultId, @QueryParam("evenIfAr
}
}

@GET
@Path("/{vaultId}/uvf/vault.uvf")
@RolesAllowed("user")
@Transactional
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "get the vault.uvf file")
@APIResponse(responseCode = "200")
@APIResponse(responseCode = "404", description = "unknown vault")
public String getUvfMetadata(@PathParam("vaultId") UUID vaultId) {
var vault = vaultRepo.findById(vaultId);
if (vault == null || vault.getUvfMetadataFile() == null) {
throw new NotFoundException();
}
return vault.getUvfMetadataFile();
}

@GET
@Path("/{vaultId}/uvf/jwks.json")
@RolesAllowed("user")
@Transactional
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "get public vault keys", description = "retrieves a JWK Set containing public keys related to this vault")
@APIResponse(responseCode = "200")
@APIResponse(responseCode = "404", description = "unknown vault")
public String getUvfKeys(@PathParam("vaultId") UUID vaultId) {
var vault = vaultRepo.findById(vaultId);
if (vault == null || vault.getUvfMetadataFile() == null) {
throw new NotFoundException();
}
return vault.getUvfKeySet();
}

@POST
@Path("/{vaultId}/access-tokens")
@RolesAllowed("user")
Expand Down Expand Up @@ -582,6 +621,8 @@ public Response createOrUpdate(@PathParam("vaultId") UUID vaultId, @Valid @NotNu
var oldEmergencyKeyShares = vault.getEmergencyKeyShares().values();
vault.setRequiredEmergencyKeyShares(vaultDto.requiredEmergencyKeyShares);
vault.setEmergencyKeyShares(vaultDto.emergencyKeyShares);
vault.setUvfMetadataFile(vaultDto.uvfMetadataFile);
vault.setUvfKeySet(vaultDto.uvfKeySet);

vaultRepo.persistAndFlush(vault); // trigger PersistenceException before we continue with

Expand Down Expand Up @@ -669,18 +710,25 @@ public Response claimOwnership(@PathParam("vaultId") UUID vaultId, @FormParam("p
@JsonInclude(JsonInclude.Include.NON_NULL)
public record VaultDto(@JsonProperty("id") @NotNull UUID id,
@JsonProperty("name") @NoHtmlOrScriptChars @NotBlank String name,
@JsonProperty("creationTime") Instant creationTime, @JsonProperty("description") @NoHtmlOrScriptChars String description,
@JsonProperty("creationTime") Instant creationTime,
@JsonProperty("description") @NoHtmlOrScriptChars String description,
@JsonProperty("archived") boolean archived,
@JsonProperty("requiredEmergencyKeyShares") @Min(0) int requiredEmergencyKeyShares,
@JsonProperty("emergencyKeyShares") Map<String, String> emergencyKeyShares,
@JsonProperty("uvfMetadataFile") String uvfMetadataFile,
@JsonProperty("uvfKeySet") String uvfKeySet,
// Legacy properties ("Vault Admin Password"):
@JsonProperty("masterkey") @OnlyBase64Chars String masterkey, @JsonProperty("iterations") Integer iterations,
@JsonProperty("salt") @OnlyBase64Chars String salt,
@JsonProperty("masterkey") @OnlyBase64Chars String masterkey, @JsonProperty("iterations") Integer iterations, @JsonProperty("salt") @OnlyBase64Chars String salt,
@JsonProperty("authPublicKey") @OnlyBase64Chars String authPublicKey, @JsonProperty("authPrivateKey") @OnlyBase64Chars String authPrivateKey

) {

public static VaultDto fromEntity(Vault entity) {
return new VaultDto(entity.getId(), entity.getName(), entity.getCreationTime().truncatedTo(ChronoUnit.MILLIS), entity.getDescription(), entity.isArchived(), entity.getRequiredEmergencyKeyShares(), entity.getEmergencyKeyShares(), entity.getMasterkey(), entity.getIterations(), entity.getSalt(), entity.getAuthenticationPublicKey(), entity.getAuthenticationPrivateKey());
return new VaultDto(entity.getId(), entity.getName(), entity.getCreationTime().truncatedTo(ChronoUnit.MILLIS), entity.getDescription(), entity.isArchived(), entity.getRequiredEmergencyKeyShares(), entity.getEmergencyKeyShares(),
// uvf:
entity.getUvfMetadataFile(), entity.getUvfKeySet(),
// legacy properties:
entity.getMasterkey(), entity.getIterations(), entity.getSalt(), entity.getAuthenticationPublicKey(), entity.getAuthenticationPrivateKey());
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ SELECT COUNT(DISTINCT u.id)
FROM EffectiveVaultAccess eva
WHERE eva.id.vaultId = :vaultId AND eva.id.authorityId = :authorityId
""")
@NamedQuery(name = "EffectiveVaultAccess.findMembersWithoutAccessTokens", query = """
SELECT eva
FROM EffectiveVaultAccess eva
INNER JOIN FETCH eva.authority u
LEFT JOIN AccessToken token ON token.id.vaultId = eva.id.vaultId AND token.id.userId = u.id
WHERE eva.id.vaultId = :vaultId AND token.vault IS NULL AND u.ecdhPublicKey IS NOT NULL
"""
)
public class EffectiveVaultAccess {

@EmbeddedId
Expand Down Expand Up @@ -141,10 +149,14 @@ public long countSeatOccupyingUsersOfGroup(String groupId) {

public Collection<VaultAccess.Role> listRoles(UUID vaultId, String authorityId) {
return find("#EffectiveVaultAccess.findByAuthorityAndVault", Parameters.with("vaultId", vaultId).and("authorityId", authorityId)).stream()
.map(eva -> eva.getId().role())
.map(EffectiveVaultAccess::getRole)
.collect(Collectors.toUnmodifiableSet());
}

public Stream<EffectiveVaultAccess> findMembersWithoutAccessTokens(UUID vaultId) {
return find("#EffectiveVaultAccess.findMembersWithoutAccessTokens", Parameters.with("vaultId", vaultId)).stream();
}

public Stream<String> usersSeatedOnOtherVaults(UUID vaultId) {
return find("#EffectiveVaultAccess.usersSeatedOnOtherVaults", Parameters.with("vaultId", vaultId)).project(String.class).stream();
}
Expand Down
37 changes: 27 additions & 10 deletions backend/src/main/java/org/cryptomator/hub/entities/Vault.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ public class Vault {
@Column(name = "emergency_key_share")
private Map<String, String> emergencyKeyShares = new HashMap<>();

@Column(name = "uvf_metadata_file")
private String uvfMetadataFile;

@Column(name = "uvf_jwks")
private String uvfKeySet;

public Optional<ECPublicKey> getAuthenticationPublicKeyOptional() {
if (authenticationPublicKey == null) {
return Optional.empty();
Expand Down Expand Up @@ -256,24 +262,33 @@ public void setEmergencyKeyShares(Map<String, String> emergencyKeyShares) {
this.emergencyKeyShares.putAll(emergencyKeyShares);
}

public String getUvfMetadataFile() {
return uvfMetadataFile;
}

public void setUvfMetadataFile(String uvfMetadataFile) {
this.uvfMetadataFile = uvfMetadataFile;
}

public String getUvfKeySet() {
return uvfKeySet;
}

public void setUvfKeySet(String uvfKeySet) {
this.uvfKeySet = uvfKeySet;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Vault vault = (Vault) o;
return Objects.equals(id, vault.id)
&& Objects.equals(name, vault.name)
&& Objects.equals(salt, vault.salt)
&& Objects.equals(iterations, vault.iterations)
&& Objects.equals(masterkey, vault.masterkey)
&& Objects.equals(archived, vault.archived)
&& Objects.equals(requiredEmergencyKeyShares, vault.requiredEmergencyKeyShares)
&& Objects.equals(emergencyKeyShares, vault.emergencyKeyShares);
return Objects.equals(id, vault.id);
}

@Override
public int hashCode() {
return Objects.hash(id, name, salt, iterations, masterkey, archived, requiredEmergencyKeyShares, emergencyKeyShares);
return Objects.hash(id);
}

@Override
Expand All @@ -283,14 +298,16 @@ public String toString() {
", members=" + directMembers.stream().map(Authority::getId).collect(Collectors.joining(", ")) +
", accessToken=" + accessTokens.stream().map(a -> a.getId().toString()).collect(Collectors.joining(", ")) +
", name='" + name + '\'' +
", archived='" + archived + '\'' +
", salt='" + salt + '\'' +
", iterations='" + iterations + '\'' +
", masterkey='" + masterkey + '\'' +
", authenticationPublicKey='" + authenticationPublicKey + '\'' +
", authenticationPrivateKey='" + authenticationPrivateKey + '\'' +
", requiredEmergencyKeyShares='" + requiredEmergencyKeyShares + '\'' +
", emergencyKeyShares=" + emergencyKeyShares.keySet().stream().collect(Collectors.joining(", ")) +
", archived='" + archived + '\'' +
", uvfMetadataFile='" + uvfMetadataFile + '\'' +
", uvfKeySet='" + uvfKeySet + '\'' +
'}';
}

Expand Down
Binary file modified backend/src/main/resources/org/cryptomator/hub/flyway/ERM.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE vault ADD uvf_metadata_file VARCHAR UNIQUE; -- vault.uvf file, encrypted as JWE
ALTER TABLE vault ADD uvf_jwks VARCHAR UNIQUE; -- encoded as JWKs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ void testUpdateVaultDespiteLicenseExceeded() {
Assumptions.assumeTrue(vaultResourceIT.effectiveVaultAccessRepo.countSeatOccupyingUsers() == 5);
var vaultId = "7E57C0DE-0000-4000-8000-000100001111";

var vaultDto = new VaultResource.VaultDto(UUID.fromString(vaultId), "Vault 1", Instant.parse("2222-11-11T11:11:11Z"), "This is a testvault.", false, 0, Map.of(), "someVaule", -1, "doNotUpdate", "doNotUpdate", "doNotUpdate");
var vaultDto = new VaultResource.VaultDto(UUID.fromString(vaultId), "Vault 1", Instant.parse("2222-11-11T11:11:11Z"), "This is a testvault.", false, 0, Map.of(), "doNotUpdate", "doNotUpdate", "someVaule", -1, "doNotUpdate", "doNotUpdate", "doNotUpdate");
given().contentType(ContentType.JSON)
.body(vaultDto)
.when().put("/vaults/{vaultId}", vaultId)
Expand All @@ -207,7 +207,7 @@ void testCreateVaultExceedingSeats() throws SQLException {
Assumptions.assumeTrue(vaultResourceIT.effectiveVaultAccessRepo.countSeatOccupyingUsers() > 5);

var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-0001FFFF3333");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 4", false, 0, Map.of(), "masterkey3", 42, "NaCl", "authPubKey3", "authPrvKey3");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 4", false, 0, Map.of(), "uvfMetadata3", "uvfKeySet3", "masterkey3", 42, "NaCl", "authPubKey3", "authPrvKey3");
given().contentType(ContentType.JSON).body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-0001FFFF3333")
.then().statusCode(402);
Expand Down Expand Up @@ -235,7 +235,7 @@ void unarchiveVaultExceedingSeats() {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-00010000AAAA ignores archived flag in createOrUpdate")
void createOrUpdateIgnoresArchivedFlag() {
var vaultId = "7E57C0DE-0000-4000-8000-00010000AAAA";
var vaultDto = new VaultResource.VaultDto(UUID.fromString(vaultId), "Vault Archived", Instant.parse("2020-02-20T20:20:20Z"), "This is a archived vault.", false, 0, Map.of(), "masterkey3", 42, "salt3", "doNotUpdate", "doNotUpdate");
var vaultDto = new VaultResource.VaultDto(UUID.fromString(vaultId), "Vault Archived", Instant.parse("2020-02-20T20:20:20Z"), "This is a archived vault.", false, 0, Map.of(), "uvfMetadata3", "uvfKeySet3", "masterkey3", 42, "salt3", "doNotUpdate", "doNotUpdate");
given().contentType(ContentType.JSON)
.body(vaultDto)
.when().put("/vaults/{vaultId}", vaultId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,12 @@ class TestVaultDtoValidation {
private static final String VALID_SALT = "base64";
private static final String VALID_AUTH_PUB = "base64";
private static final String VALID_AUTH_PRI = "base64";
private static final String VALID_UVF_METADATA_FILE = "{json}";
private static final String VALID_UVF_RECOVERY_KEY = "base64";

@Test
void testValidDto() {
var dto = new VaultResource.VaultDto(VALID_ID, VALID_NAME, Instant.parse("2020-02-20T20:20:20Z"), "foobarbaz", false, 0, Map.of(), VALID_MASTERKEY, 8, VALID_SALT, VALID_AUTH_PUB, VALID_AUTH_PRI);
var dto = new VaultResource.VaultDto(VALID_ID, VALID_NAME, Instant.parse("2020-02-20T20:20:20Z"), "foobarbaz", false, 0, Map.of(), VALID_UVF_METADATA_FILE, VALID_UVF_RECOVERY_KEY, VALID_MASTERKEY, 8, VALID_SALT, VALID_AUTH_PUB, VALID_AUTH_PRI);
var violations = validator.validate(dto);
MatcherAssert.assertThat(violations, Matchers.empty());
}
Expand Down Expand Up @@ -339,7 +341,7 @@ void testUnlock() {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-000100003333 returns 403 for missing role")
void testCreateVaultWithMissingRole() {
var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-000100003333");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 3", false, 0, Map.of(), "masterkey3", 42, "NaCl", "authPubKey3", "authPrvKey3");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 3", false, 0, Map.of(), "uvfMetadata3", "uvfKeySet3", "masterkey3", 42, "NaCl", "authPubKey3", "authPrvKey3");

given().contentType(ContentType.JSON).body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-000100003333")
Expand All @@ -362,7 +364,7 @@ class CreateVaults {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-000100003333 returns 201")
void testCreateVault1() {
var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-000100003333");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 3", false, 0, Map.of(), "masterkey3", 42, "NaCl", "authPubKey3", "authPrvKey3");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 3", false, 0, Map.of(), "uvfMetadata3", "uvfKeySet3", "masterkey3", 42, "NaCl", "authPubKey3", "authPrvKey3");

given().contentType(ContentType.JSON).body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-000100003333")
Expand All @@ -387,7 +389,7 @@ void testCreateVault2() {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-000100004444 returns 201 ignoring archived flag")
void testCreateVault3() {
var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-000100004444");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 4", true, 0, Map.of(), "masterkey4", 42, "NaCl", "authPubKey4", "authPrvKey4");
var vaultDto = new VaultResource.VaultDto(uuid, "My Vault", Instant.parse("2112-12-21T21:12:21Z"), "Test vault 4", true, 0, Map.of(), "uvfMetadata4", "uvfKeySet4", "masterkey4", 42, "NaCl", "authPubKey4", "authPrvKey4");

given().contentType(ContentType.JSON).body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-000100004444")
Expand All @@ -403,7 +405,7 @@ void testCreateVault3() {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-000100003333 returns 200, updating only name and description (archived flag ignored)")
void testUpdateVault() {
var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-000100003333");
var vaultDto = new VaultResource.VaultDto(uuid, "VaultUpdated", Instant.parse("2222-11-11T11:11:11Z"), "Vault updated.", true, 0, Map.of(), "doNotUpdate", 27, "doNotUpdate", "doNotUpdate", "doNotUpdate");
var vaultDto = new VaultResource.VaultDto(uuid, "VaultUpdated", Instant.parse("2222-11-11T11:11:11Z"), "Vault updated.", true, 0, Map.of(), "doNotUpdate", "doNotUpdate", "doNotUpdate", 27, "doNotUpdate", "doNotUpdate", "doNotUpdate");
given().contentType(ContentType.JSON)
.body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-000100003333")
Expand Down Expand Up @@ -1002,7 +1004,7 @@ void testAdminUnarchiveVault() {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-000100001111 returns 403 for admin updating vault they don't own")
void testAdminCannotUpdateVaultTheyDontOwn() {
var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-000100001111");
var vaultDto = new VaultResource.VaultDto(uuid, "Vault 1", Instant.parse("2020-02-20T20:20:20Z"), "This is a testvault.", true, 0, Map.of(), "masterkey1", 42, "salt1", "authPubKey1", "authPrvKey1");
var vaultDto = new VaultResource.VaultDto(uuid, "Vault 1", Instant.parse("2020-02-20T20:20:20Z"), "This is a testvault.", true, 0, Map.of(), "uvfMetadata1", "uvfKeySet1", "masterkey1", 42, "salt1", "authPubKey1", "authPrvKey1");

given().contentType(ContentType.JSON).body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-000100001111")
Expand All @@ -1014,7 +1016,7 @@ void testAdminCannotUpdateVaultTheyDontOwn() {
@DisplayName("PUT /vaults/7E57C0DE-0000-4000-8000-000100005555 returns 403 for admin creating vault without create-vaults role")
void testAdminCannotCreateVaultWithoutCreateVaultsRole() {
var uuid = UUID.fromString("7E57C0DE-0000-4000-8000-000100005555");
var vaultDto = new VaultResource.VaultDto(uuid, "New Vault", Instant.parse("2112-12-21T21:12:21Z"), "Should not be created", false, 0, Map.of(), "masterkey5", 42, "NaCl", "authPubKey5", "authPrvKey5");
var vaultDto = new VaultResource.VaultDto(uuid, "New Vault", Instant.parse("2112-12-21T21:12:21Z"), "Should not be created", false, 0, Map.of(), "uvfMetadata5", "uvfKeySet5", "masterkey5", 42, "NaCl", "authPubKey5", "authPrvKey5");

given().contentType(ContentType.JSON).body(vaultDto)
.when().put("/vaults/{vaultId}", "7E57C0DE-0000-4000-8000-000100005555")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,18 @@ VALUES
('7E57C0DE-0000-4000-8000-000100001111', 'Vault 1', 'This is a testvault.', '2020-02-20 20:20:20', 'salt1', 42, 'masterkey1',
'MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAElS+JW3VaBvVr9GKZGn1399WDTd61Q9fwQMmZuBGAYPdl/rWk705QY6WhlmbokmEVva/mEHSoNQ98wFm9FBCqzh45IGd/DGwZ04Xhi5ah+1bKbkVhtds8nZtHRdSJokYp',
'MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAa57e0Q/KAqmIVOVcWX7b+Sm5YVNRUx8W7nc4wk1IBj2QJmsj+MeShQRHG4ozTE9KhZANiAASVL4lbdVoG9Wv0YpkafXf31YNN3rVD1/BAyZm4EYBg92X+taTvTlBjpaGWZuiSYRW9r+YQdKg1D3zAWb0UEKrOHjkgZ38MbBnTheGLlqH7VspuRWG12zydm0dF1ImiRik=',
FALSE),
FALSE
),
('7E57C0DE-0000-4000-8000-000100002222', 'Vault 2', 'This is a testvault.', '2020-02-20 20:20:20', 'salt2', 42, 'masterkey2',
'MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii1D3jaW6pmGVJFhodzC31cy5sfOYotrzF',
'MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCAHpFQ62QnGCEvYh/pE9QmR1C9aLcDItRbslbmhen/h1tt8AyMhskeenT+rAyyPhGhZANiAAQLW5ZJePZzMIPAxMtZXkEWbDF0zo9f2n4+T1h/2sh/fviblc/VTyrv10GEtIi5qiOy85Pf1RRw8lE5IPUWpgu553SteKigiKLUPeNpbqmYZUkWGh3MLfVzLmx85ii2vMU=',
FALSE),
FALSE
),
('7E57C0DE-0000-4000-8000-00010000AAAA', 'Vault Archived', 'This is a archived vault.', '2020-02-20 20:20:20', 'salt3', 42, 'masterkey3',
'MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii1D3jaW6pmGVJFhodzC31cy5sfOYotrzF',
'MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCAHpFQ62QnGCEvYh/pE9QmR1C9aLcDItRbslbmhen/h1tt8AyMhskeenT+rAyyPhGhZANiAAQLW5ZJePZzMIPAxMtZXkEWbDF0zo9f2n4+T1h/2sh/fviblc/VTyrv10GEtIi5qiOy85Pf1RRw8lE5IPUWpgu553SteKigiKLUPeNpbqmYZUkWGh3MLfVzLmx85ii2vMU=',
TRUE);
TRUE
);

INSERT INTO "vault_access" ("vault_id", "authority_id", "role")
VALUES
Expand Down
Loading