From e7413508a22f28c442c56dbb28bbc7930b9eeacb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de>
Date: Thu, 14 Sep 2023 10:19:01 +0200
Subject: [PATCH] Support updating private workflows

#61
---
 src/client/workflow/index.ts                  |   2 +
 .../workflow/models/DevWorkflowExecutionIn.ts |   4 -
 src/client/workflow/models/IconUpdateOut.ts   |  12 ++
 .../workflow/models/WorkflowCredentialsIn.ts  |   4 -
 .../workflow/models/WorkflowCredentialsOut.ts |  12 ++
 src/client/workflow/models/WorkflowIn.ts      |   4 -
 .../services/WorkflowCredentialsService.ts    |  44 +++++--
 .../workflow/services/WorkflowService.ts      |   7 +-
 .../services/WorkflowVersionService.ts        |   7 +-
 .../workflows/modals/CreateWorkflowModal.vue  |   1 -
 .../modals/UpdateWorkflowCredentialsModal.vue |   1 -
 .../workflows/modals/UpdateWorkflowModal.vue  | 122 +++++++++---------
 .../modals/UpdateWorkflowVersionIconModal.vue |   4 +-
 src/views/workflows/MyWorkflowsView.vue       |   1 -
 14 files changed, 131 insertions(+), 94 deletions(-)
 create mode 100644 src/client/workflow/models/IconUpdateOut.ts
 create mode 100644 src/client/workflow/models/WorkflowCredentialsOut.ts

diff --git a/src/client/workflow/index.ts b/src/client/workflow/index.ts
index 4f6dc72..3b82994 100644
--- a/src/client/workflow/index.ts
+++ b/src/client/workflow/index.ts
@@ -12,9 +12,11 @@ export type { DevWorkflowExecutionIn } from './models/DevWorkflowExecutionIn';
 export { DocumentationEnum } from './models/DocumentationEnum';
 export type { ErrorDetail } from './models/ErrorDetail';
 export type { HTTPValidationError } from './models/HTTPValidationError';
+export type { IconUpdateOut } from './models/IconUpdateOut';
 export { Status } from './models/Status';
 export type { ValidationError } from './models/ValidationError';
 export type { WorkflowCredentialsIn } from './models/WorkflowCredentialsIn';
+export type { WorkflowCredentialsOut } from './models/WorkflowCredentialsOut';
 export type { WorkflowExecutionIn } from './models/WorkflowExecutionIn';
 export type { WorkflowExecutionOut } from './models/WorkflowExecutionOut';
 export { WorkflowExecutionStatus } from './models/WorkflowExecutionStatus';
