Merge pull request #30 from frikky/dev

Updates to fix HTTPS, app actions, easier deployment and more
This commit is contained in:
Frikkylikeme
2020-05-23 18:02:18 +09:00
committed by GitHub
33 changed files with 928 additions and 649 deletions
+6
View File
@@ -2,8 +2,14 @@
ORG_ID=Shuffle ORG_ID=Shuffle
ENVIRONMENT_NAME=Shuffle ENVIRONMENT_NAME=Shuffle
# Different locations etc
APP_DOWNLOAD_LOCATION=https://github.com/frikky/shuffle-apps
APP_DOWNLOAD_AUTH_USERNAME=""
APP_DOWNLOAD_AUTH_PASSWORD=""
# Other configs # Other configs
BACKEND_HOSTNAME=shuffle-backend BACKEND_HOSTNAME=shuffle-backend
BACKEND_PORT=5001 BACKEND_PORT=5001
FRONTEND_PORT=3001 FRONTEND_PORT=3001
FRONTEND_PORT_HTTPS=3443
OUTER_HOSTNAME=shuffle-backend OUTER_HOSTNAME=shuffle-backend
+1
View File
@@ -28,6 +28,7 @@ require (
google.golang.org/api v0.23.0 google.golang.org/api v0.23.0
google.golang.org/appengine v1.6.6 google.golang.org/appengine v1.6.6
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31
gopkg.in/src-d/go-git.v4 v4.13.1 // indirect
gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86
) )
+14
View File
@@ -46,6 +46,7 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -146,6 +147,7 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@@ -153,6 +155,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -160,9 +163,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
@@ -178,6 +186,7 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
@@ -289,6 +298,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -385,6 +395,10 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+89 -47
View File
@@ -51,6 +51,7 @@ import (
// Web // Web
// "github.com/gorilla/handlers" // "github.com/gorilla/handlers"
"github.com/gorilla/mux" "github.com/gorilla/mux"
http2 "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
// Old items (cloud) // Old items (cloud)
// "google.golang.org/appengine" // "google.golang.org/appengine"
// "google.golang.org/appengine/memcache" // "google.golang.org/appengine/memcache"
@@ -1980,7 +1981,7 @@ func handleLogin(resp http.ResponseWriter, request *http.Request) {
}) })
loginData = fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]}`, Userdata.Session, expiration.Unix()) loginData = fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]}`, Userdata.Session, expiration.Unix())
log.Printf("SESSION LENGTH MORE THAN 0 IN LOGIN: %s", Userdata.Session) //log.Printf("SESSION LENGTH MORE THAN 0 IN LOGIN: %s", Userdata.Session)
err = SetSession(ctx, *Userdata, Userdata.Session) err = SetSession(ctx, *Userdata, Userdata.Session)
if err != nil { if err != nil {
@@ -3921,6 +3922,14 @@ func setBadMemcache(ctx context.Context, path string) {
//} //}
} }
type Result struct {
Success bool `json:"success"`
Reason string `json:"reason"`
List []string `json:"list"`
}
var docs_list = Result{List: []string{}}
func getDocList(resp http.ResponseWriter, request *http.Request) { func getDocList(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request) cors := handleCors(resp, request)
if cors { if cors {
@@ -3939,11 +3948,24 @@ func getDocList(resp http.ResponseWriter, request *http.Request) {
// return // return
//} //}
if len(docs_list.List) > 0 {
b, err := json.Marshal(docs_list)
if err != nil {
log.Printf("Failed marshaling result: %s", err)
//http.Error(resp, err.Error(), 500)
} else {
resp.WriteHeader(200)
resp.Write(b)
return
}
}
client := github.NewClient(nil) client := github.NewClient(nil)
_, item1, _, err := client.Repositories.GetContents(ctx, "shaffuru", "shuffle-docs", "docs", nil) _, item1, _, err := client.Repositories.GetContents(ctx, "frikky", "shuffle-docs", "docs", nil)
if err != nil { if err != nil {
log.Printf("Github error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error listing directory"`))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Error listing directory: %s"`, err)))
return return
} }
@@ -3964,16 +3986,12 @@ func getDocList(resp http.ResponseWriter, request *http.Request) {
log.Println(names) log.Println(names)
type Result struct {
Success bool `json:"success"`
Reason string `json:"reason"`
List []string `json:"list"`
}
var result Result var result Result
result.Success = true result.Success = true
result.Reason = "Success" result.Reason = "Success"
result.List = names result.List = names
docs_list = result
b, err := json.Marshal(result) b, err := json.Marshal(result)
if err != nil { if err != nil {
http.Error(resp, err.Error(), 500) http.Error(resp, err.Error(), 500)
@@ -4001,6 +4019,8 @@ func getDocList(resp http.ResponseWriter, request *http.Request) {
} }
// r.HandleFunc("/api/v1/docs/{key}", getDocs).Methods("GET", "OPTIONS") // r.HandleFunc("/api/v1/docs/{key}", getDocs).Methods("GET", "OPTIONS")
var alldocs = map[string][]byte{}
func getDocs(resp http.ResponseWriter, request *http.Request) { func getDocs(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request) cors := handleCors(resp, request)
if cors { if cors {
@@ -4016,16 +4036,15 @@ func getDocs(resp http.ResponseWriter, request *http.Request) {
//ctx := context.Background() //ctx := context.Background()
docPath := fmt.Sprintf("https://raw.githubusercontent.com/shaffuru/shuffle-docs/master/docs/%s.md", location[4]) docPath := fmt.Sprintf("https://raw.githubusercontent.com/shaffuru/shuffle-docs/master/docs/%s.md", location[4])
//if item, err := memcache.Get(ctx, docPath); err == memcache.ErrCacheMiss { //location[4]
// // Not in cache //var, ok := alldocs["asd"]
//} else if err != nil { key, ok := alldocs[fmt.Sprintf("%s", location[4])]
// // Error with cache // Custom cache for github issues lol
// log.Printf("Error getting item: %v", err) if ok {
//} else { resp.WriteHeader(200)
// resp.WriteHeader(200) resp.Write(key)
// resp.Write([]byte(item.Value)) return
// return }
//}
client := &http.Client{} client := &http.Client{}
req, err := http.NewRequest( req, err := http.NewRequest(
@@ -4078,6 +4097,8 @@ func getDocs(resp http.ResponseWriter, request *http.Request) {
return return
} }
alldocs[location[4]] = b
// Add to cache if it doesn't exist // Add to cache if it doesn't exist
//item := &memcache.Item{ //item := &memcache.Item{
// Key: docPath, // Key: docPath,
@@ -5601,30 +5622,6 @@ func runInit(ctx context.Context) {
} }
} }
// Getting apps to see if we should initialize a test
workflowapps, err := getAllWorkflowApps(ctx)
if err != nil {
log.Printf("Failed getting apps: %s", err)
} else if err == nil && len(workflowapps) == 0 {
log.Printf("Apps: loading TEST")
fs := memfs.New()
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, &git.CloneOptions{
URL: "https://github.com/frikky/shuffle-apps",
})
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
}
dir, err := fs.ReadDir("")
if err != nil {
log.Printf("FAiled reading folder: %s", err)
}
_ = r
iterateAppGithubFolders(fs, dir, "", "testing")
}
// Gets schedules and starts them // Gets schedules and starts them
schedules, err := getAllSchedules(ctx) schedules, err := getAllSchedules(ctx)
if err != nil { if err != nil {
@@ -5654,6 +5651,51 @@ func runInit(ctx context.Context) {
} }
} }
// Getting apps to see if we should initialize a test
workflowapps, err := getAllWorkflowApps(ctx)
if err != nil {
log.Printf("Failed getting apps: %s", err)
} else if err == nil && len(workflowapps) == 0 {
log.Printf("Apps: loading TEST")
fs := memfs.New()
storer := memory.NewStorage()
url := os.Getenv("APP_DOWNLOAD_LOCATION")
if len(url) == 0 {
url = "https://github.com/frikky/shuffle-apps"
}
username := os.Getenv("APP_DOWNLOAD_AUTH_USERNAME")
password := os.Getenv("APP_DOWNLOAD_AUTH_PASSWORD")
cloneOptions := &git.CloneOptions{
URL: url,
}
if len(username) > 0 && len(password) > 0 {
cloneOptions.Auth = &http2.BasicAuth{
Username: username,
Password: password,
}
}
log.Printf("Getting apps from %s", url)
r, err := git.Clone(storer, fs, cloneOptions)
if err != nil {
log.Printf("Failed loading repo into memory: %s", err)
}
dir, err := fs.ReadDir("")
if err != nil {
log.Printf("Failed reading folder: %s", err)
}
_ = r
//iterateAppGithubFolders(fs, dir, "", "testing")
// FIXME: Get all the apps?
iterateAppGithubFolders(fs, dir, "", "")
}
log.Printf("Finished INIT") log.Printf("Finished INIT")
} }
@@ -5701,16 +5743,16 @@ func init() {
r.HandleFunc("/api/v1/streams", handleWorkflowQueue).Methods("POST") r.HandleFunc("/api/v1/streams", handleWorkflowQueue).Methods("POST")
r.HandleFunc("/api/v1/streams/results", handleGetStreamResults).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/streams/results", handleGetStreamResults).Methods("POST", "OPTIONS")
// Apps // App specific
r.HandleFunc("/api/v1/apps/get_existing", loadExistingApps).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/apps/get_existing", loadSpecificApps).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/get_existing/{appname}", loadExistingApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}", deleteWorkflowApp).Methods("DELETE", "OPTIONS") r.HandleFunc("/api/v1/apps/{appId}", deleteWorkflowApp).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/apps/{appId}/config", getWorkflowAppConfig).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/apps/{appId}/config", getWorkflowAppConfig).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS") r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
r.HandleFunc("/api/v1/apps/search", getSpecificApps).Methods("POST", "OPTIONS")
// Legacy things // Legacy app things
r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
r.HandleFunc("/api/v1/workflows/apps", getWorkflowApps).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows/apps", getWorkflowApps).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS") r.HandleFunc("/api/v1/workflows/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
+120 -13
View File
@@ -26,6 +26,7 @@ import (
"github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
http2 "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
newscheduler "github.com/carlescere/scheduler" newscheduler "github.com/carlescere/scheduler"
"github.com/go-git/go-git/v5/storage/memory" "github.com/go-git/go-git/v5/storage/memory"
@@ -2916,6 +2917,51 @@ func handleGetfile(resp http.ResponseWriter, request *http.Request) ([]byte, err
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func getSpecificApps(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request)
if cors {
return
}
// Just need to be logged in
// FIXME - should have some permissions?
_, err := handleApiAuthentication(resp, request)
if err != nil {
log.Printf("Api authentication failed in set new app: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("Error with body read: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
type tmpStruct struct {
Search string `json:"search"`
}
var tmpBody tmpStruct
err = json.Unmarshal(body, &tmpBody)
if err != nil {
log.Printf("Error with unmarshal tmpBody: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// FIXME - continue the search here with github repos etc.
// Caching might be smart :D
log.Printf("Body: %s", string(body))
resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
}
func validateAppInput(resp http.ResponseWriter, request *http.Request) { func validateAppInput(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request) cors := handleCors(resp, request)
if cors { if cors {
@@ -3113,7 +3159,7 @@ func deployWebhookFunction(ctx context.Context, name, localization, applocation
return nil return nil
} }
func loadExistingApps(resp http.ResponseWriter, request *http.Request) { func loadSpecificApps(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request) cors := handleCors(resp, request)
if cors { if cors {
return return
@@ -3129,22 +3175,83 @@ func loadExistingApps(resp http.ResponseWriter, request *http.Request) {
return return
} }
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("Error with body read: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
// Field1 & 2 can be a lot of things..
type tmpStruct struct {
URL string `json:"url"`
Field1 string `json:"field_1"`
Field2 string `json:"field_2"`
}
//log.Printf("Body: %s", string(body))
var tmpBody tmpStruct
err = json.Unmarshal(body, &tmpBody)
if err != nil {
log.Printf("Error with unmarshal tmpBody: %s", err)
resp.WriteHeader(401)
resp.Write([]byte(`{"success": false}`))
return
}
fs := memfs.New() fs := memfs.New()
storer := memory.NewStorage()
r, err := git.Clone(storer, fs, &git.CloneOptions{
URL: "https://github.com/frikky/shuffle-apps",
})
if err != nil { if strings.Contains(tmpBody.URL, "github") || strings.Contains(tmpBody.URL, "gitlab") || strings.Contains(tmpBody.URL, "bitbucket") {
log.Printf("Failed loading repo into memory: %s", err) cloneOptions := &git.CloneOptions{
} URL: tmpBody.URL,
}
dir, err := fs.ReadDir("/") // FIXME: Better auth.
if err != nil { if len(tmpBody.Field1) > 0 && len(tmpBody.Field2) > 0 {
log.Printf("FAiled reading folder: %s", err) 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
iterateAppGithubFolders(fs, dir, "", "")
} 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.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s is unsupported"}`, tmpBody.URL)))
return
} }
_ = r
iterateAppGithubFolders(fs, dir, "", "")
resp.WriteHeader(200) resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true}`))) resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
+5 -1
View File
@@ -6,7 +6,8 @@ services:
container_name: shuffle-frontend container_name: shuffle-frontend
hostname: shuffle-frontend hostname: shuffle-frontend
ports: ports:
- "3001:80" - "${FRONTEND_PORT}:80"
- "${FRONTEND_PORT_HTTPS}:443"
networks: networks:
- shuffle - shuffle
restart: unless-stopped restart: unless-stopped
@@ -17,6 +18,8 @@ services:
image: frikky/shuffle:database image: frikky/shuffle:database
container_name: shuffle-database container_name: shuffle-database
hostname: shuffle-database hostname: shuffle-database
ports:
- "8000:8000"
networks: networks:
- shuffle - shuffle
restart: unless-stopped restart: unless-stopped
@@ -37,6 +40,7 @@ services:
environment: environment:
- ORG_ID=${ORG_ID} - ORG_ID=${ORG_ID}
- DATASTORE_EMULATOR_HOST=shuffle-database:8000 - DATASTORE_EMULATOR_HOST=shuffle-database:8000
- APP_DOWNLOAD_LOCATION=${APP_DOWNLOAD_LOCATION}
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- database - database
+3 -3
View File
@@ -21,13 +21,13 @@ RUN mkdir -p /usr/share/nginx/html/js
RUN mkdir -p /usr/share/nginx/html/img RUN mkdir -p /usr/share/nginx/html/img
COPY --from=builder /usr/src/app/build /usr/share/nginx/html COPY --from=builder /usr/src/app/build /usr/share/nginx/html
#Localhost certificate challenge: Y#XwrJ#DoZGz2w6x
COPY --from=builder /usr/src/app/certs/fullchain.pem /etc/nginx/fullchain.cert.pem COPY --from=builder /usr/src/app/certs/fullchain.pem /etc/nginx/fullchain.cert.pem
COPY --from=builder /usr/src/app/certs/privkey.pem /etc/nginx/privkey.pem COPY --from=builder /usr/src/app/certs/privkey.pem /etc/nginx/privkey.pem
# Test
COPY --from=builder /usr/src/app/nginxtest.conf /etc/nginx/nginx.conf
# Prod # Prod
#COPY --from=builder /usr/src/app/nginx.conf /etc/nginx/nginx.conf COPY --from=builder /usr/src/app/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80 EXPOSE 80
EXPOSE 443 EXPOSE 443
+8
View File
@@ -0,0 +1,8 @@
# Certificate:
Creating a localhost certificate:
```
openssl genrsa -out privkey.pem 2048
openssl req -new -key privkey.pem -out certreq.csr
openssl x509 -req -days 3650 -in certreq.csr -signkey privkey.pem -out fullchain.pem
```
-10
View File
@@ -1,10 +0,0 @@
This directory contains your keys and certificates.
`privkey.pem` : the private key for your certificate.
`fullchain.pem`: the certificate file used in most server software.
`chain.pem` : used for OCSP stapling in Nginx >=1.3.7.
`cert.pem` : will break many server configurations, and should not be used
without reading further documentation (see link below).
We recommend not moving these files. For more information, see the Certbot
User Guide at https://certbot.eff.org/docs/using.html#where-are-my-certificates.
-31
View File
@@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFRzCCBC+gAwIBAgISA2OOAaaFtVzoqzLXCBV19fpjMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTAyMDkxMjQxMzlaFw0x
OTA1MTAxMjQxMzlaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAr4nj/G0MxSEWHnD0oC+jS03ofE6hXC87z0h6iNh5
lRdVoh9o2H22iQNTmWOWB56oqdBQEOeCcNFexYOzL9S91IVy3Q+hDev5rkJ44uFP
0VtgKbTc/aKIpEcSYPda2b1lb1mAYpJ/HqvzMDrJ+izCpTLEs2h+mD+2LAx7Ie3Z
OE+mFhU7aYdJ7rbUob7BT9cxzbp4CLGjaZHFKrC1uafSSh3bFFlXJpYmleunGVS9
4BUuveZdWJGLFMN1cAJiMGLewsKp5YXKB9eiH6gAg90udRaanPz3NgFa/8qju9iA
64YJcDNr9Aj04EIntRbPJm286+TrJbaf57ESCS32cqaDEwIDAQABo4ICXDCCAlgw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTaQOYhr73PSHSd+P+b7FJhYcVPwDAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQB
gt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3Jn
MIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHYA4mlLribo6UAJ6IYbtjuD1D7n/nSI
+6SPKJMBnd3x2/4AAAFo0n3+fgAABAMARzBFAiBebCfZn5HQoIloL8iS7Q2U9DE/
IlMLvhK0UFlhr1u5agIhAN84nfBT1slMt86E95tvvYbEHcAfapogmJmOxSoI5ati
AHUAY/Lbzeg7zCzPC3KEJ1drM6SNYXePvXWmOLHHaFRL2I0AAAFo0n4AegAABAMA
RjBEAiARET8ZHf3qcahgGa9O440U7/Zbfi5+WO0XRlN/cVQZBgIgKQpHRXv9urpk
MS+tz9jvsxERUYEEjRgsSnM1Bs3AF44wDQYJKoZIhvcNAQELBQADggEBADPUIj7w
z+He68As1CFu9tAwGMeLZDgXtPsybAOY9cWm9aL5sC5RldK+ob/5Xi2aa7YEeeij
VP44lOjXtr3EmGm34vN9pL7JyAhYAmEZToyJEt4dbyCbLhO0IT9Po4ropiXk7ze0
CRNEg2CCdXkG7KLHIxP6Am1vr1/TA8IC4lf0ocYJs5sU4/7Bj8eViuZ7F8ZcJo1t
O24jBw5m48fbmmDWkcc3YHVD55sIys3RDEQMLABgIxgN+kqRqfCslREpPYWa/o2T
jOt99S/zjdeRgGJfO8XKtI2TH8ZMHNyKaJYjmdX0CcZFmm2E8SZRYuB4j/KUdd8a
xje2fid5pAJf2Tk=
-----END CERTIFICATE-----
+19
View File
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIDBTCCAe0CAQAwgYYxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEOMAwG
A1UEBwwFVG9reW8xEDAOBgNVBAoMB1NodWZmbGUxEDAOBgNVBAsMB1NodWZmbGUx
EDAOBgNVBAMMB1NodWZmbGUxITAfBgkqhkiG9w0BCQEWEmZyaWtreUBzaHVmZmxl
ci5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANLYQupj6hNpfKzy
km3qFkTvuPFed2s6HkBBqKwgpZ6C7wdDuUrMd9SXguw9yhtgxezg+ui1O735ZL4W
6ZpT/Pf3Staj7SHgXAGDnPwcTeWgbd9rZO02UlD70Bhj6SBKYdS8FHRFJvbCe6V0
tY+pJhaTUogwPr1jJTvuHIqRhXHmUl88jVkMIj27FPTnUDEEbr+E8Q6LDYUfSxpw
beZqpv8FRGP88H+WGb/CnbFsvJMbNkHbM2Wj9b6yYiHuw8WRuTODX5YOVefGSYn/
h3JgniT2AdQAsacdB3avdE/b4Mq1FUVqsYaUGSXZ+Iysdo9/7zhYmb0UtaFMSQDA
zsOlIrMCAwEAAaA5MBYGCSqGSIb3DQEJAjEJDAdTaHVmZmxlMB8GCSqGSIb3DQEJ
BzESDBBZI1h3ckojRG9aR3oydzZ4MA0GCSqGSIb3DQEBCwUAA4IBAQCinafabm9w
EqhWrgi0lXQ+iqcklvigSegaEZx5g8lr4qYADPqRWRnzZcq8Dzifx6HUsDs6Dv6/
7INF6cwGxvPFv2CBEvS/KkPtWxHaoATxRxwGw9Vh88OQy/cE6/Jiu8t94QtGMLRL
V0bUnLfc3OKqNM5YvRf8Z1jbO+tzZ4ul3lApHF7UGq01BIcna0D4JblnwP62M4MW
vY++wzYqqsHAOrUN94tJQaTP1nc4u03lme+4duKY7G5yxMYn1A0aDp0IFeDvela9
nylRCM3V5FK1aubXuQnVYoFnnwaM2hTBVTKJbaCCWQhM0e3XYd8mCQYmgf+qlXBN
OG4enppZCsAJ
-----END CERTIFICATE REQUEST-----
-27
View File
@@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
+19 -56
View File
@@ -1,58 +1,21 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
xje2fid5pAJf2Tk=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE----- -----END CERTIFICATE-----
-34
View File
@@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF+TCCBOGgAwIBAgISA8rwfiC3p89WYm/X9RR3XhzTMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODExMDkyMTEzNTNaFw0x
OTAyMDcyMTEzNTNaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA2NIGtVlzW3fktmv74YG23LKLM6xIxn/mIPt4PgZ+
K3407GryQueToAnG5iTXTox5UnyArvqxAe5cTonrlWTai9Do5CuhrKI22EMpwrSl
Uo38dtNu2AHLENrY+aFzEwsVvkWGpIQ8/Y63T8M9ohiInF/S5ZPojIJxy7OVQ3io
MdLbb1atYfBcnt0DFKyMC1yxDyYj8w1jvwQWlKGBYQeRd2MTWEjHO7CJPgiRwiLi
rFBlDWnFz8GKntXLHI2pYL6+X4WgG9XfwzSN/w+ju48JAgCc6yTxvaQxQDpHst3D
kv4CXNTP3gt2RSIOkQldBQzi/FgBLDv/qSuXAnLGsIgk5QIDAQABo4IDDjCCAwow
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBThSBGBk0ZSYT1ptylvWQGZqdkBDjAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsr
BgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw
dC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25s
eSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4g
YWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQg
aHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3NpdG9yeS8wggECBgorBgEEAdZ5
AgQCBIHzBIHwAO4AdQB0ftqDMa0zEJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAA
AWb6ieWoAAAEAwBGMEQCIE8+auAtQOLY4U1yoEDvCTQULv4PS9Xdo1uJzQF5nhBA
AiBsfKR2UMxxIatzPOQPtuRrVEAv4+tX4o/ch5e6TAnOCAB1ACk8UZZUyDlluqpQ
/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZvqJ6BEAAAQDAEYwRAIgKj2gwlC/9AIF
hrx8nl2oEwxUoi/b4ZCCdQpz8JsJhOACIHRkuo56NErZR87lVtI0oZItZ6nzFPQz
BFaxx89eBJKPMA0GCSqGSIb3DQEBCwUAA4IBAQCFURbxUFKAF3CJRiaUsRrjFDuc
R25Dm86QgDqDLGkYf7/y5by2/amNzBbBLvcqUhScpjtalqO38Efw+2+c/UBGTQZ7
C8vU5KrjG6bnOmoHx/t+ml4E88omMlEmlRIEiL/6yfpOnCCv+3IHJjUw8iPuH7+j
57Vhwtq6mOvId2QfDfL86ELgXKvBKfbqac7YfzUHVyB4WeXagfpYiObpspTud0tZ
Yf5Qs7g8GLkXfpkOJHG1+91Hi7+Pb1cCAqkkgIwFG4oeBdxAkxkaIyBRk3ZfnXYw
9G1qofLrs2UbLUhIEyMgavI7kKwLg1pwsYs4Yn+RVR5hZPkj0ZUnc4gW7wCP
-----END CERTIFICATE-----
-12
View File
@@ -1,12 +0,0 @@
Traceback (most recent call last):
File "/usr/bin/certbot", line 11, in <module>
load_entry_point('certbot==0.10.2', 'console_scripts', 'certbot')()
File "/usr/lib/python2.7/dist-packages/certbot/main.py", line 836, in main
setup_logging(config)
File "/usr/lib/python2.7/dist-packages/certbot/main.py", line 700, in setup_logging
config, logfile=logfile, fmt=file_fmt)
File "/usr/lib/python2.7/dist-packages/certbot/main.py", line 667, in setup_log_file_handler
raise errors.Error(_PERM_ERR_FMT.format(error))
Error: The following error was encountered:
[Errno 13] Permission denied: '/var/log/letsencrypt/letsencrypt.log'
If running as non-root, set --config-dir, --logs-dir, and --work-dir to writeable paths.
-27
View File
@@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-61
View File
@@ -1,61 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF+TCCBOGgAwIBAgISA8rwfiC3p89WYm/X9RR3XhzTMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODExMDkyMTEzNTNaFw0x
OTAyMDcyMTEzNTNaMBMxETAPBgNVBAMTCGVuZGFvLmlvMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA2NIGtVlzW3fktmv74YG23LKLM6xIxn/mIPt4PgZ+
K3407GryQueToAnG5iTXTox5UnyArvqxAe5cTonrlWTai9Do5CuhrKI22EMpwrSl
Uo38dtNu2AHLENrY+aFzEwsVvkWGpIQ8/Y63T8M9ohiInF/S5ZPojIJxy7OVQ3io
MdLbb1atYfBcnt0DFKyMC1yxDyYj8w1jvwQWlKGBYQeRd2MTWEjHO7CJPgiRwiLi
rFBlDWnFz8GKntXLHI2pYL6+X4WgG9XfwzSN/w+ju48JAgCc6yTxvaQxQDpHst3D
kv4CXNTP3gt2RSIOkQldBQzi/FgBLDv/qSuXAnLGsIgk5QIDAQABo4IDDjCCAwow
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBThSBGBk0ZSYT1ptylvWQGZqdkBDjAfBgNV
HSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYI
KwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMBMG
A1UdEQQMMAqCCGVuZGFvLmlvMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsr
BgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw
dC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25s
eSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4g
YWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQg
aHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3NpdG9yeS8wggECBgorBgEEAdZ5
AgQCBIHzBIHwAO4AdQB0ftqDMa0zEJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAA
AWb6ieWoAAAEAwBGMEQCIE8+auAtQOLY4U1yoEDvCTQULv4PS9Xdo1uJzQF5nhBA
AiBsfKR2UMxxIatzPOQPtuRrVEAv4+tX4o/ch5e6TAnOCAB1ACk8UZZUyDlluqpQ
/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABZvqJ6BEAAAQDAEYwRAIgKj2gwlC/9AIF
hrx8nl2oEwxUoi/b4ZCCdQpz8JsJhOACIHRkuo56NErZR87lVtI0oZItZ6nzFPQz
BFaxx89eBJKPMA0GCSqGSIb3DQEBCwUAA4IBAQCFURbxUFKAF3CJRiaUsRrjFDuc
R25Dm86QgDqDLGkYf7/y5by2/amNzBbBLvcqUhScpjtalqO38Efw+2+c/UBGTQZ7
C8vU5KrjG6bnOmoHx/t+ml4E88omMlEmlRIEiL/6yfpOnCCv+3IHJjUw8iPuH7+j
57Vhwtq6mOvId2QfDfL86ELgXKvBKfbqac7YfzUHVyB4WeXagfpYiObpspTud0tZ
Yf5Qs7g8GLkXfpkOJHG1+91Hi7+Pb1cCAqkkgIwFG4oeBdxAkxkaIyBRk3ZfnXYw
9G1qofLrs2UbLUhIEyMgavI7kKwLg1pwsYs4Yn+RVR5hZPkj0ZUnc4gW7wCP
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-28
View File
@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDY0ga1WXNbd+S2
a/vhgbbcsoszrEjGf+Yg+3g+Bn4rfjTsavJC55OgCcbmJNdOjHlSfICu+rEB7lxO
ieuVZNqL0OjkK6GsojbYQynCtKVSjfx2027YAcsQ2tj5oXMTCxW+RYakhDz9jrdP
wz2iGIicX9Llk+iMgnHLs5VDeKgx0ttvVq1h8Fye3QMUrIwLXLEPJiPzDWO/BBaU
oYFhB5F3YxNYSMc7sIk+CJHCIuKsUGUNacXPwYqe1cscjalgvr5fhaAb1d/DNI3/
D6O7jwkCAJzrJPG9pDFAOkey3cOS/gJc1M/eC3ZFIg6RCV0FDOL8WAEsO/+pK5cC
csawiCTlAgMBAAECggEALGoxp5qQT+9qcZgDO/mnbORCMa6cJdVzXdRFmGcaF2y+
CKQLxnrLud/m16Q6WsPZ4nTQo4eFFQEv9YK5OJw1TKjZ3Eu3zbZZB8oSVulMaHHf
grPjI+qSH3zFL7XL7d26cYSqhS71k3dVw8gZ6wedjHLwr8ixvX7HMtQxwmWIBtRr
Sj9zYyqkoBLDWrhoGh7GlAHHiPw4cFY7XRaAbq36JYhkO+VUK7BRJMMPwSSMbmx1
S3O8PhXy5he893HVRAHhQq8xIup/Q+PktB39xgQX0M+mjMoqD9mJ0fgaKnff8K3U
C3ovU9YmAR9VTGE/1S4yeT5BreXGbCwXKGSHO4KBLQKBgQDtZWjbtUCHyuiNk8pp
17mgpWEZOHl7+hehO6uN2GwE4bdrBRxK3b+ZQRJqVRQnhQRkYA4x1vVOG05A0b2C
QJBERd66XWMZHs3820kexo+Lw0XgAaM5bIoW8VZxAhHL9J49piiboawp/sNlFPVl
HL0x5ztkP/7QHRwvInY9giVNAwKBgQDpz9S7N/wNwQf6NrqbboYpUkA8WcAjGdzi
gsgK47rm2Nvs5CTWgVykTVokN/HjUCnkzNcET2e0lwF3M2Z6f3wyWiwngrGCWVyL
YXgcMT080CPWvfpVZ/kjkOORsD4zhceVs/ECJDPwNH7rKderILxQld7BQ+PcY32n
5iu4L3Cd9wKBgQDIUWsjAhX6v+BuHwiNOYicoxCFHJ9+WvF3jwdbAQVdNS31s3FF
R0q2wi8M5M/F7Ttgi6FOswl5qBbnIVTdRSe3RJIGBmlpuBGvTUatHnXgRJ2AwUD/
YrQ/WdRMNafYx4iDkuLvOIQzR5OPhxjvAkovguQd2tZkvDudFmJZ0qkxCwKBgAKK
R31hNlPP7Q5C2fQmVz7Lrfb54qR++29ajGHR543qfTktoVjTPvZqALi0AuS9Ujcy
IoPhePb1TQbGgC6EhAzn/eLQAK2x2teIz40+27N1b2490iJrZsGEKXTDvWlB4tE1
i0DCs+3AJEDZy4YIbQNTHYBsBGW4jvzr+z2dBlQxAoGAZaQ8pL6wnaXqCQA/ULO+
lcF5c98pOLHpNTE19zodDEpG1OmavHgDhThOXJYfogkeAJaoovaQ5hHS/YLkXVOU
Xd2JN5FLbAwLN1jorB5tH1+c2SOOXaGoi7BTM9/mcUkJqYIthK4SoYw0oO2nphGZ
Mm8KDWDzu7D3r3XB8Xpl8ng=
-----END PRIVATE KEY-----
+27 -28
View File
@@ -1,28 +1,27 @@
-----BEGIN PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
xIKG1OZD55i9MuHng2uBJBc= -----END RSA PRIVATE KEY-----
-----END PRIVATE KEY-----
+45 -11
View File
@@ -27,29 +27,63 @@ http {
server { server {
listen 80; listen 80;
server_name "shuffler.io"; server_name "localhost";
return 301 https://$server_name$request_uri; location / {
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
location /api/v1 {
proxy_pass http://shuffle-backend:5001;
}
} }
server { server {
listen 443 ssl; listen 443 ssl;
server_name "shuffler.io"; server_name "localhost";
ssl_certificate fullchain.cert.pem; ssl_certificate fullchain.cert.pem;
ssl_certificate_key privkey.pem; ssl_certificate_key privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2; ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5; ssl_ciphers HIGH:!aNULL:!MD5;
location / { location / {
root /usr/share/nginx/html; # avoid clickjacking
gzip_static on; add_header X-Frame-Options DENY;
expires 1y; # block MIME sniffing
add_header Cache-Control public; add_header X-Content-Type-Options nosniff;
add_header ETag "";
try_files $uri /index.html; # security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
} }
# Get the hostname from environment here?
location /api/v1 { location /api/v1 {
proxy_pass http://192.168.239.142:5001; proxy_pass http://shuffle-backend:5001;
} }
} }
} }
-89
View File
@@ -1,89 +0,0 @@
user nobody nogroup;
worker_processes auto; # auto-detect number of logical CPU cores
events {
worker_connections 512; # set the max number of simultaneous connections (per worker process)
}
http {
client_max_body_size 250M;
include mime.types;
# thanks stackoverflow http://stackoverflow.com/a/5132440/2406040
gzip on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
# make sure gzip does not lose large gzipped js or css files
# see http://blog.leetsoft.com/2007/07/25/nginx-gzip-ssl.html
gzip_buffers 16 8k;
# Disable gzip for certain browsers.
gzip_disable “MSIE [1-6].(?!.*SV1)”;
server {
listen 80;
server_name "localhost";
location / {
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
location /api/v1 {
proxy_pass http://shuffle-backend:5001;
}
}
server {
listen 443 ssl;
server_name "localhost";
ssl_certificate fullchain.cert.pem;
ssl_certificate_key privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
# avoid clickjacking
add_header X-Frame-Options DENY;
# block MIME sniffing
add_header X-Content-Type-Options nosniff;
# security headers
add_header X-XSS-Protection "1; mode=block";
# add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "no-referrer";
server_tokens off;
root /usr/share/nginx/html;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
try_files $uri /index.html;
}
# Get the hostname from environment here?
location /api/v1 {
proxy_pass http://shuffle-backend:5001;
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ echo "Starting server"
# Rerun build locally for it to update :) # Rerun build locally for it to update :)
docker run -it \ docker run -it \
-p 3001:80 \ -p 3001:80 \
-p 3443:443 \ -p 3002:443 \
-v $(pwd)/build:/usr/share/nginx/html:ro \ -v $(pwd)/build:/usr/share/nginx/html:ro \
--rm \ --rm \
nginx nginx
+1 -1
View File
@@ -141,7 +141,7 @@ const AdminAccount = props => {
const basedata = const basedata =
<div style={bodyDivStyle}> <div style={bodyDivStyle}>
<Paper style={boxStyle}> <Paper style={boxStyle}>
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}> <form onSubmit={onSubmit} style={{color: "white", margin: "15px 15px 15px 15px"}}>
<h2>{formtitle}</h2> <h2>{formtitle}</h2>
Username Username
<div> <div>
+131 -64
View File
@@ -90,8 +90,8 @@ const AngularWorkflow = (props) => {
const [cystyle, ] = useState(cytoscapestyle) const [cystyle, ] = useState(cytoscapestyle)
const [cy, setCy] = React.useState() const [cy, setCy] = React.useState()
const [appSearch, setAppSearch] = React.useState("")
const [currentView, setCurrentView] = React.useState("apps") const [currentView, setCurrentView] = React.useState("apps")
const [, setAppSearchValue] = React.useState("")
const [triggerAuthentication, setTriggerAuthentication] = React.useState({}) const [triggerAuthentication, setTriggerAuthentication] = React.useState({})
const [triggerFolders, setTriggerFolders] = React.useState([]) const [triggerFolders, setTriggerFolders] = React.useState([])
@@ -1385,10 +1385,6 @@ const AngularWorkflow = (props) => {
}); });
} }
const setAppSearch = (event) => {
setFilteredApps(apps.filter(app => app.name.includes(event.target.value)))
}
const appViewStyle = { const appViewStyle = {
marginLeft: "5px", marginLeft: "5px",
marginRight: "5px", marginRight: "5px",
@@ -1525,10 +1521,10 @@ const AngularWorkflow = (props) => {
<MoreVertIcon /> <MoreVertIcon />
</IconButton> </IconButton>
<Menu <Menu
id="long-menu" id="long-menu"
anchorEl={anchorEl} anchorEl={anchorEl}
keepMounted keepMounted
open={open} open={open}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: surfaceColor, backgroundColor: surfaceColor,
@@ -1568,6 +1564,7 @@ const AngularWorkflow = (props) => {
} }
const HandleLeftView = () => { const HandleLeftView = () => {
// Defaults to apps.
var thisview = <AppView /> var thisview = <AppView />
if (currentView === "triggers") { if (currentView === "triggers") {
thisview = <TriggersView /> thisview = <TriggersView />
@@ -1577,14 +1574,6 @@ const AngularWorkflow = (props) => {
return( return(
<div> <div>
<div style={{cursor: "pointer", height: 20, marginLeft: 10, marginTop: 10}} onClick={() => {
setLeftViewOpen(false)
setLeftBarSize(50)
}}>
<Tooltip color="primary" title="Minimize" placement="top">
<KeyboardArrowLeftIcon />
</Tooltip>
</div>
<Divider style={{marginTop: 10, height: 1, width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/> <Divider style={{marginTop: 10, height: 1, width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
<div style={{minHeight: bodyHeight-appBarSize-150, maxHeight: bodyHeight-appBarSize-100}}> <div style={{minHeight: bodyHeight-appBarSize-150, maxHeight: bodyHeight-appBarSize-100}}>
{thisview} {thisview}
@@ -1981,11 +1970,36 @@ const AngularWorkflow = (props) => {
overflowX: "hidden", overflowX: "hidden",
} }
const runAppSearch = (event) => {
setAppSearch(event.target.value)
setFilteredApps(apps.filter(app => app.name.toLowerCase().includes(event.target.value.trim().toLowerCase())))
}
const AppView = () => { const AppView = () => {
return( return(
<div style={appViewStyle}> <div style={appViewStyle}>
<div style={{flex: "1"}}> <div style={{flex: "1"}}>
<div style={appScrollStyle}> <div style={appScrollStyle}>
{/*
<TextField
style={{backgroundColor: inputColor}}
InputProps={{
style:{
color: "white",
minHeight: "50px",
marginLeft: "5px",
maxWidth: "95%",
fontSize: "1em",
},
}}
fullWidth
color="primary"
placeholder={"Search apps"}
onChange={(event) => {
runAppSearch(event)
}}
/>
*/}
{filteredApps.map(app=> { {filteredApps.map(app=> {
// FIXME - add label to apps, as this might be slow with A LOT of apps // FIXME - add label to apps, as this might be slow with A LOT of apps
var newAppname = app.name var newAppname = app.name
@@ -2299,7 +2313,7 @@ const AngularWorkflow = (props) => {
try { try {
JSON.parse(event.target.value) JSON.parse(event.target.value)
} catch (e) { } catch (e) {
alert.error("Failed to parse json") alert.error("Failed to parse json: ", e)
} }
} }
}} }}
@@ -2324,10 +2338,15 @@ const AngularWorkflow = (props) => {
<div> <div>
<Select <Select
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: inputColor, backgroundColor: inputColor,
} }
}} }}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
value={selectedActionParameters[count].action_field} value={selectedActionParameters[count].action_field}
fullWidth fullWidth
onChange={(e) => { onChange={(e) => {
@@ -2378,10 +2397,15 @@ const AngularWorkflow = (props) => {
datafield = datafield =
<Select <Select
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: inputColor, backgroundColor: inputColor,
} }
}} }}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
fullWidth fullWidth
value={selectedAction.parameters[count].action_field} value={selectedAction.parameters[count].action_field}
onChange={(e) => { onChange={(e) => {
@@ -2537,6 +2561,11 @@ const AngularWorkflow = (props) => {
backgroundColor: inputColor, backgroundColor: inputColor,
} }
}} }}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
fullWidth fullWidth
onChange={(e) => { onChange={(e) => {
const env = environments.find(a => a.Name === e.target.value) const env = environments.find(a => a.Name === e.target.value)
@@ -2572,6 +2601,11 @@ const AngularWorkflow = (props) => {
fullWidth fullWidth
onChange={setNewSelectedAction} onChange={setNewSelectedAction}
style={{backgroundColor: inputColor, color: "white", height: "50px"}} style={{backgroundColor: inputColor, color: "white", height: "50px"}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
> >
{selectedApp.actions.map(data => { {selectedApp.actions.map(data => {
var newActionname = data.name var newActionname = data.name
@@ -2806,18 +2840,23 @@ const AngularWorkflow = (props) => {
datafield = datafield =
<div> <div>
<Select <Select
value={data.action_field} value={data.action_field}
fullWidth fullWidth
onChange={(e) => { onChange={(e) => {
changeActionVariable(e.target.value, data.value) changeActionVariable(e.target.value, data.value)
}} }}
style={{backgroundColor: inputColor, color: "white", height: "50px"}} style={{backgroundColor: inputColor, color: "white", height: "50px"}}
> >
{parents.map(data => ( {parents.map(data => (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.label}> <MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.label}>
{data.label} {data.label}
</MenuItem> </MenuItem>
))} ))}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
</Select> </Select>
<TextField <TextField
style={{backgroundColor: inputColor}} style={{backgroundColor: inputColor}}
@@ -2858,11 +2897,16 @@ const AngularWorkflow = (props) => {
<Select <Select
fullWidth fullWidth
value={data.action_field} value={data.action_field}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: inputColor, backgroundColor: inputColor,
} }
}} }}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
onChange={(e) => { onChange={(e) => {
changeActionVariable(e.target.value, data.value) changeActionVariable(e.target.value, data.value)
}} }}
@@ -2939,23 +2983,32 @@ const AngularWorkflow = (props) => {
<div style={{flex: "10"}}> <div style={{flex: "10"}}>
<b>{data.name} </b> <b>{data.name} </b>
</div> </div>
<div style={{cursor: "pointer", color: staticcolor}} onClick={() => { <Tooltip color="primary" title="Static data" placement="top">
changeActionParameterVariant("STATIC_VALUE") <div style={{cursor: "pointer", color: staticcolor}} onClick={(e) => {
e.preventDefault()
changeActionParameterVariant("STATIC_VALUE")
}}>
<CreateIcon />
</div>
</Tooltip>
&nbsp;|&nbsp;
<Tooltip color="primary" title="Data from previous action" placement="top">
<div style={{cursor: "pointer", color: actioncolor}} onClick={(e) => {
e.preventDefault()
changeActionParameterVariant("ACTION_RESULT")
}}> }}>
static <AppsIcon />
</div> </div>
</Tooltip>
&nbsp;|&nbsp; &nbsp;|&nbsp;
<div style={{cursor: "pointer", color: actioncolor}} onClick={() => { <Tooltip color="primary" title="Use local variable" placement="top">
changeActionParameterVariant("ACTION_RESULT") <div style={{cursor: "pointer", color: varcolor}} onClick={(e) => {
}}> e.preventDefault()
action changeActionParameterVariant("WORKFLOW_VARIABLE")
</div> }}>
&nbsp;|&nbsp; <FavoriteBorderIcon />
<div style={{cursor: "pointer", color: varcolor}} onClick={() => { </div>
changeActionParameterVariant("WORKFLOW_VARIABLE") </Tooltip>
}}>
var
</div>
</div> </div>
{datafield} {datafield}
</div> </div>
@@ -3091,8 +3144,16 @@ const AngularWorkflow = (props) => {
const [anchorEl, setAnchorEl] = React.useState(null); const [anchorEl, setAnchorEl] = React.useState(null);
const deleteCondition = (conditionIndex) => { const deleteCondition = (conditionIndex) => {
//selectedEdge.conditions.splice(conditionIndex, 1) console.log(selectedEdge)
//setSelectedEdge(selectedEdge) if (selectedEdge.conditions.length === 1) {
selectedEdge.conditions = []
} else {
selectedEdge.conditions.splice(conditionIndex, 1)
}
setSelectedEdge(selectedEdge)
setOpen(false)
setUpdate("delete "+conditionIndex)
} }
const paperVariableStyle = { const paperVariableStyle = {
@@ -3108,6 +3169,7 @@ const AngularWorkflow = (props) => {
} }
const menuClick = (event) => { const menuClick = (event) => {
console.log("MENU CLICK")
setOpen(!open) setOpen(!open)
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
} }
@@ -3350,11 +3412,16 @@ const AngularWorkflow = (props) => {
value={selectedTrigger.parameters[0].value.split(splitter)} value={selectedTrigger.parameters[0].value.split(splitter)}
style={{backgroundColor: inputColor, color: "white"}} style={{backgroundColor: inputColor, color: "white"}}
PaperProps={{ PaperProps={{
style: { style: {
height: "200px", height: "200px",
backgroundColor: inputColor, backgroundColor: inputColor,
} }
}} }}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
onChange={(e) => { onChange={(e) => {
//setTriggerFolderWrapper(e) //setTriggerFolderWrapper(e)
setTriggerFolderWrapperMulti(e) setTriggerFolderWrapperMulti(e)
+4 -4
View File
@@ -52,10 +52,10 @@ const theme = createMuiTheme({
palette: { palette: {
primary: { primary: {
main: "#f85a3e" main: "#f85a3e"
}, },
secondary: { secondary: {
main: '#e8eaf6', main: '#e8eaf6',
}, },
}, },
typography: { typography: {
useNextVariants: true useNextVariants: true
+12 -15
View File
@@ -35,6 +35,7 @@ const actionListStyle = {
marginTop: "5px", marginTop: "5px",
backgroundColor: inputColor, backgroundColor: inputColor,
display: "flex", display: "flex",
color: "white",
} }
const boxStyle = { const boxStyle = {
@@ -1013,7 +1014,7 @@ const AppCreator = (props) => {
</Dialog> </Dialog>
const actionView = const actionView =
<div> <div style={{color: "white"}}>
<h2>Actions</h2> <h2>Actions</h2>
Actions are the tasks performed by an app. Read more about actions and apps Actions are the tasks performed by an app. Read more about actions and apps
<a href="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</a>. <a href="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</a>.
@@ -1038,7 +1039,7 @@ const AppCreator = (props) => {
</div> </div>
const testView = const testView =
<div> <div style={{color: "white"}}>
<h2>Test</h2> <h2>Test</h2>
Test an action to see whether it performs in an expected way. Test an action to see whether it performs in an expected way.
<a href="/docs/apps#testing" style={{textDecoration: "none", color: "#f85a3e"}}>&nbsp;Click here to learn more about testing</a>. <a href="/docs/apps#testing" style={{textDecoration: "none", color: "#f85a3e"}}>&nbsp;Click here to learn more about testing</a>.
@@ -1087,18 +1088,18 @@ const AppCreator = (props) => {
// Random names for type & autoComplete. Didn't research :^) // Random names for type & autoComplete. Didn't research :^)
const landingpageDataBrowser = const landingpageDataBrowser =
<div style={{paddingBottom: "100px"}}> <div style={{paddingBottom: 100, color: "white",}}>
<Paper style={boxStyle}> <Paper style={boxStyle}>
<h2 style={{marginBottom: "10px"}}>General information</h2> <h2 style={{marginBottom: "10px", color: "white"}}>General information</h2>
<a href="/docs/apps#create" style={{textDecoration: "none", color: "#f85a3e"}}>Click here to learn more about app creation</a> <a href="/docs/apps#create" style={{textDecoration: "none", color: "#f85a3e"}}>Click here to learn more about app creation</a>
<div style={{flex: "1", display: "flex", flexDirection: "row"}}> <div style={{color: "white", flex: "1", display: "flex", flexDirection: "row"}}>
<Tooltip title="Click to edit the app's image" placement="bottom"> <Tooltip title="Click to edit the app's image" placement="bottom">
<div style={{flex: "1", margin: 10, border: "1px solid #f85a3e", cursor: "pointer", backgroundColor: inputColor, maxWidth: 174, maxHeight: 174}} onClick={() => {upload.click()}}> <div style={{flex: "1", margin: 10, border: "1px solid #f85a3e", cursor: "pointer", backgroundColor: inputColor, maxWidth: 174, maxHeight: 174}} onClick={() => {upload.click()}}>
<input hidden type="file" ref={(ref) => upload = ref} onChange={editHeaderImage} /> <input hidden type="file" ref={(ref) => upload = ref} onChange={editHeaderImage} />
{imageInfo} {imageInfo}
</div> </div>
</Tooltip> </Tooltip>
<div style={{flex: "3"}}> <div style={{flex: "3", color: "white",}}>
<div style={{marginTop: "10px"}}/> <div style={{marginTop: "10px"}}/>
Name Name
<TextField <TextField
@@ -1149,8 +1150,8 @@ const AppCreator = (props) => {
</div> </div>
</div> </div>
<Divider style={{marginBottom: "10px", marginTop: "30px", height: "1px", width: "100%", backgroundColor: "grey"}}/> <Divider style={{marginBottom: "10px", marginTop: "30px", height: "1px", width: "100%", backgroundColor: "grey"}}/>
<h3 style={{marginBottom: "10px"}}>API information</h3> <h3 style={{marginBottom: "10px", color: "white",}}>API information</h3>
Base URL - leave empty if user changeable <span style={{color: "white"}}>Base URL - leave empty if user changeable</span>
<TextField <TextField
color="primary" color="primary"
style={{backgroundColor: inputColor, marginTop: "5px"}} style={{backgroundColor: inputColor, marginTop: "5px"}}
@@ -1176,7 +1177,7 @@ const AppCreator = (props) => {
onChange={e => setBaseUrl(e.target.value)} onChange={e => setBaseUrl(e.target.value)}
/> />
<FormControl style={{marginTop: "15px",}} variant="outlined"> <FormControl style={{marginTop: "15px",}} variant="outlined">
<h5 style={{marginBottom: "10px"}}>Authentication</h5> <h5 style={{marginBottom: "10px", color: "white",}}>Authentication</h5>
<Select <Select
fullWidth fullWidth
onChange={(e) => { onChange={(e) => {
@@ -1213,12 +1214,8 @@ const AppCreator = (props) => {
const loadedCheck = isLoaded && isAppLoaded && !firstrequest ? const loadedCheck = isLoaded && isAppLoaded && !firstrequest ?
<div> <div>
<BrowserView> <div style={bodyDivStyle}>{landingpageDataBrowser}</div>
<div style={bodyDivStyle}>{landingpageDataBrowser}</div> {newActionModal}
{newActionModal}
</BrowserView>
<MobileView>
</MobileView>
</div> </div>
: :
<div> <div>
+271 -53
View File
@@ -3,13 +3,16 @@ import React, { useEffect} from 'react';
import { useInterval } from 'react-powerhooks'; import { useInterval } from 'react-powerhooks';
import Grid from '@material-ui/core/Grid'; import Grid from '@material-ui/core/Grid';
import Select from '@material-ui/core/Select';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import Divider from '@material-ui/core/Divider'; import Divider from '@material-ui/core/Divider';
import ButtonBase from '@material-ui/core/ButtonBase'; import ButtonBase from '@material-ui/core/ButtonBase';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import FormControl from '@material-ui/core/FormControl'; import FormControl from '@material-ui/core/FormControl';
import MenuItem from '@material-ui/core/MenuItem';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import Input from '@material-ui/core/Input';
import YAML from 'yaml' import YAML from 'yaml'
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
@@ -30,6 +33,7 @@ const Apps = (props) => {
const { globalUrl, isLoggedIn, isLoaded } = props; const { globalUrl, isLoggedIn, isLoaded } = props;
//const [workflows, setWorkflows] = React.useState([]); //const [workflows, setWorkflows] = React.useState([]);
const baseRepository = "https://github.com/frikky/shuffle-apps"
const alert = useAlert() const alert = useAlert()
const [selectedApp, setSelectedApp] = React.useState({}); const [selectedApp, setSelectedApp] = React.useState({});
const [firstrequest, setFirstrequest] = React.useState(true) const [firstrequest, setFirstrequest] = React.useState(true)
@@ -37,13 +41,19 @@ const Apps = (props) => {
const [filteredApps, setFilteredApps] = React.useState([]) const [filteredApps, setFilteredApps] = React.useState([])
const [validation, setValidation] = React.useState(false) const [validation, setValidation] = React.useState(false)
const [isLoading, setIsLoading] = React.useState(false) const [isLoading, setIsLoading] = React.useState(false)
const [appSearchLoading, setAppSearchLoading] = React.useState(false)
const [selectedAction, setSelectedAction] = React.useState({})
const [openApi, setOpenApi] = React.useState("") const [openApi, setOpenApi] = React.useState("")
const [openApiData, setOpenApiData] = React.useState("") const [openApiData, setOpenApiData] = React.useState("")
const [appValidation, setAppValidation] = React.useState("") const [appValidation, setAppValidation] = React.useState("")
const [loadAppsModalOpen, setLoadAppsModalOpen] = React.useState(false);
const [openApiModal, setOpenApiModal] = React.useState(false); const [openApiModal, setOpenApiModal] = React.useState(false);
const [openApiModalType, setOpenApiModalType] = React.useState(""); const [openApiModalType, setOpenApiModalType] = React.useState("");
const [openApiError, setOpenApiError] = React.useState("") const [openApiError, setOpenApiError] = React.useState("")
const [field1, setField1] = React.useState("")
const [field2, setField2] = React.useState("")
const { start, stop } = useInterval({ const { start, stop } = useInterval({
duration: 5000, duration: 5000,
startImmediate: false, startImmediate: false,
@@ -69,6 +79,7 @@ const Apps = (props) => {
color: "#ffffff", color: "#ffffff",
width: "100%", width: "100%",
display: "flex", display: "flex",
margin: 20,
} }
const paperAppStyle = { const paperAppStyle = {
@@ -103,8 +114,11 @@ const Apps = (props) => {
setFilteredApps(responseJson) setFilteredApps(responseJson)
if (responseJson.length > 0) { if (responseJson.length > 0) {
setSelectedApp(responseJson[0]) setSelectedApp(responseJson[0])
if (responseJson[0].actions.length > 0) {
setSelectedAction(responseJson[0].actions[0])
}
} }
}) })
.catch(error => { .catch(error => {
alert.error(error.toString()) alert.error(error.toString())
}); });
@@ -205,6 +219,10 @@ const Apps = (props) => {
<Paper square style={paperAppStyle} onClick={() => { <Paper square style={paperAppStyle} onClick={() => {
if (selectedApp.id !== data.id) { if (selectedApp.id !== data.id) {
setSelectedApp(data) setSelectedApp(data)
if (data.actions.length > 0) {
console.log(data.actions[0])
setSelectedAction(data.actions[0])
}
} }
}}> }}>
<Grid container style={{margin: 10, flex: "10"}}> <Grid container style={{margin: 10, flex: "10"}}>
@@ -231,9 +249,11 @@ const Apps = (props) => {
</Grid> </Grid>
</Grid> </Grid>
<Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}} onClick={() => {downloadApp(data)}}> <Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}} onClick={() => {downloadApp(data)}}>
{/*
<Tooltip title={"Download"} style={{marginTop: "28px", width: "100%"}} aria-label={data.name}> <Tooltip title={"Download"} style={{marginTop: "28px", width: "100%"}} aria-label={data.name}>
<CloudDownload /> <CloudDownload />
</Tooltip> </Tooltip>
*/}
</Grid> </Grid>
</Paper> </Paper>
) )
@@ -249,33 +269,6 @@ const Apps = (props) => {
marginBottom: 10, marginBottom: 10,
} }
//const handleFile = (event) =>{
// const formData = new FormData();
// formData.append('file', event.target.files[0]);
// fetch(globalUrl+"/api/v1/workflows/apps/validate", {
// method: 'POST',
// headers: {
// 'Accept': 'application/json',
// },
// body: formData,
// credentials: "include",
// })
// .then((response) => {
// if (response.status !== 200) {
// console.log("Status not 200 for apps :O!")
// return
// }
// return response.json()
// })
// .then((responseJson) => {
// console.log(responseJson)
// })
// .catch(error => {
// alert.error(error.toString())
// });
//}
const UploadView = () => { const UploadView = () => {
//var imageline = selectedApp.large_image === undefined || selectedApp.large_image.length === 0 ? //var imageline = selectedApp.large_image === undefined || selectedApp.large_image.length === 0 ?
// <img alt="" style={{width: "80px"}} /> // <img alt="" style={{width: "80px"}} />
@@ -325,9 +318,65 @@ const Apps = (props) => {
<h2>{newAppname}</h2> <h2>{newAppname}</h2>
<p>{description}</p> <p>{description}</p>
<Divider style={{marginBottom: "10px", marginTop: "10px", backgroundColor: dividerColor}}/> <Divider style={{marginBottom: "10px", marginTop: "10px", backgroundColor: dividerColor}}/>
<p>URL: {selectedApp.link}</p> {selectedApp.link.length > 0 ? <p>URL: {selectedApp.link}</p> : null}
<p>ID: {selectedApp.id}</p> <p>ID: {selectedApp.id}</p>
<p>PrivateID: {selectedApp.privateId}</p> {selectedApp.privateId !== undefined && selectedApp.privateId.length > 0 ? <p>PrivateID: {selectedApp.privateId}</p> : null}
<div style={{marginTop: 15, marginBottom: 15}}>
<b>Actions</b>
<Select
fullWidth
value={selectedAction}
onChange={(event) => {
setSelectedAction(event.target.value)
}}
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
>
{selectedApp.actions.map(data => {
var newActionname = data.label !== undefined && data.label.length > 0 ? data.label : data.name
// ROFL FIXME - loop
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.replace("_", " ")
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
return (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
{newActionname}
</MenuItem>
)
})}
</Select>
</div>
{selectedAction.parameters !== undefined ?
<div style={{marginTop: 15, marginBottom: 15}}>
<b>Arguments</b>
{selectedAction.parameters.map(data => {
var itemColor = "#f85a3e"
if (!data.required) {
itemColor = "#ffeb3b"
}
const circleSize = 10
return (
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
<div style={{width: circleSize, height: circleSize, borderRadius: circleSize / 2, backgroundColor: itemColor, marginRight: "10px"}}/>
{data.name}
</MenuItem>
)
})}
</div>
: null}
{editButton} {editButton}
{deleteButton} {deleteButton}
</div> </div>
@@ -338,11 +387,11 @@ const Apps = (props) => {
<div> <div>
<Paper square style={uploadViewPaperStyle}> <Paper square style={uploadViewPaperStyle}>
<div style={{width: "100%", margin: 25}}> <div style={{width: "100%", margin: 25}}>
<h2>App creation</h2> <h2>App Creator</h2>
<Link to="/docs/apps" style={{textDecoration: "none", color: "#f85a3e"}}>What are apps?</Link> <a href="https://github.com/frikky/OpenAPI-security-definitions" style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">Security API's</a>
&nbsp;- <a href="https://swagger.io/specification/" style={{textDecoration: "none", color: "#f85a3e"}}>OpenAPI specification</a> &nbsp;- <a href="https://apis.guru/browse-apis/" style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">OpenAPI directory</a>
<div/> <div/>
Apps are how you interact with workflows, and are used to execute workflows. They are created with the app creator, using OpenAPI specification or manually in python. Apps interact with eachother in workflows. They are created with the app creator, using OpenAPI specification or manually in python. Use the links above to find potential apps you're looking for using OpenAPI or make one from scratch. There's 1000+ available.
<div/> <div/>
<div style={{marginTop: 20}}> <div style={{marginTop: 20}}>
<Button <Button
@@ -381,34 +430,54 @@ const Apps = (props) => {
const handleSearchChange = (event) => { const handleSearchChange = (event) => {
const searchfield = event.target.value.toLowerCase() const searchfield = event.target.value.toLowerCase()
const newapps = apps.filter(data => data.name.toLowerCase().includes(searchfield) || data.description.toLowerCase().includes(searchfield)) const newapps = apps.filter(data => data.name.toLowerCase().includes(searchfield) || data.description.toLowerCase().includes(searchfield))
setFilteredApps(newapps)
if (newapps.length === 0 && !appSearchLoading) {
setAppSearchLoading(true)
runAppSearch(searchfield)
} else {
setFilteredApps(newapps)
}
} }
const appView = isLoggedIn ? const appView = isLoggedIn ?
<div style={{width: 1366, margin: "auto"}}> <div style={{maxWidth: 1366, margin: "auto",}}>
<div style={appViewStyle}> <div style={appViewStyle}>
<div style={{flex: "1", marginLeft: "10px", marginRight: "10px"}}> <div style={{flex: "1", marginLeft: 10, marginRight: 10}}>
<h2>Upload</h2> <h2>Upload</h2>
<div style={{marginTop: 20}}/> <div style={{marginTop: 20}}/>
<UploadView /> <UploadView />
</div> </div>
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "100%", width: "1px", backgroundColor: dividerColor}}/> <Divider style={{marginBottom: "10px", marginTop: "10px", height: "100%", width: "1px", backgroundColor: dividerColor}}/>
<div style={{flex: 1, marginLeft: "10px", marginRight: "10px"}}> <div style={{flex: 1, marginLeft: 10, marginRight: 10}}>
<div style={{display: "flex"}}> <div style={{display: "flex"}}>
<div style={{flex: 10}}> <div style={{flex: 10}}>
<h2>Available integrations</h2> <h2>Available integrations</h2>
</div> </div>
{isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null} {isLoading ? <CircularProgress style={{marginTop: 13, marginRight: 15}} /> : null}
{/*
<Button <Button
variant="contained" variant="outlined"
component="label" component="label"
color="primary" color="primary"
style={{maxHeight: 50, marginTop: 10}} style={{margin: 5, maxHeight: 50, marginTop: 10}}
onClick={() => { onClick={() => {
getExistingApps() getSpecificApps(baseRepository)
}} }}
> >
Load existing apps Load apps
</Button>
*/}
<Button
variant="outlined"
component="label"
color="primary"
style={{margin: 5, maxHeight: 50, marginTop: 10}}
onClick={() => {
setOpenApi(baseRepository)
setLoadAppsModalOpen(true)
}}
>
Download from URL
</Button> </Button>
</div> </div>
<TextField <TextField
@@ -432,7 +501,7 @@ const Apps = (props) => {
<div style={{marginTop: 15}}> <div style={{marginTop: 15}}>
{apps.length > 0 ? {apps.length > 0 ?
filteredApps.length > 0 ? filteredApps.length > 0 ?
<div style={{maxHeight: "80vh", overflowY: "scroll"}}> <div style={{maxHeight: "78vh", overflowY: "scroll"}}>
{filteredApps.map(app => { {filteredApps.map(app => {
return ( return (
appPaper(app) appPaper(app)
@@ -444,6 +513,12 @@ const Apps = (props) => {
<h4> <h4>
Try a broader search term. E.g. "http" or "TheHive" Try a broader search term. E.g. "http" or "TheHive"
</h4> </h4>
<div/>
{appSearchLoading ?
<CircularProgress color="primary" style={{margin: "auto"}}/>
: null
}
</Paper> </Paper>
: :
<Paper square style={uploadViewPaperStyle}> <Paper square style={uploadViewPaperStyle}>
@@ -459,28 +534,38 @@ const Apps = (props) => {
: :
null null
// Gets the URL itself (hopefully this works in most cases? // Load data e.g. from github
// Will then forward the data to an internal endpoint to validate the api const getSpecificApps = (url) => {
const getExistingApps = () => {
setValidation(true) setValidation(true)
setIsLoading(true) setIsLoading(true)
start() start()
alert.success("Downloading and building apps. Feel free to move around meanwhile.") const parsedData = {
"url": url,
}
if (field1.length > 0) {
parsedData["field_1"] = field1
}
if (field2.length > 0) {
parsedData["field_2"] = field2
}
alert.success("Getting specific apps from your URL.")
var cors = "cors" var cors = "cors"
fetch(globalUrl+"/api/v1/apps/get_existing", { fetch(globalUrl+"/api/v1/apps/get_existing", {
method: "GET", method: "POST",
mode: "cors", mode: "cors",
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
}, },
body: JSON.stringify(parsedData),
credentials: "include", credentials: "include",
}) })
.then((response) => { .then((response) => {
if (response.status !== 200) { if (response.status === 200) {
alert.success("Failed loading.")
} else {
response.text().then(function (text) { response.text().then(function (text) {
console.log("RETURN: ", text) console.log("RETURN: ", text)
alert.success("Loaded existing apps!") alert.success("Loaded existing apps!")
@@ -488,6 +573,16 @@ const Apps = (props) => {
} }
setIsLoading(false) setIsLoading(false)
stop() stop()
return response.json()
})
.then((responseJson) => {
console.log("DATA: ", responseJson)
if (responseJson.reason !== undefined) {
alert.error("Failed loading: "+responseJson.reason)
} else {
alert.error("Failed loading")
}
}) })
.catch(error => { .catch(error => {
alert.error(error.toString()) alert.error(error.toString())
@@ -540,6 +635,29 @@ const Apps = (props) => {
}); });
} }
const runAppSearch = (searchterm) => {
const data = {"search": searchterm}
fetch(globalUrl+"/api/v1/apps/search", {
method: 'POST',
headers: {
'Accept': 'application/json',
},
body: JSON.stringify(data),
credentials: "include",
})
.then((response) => {
setAppSearchLoading(false)
return response.json()
})
.then((responseJson) => {
console.log(responseJson)
})
.catch(error => {
alert.error(error.toString())
});
}
const validateRemote = () => { const validateRemote = () => {
setValidation(true) setValidation(true)
@@ -621,6 +739,105 @@ const Apps = (props) => {
window.location.href = "/apps/new?id="+appValidation window.location.href = "/apps/new?id="+appValidation
} }
const handleGithubValidation = () => {
getSpecificApps(openApi)
setLoadAppsModalOpen(false)
}
const appsModalLoad = loadAppsModalOpen ?
<Dialog modal
open={loadAppsModalOpen}
onClose={() => {
setOpenApi("")
setLoadAppsModalOpen(false)
setField1("")
setField2("")
}}
PaperProps={{
style: {
backgroundColor: surfaceColor,
color: "white",
minWidth: "800px",
minHeight: "320px",
},
}}
>
<DialogTitle>
<div style={{color: "rgba(255,255,255,0.9)"}}>
Load from github repo
</div>
</DialogTitle>
<DialogContent style={{color: "rgba(255,255,255,0.65)"}}>
Repository (supported: github, gitlab, bitbucket)
<TextField
style={{backgroundColor: inputColor}}
variant="outlined"
margin="normal"
defaultValue="https://github.com/frikky/shuffle-apps"
InputProps={{
style:{
color: "white",
height: "50px",
fontSize: "1em",
},
}}
onChange={e => setOpenApi(e.target.value)}
placeholder="https://github.com/frikky/shuffle-apps"
fullWidth
/>
<span style={{marginTop: 10}}>Authentication (optional - private repos etc):</span>
<div style={{display: "flex"}}>
<TextField
style={{flex: 1, backgroundColor: inputColor}}
variant="outlined"
margin="normal"
InputProps={{
style:{
color: "white",
height: "50px",
fontSize: "1em",
},
}}
onChange={e => setField1(e.target.value)}
type="username"
placeholder="Username / APIkey (optional)"
fullWidth
/>
<TextField
style={{flex: 1, backgroundColor: inputColor}}
variant="outlined"
margin="normal"
InputProps={{
style:{
color: "white",
height: "50px",
fontSize: "1em",
},
}}
onChange={e => setField2(e.target.value)}
type="password"
placeholder="Password (optional)"
fullWidth
/>
</div>
</DialogContent>
<DialogActions>
{circularLoader}
<Button style={{borderRadius: "0px"}} onClick={() => setLoadAppsModalOpen(false)} color="primary">
Cancel
</Button>
<Button style={{borderRadius: "0px"}} disabled={openApi.length === 0 || !openApi.includes("http")} onClick={() => {
handleGithubValidation()
}} color="primary">
Submit
</Button>
</DialogActions>
</Dialog>
: null
const errorText = openApiError.length > 0 ? <div>Error: {openApiError}</div> : null const errorText = openApiError.length > 0 ? <div>Error: {openApiError}</div> : null
const circularLoader = validation ? <CircularProgress color="primary" /> : null const circularLoader = validation ? <CircularProgress color="primary" /> : null
const modalView = openApiModal ? const modalView = openApiModal ?
@@ -693,11 +910,11 @@ const Apps = (props) => {
<Button style={{borderRadius: "0px"}} onClick={() => setOpenApiModal(false)} color="primary"> <Button style={{borderRadius: "0px"}} onClick={() => setOpenApiModal(false)} color="primary">
Cancel Cancel
</Button> </Button>
<Button style={{borderRadius: "0px"}} disabled={appValidation.length === 0} onClick={() => { <Button style={{borderRadius: "0px"}} disabled={appValidation.length === 0} onClick={() => {
redirectOpenApi() redirectOpenApi()
}} color="primary"> }} color="primary">
Submit Submit
</Button> </Button>
</DialogActions> </DialogActions>
</FormControl> </FormControl>
</Dialog> </Dialog>
@@ -708,6 +925,7 @@ const Apps = (props) => {
<div> <div>
{appView} {appView}
{modalView} {modalView}
{appsModalLoad}
</div> </div>
: :
<div> <div>
+95 -23
View File
@@ -10,9 +10,9 @@ import MenuItem from '@material-ui/core/MenuItem';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
const Body = { const Body = {
maxWidth: '1000px', maxWidth: '1000px',
minWidth: '768px', minWidth: '768px',
margin: 'auto', margin: 'auto',
display: "flex", display: "flex",
heigth: "100%", heigth: "100%",
color: "white", color: "white",
@@ -32,7 +32,7 @@ const hrefStyle = {
} }
const Docs = (props) => { const Docs = (props) => {
const { isLoaded, globalUrl } = props; const { isLoaded, globalUrl } = props;
const [data, setData] = useState(""); const [data, setData] = useState("");
const [firstrequest, setFirstrequest] = useState(true); const [firstrequest, setFirstrequest] = useState(true);
@@ -52,19 +52,84 @@ const Docs = (props) => {
if (firstrequest) { if (firstrequest) {
setFirstrequest(false) setFirstrequest(false)
fetchDocList() fetchDocList()
fetchDocs() fetchDocs(props.match.params.key)
return return
} }
// Continue this, and find the h2 with the data in it lol
if (window.location.hash.length > 0) {
console.log("HELLO")
var parent = document.getElementById("markdown_wrapper")
if (parent !== null) {
var elements = parent.getElementsByTagName('h2')
const name = window.location.hash.slice(1, window.location.hash.lenth).toLowerCase().split("%20").join(" ").split("_").join(" ")
console.log(name)
var found = false
for (var key in elements) {
const element = elements[key]
if (element.innerHTML === undefined) {
continue
}
// Fix location..
if (element.innerHTML.toLowerCase() === name) {
element.scrollIntoView({behavior: "smooth"})
found = true
//element.scrollTo({
// top: element.offsetTop-100,
// behavior: "smooth"
//})
}
}
// H#
if (!found) {
var elements = parent.getElementsByTagName('h3')
console.log(name)
var found = false
for (var key in elements) {
const element = elements[key]
if (element.innerHTML === undefined) {
continue
}
// Fix location..
if (element.innerHTML.toLowerCase() === name) {
element.scrollIntoView({behavior: "smooth"})
found = true
//element.scrollTo({
// top: element.offsetTop-100,
// behavior: "smooth"
//})
}
}
}
}
//console.log(element)
//console.log("NAME: ", name)
//console.log(document.body.innerHTML)
// parent = document.getElementById(parent);
//var descendants = parent.getElementsByTagName(tagname);
// this.scrollDiv.current.scrollIntoView({ behavior: 'smooth' });
//$(".parent").find("h2:contains('Statistics')").parent();
}
}) })
const fetchDocList = () => { const fetchDocList = () => {
fetch(globalUrl+"/api/v1/docs", { fetch(globalUrl+"/api/v1/docs", {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
}, },
}) })
.then((response) => response.json()) .then((response) => response.json())
.then((responseJson) => { .then((responseJson) => {
if (responseJson.success) { if (responseJson.success) {
@@ -77,8 +142,8 @@ const Docs = (props) => {
.catch(error => {}); .catch(error => {});
} }
const fetchDocs = () => { const fetchDocs = (docId) => {
fetch(globalUrl+"/api/v1/docs/"+props.match.params.key, { fetch(globalUrl+"/api/v1/docs/"+docId, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -99,10 +164,15 @@ const Docs = (props) => {
const markdownStyle = { const markdownStyle = {
color: "rgba(255, 255, 255, 0.65)", color: "rgba(255, 255, 255, 0.65)",
flex: "1", flex: "1",
maxWidth: 750,
overflow: "hidden",
} }
function Link(props) { function OuterLink(props) {
return <a href={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</a> if (props.href.includes("http") || props.href.includes("mailto")) {
return <a href={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</a>
}
return <Link to={props.href} style={{color: "#f85a3e", textDecoration: "none"}}>{props.children}</Link>
} }
function Img(props) { function Img(props) {
@@ -117,7 +187,7 @@ const Docs = (props) => {
// ); // );
//} //}
const postDataBrowser = const postDataBrowser =
<div style={Body}> <div style={Body}>
<div style={SideBar}> <div style={SideBar}>
<ul style={{listStyle: "none", paddingLeft: "0"}}> <ul style={{listStyle: "none", paddingLeft: "0"}}>
@@ -128,22 +198,23 @@ const Docs = (props) => {
</li> </li>
{list.map(item => { {list.map(item => {
const path = "/docs/"+item const path = "/docs/"+item
const newname = item.charAt(0).toUpperCase()+item.substring(1) const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ")
return ( return (
<li style={{marginTop: "10px"}}> <li style={{marginTop: "10px"}}>
<a style={hrefStyle} href={path}> <Link style={hrefStyle} to={path} onClick={() => {fetchDocs(item)}}>
<h2>{newname}</h2> <h2>{newname}</h2>
</a> </Link>
</li> </li>
) )
})} })}
</ul> </ul>
</div> </div>
<div style={markdownStyle}> <div id="markdown_wrapper" style={markdownStyle}>
<ReactMarkdown <ReactMarkdown
id="markdown_wrapper"
escapeHtml={false} escapeHtml={false}
source={data} source={data}
renderers={{link: Link, image: Img}} renderers={{link: OuterLink, image: Img}}
/> />
</div> </div>
</div> </div>
@@ -172,7 +243,7 @@ const Docs = (props) => {
> >
{list.map(item => { {list.map(item => {
const path = "/docs/"+item const path = "/docs/"+item
const newname = item.charAt(0).toUpperCase()+item.substring(1) const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ")
return ( return (
<MenuItem onClick={() => {window.location.pathname = path}}>{newname}</MenuItem> <MenuItem onClick={() => {window.location.pathname = path}}>{newname}</MenuItem>
) )
@@ -180,9 +251,10 @@ const Docs = (props) => {
</Menu> </Menu>
<div style={markdownStyle}> <div style={markdownStyle}>
<ReactMarkdown <ReactMarkdown
id="markdown_wrapper"
escapeHtml={false} escapeHtml={false}
source={data} source={data}
renderers={{link: Link, image: Img}} renderers={{link: OuterLink, image: Img}}
/> />
</div> </div>
<Divider style={{marginTop: "10px", marginBottom: "10px", backgroundColor: dividerColor}}/> <Divider style={{marginTop: "10px", marginBottom: "10px", backgroundColor: dividerColor}}/>
+1 -1
View File
@@ -172,7 +172,7 @@ const LoginDialog = props => {
const basedata = const basedata =
<div style={bodyDivStyle}> <div style={bodyDivStyle}>
<Paper style={boxStyle}> <Paper style={boxStyle}>
<form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px"}}> <form onSubmit={onSubmit} style={{margin: "15px 15px 15px 15px", color: "white",}}>
<h2>{formtitle}</h2> <h2>{formtitle}</h2>
Username Username
<div> <div>
+35 -7
View File
@@ -19,6 +19,7 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
network "github.com/docker/docker/api/types/network"
dockerclient "github.com/docker/docker/client" dockerclient "github.com/docker/docker/client"
//network "github.com/docker/docker/api/types/network" //network "github.com/docker/docker/api/types/network"
//natting "github.com/docker/go-connections/nat" //natting "github.com/docker/go-connections/nat"
@@ -26,6 +27,7 @@ import (
var baseUrl = os.Getenv("BASE_URL") var baseUrl = os.Getenv("BASE_URL")
var baseimagename = "frikky/shuffle" var baseimagename = "frikky/shuffle"
var dockerApiVersion = os.Getenv("DOCKER_API_VERSION") var dockerApiVersion = os.Getenv("DOCKER_API_VERSION")
var environment = os.Getenv("ENVIRONMENT_NAME") var environment = os.Getenv("ENVIRONMENT_NAME")
var orgId = os.Getenv("ORG_ID") var orgId = os.Getenv("ORG_ID")
@@ -67,14 +69,32 @@ func deployWorker(cli *dockerclient.Client, image string, identifier string, env
Image: image, Image: image,
Env: env, Env: env,
} }
//Volumes: map[string]struct{}{
// "/var/run/docker.sock": {}, // Set the network
//}, networkConfig := &network.NetworkingConfig{}
if baseUrl == "http://shuffle-backend:5001" {
networkConfig = &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
"shuffle_shuffle": {
NetworkID: "shuffle_shuffle",
},
},
}
} else {
//log.Printf("Bad config: %s. Using default.", baseUrl)
}
//test := &network.EndpointSettings{
// Gateway: "helo",
//}
//NetworkID
//if connect.EndpointConfig.NetworkID != "NetworkID" {
cont, err := cli.ContainerCreate( cont, err := cli.ContainerCreate(
context.Background(), context.Background(),
config, config,
hostConfig, hostConfig,
networkConfig,
nil, nil,
identifier, identifier,
) )
@@ -84,8 +104,12 @@ func deployWorker(cli *dockerclient.Client, image string, identifier string, env
return err return err
} }
cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{}) err = cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
log.Printf("Container %s is created", cont.ID) if err != nil {
log.Printf("Failed to start container: %s", err)
} else {
log.Printf("Container %s is created", cont.ID)
}
return nil return nil
} }
@@ -283,11 +307,14 @@ func main() {
env := []string{ env := []string{
fmt.Sprintf("AUTHORIZATION=%s", execution.Authorization), fmt.Sprintf("AUTHORIZATION=%s", execution.Authorization),
fmt.Sprintf("EXECUTIONID=%s", execution.ExecutionId), fmt.Sprintf("EXECUTIONID=%s", execution.ExecutionId),
fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion),
fmt.Sprintf("ENVIRONMENT_NAME=%s", environment), fmt.Sprintf("ENVIRONMENT_NAME=%s", environment),
fmt.Sprintf("BASE_URL=%s", baseUrl), fmt.Sprintf("BASE_URL=%s", baseUrl),
} }
if dockerApiVersion != "" {
env = append(env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
}
err = deployWorker(dockercli, workerImage, containerName, env) err = deployWorker(dockercli, workerImage, containerName, env)
if err != nil { if err != nil {
stats, err := dockercli.ContainerInspect(context.Background(), containerName) stats, err := dockercli.ContainerInspect(context.Background(), containerName)
@@ -360,7 +387,8 @@ func main() {
continue continue
} }
log.Println(string(body)) _ = body
//log.Println(string(body))
// FIXME - remove these // FIXME - remove these
//log.Println(string(body)) //log.Println(string(body))
+4 -1
View File
@@ -1,5 +1,8 @@
docker run \ docker run \
--env ORG_ID=$ORG_ID \ --env ORG_ID=$ORG_ID \
--env BASE_URL=$BASE_URL \ --env ENVIRONMENT_NAME="Shuffle" \
--env BASE_URL=http://shuffle-backend:5001 \
--env DOCKER_API_VERSION=1.42 \
--network "shuffle_shuffle" \
-v /var/run/docker.sock:/var/run/docker.sock \ -v /var/run/docker.sock:/var/run/docker.sock \
frikky/shuffle:orborus frikky/shuffle:orborus
Binary file not shown.
+17 -1
View File
@@ -16,6 +16,7 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
network "github.com/docker/docker/api/types/network"
dockerclient "github.com/docker/docker/client" dockerclient "github.com/docker/docker/client"
) )
@@ -284,10 +285,24 @@ func deployApp(cli *dockerclient.Client, image string, identifier string, env []
Env: env, Env: env,
} }
networkConfig := &network.NetworkingConfig{}
if baseUrl == "http://shuffle-backend:5001" {
networkConfig = &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
"shuffle_shuffle": {
NetworkID: "shuffle_shuffle",
},
},
}
} else {
log.Printf("Bad config: %s. Using default network", baseUrl)
}
cont, err := cli.ContainerCreate( cont, err := cli.ContainerCreate(
context.Background(), context.Background(),
config, config,
hostConfig, hostConfig,
networkConfig,
nil, nil,
identifier, identifier,
) )
@@ -375,6 +390,7 @@ func handleExecution(client *http.Client, req *http.Request, workflowExecution W
children[branch.SourceID] = append(children[branch.SourceID], branch.DestinationID) children[branch.SourceID] = append(children[branch.SourceID], branch.DestinationID)
} }
log.Printf("Actions: %d", len(workflowExecution.Workflow.Actions))
for _, action := range workflowExecution.Workflow.Actions { for _, action := range workflowExecution.Workflow.Actions {
if action.Environment != environment { if action.Environment != environment {
continue continue
@@ -395,7 +411,7 @@ func handleExecution(client *http.Client, req *http.Request, workflowExecution W
} }
if len(onpremApps) == 0 { if len(onpremApps) == 0 {
return errors.New("No apps to handle onprem") return errors.New(fmt.Sprintf("No apps to handle onprem (%s)", environment))
} }
pullOptions := types.ImagePullOptions{} pullOptions := types.ImagePullOptions{}