Skip to content

Commit

Permalink
Merge branch 'release/1.3.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Jan 10, 2024
2 parents 05c6b42 + 4afc33d commit 03cd1af
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 54 deletions.
2 changes: 1 addition & 1 deletion backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>hub-backend</artifactId>
<version>1.3.0</version>
<version>1.3.1</version>

<properties>
<compiler-plugin.version>3.11.0 </compiler-plugin.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public ConfigDto getConfig() {
var authUri = replacePrefix(oidcConfData.getAuthorizationUri(), trimTrailingSlash(internalRealmUrl), publicRealmUri);
var tokenUri = replacePrefix(oidcConfData.getTokenUri(), trimTrailingSlash(internalRealmUrl), publicRealmUri);

return new ConfigDto(keycloakPublicUrl, keycloakRealm, keycloakClientIdHub, keycloakClientIdCryptomator, authUri, tokenUri, Instant.now().truncatedTo(ChronoUnit.MILLIS), 1);
return new ConfigDto(keycloakPublicUrl, keycloakRealm, keycloakClientIdHub, keycloakClientIdCryptomator, authUri, tokenUri, Instant.now().truncatedTo(ChronoUnit.MILLIS), 2);
}

//visible for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ public Response legacyUnlock(@PathParam("vaultId") UUID vaultId, @PathParam("dev
@APIResponse(responseCode = "410", description = "Vault is archived. Only returned if evenIfArchived query param is false or not set, otherwise the archived flag is ignored")
@APIResponse(responseCode = "449", description = "User account not yet initialized. Retry after setting up user")
@ActiveLicense // may throw 402
public String unlock(@PathParam("vaultId") UUID vaultId, @QueryParam("evenIfArchived") @DefaultValue("false") boolean ignoreArchived) {
public Response unlock(@PathParam("vaultId") UUID vaultId, @QueryParam("evenIfArchived") @DefaultValue("false") boolean ignoreArchived) {
var vault = Vault.<Vault>findById(vaultId); // should always be found, since @VaultRole filter would have triggered
if (vault.archived && !ignoreArchived) {
throw new GoneException("Vault is archived.");
Expand All @@ -316,7 +316,9 @@ public String unlock(@PathParam("vaultId") UUID vaultId, @QueryParam("evenIfArch
var access = AccessToken.unlock(vaultId, jwt.getSubject());
if (access != null) {
AuditEventVaultKeyRetrieve.log(jwt.getSubject(), vaultId, AuditEventVaultKeyRetrieve.Result.SUCCESS);
return access.vaultKey;
var subscriptionStateHeaderName = "Hub-Subscription-State";
var subscriptionStateHeaderValue = license.isSet() ? "ACTIVE" : "INACTIVE"; // license expiration is not checked here, because it is checked in the ActiveLicense filter
return Response.ok(access.vaultKey).header(subscriptionStateHeaderName, subscriptionStateHeaderValue).build();
} else if (Vault.findById(vaultId) == null) {
throw new NotFoundException("No such vault.");
} else {
Expand Down
6 changes: 3 additions & 3 deletions frontend/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"[typescript]": {
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll.tslint": true
"source.organizeImports": "explicit",
"source.fixAll.tslint": "explicit"
},
"editor.foldingStrategy": "indentation",
"editor.formatOnSave": true,
Expand All @@ -27,4 +27,4 @@
"mochaExplorer.files": "test/**/*.spec.ts",
"mochaExplorer.require": "ts-node/register",
"eslint.validate": ["typescript", "javascript", "vue"]
}
}
22 changes: 18 additions & 4 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
# Vue 3 + Typescript + Vite
# Cryptomator Frontend

This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
This project uses Vue 3 + Typescript + Vite.

## Recommended IDE Setup

- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)

## Type Support For `.vue` Imports in TS
## Dev Mode

Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's `.vue` type support plugin by running `Volar: Switch TS Plugin on/off` from VSCode command palette.
You can run your application in dev mode that enables live coding using:

```shell script
npm install
npm run dev
```

## Production Build

To build an optimized (production) version of the app, run:

```shell script
npm install
npm run dist
```
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 20 additions & 20 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cryptomator-hub",
"version": "1.3.0",
"version": "1.3.1",
"description": "Web-Frontend for Cryptomator Hub",
"author": "Skymatic GmbH",
"license": "AGPL-3.0-or-later",
Expand All @@ -12,26 +12,26 @@
"lint": "eslint -c .eslintrc.js",
"test": "nyc --reporter lcov mocha -r ts-node/register test/**/*.spec.ts",
"serve": "vite preview",
"dist": "vite build --sourcemap --outDir=\"../backend/src/main/resources/META-INF/resources\" --emptyOutDir"
"dist": "vue-tsc --noEmit && vite build --sourcemap --outDir=\"../backend/src/main/resources/META-INF/resources\" --emptyOutDir"
},
"directories": {
"src": "./src",
"test": "./test"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^1.4.0",
"@tailwindcss/forms": "^0.5.6",
"@types/blueimp-md5": "^2.18.1",
"@types/chai": "^4.3.9",
"@types/chai-as-promised": "^7.1.7",
"@types/file-saver": "^2.0.6",
"@types/mocha": "^10.0.3",
"@tailwindcss/forms": "^0.5.7",
"@types/blueimp-md5": "^2.18.2",
"@types/chai": "^4.3.11",
"@types/chai-as-promised": "^7.1.8",
"@types/file-saver": "^2.0.7",
"@types/mocha": "^10.0.6",
"@types/node": "^20.8.10",
"@types/semver": "^7.5.4",
"@types/semver": "^7.5.6",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/compiler-sfc": "^3.3.4",
"@vitejs/plugin-vue": "^4.4.1",
"@vue/compiler-sfc": "^3.3.13",
"autoprefixer": "^10.4.16",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
Expand All @@ -40,27 +40,27 @@
"eslint-plugin-vue": "^9.18.1",
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"postcss": "^8.4.31",
"tailwindcss": "^3.3.5",
"ts-node": "^10.9.1",
"postcss": "^8.4.33",
"tailwindcss": "^3.3.7",
"ts-node": "^10.9.2",
"typescript": "^5.2.2",
"vite": "^4.5.0",
"vue-tsc": "^1.8.22"
"vite": "^4.5.1",
"vue-tsc": "^1.8.27"
},
"dependencies": {
"@headlessui/tailwindcss": "^0.2.0",
"@headlessui/vue": "^1.7.16",
"@headlessui/vue": "^1.7.17",
"@heroicons/vue": "^2.0.18",
"axios": "^1.6.0",
"axios": "^1.6.5",
"file-saver": "^2.0.5",
"jdenticon": "^3.2.0",
"jszip": "^3.10.1",
"keycloak-js": "^22.0.5",
"miscreant": "^0.3.2",
"rfc4648": "^1.5.3",
"semver": "^7.5.4",
"vue": "^3.3.4",
"vue-i18n": "^9.6.2",
"vue": "^3.3.13",
"vue-i18n": "^9.6.5",
"vue-router": "^4.2.5"
}
}
4 changes: 2 additions & 2 deletions frontend/src/components/DeviceList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ async function determineMyDevice() {
throw new Error('User not initialized.');
}
const browserKeys = await BrowserKeys.load(me.value.id);
const browserId = await browserKeys.id();
const browserId = await browserKeys?.id();
myDevice.value = me.value.devices.find(d => d.id == browserId);
}
Expand All @@ -138,7 +138,7 @@ async function determineMyDevice() {
// /* decrypt user key on this browser: */
// const userPublicKey = crypto.subtle.importKey('spki', base64.parse(me.value.publicKey), UserKeys.KEY_DESIGNATION, false, []);
// const browserKeys = await BrowserKeys.load(me.value.id);
// const browserId = await browserKeys.id();
// const browserId = await browserKeys?.id();
// const browser = me.value.devices.find(d => d.id === browserId);
// if (!browser || !browser.userPrivateKey) {
// throw new Error('Browser not validated.');
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/ManageSetupCode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ async function fetchData() {
throw new Error('User not initialized.');
}
const browserKeys = await BrowserKeys.load(me.id);
if (browserKeys == null) {
throw new Error('Browser keys not found.');
}
const browserId = await browserKeys.id();
const myDevice = me.devices.find(d => d.id == browserId);
if (myDevice == null) {
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/RegenerateSetupCodeDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ async function regenerateSetupCode() {
throw new Error('User not initialized.');
}
const browserKeys = await BrowserKeys.load(me.id);
if (browserKeys == null) {
throw new Error('Browser keys not found.');
}
const browserId = await browserKeys.id();
const myDevice = me.devices.find(d => d.id == browserId);
if (myDevice == null) {
Expand Down
33 changes: 17 additions & 16 deletions frontend/src/components/VaultDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@
{{ t('vaultDetails.recoverVault') }}
</button>
</div>

</div>

<ClaimVaultOwnershipDialog v-if="claimingVaultOwnership && vault != null" ref="claimVaultOwnershipDialog" :vault="vault" @action="provedOwnership" @close="claimingVaultOwnership = false" />
Expand Down Expand Up @@ -260,28 +259,30 @@ async function fetchData() {
}
async function fetchOwnerData() {
try {
const vaultKeyJwe = await backend.vaults.accessToken(props.vaultId, true);
vaultKeys.value = await loadVaultKeys(vaultKeyJwe);
(await backend.vaults.getMembers(props.vaultId)).forEach(member => members.value.set(member.id, member));
usersRequiringAccessGrant.value = await backend.vaults.getUsersRequiringAccessGrant(props.vaultId);
vaultRecoveryRequired.value = false;
} catch(error) {
if (error instanceof ForbiddenError) {
vaultRecoveryRequired.value = true;
} else {
console.error('Retrieving ownership failed.', error);
onFetchError.value = error instanceof Error ? error : new Error('Unknown Error');
}
try {
const vaultKeyJwe = await backend.vaults.accessToken(props.vaultId, true);
vaultKeys.value = await loadVaultKeys(vaultKeyJwe);
(await backend.vaults.getMembers(props.vaultId)).forEach(member => members.value.set(member.id, member));
usersRequiringAccessGrant.value = await backend.vaults.getUsersRequiringAccessGrant(props.vaultId);
vaultRecoveryRequired.value = false;
} catch (error) {
if (error instanceof ForbiddenError) {
vaultRecoveryRequired.value = true;
} else {
console.error('Retrieving ownership failed.', error);
onFetchError.value = error instanceof Error ? error : new Error('Unknown Error');
}
}
}
async function loadVaultKeys(vaultKeyJwe: string): Promise<VaultKeys> {
if (!me.value || !me.value.publicKey) {
throw new Error('User not initialized.');
}
const browserKeys = await BrowserKeys.load(me.value.id);
if (browserKeys == null) {
throw new Error('Browser keys not found.');
}
const browserId = await browserKeys.id();
const myDevice = me.value.devices.find(d => d.id == browserId);
if (myDevice == null) {
Expand Down Expand Up @@ -421,7 +422,7 @@ function refreshVault(updatedVault: VaultDto) {
}
async function reloadView() {
await fetchOwnerData()
await fetchOwnerData();
vaultRecoveryRequired.value = false;
}
Expand Down
1 change: 1 addition & 0 deletions frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"noUnusedLocals": true,
"useUnknownInCatchVariables": false, // Workaround for `node_modules/miscreant/src/providers/webcrypto.ts:21:11 - error TS18046: 'e' is of type 'unknown'.`
},
"ts-node": {
"compilerOptions": {
Expand Down
6 changes: 3 additions & 3 deletions hub.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"typescript.referencesCodeLens.enabled": true,
"typescript.implementationsCodeLens.enabled": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll.eslint": true
"source.organizeImports": "explicit",
"source.fixAll.eslint": "explicit"
}
}
}
}

0 comments on commit 03cd1af

Please sign in to comment.