Merge pull request #126 from frikky/1.0.0

0.6.5
This commit is contained in:
Frikky
2020-08-24 19:37:33 +02:00
committed by GitHub
13 changed files with 1056 additions and 299 deletions
+3 -2
View File
@@ -3,9 +3,10 @@ ORG_ID=Shuffle
ENVIRONMENT_NAME=Shuffle ENVIRONMENT_NAME=Shuffle
# Remote github config for first load # Remote github config for first load
SHUFFLE_DOWNLOAD_WORKFLOW_LOCATION=
SHUFFLE_DOWNLOAD_AUTH_USERNAME=
SHUFFLE_DOWNLOAD_AUTH_PASSWORD=
APP_DOWNLOAD_LOCATION=https://github.com/frikky/shuffle-apps APP_DOWNLOAD_LOCATION=https://github.com/frikky/shuffle-apps
APP_DOWNLOAD_AUTH_USERNAME=
APP_DOWNLOAD_AUTH_PASSWORD=
# User config for first load. Username & PW: min length 3 # User config for first load. Username & PW: min length 3
SHUFFLE_DEFAULT_USERNAME= SHUFFLE_DEFAULT_USERNAME=
+41 -10
View File
@@ -254,11 +254,14 @@ func makePythoncode(swagger *openapi3.Swagger, name, url, method string, paramet
if len(optionalQueries) > 0 { if len(optionalQueries) > 0 {
queryString += ", " queryString += ", "
for _, query := range optionalQueries { for _, query := range optionalQueries {
// Check if it's a part of the URL already
queryString += fmt.Sprintf("%s=\"\", ", query) queryString += fmt.Sprintf("%s=\"\", ", query)
queryData += fmt.Sprintf(` queryData += fmt.Sprintf(`
if %s: if %s:
url += f"&%s={%s}"`, query, query, query) url += f"&%s={%s}"`, query, query, query)
} }
} else {
//log.Printf("No optional queries?")
} }
// api.Authentication.Parameters[0].Value = "BearerAuth" // api.Authentication.Parameters[0].Value = "BearerAuth"
@@ -398,7 +401,7 @@ func makePythoncode(swagger *openapi3.Swagger, name, url, method string, paramet
verifyAddin, verifyAddin,
) )
//log.Printf("%s", data) //log.Printf(data)
return functionname, data return functionname, data
} }
@@ -594,10 +597,10 @@ func generateYaml(swagger *openapi3.Swagger, newmd5 string) (*openapi3.Swagger,
pythonFunctions := []string{} pythonFunctions := []string{}
for actualPath, path := range swagger.Paths { for actualPath, path := range swagger.Paths {
actualPath = strings.Replace(actualPath, " ", "_", -1) actualPath = strings.Replace(actualPath, " ", "_", -1)
actualPath = strings.Replace(actualPath, ".", "", -1) //actualPath = strings.Replace(actualPath, ".", "", -1)
actualPath = strings.Replace(actualPath, ".", "", -1)
actualPath = strings.Replace(actualPath, "\\", "", -1) actualPath = strings.Replace(actualPath, "\\", "", -1)
// FIXME: Handle everything behind questionmark (?) with dots as well.
// https://godoc.org/github.com/getkin/kin-openapi/openapi3#PathItem // https://godoc.org/github.com/getkin/kin-openapi/openapi3#PathItem
if path.Get != nil { if path.Get != nil {
action, curCode := handleGet(swagger, api, extraParameters, path, actualPath) action, curCode := handleGet(swagger, api, extraParameters, path, actualPath)
@@ -936,7 +939,11 @@ func handleConnect(swagger *openapi3.Swagger, api WorkflowApp, extraParameters [
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
@@ -1081,7 +1088,11 @@ func handleGet(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wor
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
@@ -1224,7 +1235,11 @@ func handleHead(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wo
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
@@ -1368,7 +1383,11 @@ func handleDelete(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
@@ -1511,7 +1530,11 @@ func handlePost(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wo
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
@@ -1654,7 +1677,11 @@ func handlePatch(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []W
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
@@ -1797,7 +1824,11 @@ func handlePut(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wor
continue continue
} }
if firstQuery { if strings.Contains(baseUrl, fmt.Sprintf("{%s}", param.Value.Name)) {
continue
}
if firstQuery && !strings.Contains(baseUrl, "?") {
baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s?%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
} else { } else {
baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name) baseUrl = fmt.Sprintf("%s&%s={%s}", baseUrl, param.Value.Name, param.Value.Name)
+53 -12
View File
@@ -158,6 +158,9 @@ type Environment struct {
Name string `datastore:"name"` Name string `datastore:"name"`
Type string `datastore:"type"` Type string `datastore:"type"`
Registered bool `datastore:"registered"` Registered bool `datastore:"registered"`
Default bool `datastore:"default" json:"default"`
Archived bool `datastore:"archived" json:"archived"`
Id string `datastore:"id" json:"id"`
} }
type User struct { type User struct {
@@ -1053,16 +1056,29 @@ func handleSetEnvironments(resp http.ResponseWriter, request *http.Request) {
return return
} }
// Clear old data // Clear old data? Removed for archiving purpose. No straight deletion
for _, item := range environments { //for _, item := range environments {
err = DeleteKey(ctx, "Environments", item.Name) // err = DeleteKey(ctx, "Environments", item.Name)
if err != nil { // if err != nil {
resp.WriteHeader(401) // resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Error cleaning up environment"}`)) // resp.Write([]byte(`{"success": false, "reason": "Error cleaning up environment"}`))
return // return
// }
//}
openEnvironments := 0
for _, item := range newEnvironments {
if !item.Archived {
openEnvironments += 1
} }
} }
if openEnvironments < 1 {
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false, "reason": "Can't archived all environments"}`))
return
}
for _, item := range newEnvironments { for _, item := range newEnvironments {
err = setEnvironment(ctx, &item) err = setEnvironment(ctx, &item)
if err != nil { if err != nil {
@@ -1072,9 +1088,10 @@ func handleSetEnvironments(resp http.ResponseWriter, request *http.Request) {
} }
} }
//DeleteKey(ctx, entity string, value string) error {
// FIXME - check which are in use // FIXME - check which are in use
log.Printf("FIXME: Set new environments: %#v", newEnvironments) //log.Printf("FIXME: Set new environments: %#v", newEnvironments)
log.Printf("DONT DELETE ONES THAT ARE IN USE") //log.Printf("DONT DELETE ONES THAT ARE IN USE")
resp.WriteHeader(200) resp.WriteHeader(200)
resp.Write([]byte(`{"success": true}`)) resp.Write([]byte(`{"success": true}`))
@@ -5995,7 +6012,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
if err != nil { if err != nil {
log.Printf("Docker build error: %s", err) log.Printf("Docker build error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Error in Docker build"}`))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error in Docker build"}`)))
return return
} }
@@ -6327,8 +6344,8 @@ func runInit(ctx context.Context) {
url = "https://github.com/frikky/shuffle-apps" url = "https://github.com/frikky/shuffle-apps"
} }
username := os.Getenv("APP_DOWNLOAD_AUTH_USERNAME") username := os.Getenv("SHUFFLE_DOWNLOAD_AUTH_USERNAME")
password := os.Getenv("APP_DOWNLOAD_AUTH_PASSWORD") password := os.Getenv("SHUFFLE_DOWNLOAD_AUTH_PASSWORD")
cloneOptions := &git.CloneOptions{ cloneOptions := &git.CloneOptions{
URL: url, URL: url,
} }
@@ -6388,6 +6405,30 @@ func runInit(ctx context.Context) {
log.Printf("Finished downloading extra API samples") log.Printf("Finished downloading extra API samples")
} }
workflowLocation := os.Getenv("SHUFFLE_DOWNLOAD_WORKFLOW_LOCATION")
if len(workflowLocation) > 0 {
log.Printf("Downloading WORKFLOWS from %s if no workflows - EXTRA workflows", workflowLocation)
q := datastore.NewQuery("workflow")
var workflows []Workflow
_, err = dbclient.GetAll(ctx, q, &workflows)
if err != nil {
log.Printf("Error getting workflows: %s", err)
} else {
if len(workflows) == 0 {
username := os.Getenv("SHUFFLE_DOWNLOAD_AUTH_USERNAME")
password := os.Getenv("SHUFFLE_DOWNLOAD_AUTH_PASSWORD")
err = loadGithubWorkflows(workflowLocation, username, password, "")
if err != nil {
log.Printf("Failed to upload workflows from github: %s", err)
} else {
log.Printf("Finished downloading workflows from github!")
}
} else {
log.Printf("Skipping because there are %d workflows already", len(workflows))
}
}
}
log.Printf("Finished INIT") log.Printf("Finished INIT")
} }
+95 -63
View File
@@ -120,6 +120,8 @@ type WorkflowApp struct {
} `json:"contact_info" datastore:"contact_info" yaml:"contact_info" required:false` } `json:"contact_info" datastore:"contact_info" yaml:"contact_info" required:false`
Actions []WorkflowAppAction `json:"actions" yaml:"actions" required:true datastore:"actions,noindex"` Actions []WorkflowAppAction `json:"actions" yaml:"actions" required:true datastore:"actions,noindex"`
Authentication Authentication `json:"authentication" yaml:"authentication" required:false datastore:"authentication"` Authentication Authentication `json:"authentication" yaml:"authentication" required:false datastore:"authentication"`
Tags []string `json:"tags" yaml:"tags" required:false datastore:"activated"`
Category []string `json:"category" yaml:"category" required:false datastore:"category"`
} }
type WorkflowAppActionParameter struct { type WorkflowAppActionParameter struct {
@@ -129,6 +131,7 @@ type WorkflowAppActionParameter struct {
Example string `json:"example" datastore:"example" yaml:"example"` Example string `json:"example" datastore:"example" yaml:"example"`
Value string `json:"value" datastore:"value" yaml:"value,omitempty"` Value string `json:"value" datastore:"value" yaml:"value,omitempty"`
Multiline bool `json:"multiline" datastore:"multiline" yaml:"multiline"` Multiline bool `json:"multiline" datastore:"multiline" yaml:"multiline"`
Options []string `json:"options" datastore:"options" yaml:"options"`
ActionField string `json:"action_field" datastore:"action_field" yaml:"actionfield,omitempty"` ActionField string `json:"action_field" datastore:"action_field" yaml:"actionfield,omitempty"`
Variant string `json:"variant" datastore:"variant" yaml:"variant,omitempty"` Variant string `json:"variant" datastore:"variant" yaml:"variant,omitempty"`
Required bool `json:"required" datastore:"required" yaml:"required"` Required bool `json:"required" datastore:"required" yaml:"required"`
@@ -192,7 +195,7 @@ type WorkflowExecution struct {
Description string `json:"description" datastore:"description"` Description string `json:"description" datastore:"description"`
ID string `json:"id" datastore:"id"` ID string `json:"id" datastore:"id"`
Name string `json:"name" datastore:"name"` Name string `json:"name" datastore:"name"`
Value string `json:"value" datastore:"value"` Value string `json:"value" datastore:"value,noindex"`
} `json:"execution_variables,omitempty" datastore:"execution_variables,omitempty"` } `json:"execution_variables,omitempty" datastore:"execution_variables,omitempty"`
} }
@@ -217,7 +220,7 @@ type Action struct {
Description string `json:"description" datastore:"description"` Description string `json:"description" datastore:"description"`
ID string `json:"id" datastore:"id"` ID string `json:"id" datastore:"id"`
Name string `json:"name" datastore:"name"` Name string `json:"name" datastore:"name"`
Value string `json:"value" datastore:"value"` Value string `json:"value" datastore:"value,noindex"`
} `json:"execution_variable,omitempty" datastore:"execution_variable,omitempty"` } `json:"execution_variable,omitempty" datastore:"execution_variable,omitempty"`
Position struct { Position struct {
X float64 `json:"x" datastore:"x"` X float64 `json:"x" datastore:"x"`
@@ -307,7 +310,7 @@ type Workflow struct {
Description string `json:"description" datastore:"description"` Description string `json:"description" datastore:"description"`
ID string `json:"id" datastore:"id"` ID string `json:"id" datastore:"id"`
Name string `json:"name" datastore:"name"` Name string `json:"name" datastore:"name"`
Value string `json:"value" datastore:"value"` Value string `json:"value" datastore:"value,noindex"`
} `json:"execution_variables,omitempty" datastore:"execution_variables"` } `json:"execution_variables,omitempty" datastore:"execution_variables"`
} }
@@ -1121,6 +1124,10 @@ func getWorkflows(resp http.ResponseWriter, request *http.Request) {
// With user, do a search for workflows with user or user's org attached // With user, do a search for workflows with user or user's org attached
q := datastore.NewQuery("workflow").Filter("owner =", user.Id) q := datastore.NewQuery("workflow").Filter("owner =", user.Id)
if user.Role == "admin" {
q = datastore.NewQuery("workflow")
}
var workflows []Workflow var workflows []Workflow
_, err = dbclient.GetAll(ctx, q, &workflows) _, err = dbclient.GetAll(ctx, q, &workflows)
if err != nil { if err != nil {
@@ -1236,11 +1243,16 @@ func setNewWorkflow(resp http.ResponseWriter, request *http.Request) {
workflowapps, err := getAllWorkflowApps(ctx) workflowapps, err := getAllWorkflowApps(ctx)
if err == nil { if err == nil {
// FIXME: Add real env // FIXME: Add real env
//q := datastore.NewQuery("Environments").Limit(1) envName := "Shuffle"
//count, err := dbclient.Get(ctx, q) environments, err := getEnvironments(ctx)
//envName := "Shuffle" if err == nil {
//if err == nil { for _, env := range environments {
//} if env.Default {
envName = env.Name
break
}
}
}
for _, item := range workflowapps { for _, item := range workflowapps {
if item.Name == "Testing" && item.AppVersion == "1.0.0" { if item.Name == "Testing" && item.AppVersion == "1.0.0" {
@@ -1249,7 +1261,7 @@ func setNewWorkflow(resp http.ResponseWriter, request *http.Request) {
newActions = append(newActions, Action{ newActions = append(newActions, Action{
Label: "Start node", Label: "Start node",
Name: "hello_world", Name: "hello_world",
Environment: "Shuffle", Environment: envName,
Parameters: []WorkflowAppActionParameter{}, Parameters: []WorkflowAppActionParameter{},
Position: struct { Position: struct {
X float64 "json:\"x\" datastore:\"x\"" X float64 "json:\"x\" datastore:\"x\""
@@ -3100,6 +3112,18 @@ func getWorkflow(ctx context.Context, id string) (*Workflow, error) {
return workflow, nil return workflow, nil
} }
func getEnvironments(ctx context.Context) ([]Environment, error) {
var environments []Environment
q := datastore.NewQuery("Environments")
_, err := dbclient.GetAll(ctx, q, &environments)
if err != nil {
return []Environment{}, err
}
return environments, nil
}
func getAllWorkflows(ctx context.Context) ([]Workflow, error) { func getAllWorkflows(ctx context.Context) ([]Workflow, error) {
var allworkflows []Workflow var allworkflows []Workflow
q := datastore.NewQuery("workflow") q := datastore.NewQuery("workflow")
@@ -4045,6 +4069,62 @@ func deployWebhookFunction(ctx context.Context, name, localization, applocation
return nil return nil
} }
func loadGithubWorkflows(url, username, password, userId string) error {
fs := memfs.New()
if strings.Contains(url, "github") || strings.Contains(url, "gitlab") || strings.Contains(url, "bitbucket") {
cloneOptions := &git.CloneOptions{
URL: url,
}
// FIXME: Better auth.
if len(username) > 0 && len(password) > 0 {
cloneOptions.Auth = &http2.BasicAuth{
Username: username,
Password: password,
}
}
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, cloneOptions)
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
return err
}
dir, err := fs.ReadDir("/")
if err != nil {
log.Printf("FAiled reading folder: %s", err)
}
_ = r
log.Printf("Starting workflow folder iteration")
iterateWorkflowGithubFolders(fs, dir, "", "", userId)
} else if strings.Contains(url, "s3") {
//https://docs.aws.amazon.com/sdk-for-go/api/service/s3/
//sess := session.Must(session.NewSession())
//downloader := s3manager.NewDownloader(sess)
//// Write the contents of S3 Object to the file
//storer := memory.NewStorage()
//n, err := downloader.Download(storer, &s3.GetObjectInput{
// Bucket: aws.String(myBucket),
// Key: aws.String(myString),
//})
//if err != nil {
// return fmt.Errorf("failed to download file, %v", err)
//}
//fmt.Printf("file downloaded, %d bytes\n", n)
} else {
return errors.New(fmt.Sprintf("URL %s is unsupported when downloading workflows", url))
}
return nil
}
func loadSpecificWorkflows(resp http.ResponseWriter, request *http.Request) { func loadSpecificWorkflows(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request) cors := handleCors(resp, request)
if cors { if cors {
@@ -4064,7 +4144,7 @@ func loadSpecificWorkflows(resp http.ResponseWriter, request *http.Request) {
if user.Role != "admin" { if user.Role != "admin" {
log.Printf("Wrong user (%s) when downloading from github", user.Username) log.Printf("Wrong user (%s) when downloading from github", user.Username)
resp.WriteHeader(401) resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`)) resp.Write([]byte(`{"success": false, "reason": "Downloading remotely requires admin"}`))
return return
} }
@@ -4093,59 +4173,11 @@ func loadSpecificWorkflows(resp http.ResponseWriter, request *http.Request) {
return return
} }
fs := memfs.New() err = loadGithubWorkflows(tmpBody.URL, tmpBody.Field1, tmpBody.Field2, user.Id)
if err != nil {
if strings.Contains(tmpBody.URL, "github") || strings.Contains(tmpBody.URL, "gitlab") || strings.Contains(tmpBody.URL, "bitbucket") { log.Printf("Failed to update workflows: %s", err)
cloneOptions := &git.CloneOptions{
URL: tmpBody.URL,
}
// FIXME: Better auth.
if len(tmpBody.Field1) > 0 && len(tmpBody.Field2) > 0 {
cloneOptions.Auth = &http2.BasicAuth{
Username: tmpBody.Field1,
Password: tmpBody.Field2,
}
}
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, cloneOptions)
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, err)))
return
}
dir, err := fs.ReadDir("/")
if err != nil {
log.Printf("FAiled reading folder: %s", err)
}
_ = r
log.Printf("Starting workflow folder iteration")
iterateWorkflowGithubFolders(fs, dir, "", "", user.Id)
} else if strings.Contains(tmpBody.URL, "s3") {
//https://docs.aws.amazon.com/sdk-for-go/api/service/s3/
//sess := session.Must(session.NewSession())
//downloader := s3manager.NewDownloader(sess)
//// Write the contents of S3 Object to the file
//storer := memory.NewStorage()
//n, err := downloader.Download(storer, &s3.GetObjectInput{
// Bucket: aws.String(myBucket),
// Key: aws.String(myString),
//})
//if err != nil {
// return fmt.Errorf("failed to download file, %v", err)
//}
//fmt.Printf("file downloaded, %d bytes\n", n)
} else {
resp.WriteHeader(401) resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s is unsupported. Try e.g. github"}`, tmpBody.URL))) resp.Write([]byte(`{"success": false}`))
return return
} }
@@ -4489,7 +4521,7 @@ func iterateWorkflowGithubFolders(fs billy.Filesystem, dir []os.FileInfo, extra
log.Printf("Failed setting (download) workflow: %s", err) log.Printf("Failed setting (download) workflow: %s", err)
continue continue
} }
log.Printf("Uploaded workflow %s!", filename) log.Printf("Uploaded workflow %s for user %s!", filename, userId)
} }
} }
} }
+1 -1
View File
@@ -16,7 +16,7 @@ services:
depends_on: depends_on:
- backend - backend
backend: backend:
build: ./backend #build: ./backend
image: frikky/shuffle:backend image: frikky/shuffle:backend
container_name: shuffle-backend container_name: shuffle-backend
hostname: ${BACKEND_HOSTNAME} hostname: ${BACKEND_HOSTNAME}
+6
View File
@@ -2,8 +2,10 @@
FROM node as builder FROM node as builder
RUN mkdir /usr/src/app RUN mkdir /usr/src/app
WORKDIR /usr/src/app WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json COPY package.json /usr/src/app/package.json
RUN npm install --verbose RUN npm install --verbose
@@ -15,6 +17,10 @@ COPY ./src /usr/src/app/src/
COPY ./*.sh /usr/src/app/ COPY ./*.sh /usr/src/app/
COPY ./*.json /usr/src/app/ COPY ./*.json /usr/src/app/
# There were issues with the webpack installer from package.json
RUN rm -rf /usr/src/app/node_modules/webpack
RUN npm install webpack@4.42.0
RUN npm run-script build RUN npm run-script build
# Production environment # Production environment
+396 -43
View File
@@ -4332,13 +4332,14 @@
} }
}, },
"asn1.js": { "asn1.js": {
"version": "4.10.1", "version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"requires": { "requires": {
"bn.js": "^4.0.0", "bn.js": "^4.0.0",
"inherits": "^2.0.1", "inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0" "minimalistic-assert": "^1.0.0",
"safer-buffer": "^2.1.0"
}, },
"dependencies": { "dependencies": {
"bn.js": { "bn.js": {
@@ -5265,9 +5266,9 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
}, },
"bn.js": { "bn.js": {
"version": "5.1.2", "version": "5.1.3",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
"integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ=="
}, },
"body-parser": { "body-parser": {
"version": "1.19.0", "version": "1.19.0",
@@ -5438,15 +5439,15 @@
} }
}, },
"browserify-sign": { "browserify-sign": {
"version": "4.2.0", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
"integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==", "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
"requires": { "requires": {
"bn.js": "^5.1.1", "bn.js": "^5.1.1",
"browserify-rsa": "^4.0.1", "browserify-rsa": "^4.0.1",
"create-hash": "^1.2.0", "create-hash": "^1.2.0",
"create-hmac": "^1.1.7", "create-hmac": "^1.1.7",
"elliptic": "^6.5.2", "elliptic": "^6.5.3",
"inherits": "^2.0.4", "inherits": "^2.0.4",
"parse-asn1": "^5.1.5", "parse-asn1": "^5.1.5",
"readable-stream": "^3.6.0", "readable-stream": "^3.6.0",
@@ -5868,9 +5869,9 @@
} }
}, },
"class-transformer": { "class-transformer": {
"version": "0.2.3", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.2.3.tgz", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz",
"integrity": "sha512-qsP+0xoavpOlJHuYsQJsN58HXSl8Jvveo+T37rEvCEeRfMWoytAyR0Ua/YsFgpM6AZYZ/og2PJwArwzJl1aXtQ==" "integrity": "sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA=="
}, },
"class-utils": { "class-utils": {
"version": "0.3.6", "version": "0.3.6",
@@ -6341,12 +6342,12 @@
} }
}, },
"create-ecdh": { "create-ecdh": {
"version": "4.0.3", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
"integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"requires": { "requires": {
"bn.js": "^4.1.0", "bn.js": "^4.1.0",
"elliptic": "^6.0.0" "elliptic": "^6.5.3"
}, },
"dependencies": { "dependencies": {
"bn.js": { "bn.js": {
@@ -7558,9 +7559,9 @@
"integrity": "sha512-vcTeLpPm4+ccoYFXnepvkFt0KujdyrBU19KNEO40Pnkhta6mUi2K0Dn7NmpRcNz7BvysnSqeuIYScP003HWuYg==" "integrity": "sha512-vcTeLpPm4+ccoYFXnepvkFt0KujdyrBU19KNEO40Pnkhta6mUi2K0Dn7NmpRcNz7BvysnSqeuIYScP003HWuYg=="
}, },
"elliptic": { "elliptic": {
"version": "6.5.2", "version": "6.5.3",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
"integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
"requires": { "requires": {
"bn.js": "^4.4.0", "bn.js": "^4.4.0",
"brorand": "^1.0.1", "brorand": "^1.0.1",
@@ -7610,9 +7611,9 @@
} }
}, },
"enhanced-resolve": { "enhanced-resolve": {
"version": "4.2.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
"integrity": "sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ==", "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"memory-fs": "^0.5.0", "memory-fs": "^0.5.0",
@@ -8250,9 +8251,9 @@
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
}, },
"events": { "events": {
"version": "3.1.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
"integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==" "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg=="
}, },
"eventsource": { "eventsource": {
"version": "1.0.7", "version": "1.0.7",
@@ -13442,13 +13443,12 @@
} }
}, },
"parse-asn1": { "parse-asn1": {
"version": "5.1.5", "version": "5.1.6",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
"integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
"requires": { "requires": {
"asn1.js": "^4.0.0", "asn1.js": "^5.2.0",
"browserify-aes": "^1.0.0", "browserify-aes": "^1.0.0",
"create-hash": "^1.1.0",
"evp_bytestokey": "^1.0.0", "evp_bytestokey": "^1.0.0",
"pbkdf2": "^3.0.3", "pbkdf2": "^3.0.3",
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
@@ -15566,11 +15566,205 @@
"workbox-webpack-plugin": "4.3.1" "workbox-webpack-plugin": "4.3.1"
}, },
"dependencies": { "dependencies": {
"@webassemblyjs/ast": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
"integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
"requires": {
"@webassemblyjs/helper-module-context": "1.8.5",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5",
"@webassemblyjs/wast-parser": "1.8.5"
}
},
"@webassemblyjs/floating-point-hex-parser": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
"integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ=="
},
"@webassemblyjs/helper-api-error": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
"integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA=="
},
"@webassemblyjs/helper-buffer": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
"integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q=="
},
"@webassemblyjs/helper-code-frame": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
"integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
"requires": {
"@webassemblyjs/wast-printer": "1.8.5"
}
},
"@webassemblyjs/helper-fsm": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
"integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow=="
},
"@webassemblyjs/helper-module-context": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
"integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"mamacro": "^0.0.3"
}
},
"@webassemblyjs/helper-wasm-bytecode": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
"integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ=="
},
"@webassemblyjs/helper-wasm-section": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
"integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/helper-buffer": "1.8.5",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5",
"@webassemblyjs/wasm-gen": "1.8.5"
}
},
"@webassemblyjs/ieee754": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
"integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
"requires": {
"@xtuc/ieee754": "^1.2.0"
}
},
"@webassemblyjs/leb128": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
"integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
"requires": {
"@xtuc/long": "4.2.2"
}
},
"@webassemblyjs/utf8": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
"integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw=="
},
"@webassemblyjs/wasm-edit": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
"integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/helper-buffer": "1.8.5",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5",
"@webassemblyjs/helper-wasm-section": "1.8.5",
"@webassemblyjs/wasm-gen": "1.8.5",
"@webassemblyjs/wasm-opt": "1.8.5",
"@webassemblyjs/wasm-parser": "1.8.5",
"@webassemblyjs/wast-printer": "1.8.5"
}
},
"@webassemblyjs/wasm-gen": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
"integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5",
"@webassemblyjs/ieee754": "1.8.5",
"@webassemblyjs/leb128": "1.8.5",
"@webassemblyjs/utf8": "1.8.5"
}
},
"@webassemblyjs/wasm-opt": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
"integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/helper-buffer": "1.8.5",
"@webassemblyjs/wasm-gen": "1.8.5",
"@webassemblyjs/wasm-parser": "1.8.5"
}
},
"@webassemblyjs/wasm-parser": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
"integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/helper-api-error": "1.8.5",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5",
"@webassemblyjs/ieee754": "1.8.5",
"@webassemblyjs/leb128": "1.8.5",
"@webassemblyjs/utf8": "1.8.5"
}
},
"@webassemblyjs/wast-parser": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
"integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/floating-point-hex-parser": "1.8.5",
"@webassemblyjs/helper-api-error": "1.8.5",
"@webassemblyjs/helper-code-frame": "1.8.5",
"@webassemblyjs/helper-fsm": "1.8.5",
"@xtuc/long": "4.2.2"
}
},
"@webassemblyjs/wast-printer": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
"integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/wast-parser": "1.8.5",
"@xtuc/long": "4.2.2"
}
},
"acorn": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
},
"cacache": {
"version": "12.0.4",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
"integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
"requires": {
"bluebird": "^3.5.5",
"chownr": "^1.1.1",
"figgy-pudding": "^3.5.1",
"glob": "^7.1.4",
"graceful-fs": "^4.1.15",
"infer-owner": "^1.0.3",
"lru-cache": "^5.1.1",
"mississippi": "^3.0.0",
"mkdirp": "^0.5.1",
"move-concurrently": "^1.0.1",
"promise-inflight": "^1.0.1",
"rimraf": "^2.6.3",
"ssri": "^6.0.1",
"unique-filename": "^1.1.1",
"y18n": "^4.0.0"
}
},
"dotenv": { "dotenv": {
"version": "8.2.0", "version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
}, },
"eslint-scope": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
"integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"fs-extra": { "fs-extra": {
"version": "8.1.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -15586,10 +15780,102 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
}, },
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"requires": {
"yallist": "^3.0.2"
}
},
"schema-utils": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
"integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
"requires": {
"ajv": "^6.1.0",
"ajv-errors": "^1.0.0",
"ajv-keywords": "^3.1.0"
}
},
"semver": { "semver": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"serialize-javascript": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"requires": {
"randombytes": "^2.1.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"ssri": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
"integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
"requires": {
"figgy-pudding": "^3.5.1"
}
},
"webpack": {
"version": "4.42.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.0.tgz",
"integrity": "sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==",
"requires": {
"@webassemblyjs/ast": "1.8.5",
"@webassemblyjs/helper-module-context": "1.8.5",
"@webassemblyjs/wasm-edit": "1.8.5",
"@webassemblyjs/wasm-parser": "1.8.5",
"acorn": "^6.2.1",
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^4.1.0",
"eslint-scope": "^4.0.3",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^2.4.0",
"loader-utils": "^1.2.3",
"memory-fs": "^0.4.1",
"micromatch": "^3.1.10",
"mkdirp": "^0.5.1",
"neo-async": "^2.6.1",
"node-libs-browser": "^2.2.1",
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
"terser-webpack-plugin": "^1.4.3",
"watchpack": "^1.6.0",
"webpack-sources": "^1.4.1"
},
"dependencies": {
"terser-webpack-plugin": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
"integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"requires": {
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
"serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
"worker-farm": "^1.7.0"
}
}
}
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
} }
} }
}, },
@@ -18337,14 +18623,81 @@
} }
}, },
"watchpack": { "watchpack": {
"version": "1.7.2", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
"integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==", "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
"requires": { "requires": {
"chokidar": "^3.4.0", "chokidar": "^3.4.1",
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"neo-async": "^2.5.0", "neo-async": "^2.5.0",
"watchpack-chokidar2": "^2.0.0" "watchpack-chokidar2": "^2.0.0"
},
"dependencies": {
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"optional": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"optional": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"chokidar": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
"integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
"optional": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.4.0"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"optional": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"optional": true
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"optional": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"optional": true,
"requires": {
"is-number": "^7.0.0"
}
}
} }
}, },
"watchpack-chokidar2": { "watchpack-chokidar2": {
@@ -18574,9 +18927,9 @@
} }
}, },
"serialize-javascript": { "serialize-javascript": {
"version": "3.1.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"requires": { "requires": {
"randombytes": "^2.1.0" "randombytes": "^2.1.0"
} }
@@ -18595,15 +18948,15 @@
} }
}, },
"terser-webpack-plugin": { "terser-webpack-plugin": {
"version": "1.4.4", "version": "1.4.5",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
"integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==", "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"requires": { "requires": {
"cacache": "^12.0.2", "cacache": "^12.0.2",
"find-cache-dir": "^2.1.0", "find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0", "is-wsl": "^1.1.0",
"schema-utils": "^1.0.0", "schema-utils": "^1.0.0",
"serialize-javascript": "^3.1.0", "serialize-javascript": "^4.0.0",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"terser": "^4.1.2", "terser": "^4.1.2",
"webpack-sources": "^1.4.0", "webpack-sources": "^1.4.0",
+2 -1
View File
@@ -8,7 +8,7 @@
"@material-ui/icons": "^4.5.1", "@material-ui/icons": "^4.5.1",
"@material-ui/styles": "^4.5.2", "@material-ui/styles": "^4.5.2",
"@use-it/interval": "^0.1.3", "@use-it/interval": "^0.1.3",
"class-transformer": "^0.3.1", "class-transformer": "^0.3.1",
"create-react-app": "^2.0.3", "create-react-app": "^2.0.3",
"cytoscape": "^3.11.0", "cytoscape": "^3.11.0",
"cytoscape-clipboard": "^2.2.1", "cytoscape-clipboard": "^2.2.1",
@@ -54,6 +54,7 @@
"shellwords": "^0.1.1", "shellwords": "^0.1.1",
"simplebar": "^4.2.3", "simplebar": "^4.2.3",
"styled-components": "^4.4.0", "styled-components": "^4.4.0",
"webpack": "^4.42.0",
"websocket": "^1.0.30", "websocket": "^1.0.30",
"yaml": "^1.7.2", "yaml": "^1.7.2",
"yamljs": "^0.3.0", "yamljs": "^0.3.0",
+101 -11
View File
@@ -47,6 +47,7 @@ const Admin = (props) => {
const [selectedUserModalOpen, setSelectedUserModalOpen] = React.useState(false) const [selectedUserModalOpen, setSelectedUserModalOpen] = React.useState(false)
const [selectedAuthentication, setSelectedAuthentication] = React.useState({}) const [selectedAuthentication, setSelectedAuthentication] = React.useState({})
const [selectedAuthenticationModalOpen, setSelectedAuthenticationModalOpen] = React.useState(false) const [selectedAuthenticationModalOpen, setSelectedAuthenticationModalOpen] = React.useState(false)
const [showArchived, setShowArchived] = React.useState(false)
const alert = useAlert() const alert = useAlert()
@@ -129,7 +130,8 @@ const Admin = (props) => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
alert.error("Failed setting new password") alert.error("Failed setting new password")
} else { } else {
alert.success("Changed password!") alert.success("Successfully password!")
setSelectedUserModalOpen(false)
} }
}), }),
) )
@@ -169,7 +171,6 @@ const Admin = (props) => {
} }
const submitUser = (data) => { const submitUser = (data) => {
// FIXME - add some check here ROFL
console.log("INPUT: ", data) console.log("INPUT: ", data)
// Just use this one? // Just use this one?
@@ -200,13 +201,21 @@ const Admin = (props) => {
}); });
} }
const deleteEnvironment = (name) => { // Horrible frontend fix for environments
const setDefaultEnvironment = (name) => {
// FIXME - add some check here ROFL // FIXME - add some check here ROFL
alert.info("Deleting environment " + name) alert.info("Setting default env to " + name)
var newEnv = [] var newEnv = []
for (var key in environments) { for (var key in environments) {
if (environments[key].Name == name) { if (environments[key].Name == name) {
continue if (environments[key].archived) {
alert.error("Can't set archived to default")
return
}
environments[key].default = true
} else if (environments[key].default == true && environments[key].name !== name) {
environments[key].default = false
} }
newEnv.push(environments[key]) newEnv.push(environments[key])
@@ -226,6 +235,7 @@ const Admin = (props) => {
response.json().then(responseJson => { response.json().then(responseJson => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
alert.error(responseJson.reason) alert.error(responseJson.reason)
getEnvironments()
} else { } else {
setLoginInfo("") setLoginInfo("")
setModalOpen(false) setModalOpen(false)
@@ -233,14 +243,60 @@ const Admin = (props) => {
} }
}), }),
) )
//.catch(error => { .catch(error => {
// console.log("Error in userdata: ", error) console.log("Error in backend data: ", error)
//}); })
}
const deleteEnvironment = (name) => {
// FIXME - add some check here ROFL
alert.info("Deleting environment " + name)
var newEnv = []
for (var key in environments) {
if (environments[key].Name == name) {
if (environments[key].default) {
alert.info("Can't delete the default environment")
return
}
environments[key].archived = true
}
newEnv.push(environments[key])
}
// Just use this one?
const url = globalUrl + '/api/v1/setenvironments';
fetch(url, {
method: 'PUT',
credentials: "include",
body: JSON.stringify(newEnv),
headers: {
'Content-Type': 'application/json',
},
})
.then(response =>
response.json().then(responseJson => {
if (responseJson["success"] === false) {
alert.error(responseJson.reason)
getEnvironments()
} else {
setLoginInfo("")
setModalOpen(false)
getEnvironments()
}
}),
)
.catch(error => {
console.log("Error when deleting: ", error)
})
} }
const submitEnvironment = (data) => { const submitEnvironment = (data) => {
// FIXME - add some check here ROFL // FIXME - add some check here ROFL
environments.push({ "name": data.environment, "type": "onprem" }) environments.push({
"name": data.environment,
"type": "onprem",
})
// Just use this one? // Just use this one?
var baseurl = globalUrl var baseurl = globalUrl
@@ -257,6 +313,7 @@ const Admin = (props) => {
response.json().then(responseJson => { response.json().then(responseJson => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
setLoginInfo("Error in input: " + responseJson.reason) setLoginInfo("Error in input: " + responseJson.reason)
getEnvironments()
} else { } else {
setLoginInfo("") setLoginInfo("")
setModalOpen(false) setModalOpen(false)
@@ -342,7 +399,6 @@ const Admin = (props) => {
return response.json() return response.json()
}) })
.then((responseJson) => { .then((responseJson) => {
console.log(responseJson)
setEnvironments(responseJson) setEnvironments(responseJson)
}) })
.catch(error => { .catch(error => {
@@ -934,6 +990,7 @@ const Admin = (props) => {
</div> </div>
: null : null
console.log("Environments: ", environments)
const environmentView = curTab === 2 ? const environmentView = curTab === 2 ?
<div> <div>
<div style={{marginTop: 20, marginBottom: 20,}}> <div style={{marginTop: 20, marginBottom: 20,}}>
@@ -967,12 +1024,29 @@ const Admin = (props) => {
primary="Orborus running (TBD)" primary="Orborus running (TBD)"
style={{minWidth: 200, maxWidth: 200}} style={{minWidth: 200, maxWidth: 200}}
/> />
<ListItemText
primary="Default"
style={{minWidth: 150, maxWidth: 150}}
/>
<ListItemText <ListItemText
primary="Actions" primary="Actions"
style={{minWidth: 150, maxWidth: 150}} style={{minWidth: 150, maxWidth: 150}}
/> />
<ListItemText
primary="Archived"
style={{minWidth: 150, maxWidth: 150}}
/>
</ListItem> </ListItem>
{environments === undefined ? null : environments.map(environment => { {environments === undefined ? null : environments.map(environment => {
if (!showArchived && environment.archived) {
return null
}
if (environment.archived === undefined) {
getEnvironments()
return null
}
return ( return (
<ListItem> <ListItem>
<ListItemText <ListItemText
@@ -983,9 +1057,25 @@ const Admin = (props) => {
primary={"TBD"} primary={"TBD"}
style={{minWidth: 200, maxWidth: 200, overflow: "hidden"}} style={{minWidth: 200, maxWidth: 200, overflow: "hidden"}}
/> />
<ListItemText> <ListItemText
style={{minWidth: 150, maxWidth: 150, overflow: "hidden"}}
primary={environment.default ? "true" : null}
>
{environment.default ?
null
:
<Button variant="outlined" style={{borderRadius: "0px"}} onClick={() => setDefaultEnvironment(environment.Name)} color="primary">Set default</Button>
}
</ListItemText>
<ListItemText
style={{minWidth: 150, maxWidth: 150, overflow: "hidden"}}
>
<Button variant="outlined" style={{borderRadius: "0px"}} onClick={() => deleteEnvironment(environment.Name)} color="primary">Delete</Button> <Button variant="outlined" style={{borderRadius: "0px"}} onClick={() => deleteEnvironment(environment.Name)} color="primary">Delete</Button>
</ListItemText> </ListItemText>
<ListItemText
style={{minWidth: 150, maxWidth: 150, overflow: "hidden"}}
primary={environment.archived.toString()}
/>
</ListItem> </ListItem>
) )
})} })}
File diff suppressed because one or more lines are too long
+29 -10
View File
@@ -20,6 +20,7 @@ import Tooltip from '@material-ui/core/Tooltip';
import CheckCircleIcon from '@material-ui/icons/CheckCircle'; import CheckCircleIcon from '@material-ui/icons/CheckCircle';
import Breadcrumbs from '@material-ui/core/Breadcrumbs'; import Breadcrumbs from '@material-ui/core/Breadcrumbs';
import AppsIcon from '@material-ui/icons/Apps'; import AppsIcon from '@material-ui/icons/Apps';
import CircularProgress from '@material-ui/core/CircularProgress';
import ErrorOutline from '@material-ui/icons/ErrorOutline'; import ErrorOutline from '@material-ui/icons/ErrorOutline';
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
@@ -210,6 +211,7 @@ const AppCreator = (props) => {
const [, setBasedata] = React.useState({}) const [, setBasedata] = React.useState({})
const [actions, setActions] = useState([]) const [actions, setActions] = useState([])
const [errorCode, setErrorCode] = useState("") const [errorCode, setErrorCode] = useState("")
const [appBuilding, setAppBuilding] = useState(false)
//const [actions, setActions] = useState([{ //const [actions, setActions] = useState([{
// "name": "Get workflows", // "name": "Get workflows",
@@ -279,9 +281,9 @@ const AppCreator = (props) => {
return response.json() return response.json()
}) })
.then((responseJson) => { .then((responseJson) => {
setIsAppLoaded(true)
if (!responseJson.success) { if (!responseJson.success) {
alert.error("Failed to get the app") alert.error("Failed to get the app")
setIsAppLoaded(true)
} else { } else {
const data = JSON.parse(responseJson.body) const data = JSON.parse(responseJson.body)
parseIncomingOpenapiData(data) parseIncomingOpenapiData(data)
@@ -365,6 +367,8 @@ const AppCreator = (props) => {
var firstUrl = data.servers[0].url var firstUrl = data.servers[0].url
if (firstUrl.endsWith("/")) { if (firstUrl.endsWith("/")) {
setBaseUrl(firstUrl.slice(0, firstUrl.length-1)) setBaseUrl(firstUrl.slice(0, firstUrl.length-1))
} else {
setBaseUrl(firstUrl)
} }
} }
@@ -378,9 +382,6 @@ const AppCreator = (props) => {
securitySchemes = data.components.securitySchemes securitySchemes = data.components.securitySchemes
} }
console.log(data)
// FIXME - headers? // FIXME - headers?
var newActions = [] var newActions = []
var wordlist = {} var wordlist = {}
@@ -398,7 +399,6 @@ const AppCreator = (props) => {
"errors": [], "errors": [],
} }
for (var key in methodvalue.parameters) { for (var key in methodvalue.parameters) {
const parameter = methodvalue.parameters[key] const parameter = methodvalue.parameters[key]
if (parameter.in === "query") { if (parameter.in === "query") {
@@ -520,11 +520,13 @@ const AppCreator = (props) => {
} }
setActions(newActions) setActions(newActions)
setIsAppLoaded(true)
} }
// Saving the app that's been configured. // Saving the app that's been configured.
const submitApp = () => { const submitApp = () => {
alert.info("Uploading and building app " + name) alert.info("Uploading and building app " + name)
setAppBuilding(true)
setErrorCode("") setErrorCode("")
// Format the information // Format the information
@@ -718,6 +720,7 @@ const AppCreator = (props) => {
if (authenticationOption === "API key") { if (authenticationOption === "API key") {
if (parameterName.length === 0) { if (parameterName.length === 0) {
alert.error("A field name for the APIkey must be defined") alert.error("A field name for the APIkey must be defined")
setAppBuilding(false)
return return
} }
@@ -757,6 +760,7 @@ const AppCreator = (props) => {
// throw new Error("NOT 200 :O") // throw new Error("NOT 200 :O")
//} //}
setAppBuilding(false)
return response.json() return response.json()
}) })
.then((responseJson) => { .then((responseJson) => {
@@ -1570,7 +1574,22 @@ const AppCreator = (props) => {
margin="normal" margin="normal"
variant="outlined" variant="outlined"
value={name} value={name}
onChange={e => setName(e.target.value)} onChange={e => {
const invalid = ["#", ":", "."]
for (var key in invalid) {
if (e.target.value.includes(invalid[key])) {
alert.error("Can't use "+invalid[key]+" in name")
return
}
}
if (e.target.value.length > 100) {
alert.error("Choose a shorter name.")
return
}
setName(e.target.value)
}}
color="primary" color="primary"
InputProps={{ InputProps={{
style:{ style:{
@@ -1590,12 +1609,12 @@ const AppCreator = (props) => {
style={{flex: "1", marginTop: "5px", marginRight: "15px", backgroundColor: inputColor}} style={{flex: "1", marginTop: "5px", marginRight: "15px", backgroundColor: inputColor}}
fullWidth={true} fullWidth={true}
type="name" type="name"
id="outlined-with-placeholder" id="outlined-with-placeholder"
margin="normal" margin="normal"
variant="outlined" variant="outlined"
placeholder="A description for the service" placeholder="A description for the service"
value={description} value={description}
onChange={e => setDescription(e.target.value)} onChange={e => setDescription(e.target.value)}
InputProps={{ InputProps={{
classes: { classes: {
notchedOutline: classes.notchedOutline, notchedOutline: classes.notchedOutline,
@@ -1691,10 +1710,10 @@ const AppCreator = (props) => {
{testView} {testView}
*/} */}
<Button color="primary" variant="contained" style={{borderRadius: "0px", marginTop: "30px", height: "50px",}} onClick={() => { <Button disabled={appBuilding} color="primary" variant="contained" style={{borderRadius: "0px", marginTop: "30px", height: "50px",}} onClick={() => {
submitApp() submitApp()
}}> }}>
Save {appBuilding ? <CircularProgress /> : "Save"}
</Button> </Button>
{errorCode.length > 0 ? `Error: ${errorCode}` : null} {errorCode.length > 0 ? `Error: ${errorCode}` : null}
</Paper> </Paper>
+32 -17
View File
@@ -16,6 +16,7 @@ import Switch from '@material-ui/core/Switch';
import CircularProgress from '@material-ui/core/CircularProgress'; import CircularProgress from '@material-ui/core/CircularProgress';
import CachedIcon from '@material-ui/icons/Cached'; import CachedIcon from '@material-ui/icons/Cached';
import GetAppIcon from '@material-ui/icons/GetApp';
import EditIcon from '@material-ui/icons/Edit'; import EditIcon from '@material-ui/icons/Edit';
import MoreVertIcon from '@material-ui/icons/MoreVert'; import MoreVertIcon from '@material-ui/icons/MoreVert';
import PlayArrowIcon from '@material-ui/icons/PlayArrow'; import PlayArrowIcon from '@material-ui/icons/PlayArrow';
@@ -126,14 +127,15 @@ const Workflows = (props) => {
color: "#ffffff", color: "#ffffff",
width: "100%", width: "100%",
display: "flex", display: "flex",
maxWidth: "1768px", minWidth: 1366,
maxWidth: 1766,
margin: "auto", margin: "auto",
maxHeight: "90vh", maxHeight: "90vh",
} }
const emptyWorkflowStyle = { const emptyWorkflowStyle = {
paddingTop: "200px", paddingTop: "200px",
width: "1024px", width: 1024,
margin: "auto", margin: "auto",
} }
@@ -263,6 +265,12 @@ const Workflows = (props) => {
return new Promise((resolve) => setTimeout(resolve, time)); return new Promise((resolve) => setTimeout(resolve, time));
} }
const exportAllWorkflows = () => {
for (var key in workflows) {
exportWorkflow(workflows[key])
}
}
const exportWorkflow = (data) => { const exportWorkflow = (data) => {
console.log("export") console.log("export")
let dataStr = JSON.stringify(data) let dataStr = JSON.stringify(data)
@@ -364,9 +372,9 @@ const Workflows = (props) => {
}}> }}>
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}}> <div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}}>
</div> </div>
<Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}}> <Grid container style={{margin: "10px 10px 10px 10px", flex: 1}}>
<Grid style={{display: "flex", flexDirection: "column", width: "100%"}}> <Grid style={{display: "flex", flexDirection: "column", width: "100%"}}>
<Grid item style={{flex: "1", display: "flex"}}> <Grid item style={{flex: 1, display: "flex"}}>
<div style={{flex: "10",}} onClick={() => { <div style={{flex: "10",}} onClick={() => {
if (selectedWorkflow.id !== data.id) { if (selectedWorkflow.id !== data.id) {
setSelectedWorkflow(data) setSelectedWorkflow(data)
@@ -418,7 +426,7 @@ const Workflows = (props) => {
</Menu> </Menu>
</div> </div>
</Grid> </Grid>
<div style={{display: "flex", flex: "1"}} onClick={() => { <div style={{display: "flex", flex: 1}} onClick={() => {
if (selectedWorkflow.id !== data.id) { if (selectedWorkflow.id !== data.id) {
setSelectedWorkflow(data) setSelectedWorkflow(data)
getWorkflowExecution(data.id) getWorkflowExecution(data.id)
@@ -468,13 +476,13 @@ const Workflows = (props) => {
var results = data.results.length var results = data.results.length
} }
return ( return (
<Paper square style={paperAppStyle} onClick={() => { <Paper key={data.id} square style={paperAppStyle} onClick={() => {
setSelectedExecution(data) setSelectedExecution(data)
}}> }}>
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}} /> <div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: boxWidth, backgroundColor: boxColor}} />
<Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}}> <Grid container style={{margin: "10px 10px 10px 10px", flex: 1}}>
<Grid style={{display: "flex", flexDirection: "column", width: "100%"}}> <Grid style={{display: "flex", flexDirection: "column", width: "100%"}}>
<Grid item style={{flex: "1", display: "flex"}}> <Grid item style={{flex: 1, display: "flex"}}>
<div style={{flex: "5"}}> <div style={{flex: "5"}}>
<h3 style={{marginBottom: "0px", marginTop: "10px"}}><b>Status</b>: {data.status}</h3> <h3 style={{marginBottom: "0px", marginTop: "10px"}}><b>Status</b>: {data.status}</h3>
Actions: {results}/{actions} Actions: {results}/{actions}
@@ -681,7 +689,7 @@ const Workflows = (props) => {
*/ */
if (Object.getOwnPropertyNames(selectedExecution).length > 0 && selectedExecution.workflow.actions !== null) { if (Object.getOwnPropertyNames(selectedExecution).length > 0 && selectedExecution.workflow.actions !== null) {
return ( return (
<div> <div style={{overflowX: "hidden"}}>
<div> <div>
<b>Status:</b> {selectedExecution.status} <b>Status:</b> {selectedExecution.status}
</div> </div>
@@ -843,7 +851,7 @@ const Workflows = (props) => {
} }
const modalView = modalOpen ? const modalView = modalOpen ?
<Dialog modal <Dialog
open={modalOpen} open={modalOpen}
onClose={() => {setModalOpen(false)}} onClose={() => {setModalOpen(false)}}
PaperProps={{ PaperProps={{
@@ -910,9 +918,9 @@ const Workflows = (props) => {
const viewSize = { const viewSize = {
workflowView: 1, workflowView: 4,
executionsView: 1, executionsView: 3,
executionResults: 2, executionResults: 4,
} }
const workflowViewStyle = { const workflowViewStyle = {
@@ -943,7 +951,14 @@ const Workflows = (props) => {
</Button> </Button>
</Tooltip> </Tooltip>
*/} */}
<Tooltip color="primary" title={"Download / Import workflows"} placement="top"> <Tooltip color="primary" title={`Download ALL workflows (${workflows.length})`} placement="top">
<Button color="primary" style={{}} variant="text" onClick={() => {
exportAllWorkflows()
}}>
<GetAppIcon />
</Button>
</Tooltip>
<Tooltip color="primary" title={"Import workflows"} placement="top">
<Button color="primary" style={{}} variant="text" onClick={() => setLoadWorkflowsModalOpen(true)}> <Button color="primary" style={{}} variant="text" onClick={() => setLoadWorkflowsModalOpen(true)}>
<CloudDownloadIcon /> <CloudDownloadIcon />
</Button> </Button>
@@ -982,10 +997,10 @@ const Workflows = (props) => {
</div> </div>
<div style={{flex: viewSize.executionResults, marginLeft: "10px", marginRight: "10px", minWidth: "33%"}}> <div style={{flex: viewSize.executionResults, marginLeft: "10px", marginRight: "10px", minWidth: "33%"}}>
<div style={{display: "flex"}}> <div style={{display: "flex"}}>
<div style={{flex: "3"}}> <div style={{flex: "1"}}>
<h2>Execution Timeline</h2> <h2>Execution Timeline</h2>
</div> </div>
<div style={{flex: "1"}}> <div style={{flex: 1}}>
<FormControlLabel <FormControlLabel
style={{color: "white", marginBottom: "0px", marginTop: "10px"}} style={{color: "white", marginBottom: "0px", marginTop: "10px"}}
label={<div style={{color: "white"}}>Collapse results</div>} label={<div style={{color: "white"}}>Collapse results</div>}
@@ -1075,7 +1090,7 @@ const Workflows = (props) => {
} }
const workflowDownloadModalOpen = loadWorkflowsModalOpen ? const workflowDownloadModalOpen = loadWorkflowsModalOpen ?
<Dialog modal <Dialog
open={loadWorkflowsModalOpen} open={loadWorkflowsModalOpen}
onClose={() => { onClose={() => {
}} }}
+18 -7
View File
@@ -7,7 +7,6 @@ The Docker setup is done with docker-compose and is a single command to get set
**PS: if you're setting up Shuffle on Windows, go to the next step (Windows Docker setup)** **PS: if you're setting up Shuffle on Windows, go to the next step (Windows Docker setup)**
1. Make sure you have Docker and [docker-compose](https://docs.docker.com/compose/install/) installed. 1. Make sure you have Docker and [docker-compose](https://docs.docker.com/compose/install/) installed.
2. Run docker-compose. 2. Run docker-compose.
``` ```
git clone https://github.com/frikky/Shuffle git clone https://github.com/frikky/Shuffle
@@ -20,7 +19,7 @@ When you're done, skip to the "After installation" step below.
## Windows Docker setup ## Windows Docker setup
This step is for setting up with Docker on windows from scratch. This step is for setting up with Docker on windows from scratch.
1. Make sure you have [Docker](https://docs.docker.com/docker-for-windows/install/) and [docker-compose](https://docs.docker.com/compose/install/) installed 1. Make sure you have [Docker](https://docs.docker.com/docker-for-windows/install/) and [docker-compose](https://docs.docker.com/compose/install/) installed. WSL2 may be required.
2. Go to https://github.com/frikky/shuffle/releases and download the latest .zip release (or install git) 2. Go to https://github.com/frikky/shuffle/releases and download the latest .zip release (or install git)
3. Unzip the folder and enter it 3. Unzip the folder and enter it
4. Open the .env file and change the line with "OUTER_HOSTNAME" to contain your IP: 4. Open the .env file and change the line with "OUTER_HOSTNAME" to contain your IP:
@@ -84,14 +83,16 @@ docker-compose up
Related issue: #47 Related issue: #47
## Local development installation ## Local development installation
Frontend - requires [npm](https://nodejs.org/en/download/)/[yarn](https://yarnpkg.com/lang/en/docs/install/#debian-stable)/your preferred manager. Runs independently from backend - edit frontend/src/App.yaml (line 44~) from window.location.origin to http://YOUR IP:5001 **Frontend - ReactJS /w cytoscape**
http://localhost:3000 - Requires [npm](https://nodejs.org/en/download/)/[yarn](https://yarnpkg.com/lang/en/docs/install/#debian-stable)/your preferred manager. Runs independently from backend.
```bash ```bash
cd frontend cd frontend
npm i npm i
npm start npm start
``` ```
Backend - API calls - requires [>=go1.13](https://golang.org/dl/) **Backend - Golang**
http://localhost:5001 - REST API - requires [>=go1.13](https://golang.org/dl/)
```bash ```bash
export DATASTORE_EMULATOR_HOST=0.0.0.0:8000 export DATASTORE_EMULATOR_HOST=0.0.0.0:8000
cd backend/go-app cd backend/go-app
@@ -99,16 +100,26 @@ go build
go run *.go go run *.go
``` ```
Database - Datastore: **Database - Datastore**
Based on Google datastore
``` ```
docker run -p 8000:8000 google/cloud-sdk gcloud beta emulators datastore start --project=shuffle --host-port 0.0.0.0:8000 --no-store-on-disk docker run -p 8000:8000 google/cloud-sdk gcloud beta emulators datastore start --project=shuffle --host-port 0.0.0.0:8000 --no-store-on-disk
``` ```
Orborus - Execution of Workflows: **Orborus**
PS: This requires some specific environment variables. Execution of Workflows:
PS: This requires some specific environment variables
``` ```
cd functions/onprem/orborus cd functions/onprem/orborus
go run orborus.go go run orborus.go
``` ```
Environments:
```
export ORG_ID=Shuffle
export ENVIRONMENT_NAME=Shuffle
export BASE_URL=http://YOUR-IP:5001
export DOCKER_API_VERSION=1.40
export SHUFFLE_PASS_WORKER_PROXY=${SHUFFLE_PASS_WORKER_PROXY}
```