Skip to content

Commit

Permalink
Download legal hold data.
Browse files Browse the repository at this point in the history
Fixes #3
  • Loading branch information
grundleborg committed Dec 14, 2023
1 parent 50e9330 commit b927ab4
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
81 changes: 81 additions & 0 deletions server/api.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package main

import (
"archive/zip"
"bufio"
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"io"
"net/http"
"time"

mattermostModel "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
Expand Down Expand Up @@ -36,6 +41,7 @@ func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Req
router.HandleFunc("/api/v1/legalhold/create", p.createLegalHold)
router.HandleFunc("/api/v1/legalhold/{legalhold_id:[A-Za-z0-9]+}/release", p.releaseLegalHold)
router.HandleFunc("/api/v1/legalhold/{legalhold_id:[A-Za-z0-9]+}/update", p.updateLegalHold)
router.HandleFunc("/api/v1/legalhold/{legalhold_id:[A-Za-z0-9]+}/download", p.downloadLegalHold)

p.router = router
p.router.ServeHTTP(w, r)
Expand Down Expand Up @@ -204,6 +210,81 @@ func (p *Plugin) updateLegalHold(w http.ResponseWriter, r *http.Request) {
}
}

func (p *Plugin) downloadLegalHold(w http.ResponseWriter, r *http.Request) {
// Get the LegalHold.
legalholdID, err := RequireLegalHoldID(r)
if err != nil {
http.Error(w, "failed to parse LegalHold ID", http.StatusBadRequest)
p.Client.Log.Error(err.Error())
return
}

legalHold, err := p.KVStore.GetLegalHoldByID(legalholdID)
if err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}

// Get the list of files to include in the download.
files, err := p.FileBackend.ListDirectoryRecursively(legalHold.BasePath())
if err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}

// Write headers for the zip file.
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", "legalholddata.zip"))
w.WriteHeader(http.StatusOK)

// Write the files to the download on-the-fly.
zipWriter := zip.NewWriter(w)
for _, entry := range files {
header := &zip.FileHeader{
Name: entry,
Method: zip.Deflate, // deflate also works, but at a cost
Modified: time.Now(),
}

entryWriter, err := zipWriter.CreateHeader(header)
if err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}

backendReader, err := p.FileBackend.Reader(entry)
if err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}

fileReader := bufio.NewReader(backendReader)

_, err = io.Copy(entryWriter, fileReader)
if err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}

if err = zipWriter.Flush(); err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}
}

if err := zipWriter.Close(); err != nil {
http.Error(w, "failed to download legal hold", http.StatusInternalServerError)
p.Client.Log.Error(err.Error())
return
}
}

func RequireLegalHoldID(r *http.Request) (string, error) {
props := mux.Vars(r)

Expand Down
4 changes: 4 additions & 0 deletions webapp/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ class APIClient {
private readonly url = `/plugins/${manifest.id}/api/v1`;
private readonly client4 = new Client4();

downloadUrl = (id: string) => {
return `${this.url}/legalhold/${id}/download`;
}

Check failure on line 13 in webapp/src/client.ts

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

Missing semicolon

getLegalHolds = () => {
const url = `${this.url}/legalhold/list`;
return this.doGet(url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import {UserProfile} from 'mattermost-redux/types/users';

import {LegalHold} from '@/types';
import Client from "@/client";

Check failure on line 5 in webapp/src/components/legal_hold_table/legal_hold_row/legal_hold_row.tsx

View workflow job for this annotation

GitHub Actions / plugin-ci / lint

Strings must use singlequote

interface LegalHoldRowProps {
legalHold: LegalHold;
Expand All @@ -26,6 +27,8 @@ const LegalHoldRow = (props: LegalHoldRowProps) => {
return 'loading...';
});

const downloadUrl = Client.downloadUrl(lh.id);

return (
<React.Fragment>
<div>{lh.display_name}</div>
Expand All @@ -40,7 +43,7 @@ const LegalHoldRow = (props: LegalHoldRowProps) => {
{'Edit'}
</a>
{' '}
<a href='#'>{'Download'}</a>
<a href={downloadUrl}>{'Download'}</a>
{' '}
<a
href='#'
Expand Down

0 comments on commit b927ab4

Please sign in to comment.