#63: Added general user editing ability for users
This commit is contained in:
+118
-5
@@ -838,6 +838,84 @@ func checkPasswordStrength(password 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 (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 :)
|
// No more emails :)
|
||||||
func checkUsername(Username string) error {
|
func checkUsername(Username string) error {
|
||||||
// Stupid first check of email loool
|
// Stupid first check of email loool
|
||||||
@@ -1308,8 +1386,9 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type newUserStruct struct {
|
type newUserStruct struct {
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
UserId string `json:"user_id"`
|
Username string `json:"username"`
|
||||||
|
UserId string `json:"user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@@ -1331,7 +1410,7 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
foundUser, err := getUser(ctx, t.UserId)
|
foundUser, err := getUser(ctx, t.UserId)
|
||||||
if err != nil {
|
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.WriteHeader(401)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
||||||
return
|
return
|
||||||
@@ -1355,6 +1434,33 @@ func handleUpdateUser(resp http.ResponseWriter, request *http.Request) {
|
|||||||
foundUser.Roles = []string{t.Role}
|
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)
|
err = setUser(ctx, foundUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error patching user %s: %s", foundUser.Username, err)
|
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) {
|
func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
||||||
|
log.Printf("APIGEN!")
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
return
|
return
|
||||||
@@ -1394,6 +1501,7 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
|||||||
userInfo = newUserInfo
|
userInfo = newUserInfo
|
||||||
log.Printf("Updated apikey for user %s", userInfo.Username)
|
log.Printf("Updated apikey for user %s", userInfo.Username)
|
||||||
} else if request.Method == "POST" {
|
} else if request.Method == "POST" {
|
||||||
|
log.Printf("Handling post!")
|
||||||
body, err := ioutil.ReadAll(request.Body)
|
body, err := ioutil.ReadAll(request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Failed reading body")
|
log.Println("Failed reading body")
|
||||||
@@ -1424,7 +1532,7 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
foundUser, err := getUser(ctx, t.UserId)
|
foundUser, err := getUser(ctx, t.UserId)
|
||||||
if err != nil {
|
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.WriteHeader(401)
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
||||||
return
|
return
|
||||||
@@ -1438,6 +1546,10 @@ func handleApiGeneration(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
foundUser = &newUserInfo
|
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)
|
resp.WriteHeader(200)
|
||||||
@@ -6232,6 +6344,7 @@ func init() {
|
|||||||
r.HandleFunc("/functions/outlook/getFolders", handleGetOutlookFolders).Methods("GET", "OPTIONS")
|
r.HandleFunc("/functions/outlook/getFolders", handleGetOutlookFolders).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
// Make user related locations
|
// 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/login", handleLogin).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/users/logout", handleLogout).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/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/getusers", handleGetUsers).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/users/getinfo", handleInfo).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/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/updateuser", handleUpdateUser).Methods("PUT", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/users/{user}", deleteUser).Methods("DELETE", "OPTIONS")
|
r.HandleFunc("/api/v1/users/{user}", deleteUser).Methods("DELETE", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/users", handleGetUsers).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
// General - duplicates and old.
|
// General - duplicates and old.
|
||||||
r.HandleFunc("/api/v1/login", handleLogin).Methods("POST", "OPTIONS")
|
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
|
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) {
|
func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const Admin = (props) => {
|
|||||||
|
|
||||||
const onPasswordChange = () => {
|
const onPasswordChange = () => {
|
||||||
const data = {"username": selectedUser.username, "newpassword": newPassword}
|
const data = {"username": selectedUser.username, "newpassword": newPassword}
|
||||||
const url = globalUrl+'/api/v1/passwordchange';
|
const url = globalUrl+'/api/v1/users/passwordchange';
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -135,7 +135,7 @@ const Admin = (props) => {
|
|||||||
// Just use this one?
|
// Just use this one?
|
||||||
var data = {"username": data.Username, "password": data.Password}
|
var data = {"username": data.Username, "password": data.Password}
|
||||||
var baseurl = globalUrl
|
var baseurl = globalUrl
|
||||||
const url = baseurl+'/api/v1/register';
|
const url = baseurl+'/api/v1/users/register';
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@@ -296,6 +296,7 @@ const Admin = (props) => {
|
|||||||
return response.json()
|
return response.json()
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
|
console.log(responseJson)
|
||||||
setUsers(responseJson)
|
setUsers(responseJson)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ const App = (message, props) => {
|
|||||||
|
|
||||||
const checkLogin = () => {
|
const checkLogin = () => {
|
||||||
var baseurl = globalUrl
|
var baseurl = globalUrl
|
||||||
fetch(baseurl+"/api/v1/getinfo", {
|
fetch(baseurl+"/api/v1/users/getinfo", {
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ const LoginDialog = props => {
|
|||||||
var data = {"username": username, "password": password}
|
var data = {"username": username, "password": password}
|
||||||
var baseurl = globalUrl
|
var baseurl = globalUrl
|
||||||
if (register) {
|
if (register) {
|
||||||
var url = baseurl+'/api/v1/login';
|
var url = baseurl+'/api/v1/users/login';
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -123,7 +123,7 @@ const LoginDialog = props => {
|
|||||||
setLoginInfo("Error in userdata: " + error)
|
setLoginInfo("Error in userdata: " + error)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
url = baseurl+'/api/v1/register';
|
url = baseurl+'/api/v1/users/register';
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
|
|||||||
Reference in New Issue
Block a user