Skip to content
Snippets Groups Projects
Verified Commit 1d1178ae authored by Daniel Göbel's avatar Daniel Göbel
Browse files

Fetch s3 keys with data repository architecture

#67
parent 33b21ea9
No related branches found
No related tags found
2 merge requests!84Remove development branch,!62Resolve "UI improvements"
This commit is part of merge request !62. Comments created here will be created in the context of that merge request.
...@@ -119,7 +119,7 @@ function modalClosed() { ...@@ -119,7 +119,7 @@ function modalClosed() {
class="form-control" class="form-control"
id="bucketDescriptionInput" id="bucketDescriptionInput"
required required
rows="5" rows="3"
minlength="32" minlength="32"
maxlength="65536" maxlength="65536"
v-model="bucket.description" v-model="bucket.description"
......
import { defineStore } from "pinia";
import { useAuthStore } from "@/stores/users";
import type { S3Key } from "@/client/s3proxy";
import { S3KeyService } from "@/client/s3proxy";
export const useS3KeyStore = defineStore({
id: "s3keys",
state: () =>
({
keyMapping: {},
}) as {
keyMapping: Record<string, S3Key>;
},
getters: {
keys(): S3Key[] {
const tempList = Object.values(this.keyMapping);
tempList.sort((keyA, keyB) =>
keyA.access_key > keyB.access_key ? 1 : -1,
);
return tempList;
},
},
actions: {
fetchS3Keys(uid: string, onFinally?: () => void): Promise<S3Key[]> {
if (this.keys.length > 0) {
onFinally?.();
}
return S3KeyService.s3KeyGetUserKeys(uid)
.then((keys) => {
const newMapping: Record<string, S3Key> = {};
for (const key of keys) {
newMapping[key.access_key] = key;
}
this.keyMapping = newMapping;
return keys;
})
.finally(onFinally);
},
deleteS3Key(access_id: string): Promise<void> {
const userRepository = useAuthStore();
return S3KeyService.s3KeyDeleteUserKey(
access_id,
userRepository.currentUID,
).then(() => {
delete this.keyMapping[access_id];
});
},
createS3Key(): Promise<S3Key> {
const userRepository = useAuthStore();
return S3KeyService.s3KeyCreateUserKey(userRepository.currentUID).then(
(key) => {
this.keyMapping[key.access_key] = key;
return key;
},
);
},
},
});
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import type { User } from "@/client/auth"; import type { User } from "@/client/auth";
import { UserService, RoleEnum } from "@/client/auth"; import { UserService, RoleEnum } from "@/client/auth";
import { S3KeyService } from "@/client/s3proxy";
import type { S3Key } from "@/client/s3proxy";
import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy"; import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy";
import { OpenAPI as AuthOpenAPI } from "@/client/auth"; import { OpenAPI as AuthOpenAPI } from "@/client/auth";
import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow"; import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow";
import { useWorkflowExecutionStore } from "@/stores/workflowExecutions"; import { useWorkflowExecutionStore } from "@/stores/workflowExecutions";
import { useBucketStore } from "@/stores/buckets"; import { useBucketStore } from "@/stores/buckets";
import { useWorkflowStore } from "@/stores/workflows"; import { useWorkflowStore } from "@/stores/workflows";
import { useS3KeyStore } from "@/stores/s3keys";
type DecodedToken = { type DecodedToken = {
exp: number; exp: number;
...@@ -21,7 +20,6 @@ export type RootState = { ...@@ -21,7 +20,6 @@ export type RootState = {
token: string | null; token: string | null;
decodedToken: DecodedToken | null; decodedToken: DecodedToken | null;
user: User | null; user: User | null;
s3key: S3Key | null;
userMapping: Record<string, string>; userMapping: Record<string, string>;
}; };
...@@ -48,7 +46,6 @@ export const useAuthStore = defineStore({ ...@@ -48,7 +46,6 @@ export const useAuthStore = defineStore({
token: null, token: null,
decodedToken: null, decodedToken: null,
user: null, user: null,
s3key: null,
userMapping: {}, userMapping: {},
}) as RootState, }) as RootState,
getters: { getters: {
...@@ -105,28 +102,17 @@ export const useAuthStore = defineStore({ ...@@ -105,28 +102,17 @@ export const useAuthStore = defineStore({
this.user = null; this.user = null;
} }
}, },
setS3Key(key: S3Key | null) {
this.s3key = key;
},
updateUser(user: User) { updateUser(user: User) {
this.user = user; this.user = user;
S3KeyService.s3KeyGetUserKeys(user.uid) const keyRepository = useS3KeyStore();
.then((keys) => { keyRepository.fetchS3Keys(user.uid);
if (keys.length > 0) {
this.setS3Key(keys[0]);
} else {
this.setS3Key(null);
}
})
.catch(() => {
this.setS3Key(null);
});
}, },
logout() { logout() {
this.$reset(); this.$reset();
useWorkflowExecutionStore().$reset(); useWorkflowExecutionStore().$reset();
useBucketStore().$reset(); useBucketStore().$reset();
useWorkflowStore().$reset(); useWorkflowStore().$reset();
useS3KeyStore().$reset();
}, },
fetchUsernames(uids: string[]): Promise<User[]> { fetchUsernames(uids: string[]): Promise<User[]> {
const filteredIds = uids const filteredIds = uids
......
...@@ -32,9 +32,11 @@ import { awsAuthMiddlewareOptions } from "@aws-sdk/middleware-signing"; ...@@ -32,9 +32,11 @@ import { awsAuthMiddlewareOptions } from "@aws-sdk/middleware-signing";
import { useAuthStore } from "@/stores/users"; import { useAuthStore } from "@/stores/users";
import { useBucketStore } from "@/stores/buckets"; import { useBucketStore } from "@/stores/buckets";
import { environment } from "@/environment"; import { environment } from "@/environment";
import { useS3KeyStore } from "@/stores/s3keys";
const authStore = useAuthStore(); const authStore = useAuthStore();
const bucketRepository = useBucketStore(); const bucketRepository = useBucketStore();
const keyRepository = useS3KeyStore();
const middleware = [ const middleware = [
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
...@@ -49,39 +51,20 @@ const middleware = [ ...@@ -49,39 +51,20 @@ const middleware = [
}, },
]; ];
let client = new S3Client({ const client = computed<S3Client>(() => {
region: "us-east-1", const client = new S3Client({
endpoint: environment.S3_URL, region: "us-east-1",
forcePathStyle: true, endpoint: environment.S3_URL,
credentials: { forcePathStyle: true,
accessKeyId: authStore.s3key?.access_key ?? "", credentials: {
secretAccessKey: authStore.s3key?.secret_key ?? "", accessKeyId: keyRepository.keys[0]?.access_key ?? "",
}, secretAccessKey: keyRepository.keys[0]?.secret_key ?? "",
}); },
// eslint-disable-next-line @typescript-eslint/ban-ts-comment });
// @ts-ignore // eslint-disable-next-line @typescript-eslint/ban-ts-comment
client.middlewareStack.addRelativeTo(middleware[0], middleware[1]); // @ts-ignore
client.middlewareStack.addRelativeTo(middleware[0], middleware[1]);
// If S3 Key changes return client;
authStore.$onAction(({ name, args }) => {
if (name === "setS3Key") {
if (args[0] === null) {
console.error("There are no S3 Keys");
} else {
client = new S3Client({
region: "us-east-1",
endpoint: environment.S3_URL,
forcePathStyle: true,
credentials: {
accessKeyId: args[0].access_key,
secretAccessKey: args[0].secret_key,
},
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
client.middlewareStack.addRelativeTo(middleware[0], middleware[1]);
}
}
}); });
// Constants // Constants
...@@ -427,7 +410,7 @@ function confirmedDeleteObject(key: string) { ...@@ -427,7 +410,7 @@ function confirmedDeleteObject(key: string) {
Bucket: props.bucketName, Bucket: props.bucketName,
Key: key, Key: key,
}); });
client client.value
.send(command) .send(command)
.then(() => { .then(() => {
bucketRepository.fetchBucket(props.bucketName); bucketRepository.fetchBucket(props.bucketName);
...@@ -453,7 +436,7 @@ async function downloadObject(key: string, bucket: string) { ...@@ -453,7 +436,7 @@ async function downloadObject(key: string, bucket: string) {
Bucket: bucket, Bucket: bucket,
Key: key, Key: key,
}); });
const url = await getSignedUrl(client, command, { expiresIn: 30 }); const url = await getSignedUrl(client.value, command, { expiresIn: 30 });
//creating an invisible element //creating an invisible element
const element = document.createElement("a"); const element = document.createElement("a");
element.setAttribute("href", url); element.setAttribute("href", url);
...@@ -483,7 +466,7 @@ function confirmedDeleteFolder(folderPath: string) { ...@@ -483,7 +466,7 @@ function confirmedDeleteFolder(folderPath: string) {
}), }),
}, },
}); });
client client.value
.send(command) .send(command)
.then(() => { .then(() => {
bucketRepository.fetchBucket(props.bucketName); bucketRepository.fetchBucket(props.bucketName);
......
...@@ -2,42 +2,37 @@ ...@@ -2,42 +2,37 @@
import S3KeyView from "@/views/object-storage/S3KeyView.vue"; import S3KeyView from "@/views/object-storage/S3KeyView.vue";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import { reactive, onMounted, computed } from "vue"; import { reactive, onMounted, computed } from "vue";
import type { S3Key } from "@/client/s3proxy";
import { S3KeyService } from "@/client/s3proxy";
import { useAuthStore } from "@/stores/users"; import { useAuthStore } from "@/stores/users";
import { Toast, Tooltip } from "bootstrap"; import { Toast, Tooltip } from "bootstrap";
import { useS3KeyStore } from "@/stores/s3keys";
const authStore = useAuthStore(); const authStore = useAuthStore();
const keyRepository = useS3KeyStore();
let successToast: Toast | null = null; let successToast: Toast | null = null;
let refreshTimeout: NodeJS.Timeout | undefined = undefined; let refreshTimeout: NodeJS.Timeout | undefined = undefined;
const keyState = reactive<{ const keyState = reactive<{
keys: S3Key[];
activeKey: number; activeKey: number;
initialLoading: boolean; initialLoading: boolean;
deletedKey: string; deletedKey: string;
}>({ }>({
keys: [],
activeKey: 0, activeKey: 0,
initialLoading: true, initialLoading: true,
deletedKey: "", deletedKey: "",
}); });
const allowKeyDeletion = computed<boolean>(() => keyState.keys.length > 1); const allowKeyDeletion = computed<boolean>(() => keyRepository.keys.length > 1);
function fetchKeys() { function fetchKeys() {
S3KeyService.s3KeyGetUserKeys(authStore.currentUID) keyRepository
.fetchS3Keys(authStore.currentUID, () => (keyState.initialLoading = false))
.then((keys) => { .then((keys) => {
if (keyState.activeKey >= keys.length) { if (keyState.activeKey >= keys.length) {
keyState.activeKey = keys.length - 1; keyState.activeKey = keys.length - 1;
} }
keyState.keys = keys;
}) })
.catch((err) => console.error(err)) .catch((err) => console.error(err));
.finally(() => {
keyState.initialLoading = false;
});
} }
function refreshKeys() { function refreshKeys() {
...@@ -49,14 +44,11 @@ function refreshKeys() { ...@@ -49,14 +44,11 @@ function refreshKeys() {
function deleteKey(accessKey: string) { function deleteKey(accessKey: string) {
if (allowKeyDeletion.value && authStore.authenticated) { if (allowKeyDeletion.value && authStore.authenticated) {
S3KeyService.s3KeyDeleteUserKey(accessKey, authStore.currentUID) keyRepository
.deleteS3Key(accessKey)
.then(() => { .then(() => {
keyState.deletedKey = accessKey;
keyState.activeKey = 0; keyState.activeKey = 0;
keyState.keys = keyState.keys.filter( keyState.deletedKey = accessKey;
(s3key) => s3key.access_key !== accessKey,
);
authStore.setS3Key(keyState.keys[0]);
successToast?.show(); successToast?.show();
}) })
.catch((err) => console.error(err)); .catch((err) => console.error(err));
...@@ -65,14 +57,7 @@ function deleteKey(accessKey: string) { ...@@ -65,14 +57,7 @@ function deleteKey(accessKey: string) {
function createKey() { function createKey() {
if (authStore.authenticated) { if (authStore.authenticated) {
S3KeyService.s3KeyCreateUserKey(authStore.currentUID) keyRepository.createS3Key().catch((err) => console.error(err));
.then((s3key) => {
keyState.keys.push(s3key);
keyState.keys = [...keyState.keys].sort((keyA, keyB) =>
keyA.access_key > keyB.access_key ? 1 : -1,
);
})
.catch((err) => console.error(err));
} }
} }
...@@ -153,7 +138,7 @@ onMounted(() => { ...@@ -153,7 +138,7 @@ onMounted(() => {
</div> </div>
<div v-else class="d-grid gap-3"> <div v-else class="d-grid gap-3">
<button <button
v-for="(s3key, index) in keyState.keys" v-for="(s3key, index) in keyRepository.keys"
:key="s3key.access_key" :key="s3key.access_key"
class="btn fs-5 text-truncate border hover-shadow" class="btn fs-5 text-truncate border hover-shadow"
type="button" type="button"
...@@ -170,11 +155,11 @@ onMounted(() => { ...@@ -170,11 +155,11 @@ onMounted(() => {
</div> </div>
<div class="col-7 offset-md-1"> <div class="col-7 offset-md-1">
<s3-key-view <s3-key-view
v-if="keyState.keys.length > 0 || keyState.initialLoading" v-if="keyRepository.keys.length > 0 || keyState.initialLoading"
:s3key=" :s3key="
keyState.initialLoading keyState.initialLoading
? { user: '', access_key: '', secret_key: '' } ? { user: '', access_key: '', secret_key: '' }
: keyState.keys[keyState.activeKey] : keyRepository.keys[keyState.activeKey] ?? keyRepository.keys[0]
" "
:deletable="allowKeyDeletion" :deletable="allowKeyDeletion"
:loading="keyState.initialLoading" :loading="keyState.initialLoading"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment