#63: Added basic UI for user handling
This commit is contained in:
+184
-86
@@ -155,27 +155,29 @@ type Environment struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Username string `datastore:"Username"`
|
Username string `datastore:"Username" json:"username"`
|
||||||
Password string `datastore:"password,noindex"`
|
Password string `datastore:"password,noindex" password:"password,omitempty"`
|
||||||
Session string `datastore:"session,noindex"`
|
Session string `datastore:"session,noindex" json:"session"`
|
||||||
Verified bool `datastore:"verified,noindex"`
|
Verified bool `datastore:"verified,noindex" json:"verified"`
|
||||||
PrivateApps []WorkflowApp `datastore:"privateapps"`
|
PrivateApps []WorkflowApp `datastore:"privateapps" json:"privateapps":`
|
||||||
Role string `datastore:"role"`
|
Role string `datastore:"role" json:"role"`
|
||||||
VerificationToken string `datastore:"verification_token"`
|
VerificationToken string `datastore:"verification_token" json:"verification_token"`
|
||||||
ApiKey string `datastore:"apikey"`
|
ApiKey string `datastore:"apikey" json:"apikey"`
|
||||||
ResetReference string `datastore:"reset_reference"`
|
ResetReference string `datastore:"reset_reference" json:"reset_reference"`
|
||||||
Executions ExecutionInfo `datastore:"executions" json:"executions"`
|
Executions ExecutionInfo `datastore:"executions" json:"executions"`
|
||||||
Limits UserLimits `datastore:"limits" json:"limits"`
|
Limits UserLimits `datastore:"limits" json:"limits"`
|
||||||
Authentication []UserAuth `datastore:"authentication,noindex" json:"authentication"`
|
Authentication []UserAuth `datastore:"authentication,noindex" json:"authentication"`
|
||||||
ResetTimeout int64 `datastore:"reset_timeout,noindex"`
|
ResetTimeout int64 `datastore:"reset_timeout,noindex" json:"reset_timeout"`
|
||||||
Id string `datastore:"id" json:"id"`
|
Id string `datastore:"id" json:"id"`
|
||||||
Orgs string `datastore:"orgs" json:"orgs"`
|
Orgs string `datastore:"orgs" json:"orgs"`
|
||||||
CreationTime int64 `datastore:"creation_time" json:"creation_time"`
|
CreationTime int64 `datastore:"creation_time" json:"creation_time"`
|
||||||
|
Active bool `datastore:"active" json:"active"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeout maybe? idk
|
// timeout maybe? idk
|
||||||
type session struct {
|
type session struct {
|
||||||
Username string `datastore:"Username,noindex"`
|
Username string `datastore:"Username,noindex"`
|
||||||
|
Id string `datastore:"Id,noindex"`
|
||||||
Session string `datastore:"session,noindex"`
|
Session string `datastore:"session,noindex"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,9 +711,9 @@ func handleApiAuthentication(resp http.ResponseWriter, request *http.Request) (U
|
|||||||
|
|
||||||
// Get session first
|
// Get session first
|
||||||
// Should basically never happen
|
// Should basically never happen
|
||||||
Userdata, err := getUser(ctx, session.Username)
|
Userdata, err := getUser(ctx, session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", session.Username, err)
|
log.Printf("Username %s doesn't exist (authcheck): %s", session.Username, err)
|
||||||
return User{}, err
|
return User{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,8 +881,8 @@ func handleRegisterVerification(resp http.ResponseWriter, request *http.Request)
|
|||||||
_, err := dbclient.GetAll(ctx, q, &users)
|
_, err := dbclient.GetAll(ctx, q, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed getting users for verification token: %s", err)
|
log.Printf("Failed getting users for verification token: %s", err)
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "%s"}`, defaultMessage)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, defaultMessage)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1008,11 +1010,12 @@ func handleRegister(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//log.Printf("User role: %s", user.Role)
|
if count != 0 {
|
||||||
if err == nil && user.Role != "admin" && count > 0 {
|
if user.Role != "admin" {
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Can't register without being admin (2)"}`))
|
resp.Write([]byte(`{"success": false, "reason": "Can't register without being admin (2)"}`))
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a struct of Username, password
|
// Gets a struct of Username, password
|
||||||
@@ -1042,10 +1045,18 @@ func handleRegister(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME - use it somehow
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, err = getUser(ctx, data.Username)
|
q := datastore.NewQuery("Users").Filter("Username =", data.Username)
|
||||||
if err == nil {
|
var users []User
|
||||||
|
_, err = dbclient.GetAll(ctx, q, &users)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed getting user for registration: %s", err)
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed getting username"}`)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(users) > 0 {
|
||||||
log.Printf("Username %s exists and can't register", data.Username)
|
log.Printf("Username %s exists and can't register", data.Username)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
||||||
@@ -1064,14 +1075,17 @@ func handleRegister(resp http.ResponseWriter, request *http.Request) {
|
|||||||
newUser.Username = data.Username
|
newUser.Username = data.Username
|
||||||
newUser.Password = string(hashedPassword)
|
newUser.Password = string(hashedPassword)
|
||||||
newUser.Verified = false
|
newUser.Verified = false
|
||||||
newUser.Role = "user"
|
|
||||||
newUser.CreationTime = time.Now().Unix()
|
newUser.CreationTime = time.Now().Unix()
|
||||||
|
newUser.Active = true
|
||||||
|
|
||||||
// FIXME - Remove this later
|
// FIXME - Remove this later
|
||||||
newUser.Role = "admin"
|
if count == 0 {
|
||||||
|
newUser.Role = "admin"
|
||||||
|
} else {
|
||||||
|
newUser.Role = "user"
|
||||||
|
}
|
||||||
|
|
||||||
// set limits
|
// set limits
|
||||||
// WorkflowExecutions > CloudExecutions simply because of onprem
|
|
||||||
newUser.Limits.DailyApiUsage = 100
|
newUser.Limits.DailyApiUsage = 100
|
||||||
newUser.Limits.DailyWorkflowExecutions = 1000
|
newUser.Limits.DailyWorkflowExecutions = 1000
|
||||||
newUser.Limits.DailyCloudExecutions = 100
|
newUser.Limits.DailyCloudExecutions = 100
|
||||||
@@ -1124,35 +1138,14 @@ Registration URL :)
|
|||||||
log.Printf("Couldn't send email: %v", err)
|
log.Printf("Couldn't send email: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sessionToken := uuid.NewV4()
|
|
||||||
|
|
||||||
//// Finally, we set the client cookie for "session_token" as the session token we just generated
|
|
||||||
//// we also set an expiry time of 120 seconds, the same as the cache
|
|
||||||
//http.SetCookie(resp, &http.Cookie{
|
|
||||||
// Name: "session_token",
|
|
||||||
// Value: sessionToken.String(),
|
|
||||||
// Expires: time.Now().Add(1200 * time.Second),
|
|
||||||
//})
|
|
||||||
|
|
||||||
//log.Println(Userdata)
|
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(`{"success": true}`))
|
resp.Write([]byte(`{"success": true}`))
|
||||||
log.Printf("%s Successfully registered.", data.Username)
|
log.Printf("%s Successfully registered.", data.Username)
|
||||||
|
|
||||||
//err = SetSession(*newUser, sessionToken.String())
|
err = increaseStatisticsField(ctx, "successful_register", data.Username, 1)
|
||||||
//if err != nil {
|
if err != nil {
|
||||||
// log.Printf("Error adding session to database: %s", err)
|
log.Printf("Failed to increase total apps loaded stats: %s", err)
|
||||||
//}
|
}
|
||||||
|
|
||||||
//err = SetApikey(*newUser)
|
|
||||||
//if err != nil {
|
|
||||||
// log.Printf("Error adding apikey to database: %s", err)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//err = SetSession(*newUser, sessionToken.String())
|
|
||||||
//if err != nil {
|
|
||||||
// log.Printf("Error adding apikey to database: %s", err)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCookie(request *http.Request) bool {
|
func handleCookie(request *http.Request) bool {
|
||||||
@@ -1212,9 +1205,9 @@ func handleLogout(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Get session first
|
// Get session first
|
||||||
// Should basically never happen
|
// Should basically never happen
|
||||||
_, err = getUser(ctx, session.Username)
|
_, err = getUser(ctx, session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", session.Username, err)
|
log.Printf("Username %s doesn't exist (logout): %s", session.Username, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
||||||
return
|
return
|
||||||
@@ -1306,9 +1299,9 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Get session first
|
// Get session first
|
||||||
// Should basically never happen
|
// Should basically never happen
|
||||||
userInfo, err := getUser(ctx, session.Username)
|
userInfo, err := getUser(ctx, session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", session.Username, err)
|
log.Printf("Username %s doesn't exist (apigen): %s", session.Username, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||||
return
|
return
|
||||||
@@ -1366,9 +1359,9 @@ func handleSettings(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Get session first
|
// Get session first
|
||||||
// Should basically never happen
|
// Should basically never happen
|
||||||
UserInfo, err := getUser(ctx, session.Username)
|
UserInfo, err := getUser(ctx, session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", session.Username, err)
|
log.Printf("Username %s doesn't exist (settings): %s", session.Username, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||||
return
|
return
|
||||||
@@ -1409,22 +1402,75 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Printf("Session %#v doesn't exist: %s", session, err)
|
//log.Printf("Session %#v doesn't exist: %s", session, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
resp.Write([]byte(`{"success": false, "reason": "No session"}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get session first
|
// Get session first
|
||||||
// Should basically never happen
|
// Should basically never happen
|
||||||
UserInfo, err := getUser(ctx, session.Username)
|
userInfo, err := getUser(ctx, session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", session.Username, err)
|
log.Printf("Username %s doesn't exist (info): %s", session.Username, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a long check to see if an inactive admin can access the portal
|
||||||
|
if !userInfo.Active {
|
||||||
|
if userInfo.Role == "admin" {
|
||||||
|
ctx := context.Background()
|
||||||
|
q := datastore.NewQuery("Users")
|
||||||
|
var users []User
|
||||||
|
_, err = dbclient.GetAll(ctx, q, &users)
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "Failed to get other users when verifying admin user"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeFound := false
|
||||||
|
adminFound := false
|
||||||
|
for _, user := range users {
|
||||||
|
if user.Id == userInfo.Id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Role != "admin" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Active {
|
||||||
|
activeFound = true
|
||||||
|
}
|
||||||
|
|
||||||
|
adminFound = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must ALWAYS be an active admin
|
||||||
|
// Will return no access if another admin is active
|
||||||
|
if !adminFound {
|
||||||
|
log.Printf("NO OTHER ADMINS FOUND - CONTINUE!")
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
if activeFound {
|
||||||
|
log.Printf("OTHER ACTIVE ADMINS FOUND - CAN'T PASS")
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "This user is locked"}`))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
log.Printf("NO OTHER ADMINS FOUND - CONTINUE!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "This user is locked"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//log.Printf("%s %s", session.Session, UserInfo.Session)
|
//log.Printf("%s %s", session.Session, UserInfo.Session)
|
||||||
if session.Session != UserInfo.Session {
|
if session.Session != userInfo.Session {
|
||||||
log.Printf("Session %s is not the latest. %s", session.Username, err)
|
log.Printf("Session %s is not the latest. %s", session.Username, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
resp.Write([]byte(`{"success": false, "reason": ""}`))
|
||||||
@@ -1434,11 +1480,11 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
|
|||||||
expiration := time.Now().Add(3600 * time.Second)
|
expiration := time.Now().Add(3600 * time.Second)
|
||||||
http.SetCookie(resp, &http.Cookie{
|
http.SetCookie(resp, &http.Cookie{
|
||||||
Name: "session_token",
|
Name: "session_token",
|
||||||
Value: UserInfo.Session,
|
Value: userInfo.Session,
|
||||||
Expires: expiration,
|
Expires: expiration,
|
||||||
})
|
})
|
||||||
|
|
||||||
returnData := fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]}`, UserInfo.Session, expiration.Unix())
|
returnData := fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}]}`, userInfo.Session, expiration.Unix())
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(returnData))
|
resp.Write([]byte(returnData))
|
||||||
@@ -1489,7 +1535,7 @@ func handlePasswordResetMail(resp http.ResponseWriter, request *http.Request) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
Userdata, err := getUser(ctx, t.Username)
|
Userdata, err := getUser(ctx, t.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", t.Username, err)
|
log.Printf("Username %s doesn't exist (pw reset mail): %s", t.Username, err)
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
|
||||||
return
|
return
|
||||||
@@ -1589,8 +1635,8 @@ func handlePasswordReset(resp http.ResponseWriter, request *http.Request) {
|
|||||||
_, err = dbclient.GetAll(ctx, q, &users)
|
_, err = dbclient.GetAll(ctx, q, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed getting users: %s", err)
|
log.Printf("Failed getting users: %s", err)
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "%s"}`, defaultMessage)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "%s"}`, defaultMessage)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1697,9 +1743,9 @@ func handlePasswordChange(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Get session first
|
// Get session first
|
||||||
// Should basically never happen
|
// Should basically never happen
|
||||||
Userdata, err := getUser(ctx, session.Username)
|
Userdata, err := getUser(ctx, session.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", session.Username, err)
|
log.Printf("Username %s doesn't exist (pw change): %s", session.Username, err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
||||||
return
|
return
|
||||||
@@ -1942,12 +1988,10 @@ func handleGetUsers(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkAdminLogin(resp http.ResponseWriter, request *http.Request) {
|
func checkAdminLogin(resp http.ResponseWriter, request *http.Request) {
|
||||||
log.Printf("HELLO?")
|
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("HELLO2?")
|
|
||||||
|
|
||||||
count, err := getUserCount()
|
count, err := getUserCount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1991,14 +2035,24 @@ func handleLogin(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
Userdata, err := getUser(ctx, data.Username)
|
q := datastore.NewQuery("Users").Filter("Username =", strings.ToLower(data.Username))
|
||||||
|
var users []User
|
||||||
|
_, err = dbclient.GetAll(ctx, q, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Username %s doesn't exist: %s", data.Username, err)
|
log.Printf("Failed getting user %s", data.Username)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
resp.Write([]byte(`{"success": false, "reason": "Username and/or password is incorrect"}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(users) != 1 {
|
||||||
|
log.Printf(`Found multiple users with the same username: %s: %d`, data.Username, len(users))
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Found multiple users with the same username: %s"}`, data.Username)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Userdata := users[0]
|
||||||
err = bcrypt.CompareHashAndPassword([]byte(Userdata.Password), []byte(data.Password))
|
err = bcrypt.CompareHashAndPassword([]byte(Userdata.Password), []byte(data.Password))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Password for %s is incorrect: %s", data.Username, err)
|
log.Printf("Password for %s is incorrect: %s", data.Username, err)
|
||||||
@@ -2031,7 +2085,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 {
|
||||||
log.Printf("Error adding session to database: %s", err)
|
log.Printf("Error adding session to database: %s", err)
|
||||||
}
|
}
|
||||||
@@ -2050,7 +2104,7 @@ func handleLogin(resp http.ResponseWriter, request *http.Request) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// ADD TO DATABASE
|
// ADD TO DATABASE
|
||||||
err = SetSession(ctx, *Userdata, sessionToken.String())
|
err = SetSession(ctx, Userdata, sessionToken.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error adding session to database: %s", err)
|
log.Printf("Error adding session to database: %s", err)
|
||||||
}
|
}
|
||||||
@@ -2088,8 +2142,8 @@ func getSession(ctx context.Context, thissession string) (*session, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListBooks returns a list of books, ordered by title.
|
// ListBooks returns a list of books, ordered by title.
|
||||||
func getUser(ctx context.Context, Username string) (*User, error) {
|
func getUser(ctx context.Context, id string) (*User, error) {
|
||||||
key := datastore.NameKey("Users", strings.ToLower(Username), nil)
|
key := datastore.NameKey("Users", id, nil)
|
||||||
curUser := &User{}
|
curUser := &User{}
|
||||||
if err := dbclient.Get(ctx, key, curUser); err != nil {
|
if err := dbclient.Get(ctx, key, curUser); err != nil {
|
||||||
return &User{}, err
|
return &User{}, err
|
||||||
@@ -2133,7 +2187,7 @@ func SetApikey(ctx context.Context, Userdata User) error {
|
|||||||
func SetSession(ctx context.Context, Userdata User, value string) error {
|
func SetSession(ctx context.Context, Userdata User, value string) error {
|
||||||
// Non indexed User data
|
// Non indexed User data
|
||||||
Userdata.Session = value
|
Userdata.Session = value
|
||||||
key1 := datastore.NameKey("Users", strings.ToLower(Userdata.Username), nil)
|
key1 := datastore.NameKey("Users", Userdata.Id, nil)
|
||||||
|
|
||||||
// New struct, to not add body, author etc
|
// New struct, to not add body, author etc
|
||||||
if _, err := dbclient.Put(ctx, key1, &Userdata); err != nil {
|
if _, err := dbclient.Put(ctx, key1, &Userdata); err != nil {
|
||||||
@@ -2146,6 +2200,7 @@ func SetSession(ctx context.Context, Userdata User, value string) error {
|
|||||||
sessiondata := new(session)
|
sessiondata := new(session)
|
||||||
sessiondata.Username = Userdata.Username
|
sessiondata.Username = Userdata.Username
|
||||||
sessiondata.Session = Userdata.Session
|
sessiondata.Session = Userdata.Session
|
||||||
|
sessiondata.Id = Userdata.Id
|
||||||
key2 := datastore.NameKey("sessions", sessiondata.Session, nil)
|
key2 := datastore.NameKey("sessions", sessiondata.Session, nil)
|
||||||
|
|
||||||
if _, err := dbclient.Put(ctx, key2, sessiondata); err != nil {
|
if _, err := dbclient.Put(ctx, key2, sessiondata); err != nil {
|
||||||
@@ -2193,10 +2248,7 @@ func setEnvironment(ctx context.Context, data *Environment) error {
|
|||||||
// ListBooks returns a list of books, ordered by title.
|
// ListBooks returns a list of books, ordered by title.
|
||||||
func setUser(ctx context.Context, data *User) error {
|
func setUser(ctx context.Context, data *User) error {
|
||||||
// clear session_token and API_token for user
|
// clear session_token and API_token for user
|
||||||
k := datastore.NameKey("Users", strings.ToLower(data.Username), nil)
|
k := datastore.NameKey("Users", data.Id, nil)
|
||||||
|
|
||||||
// New struct, to not add body, author etc
|
|
||||||
|
|
||||||
if _, err := dbclient.Put(ctx, k, data); err != nil {
|
if _, err := dbclient.Put(ctx, k, data); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return err
|
||||||
@@ -5881,6 +5933,41 @@ func runInit(ctx context.Context) {
|
|||||||
log.Printf("Failed increasing local stats: %s", err)
|
log.Printf("Failed increasing local stats: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix active users etc
|
||||||
|
q := datastore.NewQuery("Users").Filter("active =", true)
|
||||||
|
var users []User
|
||||||
|
_, err = dbclient.GetAll(ctx, q, &users)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting users apikey: %s", err)
|
||||||
|
} else {
|
||||||
|
if len(users) == 0 {
|
||||||
|
log.Printf("No active users found - setting ALL to active")
|
||||||
|
q := datastore.NewQuery("Users")
|
||||||
|
var users []User
|
||||||
|
_, err := dbclient.GetAll(ctx, q, &users)
|
||||||
|
if err == nil {
|
||||||
|
for _, user := range users {
|
||||||
|
user.Active = true
|
||||||
|
if len(user.Username) == 0 {
|
||||||
|
DeleteKey(ctx, "Users", strings.ToLower(user.Username))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setUser(ctx, &user)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to reset user")
|
||||||
|
} else {
|
||||||
|
log.Printf("Remade user %s with ID", user.Id)
|
||||||
|
err = DeleteKey(ctx, "Users", strings.ToLower(user.Username))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to delete old user by username")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Gets environments and inits if it doesn't exist
|
// Gets environments and inits if it doesn't exist
|
||||||
count, err := getEnvironmentCount()
|
count, err := getEnvironmentCount()
|
||||||
if count == 0 && err == nil {
|
if count == 0 && err == nil {
|
||||||
@@ -6022,18 +6109,29 @@ func init() {
|
|||||||
r.HandleFunc("/functions/outlook/register", handleNewOutlookRegister).Methods("GET", "OPTIONS")
|
r.HandleFunc("/functions/outlook/register", handleNewOutlookRegister).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/functions/outlook/getFolders", handleGetOutlookFolders).Methods("GET", "OPTIONS")
|
r.HandleFunc("/functions/outlook/getFolders", handleGetOutlookFolders).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
// General
|
// Make user related locations
|
||||||
|
r.HandleFunc("/api/v1/users/login", handleLogin).Methods("POST", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/logout", handleLogout).Methods("POST", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/register", handleRegister).Methods("POST", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/checkusers", checkAdminLogin).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/getusers", handleGetUsers).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/getinfo", handleInfo).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/getsettings", handleSettings).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/generateapikey", handleApiGeneration).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users/{user}", deleteUser).Methods("DELETE", "OPTIONS")
|
||||||
|
|
||||||
|
// General - duplicates and old.
|
||||||
r.HandleFunc("/api/v1/login", handleLogin).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/login", handleLogin).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/logout", handleLogout).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/logout", handleLogout).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/register", handleRegister).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/register", handleRegister).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/checkusers", checkAdminLogin).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/checkusers", checkAdminLogin).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/getusers", handleGetUsers).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/getusers", handleGetUsers).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
r.HandleFunc("/api/v1/getenvironments", handleGetEnvironments).Methods("GET", "OPTIONS")
|
|
||||||
r.HandleFunc("/api/v1/setenvironments", handleSetEnvironments).Methods("PUT", "OPTIONS")
|
|
||||||
r.HandleFunc("/api/v1/getinfo", handleInfo).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/getinfo", handleInfo).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/getsettings", handleSettings).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/getsettings", handleSettings).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/generateapikey", handleApiGeneration).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/generateapikey", handleApiGeneration).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
|
r.HandleFunc("/api/v1/getenvironments", handleGetEnvironments).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/setenvironments", handleSetEnvironments).Methods("PUT", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/passwordchange", handlePasswordChange).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/passwordchange", handlePasswordChange).Methods("POST", "OPTIONS")
|
||||||
|
|
||||||
r.HandleFunc("/api/v1/docs", getDocList).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/docs", getDocList).Methods("GET", "OPTIONS")
|
||||||
@@ -6042,8 +6140,6 @@ func init() {
|
|||||||
// Queuebuilder and Workflow streams. First is to update a stream, second to get a stream
|
// Queuebuilder and Workflow streams. First is to update a stream, second to get a stream
|
||||||
// Changed from workflows/streams to streams, as appengine was messing up
|
// Changed from workflows/streams to streams, as appengine was messing up
|
||||||
// This does not increase the API counter
|
// This does not increase the API counter
|
||||||
r.HandleFunc("/api/v1/workflows/queue", handleGetWorkflowqueue).Methods("GET")
|
|
||||||
r.HandleFunc("/api/v1/workflows/queue/confirm", handleGetWorkflowqueueConfirm).Methods("POST")
|
|
||||||
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")
|
||||||
|
|
||||||
@@ -6068,6 +6164,8 @@ func init() {
|
|||||||
/* Everything below here increases the counters*/
|
/* Everything below here increases the counters*/
|
||||||
r.HandleFunc("/api/v1/workflows", getWorkflows).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows", getWorkflows).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows", setNewWorkflow).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows", setNewWorkflow).Methods("POST", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/workflows/queue", handleGetWorkflowqueue).Methods("GET")
|
||||||
|
r.HandleFunc("/api/v1/workflows/queue/confirm", handleGetWorkflowqueueConfirm).Methods("POST")
|
||||||
r.HandleFunc("/api/v1/workflows/schedules", handleGetSchedules).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/schedules", handleGetSchedules).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/download_remote", loadSpecificWorkflows).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/download_remote", loadSpecificWorkflows).Methods("POST", "OPTIONS")
|
||||||
//r.HandleFunc("/api/v1/workflows/{key}/execute_fs", executeWorkflowFS)
|
//r.HandleFunc("/api/v1/workflows/{key}/execute_fs", executeWorkflowFS)
|
||||||
|
|||||||
@@ -2642,6 +2642,84 @@ func setWorkflow(ctx context.Context, workflow Workflow, id string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteUser(resp http.ResponseWriter, request *http.Request) {
|
||||||
|
cors := handleCors(resp, request)
|
||||||
|
if cors {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, userErr := handleApiAuthentication(resp, request)
|
||||||
|
if userErr != nil {
|
||||||
|
log.Printf("Api authentication failed in edit workflow: %s", userErr)
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Role != "admin" {
|
||||||
|
log.Printf("Wrong user (%s) when deleting - must be admin", user.Username)
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "Must be admin"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
location := strings.Split(request.URL.String(), "/")
|
||||||
|
var userId string
|
||||||
|
if location[1] == "api" {
|
||||||
|
if len(location) <= 4 {
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userId = location[4]
|
||||||
|
}
|
||||||
|
|
||||||
|
if userId == user.Id {
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "Can't deactivate yourself"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
q := datastore.NewQuery("Users").Filter("id =", userId)
|
||||||
|
var users []User
|
||||||
|
_, err := dbclient.GetAll(ctx, q, &users)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting users apikey: %s", err)
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "Failed getting users for verification"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(users) != 1 {
|
||||||
|
log.Printf("Found too many users!")
|
||||||
|
resp.WriteHeader(500)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "Backend error: too many users"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert. No user deletion.
|
||||||
|
if users[0].Active {
|
||||||
|
users[0].Active = false
|
||||||
|
} else {
|
||||||
|
users[0].Active = true
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setUser(ctx, &users[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed swapping active for user %s (%s)", users[0].Username, users[0].Id)
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(fmt.Sprintf(`{"success": true"}`)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Successfully inverted %s", users[0].Username)
|
||||||
|
|
||||||
|
resp.WriteHeader(200)
|
||||||
|
resp.Write([]byte(`{"success": true}`))
|
||||||
|
}
|
||||||
|
|
||||||
func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
|
func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
|
|||||||
+91
-5
@@ -63,6 +63,36 @@ const Admin = (props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteUser = (data) => {
|
||||||
|
// Just use this one?
|
||||||
|
const url = globalUrl+'/api/v1/users/'+data.id
|
||||||
|
fetch(url, {
|
||||||
|
method: 'DELETE',
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
getUsers()
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (!responseJson.success && responseJson.reason !== undefined) {
|
||||||
|
alert.error("Failed to deactivate user: "+responseJson.reason)
|
||||||
|
} else {
|
||||||
|
alert.success("Deleted user "+data.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
.catch(error => {
|
||||||
|
console.log("Error in userdata: ", error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const submitUser = (data) => {
|
const submitUser = (data) => {
|
||||||
// FIXME - add some check here ROFL
|
// FIXME - add some check here ROFL
|
||||||
console.log("INPUT: ", data)
|
console.log("INPUT: ", data)
|
||||||
@@ -244,8 +274,8 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const paperStyle = {
|
const paperStyle = {
|
||||||
minWidth: "100%",
|
maxWidth: 1250,
|
||||||
maxWidth: "100%",
|
margin: "auto",
|
||||||
color: "white",
|
color: "white",
|
||||||
backgroundColor: surfaceColor,
|
backgroundColor: surfaceColor,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
@@ -373,11 +403,67 @@ const Admin = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/>
|
<Divider style={{marginTop: 20, marginBottom: 20, backgroundColor: inputColor}}/>
|
||||||
<List>
|
<List>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemText
|
||||||
|
primary="Username"
|
||||||
|
style={{minWidth: 200, maxWidth: 200}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary="API key"
|
||||||
|
style={{minWidth: 350, maxWidth: 350, overflow: "hidden"}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary="Password"
|
||||||
|
style={{minWidth: 180, maxWidth: 180}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary="Role"
|
||||||
|
style={{minWidth: 150, maxWidth: 150}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary="Active"
|
||||||
|
style={{minWidth: 180, maxWidth: 180}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary="Actions"
|
||||||
|
style={{minWidth: 180, maxWidth: 180}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
{users === undefined ? null : users.map(data => {
|
{users === undefined ? null : users.map(data => {
|
||||||
console.log(data)
|
console.log("USER: ", data)
|
||||||
return (
|
return (
|
||||||
<ListItem>
|
<ListItem>
|
||||||
{data.Username}
|
<ListItemText
|
||||||
|
primary={data.username}
|
||||||
|
style={{minWidth: 200, maxWidth: 200}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary={data.apikey === undefined || data.apikey.length === 0 ? "" : data.apikey}
|
||||||
|
style={{maxWidth: 350, minWidth: 350,}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary="**************"
|
||||||
|
style={{minWidth: 180, maxWidth: 180}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary={data.role}
|
||||||
|
style={{minWidth: 150, maxWidth: 150}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary={data.active ? "True" : "False"}
|
||||||
|
style={{minWidth: 180, maxWidth: 180}}
|
||||||
|
onClick={() => console.log("Should set user to active")}
|
||||||
|
/>
|
||||||
|
<ListItemText>
|
||||||
|
<Button
|
||||||
|
style={{}}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => deleteUser(data)}
|
||||||
|
>
|
||||||
|
{data.active ? "Deactivate" : "Activate"}
|
||||||
|
</Button>
|
||||||
|
</ListItemText>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@@ -472,7 +558,7 @@ const Admin = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data =
|
const data =
|
||||||
<div style={{width: 1366, margin: "auto"}}>
|
<div style={{minWidth: 1366, margin: "auto"}}>
|
||||||
<Paper style={paperStyle}>
|
<Paper style={paperStyle}>
|
||||||
<Tabs
|
<Tabs
|
||||||
value={curTab}
|
value={curTab}
|
||||||
|
|||||||
Reference in New Issue
Block a user