diff --git a/src/client/workflow/models/DevWorkflowExecutionIn.ts b/src/client/workflow/models/DevWorkflowExecutionIn.ts
index f985ba9..7e69f9c 100644
--- a/src/client/workflow/models/DevWorkflowExecutionIn.ts
+++ b/src/client/workflow/models/DevWorkflowExecutionIn.ts
@@ -26,10 +26,6 @@ export type DevWorkflowExecutionIn = {
      * Token to access the content git repository
      */
     token?: (string | null);
-    /**
-     * Username belonging to the token. If not provided, it will be parsed from the git repository URL
-     */
-    username?: (string | null);
     /**
      * Mode of the workflow with an alternative entrypoint
      */
diff --git a/src/client/workflow/models/IconUpdateOut.ts b/src/client/workflow/models/IconUpdateOut.ts
new file mode 100644
index 0000000..0499796
--- /dev/null
+++ b/src/client/workflow/models/IconUpdateOut.ts
@@ -0,0 +1,12 @@
+/* generated using openapi-typescript-codegen -- do no edit */
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+export type IconUpdateOut = {
+    /**
+     * URL to the uploaded icon
+     */
+    icon_url: string;
+};
+
diff --git a/src/client/workflow/models/WorkflowCredentialsIn.ts b/src/client/workflow/models/WorkflowCredentialsIn.ts
index 277e7cd..37723a3 100644
--- a/src/client/workflow/models/WorkflowCredentialsIn.ts
+++ b/src/client/workflow/models/WorkflowCredentialsIn.ts
@@ -8,9 +8,5 @@ export type WorkflowCredentialsIn = {
      * Token to access the content git repository
      */
     token: string;
-    /**
-     * Username belonging to the token. If not provided, it will be parsed from the git repository URL
-     */
-    username?: (string | null);
 };
 
diff --git a/src/client/workflow/models/WorkflowCredentialsOut.ts b/src/client/workflow/models/WorkflowCredentialsOut.ts
new file mode 100644
index 0000000..3b669c2
--- /dev/null
+++ b/src/client/workflow/models/WorkflowCredentialsOut.ts
@@ -0,0 +1,12 @@
+/* generated using openapi-typescript-codegen -- do no edit */
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+export type WorkflowCredentialsOut = {
+    /**
+     * Token to access the content git repository
+     */
+    token: (string | null);
+};
+
diff --git a/src/client/workflow/models/WorkflowIn.ts b/src/client/workflow/models/WorkflowIn.ts
index 65baab9..544b0e3 100644
--- a/src/client/workflow/models/WorkflowIn.ts
+++ b/src/client/workflow/models/WorkflowIn.ts
@@ -30,10 +30,6 @@ export type WorkflowIn = {
      * Token to access the content git repository
      */
     token?: (string | null);
-    /**
-     * Username belonging to the token. If not provided, it will be parsed from the git repository URL
-     */
-    username?: (string | null);
     /**
      * List of modes with alternative entrypoint the new workflow has
      */
diff --git a/src/client/workflow/services/WorkflowCredentialsService.ts b/src/client/workflow/services/WorkflowCredentialsService.ts
index b1ff8ce..1f9f891 100644
--- a/src/client/workflow/services/WorkflowCredentialsService.ts
+++ b/src/client/workflow/services/WorkflowCredentialsService.ts
@@ -3,6 +3,7 @@
 /* tslint:disable */
 /* eslint-disable */
 import type { WorkflowCredentialsIn } from '../models/WorkflowCredentialsIn';
+import type { WorkflowCredentialsOut } from '../models/WorkflowCredentialsOut';
 
 import type { CancelablePromise } from '../core/CancelablePromise';
 import { OpenAPI } from '../core/OpenAPI';
@@ -11,19 +12,19 @@ import { request as __request } from '../core/request';
 export class WorkflowCredentialsService {
 
     /**
-     * Delete the credentials of a workflow
-     * Delete the credentials for the repository of a workflow.
+     * Get the credentials of a workflow
+     * Get the credentials for the repository of a workflow. Only the developer of a workflow can do this.
      *
-     * Permission "workflow:delete" required.
+     * Permission "workflow:update" required.
      * @param wid ID of a workflow
-     * @returns void
+     * @returns WorkflowCredentialsOut Successful Response
      * @throws ApiError
      */
-    public static workflowCredentialsDeleteWorkflowCredentials(
+    public static workflowCredentialsGetWorkflowCredentials(
         wid: string,
-    ): CancelablePromise<void> {
+    ): CancelablePromise<WorkflowCredentialsOut> {
         return __request(OpenAPI, {
-            method: 'DELETE',
+            method: 'GET',
             url: '/workflows/{wid}/credentials',
             path: {
                 'wid': wid,
@@ -38,7 +39,7 @@ export class WorkflowCredentialsService {
     }
 
     /**
-     * Delete the credentials of a workflow
+     * Update the credentials of a workflow
      * Update the credentials for the repository of a workflow.
      *
      * Permission "workflow:update" required.
@@ -68,4 +69,31 @@ export class WorkflowCredentialsService {
         });
     }
 
+    /**
+     * Delete the credentials of a workflow
+     * Delete the credentials for the repository of a workflow.
+     *
+     * Permission "workflow:delete" required.
+     * @param wid ID of a workflow
+     * @returns void
+     * @throws ApiError
+     */
+    public static workflowCredentialsDeleteWorkflowCredentials(
+        wid: string,
+    ): CancelablePromise<void> {
+        return __request(OpenAPI, {
+            method: 'DELETE',
+            url: '/workflows/{wid}/credentials',
+            path: {
+                'wid': wid,
+            },
+            errors: {
+                400: `Error decoding JWT Token`,
+                403: `Not authenticated`,
+                404: `Entity not Found`,
+                422: `Validation Error`,
+            },
+        });
+    }
+
 }
diff --git a/src/client/workflow/services/WorkflowService.ts b/src/client/workflow/services/WorkflowService.ts
index bc9ae91..dad2fcb 100644
--- a/src/client/workflow/services/WorkflowService.ts
+++ b/src/client/workflow/services/WorkflowService.ts
@@ -4,6 +4,7 @@
 /* eslint-disable */
 import type { Body_Workflow_Version_upload_workflow_version_icon } from '../models/Body_Workflow_Version_upload_workflow_version_icon';
 import type { DocumentationEnum } from '../models/DocumentationEnum';
+import type { IconUpdateOut } from '../models/IconUpdateOut';
 import type { Status } from '../models/Status';
 import type { WorkflowIn } from '../models/WorkflowIn';
 import type { WorkflowOut } from '../models/WorkflowOut';
@@ -365,20 +366,20 @@ export class WorkflowService {
 
     /**
      * Upload icon for workflow version
-     * Upload an icon for the workflow version.
+     * Upload an icon for the workflow version and returns the new icon URL.
      *
      * Permission "workflow:update" required.
      * @param wid ID of a workflow
      * @param gitCommitHash Git commit git_commit_hash of specific version.
      * @param formData
-     * @returns string Successful Response
+     * @returns IconUpdateOut Successful Response
      * @throws ApiError
      */
     public static workflowVersionUploadWorkflowVersionIcon(
         wid: string,
         gitCommitHash: string,
         formData: Body_Workflow_Version_upload_workflow_version_icon,
-    ): CancelablePromise<string> {
+    ): CancelablePromise<IconUpdateOut> {
         return __request(OpenAPI, {
             method: 'POST',
             url: '/workflows/{wid}/versions/{git_commit_hash}/icon',
diff --git a/src/client/workflow/services/WorkflowVersionService.ts b/src/client/workflow/services/WorkflowVersionService.ts
index 945bd0d..0d46dd9 100644
--- a/src/client/workflow/services/WorkflowVersionService.ts
+++ b/src/client/workflow/services/WorkflowVersionService.ts
@@ -4,6 +4,7 @@
 /* eslint-disable */
 import type { Body_Workflow_Version_upload_workflow_version_icon } from '../models/Body_Workflow_Version_upload_workflow_version_icon';
 import type { DocumentationEnum } from '../models/DocumentationEnum';
+import type { IconUpdateOut } from '../models/IconUpdateOut';
 import type { Status } from '../models/Status';
 import type { WorkflowVersion } from '../models/WorkflowVersion';
 import type { WorkflowVersionStatus } from '../models/WorkflowVersionStatus';
@@ -183,20 +184,20 @@ export class WorkflowVersionService {
 
     /**
      * Upload icon for workflow version
-     * Upload an icon for the workflow version.
+     * Upload an icon for the workflow version and returns the new icon URL.
      *
      * Permission "workflow:update" required.
      * @param wid ID of a workflow
      * @param gitCommitHash Git commit git_commit_hash of specific version.
      * @param formData
-     * @returns string Successful Response
+     * @returns IconUpdateOut Successful Response
      * @throws ApiError
      */
     public static workflowVersionUploadWorkflowVersionIcon(
         wid: string,
         gitCommitHash: string,
         formData: Body_Workflow_Version_upload_workflow_version_icon,
-    ): CancelablePromise<string> {
+    ): CancelablePromise<IconUpdateOut> {
         return __request(OpenAPI, {
             method: 'POST',
             url: '/workflows/{wid}/versions/{git_commit_hash}/icon',
diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue
index 7759c91..3971a16 100644
--- a/src/components/workflows/modals/CreateWorkflowModal.vue
+++ b/src/components/workflows/modals/CreateWorkflowModal.vue
@@ -54,7 +54,6 @@ const workflow = reactive<WorkflowIn>({
   git_commit_hash: "",
   initial_version: undefined,
   token: undefined,
-  username: undefined,
   modes: [],
 });
 
diff --git a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue
index 8905188..df4ddd1 100644
--- a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue
+++ b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue
@@ -33,7 +33,6 @@ const props = defineProps<{
 // =============================================================================
 const credentials = reactive<WorkflowCredentialsIn>({
   token: "",
-  username: undefined,
 });
 
 const formState = reactive<{
diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue
index f3e6720..4ce43dc 100644
--- a/src/components/workflows/modals/UpdateWorkflowModal.vue
+++ b/src/components/workflows/modals/UpdateWorkflowModal.vue
@@ -9,7 +9,7 @@ import type {
 } from "@/client/workflow";
 import BootstrapModal from "@/components/modals/BootstrapModal.vue";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
-import { WorkflowService } from "@/client/workflow";
+import { WorkflowService, WorkflowCredentialsService } from "@/client/workflow";
 import {
   GitRepository,
   requiredRepositoryFiles,
@@ -59,18 +59,39 @@ const formState = reactive<{
   loading: boolean;
   checkRepoLoading: boolean;
   allowUpload: boolean;
+  loadCredentials: boolean;
+  workflowToken?: string;
 }>({
   loading: false,
   checkRepoLoading: false,
   allowUpload: false,
   validated: false,
   missingFiles: [],
+  loadCredentials: false,
+  workflowToken: undefined,
 });
 
 watch(
   () => props.workflow,
   () => {
     resetForm();
+    if (props.workflow.private) {
+      formState.loadCredentials = true;
+      WorkflowCredentialsService.workflowCredentialsGetWorkflowCredentials(
+        props.workflow.workflow_id,
+      )
+        .then((credentials) => {
+          formState.workflowToken = credentials.token ?? undefined;
+        })
+        .catch(() => {
+          formState.workflowToken = undefined;
+        })
+        .finally(() => {
+          formState.loadCredentials = false;
+        });
+    } else {
+      formState.workflowToken = undefined;
+    }
   },
 );
 
@@ -96,21 +117,6 @@ const emit = defineEmits<{
 
 // Functions
 // =============================================================================
-/*
-function iconChanged() {
-  workflowUpdate.icon = workflowIconInputElement.value?.files?.[0].slice();
-  if (workflowUpdate.icon != undefined) {
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    workflowIconElement.value!.src = URL.createObjectURL(
-      workflowUpdate.icon.slice(),
-    );
-  } else {
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    workflowIconElement.value!.src = latestVersion.value.icon_url ?? "";
-  }
-}
-*/
-
 function modalClosed() {
   formState.validated = false;
   formState.missingFiles = [];
@@ -134,12 +140,13 @@ function checkVersionValidity() {
 
 function checkRepository() {
   formState.validated = true;
+  workflowGitCommitHashElement.value?.setCustomValidity("");
   if (workflowUpdateForm.value?.checkValidity() && !formState.allowUpload) {
     formState.missingFiles = [];
-    workflowGitCommitHashElement.value?.setCustomValidity("");
     const repo = GitRepository.buildRepository(
       props.workflow.repository_url,
       workflowUpdate.git_commit_hash,
+      formState.workflowToken,
     );
     repo
       .checkFilesExist(requiredRepositoryFiles, true)
@@ -250,6 +257,11 @@ onMounted(() => {
             target="_blank"
             >{{ props.workflow.repository_url }}</a
           >
+          <font-awesome-icon
+            v-if="props.workflow.private"
+            class="ms-2"
+            icon="fa-solid fa-lock"
+          />
           <img
             :src="latestVersion.icon_url ?? undefined"
             ref="workflowIconElement"
@@ -257,37 +269,37 @@ onMounted(() => {
             :hidden="!showIcon"
           />
         </div>
-        <div class="mb-3">
-          <label for="workflowGitCommitInput" class="form-label"
-            >Git Commit Hash</label
-          >
-          <div class="input-group">
-            <div class="input-group-text">
-              <font-awesome-icon icon="fa-solid fa-code-commit" />
+        <div class="row">
+          <div class="col-8">
+            <label for="workflowGitCommitInput" class="form-label"
+              >Git Commit Hash</label
+            >
+            <div class="input-group">
+              <div class="input-group-text">
+                <font-awesome-icon icon="fa-solid fa-code-commit" />
+              </div>
+              <input
+                type="text"
+                class="form-control text-lowercase"
+                id="workflowGitCommitInput"
+                placeholder="ba8bcd9..."
+                required
+                ref="workflowGitCommitHashElement"
+                maxlength="40"
+                pattern="[0-9a-f]{40}"
+                v-model="workflowUpdate.git_commit_hash"
+                @change="formState.allowUpload = false"
+              />
+            </div>
+            <div v-if="formState.missingFiles.length > 0" class="text-danger">
+              The following files are missing in the repository
+              <ul>
+                <li v-for="file in formState.missingFiles" :key="file">
+                  {{ file }}
+                </li>
+              </ul>
             </div>
-            <input
-              type="text"
-              class="form-control text-lowercase"
-              id="workflowGitCommitInput"
-              placeholder="ba8bcd9..."
-              required
-              ref="workflowGitCommitHashElement"
-              maxlength="40"
-              pattern="[0-9a-f]{40}"
-              v-model="workflowUpdate.git_commit_hash"
-              @change="formState.allowUpload = false"
-            />
           </div>
-        </div>
-        <div v-if="formState.missingFiles.length > 0" class="text-danger">
-          The following files are missing in the repository
-          <ul>
-            <li v-for="file in formState.missingFiles" :key="file">
-              {{ file }}
-            </li>
-          </ul>
-        </div>
-        <div class="row mb-3">
           <div class="col-4">
             <label for="workflowVersionInput" class="form-label">Version</label>
             <div class="input-group">
@@ -311,22 +323,6 @@ onMounted(() => {
               Previous Version: {{ latestVersion.version }}
             </div>
           </div>
-          <div class="col-8">
-            <label for="workflowIconInput" class="form-label"
-              >Optional Icon</label
-            >
-            <input
-              type="file"
-              ref="workflowIconInputElement"
-              accept="image/*"
-              class="form-control"
-              id="workflowIconInput"
-              aria-describedby="iconHelp"
-            />
-            <div id="iconHelp" class="form-text">
-              If not set, the previous icon will be used
-            </div>
-          </div>
         </div>
       </form>
     </template>
@@ -335,7 +331,7 @@ onMounted(() => {
         type="button"
         class="btn btn-info me-auto"
         @click="checkRepository"
-        :disabled="formState.allowUpload"
+        :disabled="formState.allowUpload || formState.loadCredentials"
       >
         <span
           v-if="formState.checkRepoLoading"
diff --git a/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue b/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue
index dafb7ff..ede37a2 100644
--- a/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue
+++ b/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue
@@ -98,9 +98,9 @@ function updateIcon() {
         icon: iconUpdate.icon,
       },
     )
-      .then((icon_url) => {
+      .then((response) => {
         formState.uploadIcon = true;
-        emit("icon-updated", props.version, icon_url);
+        emit("icon-updated", props.version, response.icon_url);
         successToast?.show();
         updateIconModal?.hide();
       })
diff --git a/src/views/workflows/MyWorkflowsView.vue b/src/views/workflows/MyWorkflowsView.vue
index 7a05c2e..882df78 100644
--- a/src/views/workflows/MyWorkflowsView.vue
+++ b/src/views/workflows/MyWorkflowsView.vue
@@ -100,7 +100,6 @@ function confirmedWorkflowVersionIconUpdate(
   version: WorkflowVersion,
   icon_url?: string,
 ) {
-  console.log("New Url", icon_url);
   const wIndex = workflowsState.workflows.findIndex(
     (w) => w.workflow_id == version.workflow_id,
   );
-- 
GitLab