#63: Added general user editing ability for users
This commit is contained in:
+116
-3
@@ -838,6 +838,84 @@ func checkPasswordStrength(password string) error {
|
||||
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 (deleteuser): %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(fmt.Sprintf(`{"success": false, "reason": "Backend error: too many or too few users with id %s: %d"}`, userId, len(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}`))
|
||||
}
|
||||
|
||||
// No more emails :)
|
||||
func checkUsername(Username string) error {
|
||||
// Stupid first check of email loool
|
||||
@@ -1309,6 +1387,7 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
type newUserStruct struct {
|
||||
Role string `json:"role"`
|
||||
Username string `json:"username"`
|
||||
UserId string `json:"user_id"`
|
||||
}
|
||||
|
||||
@@ -1331,7 +1410,7 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
foundUser, err := getUser(ctx, t.UserId)
|
||||
if err != nil {
|
||||
log.Printf("Can't find user %s (apikey gen)", t.UserId, err)
|
||||
log.Printf("Can't find user %s (update user): %s", t.UserId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
||||
return
|
||||
@@ -1355,6 +1434,33 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
||||
foundUser.Roles = []string{t.Role}
|
||||
}
|
||||
|
||||
if len(t.Username) > 0 {
|
||||
q := datastore.NewQuery("Users").Filter("username =", t.Username)
|
||||
var users []User
|
||||
_, err = dbclient.GetAll(ctx, q, &users)
|
||||
if err != nil {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "reason": "Failed getting users when updating user"}`))
|
||||
return
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, item := range users {
|
||||
if item.Username == t.Username {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "User with username %s already exists"}`, t.Username)))
|
||||
return
|
||||
}
|
||||
|
||||
foundUser.Username = t.Username
|
||||
}
|
||||
|
||||
err = setUser(ctx, foundUser)
|
||||
if err != nil {
|
||||
log.Printf("Error patching user %s: %s", foundUser.Username, err)
|
||||
@@ -1368,6 +1474,7 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
|
||||
func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
||||
log.Printf("APIGEN!")
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
@@ -1394,6 +1501,7 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
||||
userInfo = newUserInfo
|
||||
log.Printf("Updated apikey for user %s", userInfo.Username)
|
||||
} else if request.Method == "POST" {
|
||||
log.Printf("Handling post!")
|
||||
body, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
log.Println("Failed reading body")
|
||||
@@ -1424,7 +1532,7 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
||||
|
||||
foundUser, err := getUser(ctx, t.UserId)
|
||||
if err != nil {
|
||||
log.Printf("Can't find user %s (apikey gen)", t.UserId, err)
|
||||
log.Printf("Can't find user %s (apikey gen): %s", t.UserId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
||||
return
|
||||
@@ -1438,6 +1546,10 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
foundUser = &newUserInfo
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": true, "username": "%s", "verified": %t, "apikey": "%s"}`, foundUser.Username, foundUser.Verified, foundUser.ApiKey)))
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeader(200)
|
||||
@@ -6232,6 +6344,7 @@ func init() {
|
||||
r.HandleFunc("/functions/outlook/getFolders", handleGetOutlookFolders).Methods("GET", "OPTIONS")
|
||||
|
||||
// Make user related locations
|
||||
r.HandleFunc("/api/v1/users/generateapikey", handleApiGeneration).Methods("GET", "POST", "OPTIONS")
|
||||
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")
|
||||
@@ -6239,9 +6352,9 @@ func init() {
|
||||
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/updateuser", handleUpdateUser).Methods("PUT", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/users/{user}", deleteUser).Methods("DELETE", "OPTIONS")
|
||||
r.HandleFunc("/api/v1/users", handleGetUsers).Methods("GET", "OPTIONS")
|
||||
|
||||
// General - duplicates and old.
|
||||
r.HandleFunc("/api/v1/login", handleLogin).Methods("POST", "OPTIONS")
|
||||
|
||||
@@ -2929,84 +2929,6 @@ func setWorkflow(ctx context.Context, workflow Workflow, id string) error {
|
||||
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 (deleteuser): %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) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
|
||||
@@ -72,7 +72,7 @@ const Admin = (props) => {
|
||||
|
||||
const onPasswordChange = () => {
|
||||
const data = {"username": selectedUser.username, "newpassword": newPassword}
|
||||
const url = globalUrl+'/api/v1/passwordchange';
|
||||
const url = globalUrl+'/api/v1/users/passwordchange';
|
||||
fetch(url, {
|
||||
mode: 'cors',
|
||||
method: 'POST',
|
||||
@@ -135,7 +135,7 @@ const Admin = (props) => {
|
||||
// Just use this one?
|
||||
var data = {"username": data.Username, "password": data.Password}
|
||||
var baseurl = globalUrl
|
||||
const url = baseurl+'/api/v1/register';
|
||||
const url = baseurl+'/api/v1/users/register';
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
credentials: "include",
|
||||
@@ -296,6 +296,7 @@ const Admin = (props) => {
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
console.log(responseJson)
|
||||
setUsers(responseJson)
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ const App = (message, props) => {
|
||||
|
||||
const checkLogin = () => {
|
||||
var baseurl = globalUrl
|
||||
fetch(baseurl+"/api/v1/getinfo", {
|
||||
fetch(baseurl+"/api/v1/users/getinfo", {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -92,7 +92,7 @@ const LoginDialog = props => {
|
||||
var data = {"username": username, "password": password}
|
||||
var baseurl = globalUrl
|
||||
if (register) {
|
||||
var url = baseurl+'/api/v1/login';
|
||||
var url = baseurl+'/api/v1/users/login';
|
||||
fetch(url, {
|
||||
mode: 'cors',
|
||||
method: 'POST',
|
||||
@@ -123,7 +123,7 @@ const LoginDialog = props => {
|
||||
setLoginInfo("Error in userdata: " + error)
|
||||
});
|
||||
} else {
|
||||
url = baseurl+'/api/v1/register';
|
||||
url = baseurl+'/api/v1/users/register';
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
|
||||
Reference in New Issue
Block a user