#141: Added file upload capability. Next is app testing
This commit is contained in:
@@ -833,6 +833,26 @@ class AppBase:
|
|||||||
print("SHOULD GET FILES BASED ON ORG %s, workflow %s and value(s) %s" % (org_id, full_execution["workflow"]["id"], value))
|
print("SHOULD GET FILES BASED ON ORG %s, workflow %s and value(s) %s" % (org_id, full_execution["workflow"]["id"], value))
|
||||||
get_path = "/api/v1/files/%s/content?execution_id=%s" % (value, full_execution["execution_id"])
|
get_path = "/api/v1/files/%s/content?execution_id=%s" % (value, full_execution["execution_id"])
|
||||||
|
|
||||||
|
print("PATH: %s" % get_path)
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": "Bearer %s" % self.authorization
|
||||||
|
}
|
||||||
|
ret = requests.get("%s%s" % (self.url, get_path), headers=headers)
|
||||||
|
if ret.status_code == 200:
|
||||||
|
return ret.text
|
||||||
|
|
||||||
|
print("ERROR GETTING FILE: ")
|
||||||
|
print("FILE RET CONTENT: %s" % ret.text)
|
||||||
|
print("FILE RET CODE FILE: %d" % ret.status_code)
|
||||||
|
|
||||||
|
# Sets files in the backend
|
||||||
|
def set_files(full_execution, files[]):
|
||||||
|
print("FULL EXEC: %s" % full_execution)
|
||||||
|
org_id = full_execution["workflow"]["execution_org"]["id"]
|
||||||
|
print("SHOULD GET FILES BASED ON ORG %s, workflow %s and value(s) %s" % (org_id, full_execution["workflow"]["id"], value))
|
||||||
|
get_path = "/api/v1/files/%s/content?execution_id=%s" % (value, full_execution["execution_id"])
|
||||||
|
|
||||||
print("PATH: %s" % get_path)
|
print("PATH: %s" % get_path)
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -842,8 +862,6 @@ class AppBase:
|
|||||||
print("RET CONTENT: %s" % ret.text)
|
print("RET CONTENT: %s" % ret.text)
|
||||||
print("RET CODE FILE: %d" % ret.status_code)
|
print("RET CODE FILE: %d" % ret.status_code)
|
||||||
|
|
||||||
# r.HandleFunc("/api/v1/files/{fileId}/content", handleGetFileContent).Methods("GET", "OPTIONS")
|
|
||||||
|
|
||||||
# Checks whether conditions are met, otherwise set
|
# Checks whether conditions are met, otherwise set
|
||||||
branchcheck, tmpresult = check_branch_conditions(action, fullexecution)
|
branchcheck, tmpresult = check_branch_conditions(action, fullexecution)
|
||||||
if not branchcheck:
|
if not branchcheck:
|
||||||
@@ -911,6 +929,8 @@ class AppBase:
|
|||||||
multiexecution = False
|
multiexecution = False
|
||||||
multi_execution_lists = []
|
multi_execution_lists = []
|
||||||
for parameter in action["parameters"]:
|
for parameter in action["parameters"]:
|
||||||
|
|
||||||
|
# This code handles files.
|
||||||
is_file = False
|
is_file = False
|
||||||
try:
|
try:
|
||||||
if parameter["schema"]["type"] == "file":
|
if parameter["schema"]["type"] == "file":
|
||||||
@@ -920,6 +940,8 @@ class AppBase:
|
|||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print("SCHEMA ERROR: %s" % e)
|
print("SCHEMA ERROR: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
check, value, is_loop = parse_params(action, fullexecution, parameter)
|
check, value, is_loop = parse_params(action, fullexecution, parameter)
|
||||||
if check:
|
if check:
|
||||||
raise "Value check error: %s" % Exception(check)
|
raise "Value check error: %s" % Exception(check)
|
||||||
|
|||||||
+2
-168
@@ -7934,172 +7934,6 @@ func handleCloudSetup(resp http.ResponseWriter, request *http.Request) {
|
|||||||
resp.Write(respBody)
|
resp.Write(respBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
type File struct {
|
|
||||||
Id string `json:"id" datastore:"id"`
|
|
||||||
Type string `json:"type" datastore:"type"`
|
|
||||||
CreatedAt int64 `json:"created_at" datastore:"created_at"`
|
|
||||||
UpdatedAt int64 `json:"updated_at" datastore:"updated_at"`
|
|
||||||
Description string `json:"description" datastore:"description"`
|
|
||||||
ExpiresAt string `json:"expires_at" datastore:"expires_at"`
|
|
||||||
Status string `json:"status" datastore:"status"`
|
|
||||||
Filename string `json:"filename" datastore:"filename"`
|
|
||||||
URL string `json:"url" datastore:"org"`
|
|
||||||
OrgId string `json:"org_id" datastore:"org_id"`
|
|
||||||
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
|
|
||||||
Workflows []string `json:"workflows" datastore:"workflows"`
|
|
||||||
DownloadPath string `json:"download_path" datastore:"download_path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleGetFileContent(resp http.ResponseWriter, request *http.Request) {
|
|
||||||
cors := handleCors(resp, request)
|
|
||||||
if cors {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileId string
|
|
||||||
location := strings.Split(request.URL.String(), "/")
|
|
||||||
if location[1] == "api" {
|
|
||||||
if len(location) <= 4 {
|
|
||||||
log.Printf("Path too short: %d", len(location))
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileId = location[4]
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("\n\nUser is trying to get file %s\n\n", fileId)
|
|
||||||
|
|
||||||
// 1. Check user directly
|
|
||||||
// 2. Check workflow execution authorization
|
|
||||||
setOrgId := false
|
|
||||||
user, err := handleApiAuthentication(resp, request)
|
|
||||||
if err != nil {
|
|
||||||
// r.HandleFunc("/api/v1/files/{fileId}/content", handleGetFileContent).Methods("GET", "OPTIONS")
|
|
||||||
log.Printf("INITIAL Api authentication failed in file download: %s", err)
|
|
||||||
executionId, ok := request.URL.Query()["execution_id"]
|
|
||||||
if ok && len(executionId) > 0 {
|
|
||||||
ctx := context.Background()
|
|
||||||
workflowExecution, err := getWorkflowExecution(ctx, executionId[0])
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Couldn't find execution ID %s", executionId[0])
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
apikey := request.Header.Get("Authorization")
|
|
||||||
if !strings.HasPrefix(apikey, "Bearer ") {
|
|
||||||
log.Printf("Apikey doesn't start with bearer (2)")
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
apikeyCheck := strings.Split(apikey, " ")
|
|
||||||
if len(apikeyCheck) != 2 {
|
|
||||||
log.Printf("Invalid format for apikey (2)")
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is annoying af and is done because of maxlength lol
|
|
||||||
newApikey := apikeyCheck[1]
|
|
||||||
if newApikey != workflowExecution.Authorization {
|
|
||||||
log.Printf("Bad apikey for execution %s. %s vs %s", executionId[0], apikey, workflowExecution.Authorization)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Authorization is correct for execution %s! %s vs %s", executionId, apikey, workflowExecution.Authorization)
|
|
||||||
setOrgId = true
|
|
||||||
} else {
|
|
||||||
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Verify if the user has access to the file: org_id and workflow
|
|
||||||
|
|
||||||
log.Printf("Should get file %s", fileId)
|
|
||||||
ctx := context.Background()
|
|
||||||
file, err := getFile(ctx, fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("File %s not found: %s", fileId, err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a workaround for file grabs from an app
|
|
||||||
if setOrgId == true {
|
|
||||||
user.ActiveOrg.Id = file.OrgId
|
|
||||||
}
|
|
||||||
|
|
||||||
found := false
|
|
||||||
if file.OrgId == user.ActiveOrg.Id {
|
|
||||||
found = true
|
|
||||||
} else {
|
|
||||||
for _, item := range user.Orgs {
|
|
||||||
if item == file.OrgId {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
log.Printf("User %s doesn't have access to %s", user.Username, fileId)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fixme: More auth: org and workflow!
|
|
||||||
downloadPath := file.DownloadPath
|
|
||||||
log.Printf("Downloadpath: %s", downloadPath)
|
|
||||||
Openfile, err := os.Open(downloadPath)
|
|
||||||
defer Openfile.Close() //Close after function return
|
|
||||||
if err != nil {
|
|
||||||
//File not found, send 404
|
|
||||||
http.Error(resp, "File not found.", 404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//File is found, create and send the correct headers
|
|
||||||
//Get the Content-Type of the file
|
|
||||||
//Create a buffer to store the header of the file in
|
|
||||||
FileHeader := make([]byte, 512)
|
|
||||||
//Copy the headers into the FileHeader buffer
|
|
||||||
Openfile.Read(FileHeader)
|
|
||||||
//Get content type of file
|
|
||||||
FileContentType := http.DetectContentType(FileHeader)
|
|
||||||
|
|
||||||
//Get the file size
|
|
||||||
FileStat, _ := Openfile.Stat() //Get info from file
|
|
||||||
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string
|
|
||||||
|
|
||||||
//Send the headers
|
|
||||||
resp.Header().Set("Content-Disposition", "attachment; filename="+fileId)
|
|
||||||
resp.Header().Set("Content-Type", FileContentType)
|
|
||||||
resp.Header().Set("Content-Length", FileSize)
|
|
||||||
|
|
||||||
//Send the file
|
|
||||||
//We read 512 bytes from the file already, so we reset the offset back to 0
|
|
||||||
Openfile.Seek(0, 0)
|
|
||||||
io.Copy(resp, Openfile) //'Copy' the file to the client
|
|
||||||
return
|
|
||||||
|
|
||||||
//log.Printf("Should download file %s", downloadPath)
|
|
||||||
//resp.WriteHeader(200)
|
|
||||||
//resp.Write([]byte("OK"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func initHandlers() {
|
func initHandlers() {
|
||||||
var err error
|
var err error
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@@ -8233,8 +8067,8 @@ func initHandlers() {
|
|||||||
// https://developer.box.com/reference/get-files-id-content/
|
// https://developer.box.com/reference/get-files-id-content/
|
||||||
// 1. Creating the "get file" option. Make it possible to run this in the frontend.
|
// 1. Creating the "get file" option. Make it possible to run this in the frontend.
|
||||||
r.HandleFunc("/api/v1/files/{fileId}/content", handleGetFileContent).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/files/{fileId}/content", handleGetFileContent).Methods("GET", "OPTIONS")
|
||||||
//r.HandleFunc("/api/v1/files/create", handleGetFile).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/files/create", handleCreateFile).Methods("POST", "OPTIONS")
|
||||||
//r.HandleFunc("/api/v1/files/upload", handleGetFile).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/files/{fileId}/upload", handleUploadFile).Methods("POST", "OPTIONS")
|
||||||
//r.HandleFunc("/api/v1/files/{fileId}", handleGetFile).Methods("GET", "OPTIONS")
|
//r.HandleFunc("/api/v1/files/{fileId}", handleGetFile).Methods("GET", "OPTIONS")
|
||||||
//r.HandleFunc("/api/v1/files/{fileId}", handleGetFile).Methods("DELETE", "OPTIONS")
|
//r.HandleFunc("/api/v1/files/{fileId}", handleGetFile).Methods("DELETE", "OPTIONS")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user