-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #776 from upb-uc4/feature/gdpr_api
Report Management
- Loading branch information
Showing
10 changed files
with
461 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { AxiosError, AxiosResponse } from "axios"; | ||
import Course from "./api_models/course_management/Course"; | ||
import APIError from "./api_models/errors/APIError"; | ||
import handleAuthenticationError from "./AuthenticationHelper"; | ||
import Common from "./Common"; | ||
import APIResponse from "./helpers/models/APIResponse"; | ||
|
||
export default class ReportManagement extends Common { | ||
protected static endpoint = "/report-management"; | ||
|
||
constructor() { | ||
super(ReportManagement.endpoint); | ||
} | ||
|
||
static async getVersion(): Promise<string> { | ||
return super.getVersion(); | ||
} | ||
|
||
async getArchive(username: string): Promise<APIResponse<File | string>> { | ||
return await this._axios | ||
.get(`/reports/${username}/archive`, { | ||
responseType: "arraybuffer", | ||
}) | ||
.then((response: AxiosResponse) => { | ||
if (response.status === 200) { | ||
let blob: Blob = new Blob([response.data], { type: response.headers["content-type"] }); | ||
const file: File = new File([blob], "archive.zip", { type: response.headers["content-type"] }); | ||
return { | ||
error: {} as APIError, | ||
networkError: false, | ||
statusCode: response.status, | ||
returnValue: file, | ||
}; | ||
} else if (response.status === 202) { | ||
return { | ||
error: {} as APIError, | ||
networkError: false, | ||
statusCode: response.status, | ||
returnValue: response.headers["x-uc4-timestamp"], | ||
}; | ||
} else { | ||
return Promise.reject("Something went wrong in the archive request."); | ||
} | ||
}) | ||
.catch(async (error: AxiosError) => { | ||
if (error.response) { | ||
if ( | ||
await handleAuthenticationError({ | ||
statusCode: error.response.status, | ||
error: error.response.data as APIError, | ||
returnValue: {} as File, | ||
networkError: false, | ||
}) | ||
) { | ||
return await this.getArchive(username); | ||
} | ||
return { | ||
returnValue: {} as File, | ||
statusCode: error.response.status, | ||
error: error.response.data as APIError, | ||
networkError: false, | ||
}; | ||
} else { | ||
return { | ||
returnValue: {} as File, | ||
statusCode: 0, | ||
error: {} as APIError, | ||
networkError: true, | ||
}; | ||
} | ||
}); | ||
} | ||
|
||
async deleteArchive(username: string): Promise<APIResponse<boolean>> { | ||
return await this._axios | ||
.delete(`/reports/${username}/archive`) | ||
.then((response: AxiosResponse) => { | ||
return { | ||
error: {} as APIError, | ||
networkError: false, | ||
statusCode: response.status, | ||
returnValue: true, | ||
}; | ||
}) | ||
.catch(async (error: AxiosError) => { | ||
if (error.response) { | ||
if ( | ||
await handleAuthenticationError({ | ||
statusCode: error.response.status, | ||
error: error.response.data as APIError, | ||
returnValue: false, | ||
networkError: false, | ||
}) | ||
) { | ||
return await this.deleteArchive(username); | ||
} | ||
return { | ||
returnValue: false, | ||
statusCode: error.response.status, | ||
error: error.response.data as APIError, | ||
networkError: false, | ||
}; | ||
} else { | ||
return { | ||
returnValue: false, | ||
statusCode: 0, | ||
error: {} as APIError, | ||
networkError: true, | ||
}; | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
<template> | ||
<section class="border-t-2 py-8 border-gray-400"> | ||
<div class="lg:flex"> | ||
<div class="w-full lg:w-1/3 lg:block mr-12 flex flex-col mb-4"> | ||
<div class="flex mb-2 align-baseline"> | ||
<label class="block text-gray-700 text-lg font-medium">Request Stored Data</label> | ||
</div> | ||
<label class="block text-gray-600"> | ||
Place a request to retrieve and download all your data stored within the system. | ||
</label> | ||
</div> | ||
|
||
<div class="w-full lg:w-2/3"> | ||
<div class="lg:flex mb-6"> | ||
<div v-if="busy" class="mx-auto"> | ||
<loading-spinner /> | ||
</div> | ||
<div v-else class="w-full"> | ||
<div v-if="!isPending"> | ||
<button id="requestData" class="btn btn-blue-primary w-48" @click="requestData">Request Data</button> | ||
</div> | ||
<div v-else> | ||
<div v-if="gotTimestamp" class="flex flex-col w-full"> | ||
<div class="flex w-full"> | ||
<input id="timestamp" disabled class="form-input input-text w-1/2" :value="timestamp" /> | ||
<button | ||
id="refreshRequest" | ||
class="btn btn-icon-blue ml-8 w-12" | ||
title="Refresh the requested data" | ||
@click="refresh" | ||
> | ||
<i class="inline fas fa-redo-alt p-2" /> | ||
</button> | ||
<button | ||
id="deletePendingRequest" | ||
class="btn btn-icon-red ml-2 w-12s" | ||
title="Delete your request" | ||
@click="deleteData" | ||
> | ||
<i class="inline fas fa-trash-alt p-2" /> | ||
</button> | ||
</div> | ||
<p class="text-xs text-gray-600 w-1/2 mt-2"> | ||
You have already requested your stored data. It can take up to 5 minutes until the data is ready. You | ||
can hit the refresh button to check if the data is prepared. | ||
</p> | ||
</div> | ||
<div v-else-if="gotData" class="flex"> | ||
<div | ||
class="flex flex-col items-center border p-4 rounded-l-lg rounded-b-lg hover:bg-gray-400 cursor-pointer border-gray-500" | ||
title="Download your data" | ||
> | ||
<a id="downloadData" class="ml-3 text-sm btn-blue-tertiary" :href="dataUrl" download="archive.zip"> | ||
<i class="inline fas fa-file-alt p-2 text-gray-700 text-5xl" /> | ||
<p class="text-gray-700">Your data</p> | ||
</a> | ||
</div> | ||
<div | ||
id="deleteData" | ||
class="border-r border-t border-b border-gray-500 rounded-r-lg h-8 hover:bg-gray-400 cursor-pointer" | ||
title="Delete your requested data locally" | ||
@click="deleteData" | ||
> | ||
<i class="inline fas fa-times p-2 text-red-700 text-md" /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</section> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { onBeforeMount, ref } from "vue"; | ||
import LoadingSpinner from "@/components/common/loading/Spinner.vue"; | ||
import ReportManagement from "@/api/ReportManagement"; | ||
import { useStore } from "@/use/store/store"; | ||
import GenericResponseHandler from "@/use/helpers/GenericResponseHandler"; | ||
export default { | ||
name: "RequestDataSection", | ||
components: { LoadingSpinner }, | ||
setup() { | ||
const busy = ref(false); | ||
const isPending = ref(false); | ||
const gotTimestamp = ref(false); | ||
const gotData = ref(false); | ||
const timestamp = ref(""); | ||
let data = {} as File; | ||
let dataUrl = ref(""); | ||
async function requestData() { | ||
busy.value = true; | ||
const username = (await useStore().getters.user).username; | ||
const reportManagement = new ReportManagement(); | ||
const response = await reportManagement.getArchive(username); | ||
const handler = new GenericResponseHandler("archive"); | ||
const value = handler.handleResponse(response); | ||
if (typeof value === "string" && value != "") { | ||
gotTimestamp.value = true; | ||
isPending.value = true; | ||
timestamp.value = new Date(value).toLocaleString(); | ||
} else if (typeof value === "object" && value.size != 0) { | ||
isPending.value = true; | ||
gotData.value = true; | ||
gotTimestamp.value = false; | ||
data = value; | ||
let blob = new Blob([data], { type: "pem" }); | ||
dataUrl.value = URL.createObjectURL(blob); | ||
} | ||
busy.value = false; | ||
} | ||
async function refresh() { | ||
await requestData(); | ||
} | ||
async function deleteData() { | ||
busy.value = true; | ||
const username = (await useStore().getters.user).username; | ||
const reportManagement = new ReportManagement(); | ||
const response = await reportManagement.deleteArchive(username); | ||
const handler = new GenericResponseHandler("archive"); | ||
const value = handler.handleResponse(response); | ||
if (value) { | ||
isPending.value = false; | ||
gotData.value = false; | ||
gotTimestamp.value = false; | ||
data = {} as File; | ||
} | ||
busy.value = false; | ||
} | ||
return { | ||
busy, | ||
isPending, | ||
gotTimestamp, | ||
gotData, | ||
timestamp, | ||
requestData, | ||
refresh, | ||
deleteData, | ||
dataUrl, | ||
}; | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.