#1114: Added hotfix for users with missing organization mapping
This commit is contained in:
@@ -19,7 +19,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.4.17
|
github.com/shuffle/shuffle-shared v0.4.18
|
||||||
golang.org/x/crypto v0.3.0
|
golang.org/x/crypto v0.3.0
|
||||||
google.golang.org/api v0.103.0
|
google.golang.org/api v0.103.0
|
||||||
google.golang.org/appengine v1.6.7
|
google.golang.org/appengine v1.6.7
|
||||||
|
|||||||
+103
-38
@@ -791,7 +791,7 @@ func handleRegister(resp http.ResponseWriter, request *http.Request) {
|
|||||||
CloudSync: false,
|
CloudSync: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shuffle.SetOrg(ctx, newOrg, orgId)
|
err = shuffle.SetOrg(ctx, newOrg, newOrg.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed setting init organization: %s", err)
|
log.Printf("[WARNING] Failed setting init organization: %s", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -943,48 +943,104 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Updating user info if there's something wrong
|
// Updating user info if there's something wrong
|
||||||
if (len(userInfo.ActiveOrg.Name) == 0 || len(userInfo.ActiveOrg.Id) == 0) && len(userInfo.Orgs) > 0 {
|
if len(userInfo.ActiveOrg.Name) == 0 || len(userInfo.ActiveOrg.Id) == 0 {
|
||||||
_, err := shuffle.GetOrg(ctx, userInfo.Orgs[0])
|
if len(userInfo.Orgs) == 0 || (len(userInfo.Orgs) > 0 && userInfo.Orgs[0] == "") {
|
||||||
if err != nil {
|
|
||||||
orgs, err := shuffle.GetAllOrgs(ctx)
|
orgs, err := shuffle.GetAllOrgs(ctx)
|
||||||
if err == nil {
|
log.Printf("[INFO] Fixing organization for user %s (%s). Found orgs: %d", userInfo.Username, userInfo.Id, len(orgs))
|
||||||
newStringOrgs := []string{}
|
if err == nil && len(orgs) > 0 {
|
||||||
newOrgs := []shuffle.Org{}
|
|
||||||
for _, org := range orgs {
|
for _, org := range orgs {
|
||||||
if strings.ToLower(org.Name) == strings.ToLower(userInfo.Orgs[0]) {
|
if len(org.Id) == 0 {
|
||||||
newOrgs = append(newOrgs, org)
|
continue
|
||||||
newStringOrgs = append(newStringOrgs, org.Id)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if len(newOrgs) > 0 {
|
// Prolly some way here to jump into another org
|
||||||
|
// when you have access to the DB
|
||||||
userInfo.ActiveOrg = shuffle.OrgMini{
|
userInfo.ActiveOrg = shuffle.OrgMini{
|
||||||
Id: newOrgs[0].Id,
|
Name: org.Name,
|
||||||
Name: newOrgs[0].Name,
|
Id: org.Id,
|
||||||
}
|
Role: "admin",
|
||||||
|
|
||||||
userInfo.Orgs = newStringOrgs
|
|
||||||
|
|
||||||
err = shuffle.SetUser(ctx, &userInfo, true)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error patching User for activeOrg: %s", err)
|
|
||||||
} else {
|
|
||||||
log.Printf("Updated the users' org")
|
|
||||||
}
|
}
|
||||||
|
userInfo.Orgs = []string{org.Id}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.Printf("Failed getting orgs for user. Major issue.: %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
// Make a new one in case we couldn't find one
|
||||||
// 1. Check if the org exists by ID
|
if len(userInfo.ActiveOrg.Id) == 0 {
|
||||||
// 2. if it does, overwrite user
|
orgSetupName := "default"
|
||||||
userInfo.ActiveOrg = shuffle.OrgMini{
|
orgId := uuid.NewV4().String()
|
||||||
Id: userInfo.Orgs[0],
|
newOrg := shuffle.Org{
|
||||||
|
Name: orgSetupName,
|
||||||
|
Id: orgId,
|
||||||
|
Org: orgSetupName,
|
||||||
|
Users: []shuffle.User{},
|
||||||
|
Roles: []string{"admin", "user"},
|
||||||
|
CloudSync: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = shuffle.SetOrg(ctx, newOrg, newOrg.Id)
|
||||||
|
if err == nil {
|
||||||
|
userInfo.ActiveOrg = shuffle.OrgMini{
|
||||||
|
Name: newOrg.Name,
|
||||||
|
Id: newOrg.Id,
|
||||||
|
Role: "admin",
|
||||||
|
}
|
||||||
|
userInfo.Orgs = []string{newOrg.Id}
|
||||||
|
} else {
|
||||||
|
log.Printf("[WARNING] Failed to set new org: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set user
|
||||||
err = shuffle.SetUser(ctx, &userInfo, true)
|
err = shuffle.SetUser(ctx, &userInfo, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[INFO] Error patching User for activeOrg: %s", err)
|
log.Printf("[WARNING] Failed fixing org info for user %s (%s)", userInfo.Username, userInfo.Id)
|
||||||
|
} else {
|
||||||
|
log.Printf("[INFO] Set organization for %s (%s) to be %s (%s)", userInfo.Username, userInfo.Id, userInfo.ActiveOrg.Name, userInfo.ActiveOrg.Id)
|
||||||
|
}
|
||||||
|
} else if len(userInfo.Orgs) > 0 && userInfo.Orgs[0] != "" {
|
||||||
|
_, err := shuffle.GetOrg(ctx, userInfo.Orgs[0])
|
||||||
|
if err != nil {
|
||||||
|
orgs, err := shuffle.GetAllOrgs(ctx)
|
||||||
|
if err == nil {
|
||||||
|
newStringOrgs := []string{}
|
||||||
|
newOrgs := []shuffle.Org{}
|
||||||
|
for _, org := range orgs {
|
||||||
|
if strings.ToLower(org.Name) == strings.ToLower(userInfo.Orgs[0]) {
|
||||||
|
newOrgs = append(newOrgs, org)
|
||||||
|
newStringOrgs = append(newStringOrgs, org.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(newOrgs) > 0 {
|
||||||
|
userInfo.ActiveOrg = shuffle.OrgMini{
|
||||||
|
Id: newOrgs[0].Id,
|
||||||
|
Name: newOrgs[0].Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfo.Orgs = newStringOrgs
|
||||||
|
|
||||||
|
err = shuffle.SetUser(ctx, &userInfo, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error patching User for activeOrg: %s", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Updated the users' org")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("Failed getting orgs for user. Major issue.: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 1. Check if the org exists by ID
|
||||||
|
// 2. if it does, overwrite user
|
||||||
|
userInfo.ActiveOrg = shuffle.OrgMini{
|
||||||
|
Id: userInfo.Orgs[0],
|
||||||
|
}
|
||||||
|
err = shuffle.SetUser(ctx, &userInfo, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[INFO] Error patching User for activeOrg: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1383,7 +1439,7 @@ func fixUserOrg(ctx context.Context, user *shuffle.User) *shuffle.User {
|
|||||||
org.Users = append(org.Users, *user)
|
org.Users = append(org.Users, *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shuffle.SetOrg(ctx, *org, orgId)
|
err = shuffle.SetOrg(ctx, *org, org.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed setting org %s", orgId)
|
log.Printf("Failed setting org %s", orgId)
|
||||||
}
|
}
|
||||||
@@ -3924,7 +3980,7 @@ func runInitEs(ctx context.Context) {
|
|||||||
CloudSync: false,
|
CloudSync: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shuffle.SetOrg(ctx, newOrg, orgId)
|
err = shuffle.SetOrg(ctx, newOrg, newOrg.Id)
|
||||||
setUsers := false
|
setUsers := false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARNING] Failed setting organization when creating original user: %s", err)
|
log.Printf("[WARNING] Failed setting organization when creating original user: %s", err)
|
||||||
@@ -3976,6 +4032,11 @@ func runInitEs(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, org := range activeOrgs {
|
for _, org := range activeOrgs {
|
||||||
|
if len(org.Id) == 0 {
|
||||||
|
log.Printf("[DEBUG] No ID found for org with name '%s'. Why was it made?", org.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if !org.CloudSync {
|
if !org.CloudSync {
|
||||||
log.Printf("[INFO] Skipping org syncCheck for '%s' because sync isn't set (1).", org.Id)
|
log.Printf("[INFO] Skipping org syncCheck for '%s' because sync isn't set (1).", org.Id)
|
||||||
continue
|
continue
|
||||||
@@ -4151,7 +4212,7 @@ func runInitEs(ctx context.Context) {
|
|||||||
cloneOptions.ReferenceName = plumbing.ReferenceName(branch)
|
cloneOptions.ReferenceName = plumbing.ReferenceName(branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Getting apps from %s", url)
|
log.Printf("[DEBUG] Getting apps from url '%s'", url)
|
||||||
|
|
||||||
r, err := git.Clone(storer, fs, cloneOptions)
|
r, err := git.Clone(storer, fs, cloneOptions)
|
||||||
|
|
||||||
@@ -4288,11 +4349,11 @@ func runInit(ctx context.Context) {
|
|||||||
CloudSync: false,
|
CloudSync: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shuffle.SetOrg(ctx, newOrg, orgId)
|
err = shuffle.SetOrg(ctx, newOrg, newOrg.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed setting organization: %s", err)
|
log.Printf("[WARNING] Failed setting organization: %s", err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Successfully created the default org!")
|
log.Printf("[WARNING] Successfully created the default org!")
|
||||||
setUsers = true
|
setUsers = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -4810,7 +4871,7 @@ func runInit(ctx context.Context) {
|
|||||||
cloneOptions.ReferenceName = plumbing.ReferenceName(branch)
|
cloneOptions.ReferenceName = plumbing.ReferenceName(branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Getting apps from %s", url)
|
log.Printf("[DEBUG] Getting apps from URL '%s'", url)
|
||||||
|
|
||||||
r, err := git.Clone(storer, fs, cloneOptions)
|
r, err := git.Clone(storer, fs, cloneOptions)
|
||||||
|
|
||||||
@@ -5930,6 +5991,10 @@ func initHandlers() {
|
|||||||
r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/recommend", shuffle.HandleActionRecommendation).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/recommend", shuffle.HandleActionRecommendation).Methods("POST", "OPTIONS")
|
||||||
|
|
||||||
|
// New for recommendations in Shuffle
|
||||||
|
r.HandleFunc("/api/v1/recommendations/get_actions", shuffle.HandleActionRecommendation).Methods("POST", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/recommendations/modify", shuffle.HandleRecommendationAction).Methods("POST", "OPTIONS")
|
||||||
|
|
||||||
// Triggers
|
// Triggers
|
||||||
r.HandleFunc("/api/v1/hooks/new", shuffle.HandleNewHook).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/hooks/new", shuffle.HandleNewHook).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/hooks", shuffle.HandleNewHook).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/hooks", shuffle.HandleNewHook).Methods("POST", "OPTIONS")
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type endpoint struct {
|
|||||||
handler http.HandlerFunc
|
handler http.HandlerFunc
|
||||||
path string
|
path string
|
||||||
method string
|
method string
|
||||||
|
body []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -44,7 +45,7 @@ func TestAuthenticationRequired(t *testing.T) {
|
|||||||
{handler: shuffle.HandleNewOutlookRegister, path: "/functions/outlook/register", method: "GET"},
|
{handler: shuffle.HandleNewOutlookRegister, path: "/functions/outlook/register", method: "GET"},
|
||||||
{handler: shuffle.HandleGetOutlookFolders, path: "/functions/outlook/getFolders", method: "GET"},
|
{handler: shuffle.HandleGetOutlookFolders, path: "/functions/outlook/getFolders", method: "GET"},
|
||||||
{handler: shuffle.HandleApiGeneration, path: "/api/v1/users/generateapikey", method: "GET"},
|
{handler: shuffle.HandleApiGeneration, path: "/api/v1/users/generateapikey", method: "GET"},
|
||||||
{handler: handleLogin, path: "/api/v1/users/login", method: "POST"}, // prob not this one
|
{handler: shuffle.HandleLogin, path: "/api/v1/users/login", method: "POST"}, // prob not this one
|
||||||
// handleRegister generates nil pointer exception. Not necessary for this anyway.
|
// handleRegister generates nil pointer exception. Not necessary for this anyway.
|
||||||
//{handler: handleRegister, path: "/api/v1/users/register", method: "POST"},
|
//{handler: handleRegister, path: "/api/v1/users/register", method: "POST"},
|
||||||
{handler: shuffle.HandleGetUsers, path: "/api/v1/users/getusers", method: "GET"},
|
{handler: shuffle.HandleGetUsers, path: "/api/v1/users/getusers", method: "GET"},
|
||||||
@@ -108,8 +109,8 @@ func TestAuthenticationRequired(t *testing.T) {
|
|||||||
|
|
||||||
{handler: verifySwagger, path: "/api/v1/verify_swagger", method: "POST"},
|
{handler: verifySwagger, path: "/api/v1/verify_swagger", method: "POST"},
|
||||||
{handler: verifySwagger, path: "/api/v1/verify_openapi", method: "POST"},
|
{handler: verifySwagger, path: "/api/v1/verify_openapi", method: "POST"},
|
||||||
{handler: echoOpenapiData, path: "/api/v1/get_openapi_uri", method: "POST"},
|
{handler: shuffle.EchoOpenapiData, path: "/api/v1/get_openapi_uri", method: "POST"},
|
||||||
{handler: echoOpenapiData, path: "/api/v1/validate_openapi", method: "POST"},
|
{handler: shuffle.EchoOpenapiData, path: "/api/v1/validate_openapi", method: "POST"},
|
||||||
{handler: shuffle.ValidateSwagger, path: "/api/v1/validate_openapi", method: "POST"},
|
{handler: shuffle.ValidateSwagger, path: "/api/v1/validate_openapi", method: "POST"},
|
||||||
{handler: getOpenapi, path: "/api/v1/get_openapi", method: "GET"},
|
{handler: getOpenapi, path: "/api/v1/get_openapi", method: "GET"},
|
||||||
|
|
||||||
@@ -117,7 +118,7 @@ func TestAuthenticationRequired(t *testing.T) {
|
|||||||
|
|
||||||
{handler: handleCloudSetup, path: "/api/v1/cloud/setup", method: "POST"},
|
{handler: handleCloudSetup, path: "/api/v1/cloud/setup", method: "POST"},
|
||||||
{handler: shuffle.HandleGetOrgs, path: "/api/v1/orgs", method: "POST"},
|
{handler: shuffle.HandleGetOrgs, path: "/api/v1/orgs", method: "POST"},
|
||||||
{handler: shuffle.HandleGetFileContent, path: "/api/v1/files/{fileId}/content", method: "POST"},
|
{handler: shuffle.HandleGetFileContent, path: "/api/v1/files/{fileId}/content", method: "POST", body: []byte("hi")},
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@@ -197,10 +198,11 @@ func TestAuthenticationNotRequired(t *testing.T) {
|
|||||||
// requirements might change after the refactor.
|
// requirements might change after the refactor.
|
||||||
func TestCors(t *testing.T) {
|
func TestCors(t *testing.T) {
|
||||||
handlers := []endpoint{
|
handlers := []endpoint{
|
||||||
|
{handler: handleLogin, path: "/api/v1/users/login", method: "POST"}, // prob not this one
|
||||||
|
|
||||||
{handler: shuffle.HandleNewOutlookRegister, path: "/functions/outlook/register", method: "GET"},
|
{handler: shuffle.HandleNewOutlookRegister, path: "/functions/outlook/register", method: "GET"},
|
||||||
{handler: shuffle.HandleGetOutlookFolders, path: "/functions/outlook/getFolders", method: "GET"},
|
{handler: shuffle.HandleGetOutlookFolders, path: "/functions/outlook/getFolders", method: "GET"},
|
||||||
{handler: shuffle.HandleApiGeneration, path: "/api/v1/users/generateapikey", method: "GET"},
|
{handler: shuffle.HandleApiGeneration, path: "/api/v1/users/generateapikey", method: "GET"},
|
||||||
{handler: handleLogin, path: "/api/v1/users/login", method: "POST"}, // prob not this one
|
|
||||||
// handleRegister generates nil pointer exception
|
// handleRegister generates nil pointer exception
|
||||||
{handler: handleRegister, path: "/api/v1/users/register", method: "POST"},
|
{handler: handleRegister, path: "/api/v1/users/register", method: "POST"},
|
||||||
{handler: shuffle.HandleGetUsers, path: "/api/v1/users/getusers", method: "GET"},
|
{handler: shuffle.HandleGetUsers, path: "/api/v1/users/getusers", method: "GET"},
|
||||||
|
|||||||
@@ -370,6 +370,7 @@ const App = (message, props) => {
|
|||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
setCookie={setCookie}
|
setCookie={setCookie}
|
||||||
cookies={cookies}
|
cookies={cookies}
|
||||||
|
checkLogin={checkLogin}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
+237
-155
@@ -27,6 +27,7 @@ import {
|
|||||||
Divider,
|
Divider,
|
||||||
TextField,
|
TextField,
|
||||||
Button,
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
Tabs,
|
Tabs,
|
||||||
Tab,
|
Tab,
|
||||||
Grid,
|
Grid,
|
||||||
@@ -129,7 +130,7 @@ const FileCategoryInput = (props) => {
|
|||||||
|
|
||||||
|
|
||||||
const Admin = (props) => {
|
const Admin = (props) => {
|
||||||
const { globalUrl, userdata, serverside } = props;
|
const { globalUrl, userdata, serverside, checkLogin } = props;
|
||||||
|
|
||||||
var to_be_copied = "";
|
var to_be_copied = "";
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
@@ -3554,6 +3555,49 @@ const Admin = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
|
const changeRecommendation = (recommendation, action) => {
|
||||||
|
const data = {
|
||||||
|
action: action,
|
||||||
|
name: recommendation.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch(`${globalUrl}/api/v1/recommendations/modify`, {
|
||||||
|
mode: "cors",
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
credentials: "include",
|
||||||
|
crossDomain: true,
|
||||||
|
withCredentials: true,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (responseJson.success === true) {
|
||||||
|
if (checkLogin !== undefined) {
|
||||||
|
checkLogin()
|
||||||
|
getEnvironments()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (responseJson.success === false && responseJson.reason !== undefined) {
|
||||||
|
alert.error("Failed change recommendation: ", responseJson.reason)
|
||||||
|
} else {
|
||||||
|
alert.error("Failed change recommendation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert.info("Failed dismissing alert. Please contact support@shuffler.io if this persists.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const environmentView =
|
const environmentView =
|
||||||
curTab === 6 ? (
|
curTab === 6 ? (
|
||||||
<div>
|
<div>
|
||||||
@@ -3645,7 +3689,6 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (environment.archived === undefined) {
|
if (environment.archived === undefined) {
|
||||||
getEnvironments();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3654,167 +3697,206 @@ const Admin = (props) => {
|
|||||||
bgColor = "#1f2023";
|
bgColor = "#1f2023";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if there's a notification for it in userdata.priorities
|
||||||
|
var showCPUAlert = false
|
||||||
|
var foundIndex = -1
|
||||||
|
if (userdata !== undefined && userdata !== null && userdata.priorities !== undefined && userdata.priorities !== null && userdata.priorities.length > 0) {
|
||||||
|
foundIndex = userdata.priorities.findIndex(prio => prio.name.includes("CPU") && prio.active === true)
|
||||||
|
|
||||||
|
if (foundIndex >= 0 && userdata.priorities[foundIndex].name.endsWith(environment.Name)) {
|
||||||
|
showCPUAlert = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Show CPU alert: ", showCPUAlert)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem key={index} style={{ backgroundColor: bgColor }}>
|
<span key={index}>
|
||||||
<ListItemText
|
<ListItem key={index} style={{ backgroundColor: bgColor }}>
|
||||||
primary={environment.Name}
|
<ListItemText
|
||||||
style={{
|
primary={environment.Name}
|
||||||
minWidth: 150,
|
style={{
|
||||||
maxWidth: 150,
|
minWidth: 150,
|
||||||
overflow: "hidden",
|
maxWidth: 150,
|
||||||
}}
|
overflow: "hidden",
|
||||||
/>
|
}}
|
||||||
<ListItemText
|
/>
|
||||||
primary={
|
<ListItemText
|
||||||
environment.Type !== "cloud"
|
primary={
|
||||||
? environment.running_ip === undefined ||
|
environment.Type !== "cloud"
|
||||||
environment.running_ip === null ||
|
? environment.running_ip === undefined ||
|
||||||
environment.running_ip.length === 0
|
environment.running_ip === null ||
|
||||||
?
|
environment.running_ip.length === 0
|
||||||
<div>
|
?
|
||||||
Not running
|
<div>
|
||||||
</div>
|
Not running
|
||||||
: environment.running_ip
|
</div>
|
||||||
: "N/A"
|
: environment.running_ip.split(":")[0]
|
||||||
}
|
: "N/A"
|
||||||
style={{
|
}
|
||||||
minWidth: 200,
|
style={{
|
||||||
maxWidth: 200,
|
minWidth: 200,
|
||||||
overflow: "hidden",
|
maxWidth: 200,
|
||||||
}}
|
overflow: "hidden",
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<ListItemText
|
<ListItemText
|
||||||
style={{ minWidth: 100, maxWidth: 100 }}
|
style={{ minWidth: 100, maxWidth: 100 }}
|
||||||
primary={
|
primary={
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={"Copy Orborus command"}
|
title={"Copy Orborus command"}
|
||||||
style={{}}
|
|
||||||
aria-label={"Copy orborus command"}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
style={{}}
|
style={{}}
|
||||||
disabled={environment.Type === "cloud"}
|
aria-label={"Copy orborus command"}
|
||||||
onClick={() => {
|
>
|
||||||
if (environment.Type === "cloud") {
|
<IconButton
|
||||||
alert.info("No Orborus necessary for environment cloud. Create and use a different environment to run executions on-premises.")
|
style={{}}
|
||||||
return
|
disabled={environment.Type === "cloud"}
|
||||||
}
|
onClick={() => {
|
||||||
|
if (environment.Type === "cloud") {
|
||||||
const elementName = "copy_element_shuffle";
|
alert.info("No Orborus necessary for environment cloud. Create and use a different environment to run executions on-premises.")
|
||||||
const auth = environment.auth === "" ? 'cb5st3d3Z!3X3zaJ*Pc' : environment.auth
|
return
|
||||||
const commandData = `docker run --volume "/var/run/docker.sock:/var/run/docker.sock" -e ENVIRONMENT_NAME="${environment.Name}" -e 'AUTH=${auth}' -e ORG="${props.userdata.active_org.id}" -e DOCKER_API_VERSION=1.40 -e BASE_URL="${globalUrl}" --name="shuffle-orborus" -d ghcr.io/shuffle/shuffle-orborus:latest`
|
|
||||||
var copyText = document.getElementById(elementName);
|
|
||||||
if (copyText !== null && copyText !== undefined) {
|
|
||||||
const clipboard = navigator.clipboard;
|
|
||||||
if (clipboard === undefined) {
|
|
||||||
alert.error("Can only copy over HTTPS (port 3443)");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
navigator.clipboard.writeText(commandData);
|
const elementName = "copy_element_shuffle";
|
||||||
copyText.select();
|
const auth = environment.auth === "" ? 'cb5st3d3Z!3X3zaJ*Pc' : environment.auth
|
||||||
copyText.setSelectionRange(
|
const commandData = `docker run --volume "/var/run/docker.sock:/var/run/docker.sock" -e ENVIRONMENT_NAME="${environment.Name}" -e 'AUTH=${auth}' -e ORG="${props.userdata.active_org.id}" -e DOCKER_API_VERSION=1.40 -e BASE_URL="${globalUrl}" --name="shuffle-orborus" -d ghcr.io/shuffle/shuffle-orborus:latest`
|
||||||
0,
|
var copyText = document.getElementById(elementName);
|
||||||
99999
|
if (copyText !== null && copyText !== undefined) {
|
||||||
); /* For mobile devices */
|
const clipboard = navigator.clipboard;
|
||||||
|
if (clipboard === undefined) {
|
||||||
|
alert.error("Can only copy over HTTPS (port 3443)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy the text inside the text field */
|
navigator.clipboard.writeText(commandData);
|
||||||
document.execCommand("copy");
|
copyText.select();
|
||||||
|
copyText.setSelectionRange(
|
||||||
|
0,
|
||||||
|
99999
|
||||||
|
); /* For mobile devices */
|
||||||
|
|
||||||
alert.info("Orborus command copied to clipboard");
|
/* Copy the text inside the text field */
|
||||||
}
|
document.execCommand("copy");
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FileCopyIcon disabled={environment.Type === "cloud"} style={{ color: environment.Type === "cloud" ? "rgba(255,255,255,0.2)" : "rgba(255,255,255,0.8)" }} />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ListItemText
|
alert.info("Orborus command copied to clipboard");
|
||||||
primary={environment.Type}
|
}
|
||||||
style={{ minWidth: 125, maxWidth: 125 }}
|
}}
|
||||||
/>
|
>
|
||||||
<ListItemText
|
<FileCopyIcon disabled={environment.Type === "cloud"} style={{ color: environment.Type === "cloud" ? "rgba(255,255,255,0.2)" : "rgba(255,255,255,0.8)" }} />
|
||||||
style={{
|
</IconButton>
|
||||||
minWidth: 125,
|
</Tooltip>
|
||||||
maxWidth: 125,
|
}
|
||||||
overflow: "hidden",
|
/>
|
||||||
}}
|
|
||||||
primary={environment.default ? "true" : null}
|
|
||||||
>
|
|
||||||
{environment.default ? null : (
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
style={{ borderRadius: "0px", marginRight: 5 }}
|
|
||||||
onClick={() => setDefaultEnvironment(environment)}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
Make default
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</ListItemText>
|
|
||||||
<ListItemText
|
|
||||||
style={{
|
|
||||||
minWidth: 100,
|
|
||||||
maxWidth: 100,
|
|
||||||
overflow: "hidden",
|
|
||||||
marginLeft: 10,
|
|
||||||
}}
|
|
||||||
primary={environment.archived.toString()}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
style={{
|
|
||||||
minWidth: 150,
|
|
||||||
maxWidth: 150,
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
primary={
|
|
||||||
environment.edited !== undefined &&
|
|
||||||
environment.edited !== null &&
|
|
||||||
environment.edited !== 0
|
|
||||||
? new Date(environment.edited * 1000).toISOString()
|
|
||||||
: 0
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<ListItemText
|
|
||||||
style={{
|
|
||||||
minWidth: 300,
|
|
||||||
maxWidth: 300,
|
|
||||||
overflow: "hidden",
|
|
||||||
marginLeft: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: "flex" }}>
|
|
||||||
<Button
|
|
||||||
variant={environment.archived ? "contained" : "outlined"}
|
|
||||||
style={{ borderRadius: "0px" }}
|
|
||||||
onClick={() => deleteEnvironment(environment)}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{environment.archived ? "Activate" : "Disable"}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant={"outlined"}
|
|
||||||
style={{ borderRadius: "0px" }}
|
|
||||||
disabled={isCloud && environment.Name.toLowerCase() !== "cloud"}
|
|
||||||
onClick={() => {
|
|
||||||
console.log("Should clear executions for: ", environment);
|
|
||||||
|
|
||||||
if (isCloud && environment.Name.toLowerCase() === "cloud") {
|
<ListItemText
|
||||||
rerunCloudWorkflows(environment);
|
primary={environment.Type}
|
||||||
} else {
|
style={{ minWidth: 125, maxWidth: 125 }}
|
||||||
abortEnvironmentWorkflows(environment);
|
/>
|
||||||
}
|
<ListItemText
|
||||||
}}
|
style={{
|
||||||
color="primary"
|
minWidth: 125,
|
||||||
>
|
maxWidth: 125,
|
||||||
{isCloud && environment.Name.toLowerCase() === "cloud" ? "Rerun" : "Clear"}
|
overflow: "hidden",
|
||||||
</Button>
|
}}
|
||||||
</div>
|
primary={environment.default ? "true" : null}
|
||||||
</ListItemText>
|
>
|
||||||
</ListItem>
|
{environment.default ? null : (
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
style={{ marginRight: 5 }}
|
||||||
|
onClick={() => setDefaultEnvironment(environment)}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Make default
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</ListItemText>
|
||||||
|
<ListItemText
|
||||||
|
style={{
|
||||||
|
minWidth: 100,
|
||||||
|
maxWidth: 100,
|
||||||
|
overflow: "hidden",
|
||||||
|
marginLeft: 10,
|
||||||
|
}}
|
||||||
|
primary={environment.archived.toString()}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
style={{
|
||||||
|
minWidth: 150,
|
||||||
|
maxWidth: 150,
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
primary={
|
||||||
|
environment.edited !== undefined &&
|
||||||
|
environment.edited !== null &&
|
||||||
|
environment.edited !== 0
|
||||||
|
? new Date(environment.edited * 1000).toISOString()
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
style={{
|
||||||
|
minWidth: 300,
|
||||||
|
maxWidth: 300,
|
||||||
|
overflow: "hidden",
|
||||||
|
marginLeft: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<ButtonGroup style={{borderRadius: "5px 5px 5px 5px",}}>
|
||||||
|
<Button
|
||||||
|
variant={environment.archived ? "contained" : "outlined"}
|
||||||
|
style={{ }}
|
||||||
|
onClick={() => deleteEnvironment(environment)}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{environment.archived ? "Activate" : "Disable"}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={"outlined"}
|
||||||
|
style={{ }}
|
||||||
|
disabled={isCloud && environment.Name.toLowerCase() !== "cloud"}
|
||||||
|
onClick={() => {
|
||||||
|
console.log("Should clear executions for: ", environment);
|
||||||
|
|
||||||
|
if (isCloud && environment.Name.toLowerCase() === "cloud") {
|
||||||
|
rerunCloudWorkflows(environment);
|
||||||
|
} else {
|
||||||
|
abortEnvironmentWorkflows(environment);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{isCloud && environment.Name.toLowerCase() === "cloud" ? "Rerun" : "Clear"}
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</div>
|
||||||
|
</ListItemText>
|
||||||
|
</ListItem>
|
||||||
|
{showCPUAlert === false ? null :
|
||||||
|
<ListItem key={index+"_cpu"} style={{ backgroundColor: bgColor }}>
|
||||||
|
<div style={{border: "1px solid #f85a3e", borderRadius: theme.palette.borderRadius, marginTop: 10, marginBottom: 10, padding: 15, textAlign: "center", height: 70, textAlign: "left", backgroundColor: theme.palette.surfaceColor, display: "flex", }}>
|
||||||
|
<div style={{flex: 2, overflow: "hidden",}}>
|
||||||
|
<Typography variant="body1" >
|
||||||
|
90% CPU the server(s) hosting the Shuffle App Runner (Orborus) was found.
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="textSecondary">
|
||||||
|
Need help with High Availability and Scale? <a href="/docs/configuration#scale" target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>Read documentation</a> and <a href="https://shuffler.io/contact" target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>Get in touch</a>.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<div style={{flex: 1, display: "flex", marginLeft: 30, }}>
|
||||||
|
<Button style={{borderRadius: 25, width: 200, height: 50, marginTop: 8, }} variant="outlined" color="secondary" onClick={() => {
|
||||||
|
// dismiss -> get envs
|
||||||
|
changeRecommendation(userdata.priorities[foundIndex], "dismiss")
|
||||||
|
}}>
|
||||||
|
Dismiss
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</List>
|
</List>
|
||||||
@@ -3973,7 +4055,7 @@ const Admin = (props) => {
|
|||||||
style={{ minWidth: 150, maxWidth: 150 }}
|
style={{ minWidth: 150, maxWidth: 150 }}
|
||||||
/>
|
/>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary="Orborus running"
|
primary="Orborus source"
|
||||||
style={{ minWidth: 200, maxWidth: 200 }}
|
style={{ minWidth: 200, maxWidth: 200 }}
|
||||||
/>
|
/>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import (
|
|||||||
|
|
||||||
// Starts jobs in bulk, so this could be increased
|
// Starts jobs in bulk, so this could be increased
|
||||||
var sleepTime = 3
|
var sleepTime = 3
|
||||||
var maxConcurrency = 25
|
var maxConcurrency = 15
|
||||||
|
|
||||||
// Timeout if something rashes
|
// Timeout if something rashes
|
||||||
var workerTimeoutEnv = os.Getenv("SHUFFLE_ORBORUS_EXECUTION_TIMEOUT")
|
var workerTimeoutEnv = os.Getenv("SHUFFLE_ORBORUS_EXECUTION_TIMEOUT")
|
||||||
|
|||||||
Reference in New Issue
Block a user