diff --git a/user/files.go b/user/files.go
index 08b3a0d..43ff75e 100644
--- a/user/files.go
+++ b/user/files.go
@@ -124,6 +124,10 @@ func readTokensToUsers() {
log.Println("Found", len(tmp), "active sessions")
}
+func SaveUserDatabase() error {
+ return dumpRegistrationCredentials()
+}
+
func dumpRegistrationCredentials() error {
tmp := []*User{}
diff --git a/user/net.go b/user/net.go
index 09dd883..2748f93 100644
--- a/user/net.go
+++ b/user/net.go
@@ -23,7 +23,7 @@ func FromRequest(rq *http.Request) *User {
if err != nil {
return EmptyUser()
}
- return userByToken(cookie.Value)
+ return UserByToken(cookie.Value)
}
// LogoutFromRequest logs the user in `rq` out and rewrites the cookie in `w`.
diff --git a/user/user.go b/user/user.go
index 0ce6103..a1d6db5 100644
--- a/user/user.go
+++ b/user/user.go
@@ -51,6 +51,14 @@ var minimalRights = map[string]int{
"admin/shutdown": 4,
}
+var groups = []string{
+ "anon",
+ "editor",
+ "trusted",
+ "moderator",
+ "admin",
+}
+
// Group — Right
var groupRight = map[string]int{
"anon": 0,
@@ -60,6 +68,15 @@ var groupRight = map[string]int{
"admin": 4,
}
+func ValidGroup(group string) bool {
+ for _, grp := range groups {
+ if grp == group {
+ return true
+ }
+ }
+ return false
+}
+
func EmptyUser() *User {
return &User{
Name: "anon",
diff --git a/user/users.go b/user/users.go
index adf883d..8aaa4bb 100644
--- a/user/users.go
+++ b/user/users.go
@@ -56,18 +56,18 @@ func HasUsername(username string) bool {
}
func CredentialsOK(username, password string) bool {
- return userByName(username).isCorrectPassword(password)
+ return UserByName(username).isCorrectPassword(password)
}
-func userByToken(token string) *User {
+func UserByToken(token string) *User {
if usernameUntyped, ok := tokens.Load(token); ok {
username := usernameUntyped.(string)
- return userByName(username)
+ return UserByName(username)
}
return EmptyUser()
}
-func userByName(username string) *User {
+func UserByName(username string) *User {
if userUntyped, ok := users.Load(username); ok {
user := userUntyped.(*User)
return user
diff --git a/views/admin.qtpl b/views/admin.qtpl
index 8be7499..93e22bf 100644
--- a/views/admin.qtpl
+++ b/views/admin.qtpl
@@ -5,7 +5,7 @@
Manage users
-
@@ -17,14 +17,18 @@
Name |
Group |
Registered at |
+ |
{% for _, u := range userList %}
- {%s= u.Name %} |
- {%s= u.Group %} |
- {%s= u.RegisteredAt.Format("2006-01-02 15:04:05-0700") %} |
+ {%s u.Name %} |
+ {%s u.Group %} |
+ {%s u.RegisteredAt.Format("2006-01-02 15:04:05-0700") %} |
+
+ Edit
+ |
{% endfor %}
@@ -32,3 +36,26 @@
{% endfunc %}
+
+{% func AdminUsersUserHTML(u *user.User) %}
+
+
+ {%s u.Name %}
+
+
+
+
+{% endfunc %}
diff --git a/views/admin.qtpl.go b/views/admin.qtpl.go
index 0dfc69c..320bf11 100644
--- a/views/admin.qtpl.go
+++ b/views/admin.qtpl.go
@@ -28,7 +28,7 @@ func StreamAdminUsersPanelHTML(qw422016 *qt422016.Writer, userList []*user.User)
Manage users
-
@@ -40,66 +40,172 @@ func StreamAdminUsersPanelHTML(qw422016 *qt422016.Writer, userList []*user.User)
Name |
Group |
Registered at |
+ |
`)
-//line views/admin.qtpl:23
+//line views/admin.qtpl:24
for _, u := range userList {
-//line views/admin.qtpl:23
+//line views/admin.qtpl:24
qw422016.N().S(`
`)
-//line views/admin.qtpl:25
- qw422016.N().S(u.Name)
-//line views/admin.qtpl:25
- qw422016.N().S(` |
- `)
//line views/admin.qtpl:26
- qw422016.N().S(u.Group)
+ qw422016.E().S(u.Name)
//line views/admin.qtpl:26
qw422016.N().S(` |
`)
//line views/admin.qtpl:27
- qw422016.N().S(u.RegisteredAt.Format("2006-01-02 15:04:05-0700"))
+ qw422016.E().S(u.Group)
//line views/admin.qtpl:27
qw422016.N().S(` |
+ `)
+//line views/admin.qtpl:28
+ qw422016.E().S(u.RegisteredAt.Format("2006-01-02 15:04:05-0700"))
+//line views/admin.qtpl:28
+ qw422016.N().S(` |
+
+ Edit
+ |
`)
-//line views/admin.qtpl:29
+//line views/admin.qtpl:33
}
-//line views/admin.qtpl:29
+//line views/admin.qtpl:33
qw422016.N().S(`
`)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
}
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
func WriteAdminUsersPanelHTML(qq422016 qtio422016.Writer, userList []*user.User) {
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
qw422016 := qt422016.AcquireWriter(qq422016)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
StreamAdminUsersPanelHTML(qw422016, userList)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
qt422016.ReleaseWriter(qw422016)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
}
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
func AdminUsersPanelHTML(userList []*user.User) string {
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
qb422016 := qt422016.AcquireByteBuffer()
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
WriteAdminUsersPanelHTML(qb422016, userList)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
qs422016 := string(qb422016.B)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
qt422016.ReleaseByteBuffer(qb422016)
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
return qs422016
-//line views/admin.qtpl:34
+//line views/admin.qtpl:38
+}
+
+//line views/admin.qtpl:40
+func StreamAdminUsersUserHTML(qw422016 *qt422016.Writer, u *user.User) {
+//line views/admin.qtpl:40
+ qw422016.N().S(`
+
+
+ `)
+//line views/admin.qtpl:43
+ qw422016.E().S(u.Name)
+//line views/admin.qtpl:43
+ qw422016.N().S(`
+
+
+
+
+`)
+//line views/admin.qtpl:61
+}
+
+//line views/admin.qtpl:61
+func WriteAdminUsersUserHTML(qq422016 qtio422016.Writer, u *user.User) {
+//line views/admin.qtpl:61
+ qw422016 := qt422016.AcquireWriter(qq422016)
+//line views/admin.qtpl:61
+ StreamAdminUsersUserHTML(qw422016, u)
+//line views/admin.qtpl:61
+ qt422016.ReleaseWriter(qw422016)
+//line views/admin.qtpl:61
+}
+
+//line views/admin.qtpl:61
+func AdminUsersUserHTML(u *user.User) string {
+//line views/admin.qtpl:61
+ qb422016 := qt422016.AcquireByteBuffer()
+//line views/admin.qtpl:61
+ WriteAdminUsersUserHTML(qb422016, u)
+//line views/admin.qtpl:61
+ qs422016 := string(qb422016.B)
+//line views/admin.qtpl:61
+ qt422016.ReleaseByteBuffer(qb422016)
+//line views/admin.qtpl:61
+ return qs422016
+//line views/admin.qtpl:61
}
diff --git a/web/admin.go b/web/admin.go
index 5f05719..c8345cb 100644
--- a/web/admin.go
+++ b/web/admin.go
@@ -1,10 +1,13 @@
package web
import (
+ "fmt"
+ "mime"
"io"
"log"
"net/http"
"sort"
+ "strings"
"github.com/bouncepaw/mycorrhiza/cfg"
"github.com/bouncepaw/mycorrhiza/user"
@@ -19,7 +22,7 @@ func initAdmin() {
http.HandleFunc("/admin/shutdown", handlerAdminShutdown)
http.HandleFunc("/admin/reindex-users", handlerAdminReindexUsers)
- http.HandleFunc("/admin/users", handlerAdminUsers)
+ http.HandleFunc("/admin/users/", handlerAdminUsers)
}
}
@@ -49,31 +52,79 @@ func handlerAdminReindexUsers(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
if user.CanProceed(rq, "admin") && rq.Method == "POST" {
user.ReadUsersFromFilesystem()
- http.Redirect(w, rq, "/hypha/"+cfg.UserHypha, http.StatusSeeOther)
+ redirectTo := rq.Referer()
+ if redirectTo == "" {
+ redirectTo = "/hypha/"+cfg.UserHypha
+ }
+ http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
}
}
func handlerAdminUsers(w http.ResponseWriter, r *http.Request) {
util.PrepareRq(r)
if user.CanProceed(r, "admin") {
- // Get a sorted list of users
- var userList []*user.User
- for u := range user.YieldUsers() {
- userList = append(userList, u)
+ path := strings.TrimPrefix(r.URL.Path, "/admin/users")
+ parts := strings.Split(path, "/")[1:]
+
+ // Users dashboard
+ if len(parts) == 0 {
+ // Get a sorted list of users
+ var userList []*user.User
+ for u := range user.YieldUsers() {
+ userList = append(userList, u)
+ }
+
+ sort.Slice(userList, func(i, j int) bool {
+ less := userList[i].RegisteredAt.Before(userList[j].RegisteredAt)
+ return less
+ })
+
+ html := views.AdminUsersPanelHTML(userList)
+ html = views.BaseHTML("Manage users", html, user.FromRequest(r))
+
+ w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
+ if _, err := io.WriteString(w, html); err != nil {
+ log.Println(err)
+ }
+ return
}
- sort.Slice(userList, func(i, j int) bool {
- less := userList[i].RegisteredAt.Before(userList[j].RegisteredAt)
- return less
- })
+ // User edit page
+ if len(parts) == 2 && parts[1] == "edit" {
+ u := user.UserByName(parts[0])
- html := views.AdminUsersPanelHTML(userList)
- html = views.BaseHTML("Manage users", html, user.FromRequest(r))
+ if u != nil && u.Name != "anon" {
+ if r.Method == http.MethodGet {
+ html := views.AdminUsersUserHTML(u)
+ html = views.BaseHTML(fmt.Sprintf("User %s", u.Name), html, user.FromRequest(r))
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- _, err := io.WriteString(w, html)
- if err != nil {
- log.Println(err)
+ w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
+ if _, err := io.WriteString(w, html); err != nil {
+ log.Println(err)
+ }
+ return
+ } else if r.Method == http.MethodPost {
+ oldGroup := u.Group
+ newGroup := r.PostFormValue("group")
+ if user.ValidGroup(newGroup) {
+ u.Group = newGroup
+ if err := user.SaveUserDatabase(); err != nil {
+ u.Group = oldGroup
+ log.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ io.WriteString(w, err.Error())
+ } else {
+ http.Redirect(w, r, "/admin/users/", http.StatusSeeOther)
+ }
+ } else {
+ w.WriteHeader(http.StatusBadRequest)
+ io.WriteString(w, "invalid group")
+ }
+ return
+ }
+ }
}
+
+ util.HTTP404Page(w, "404 page not found")
}
}