mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-01-06 10:00:26 +00:00
Working user panel
See https://mycorrhiza.wiki/hypha/idea/user_panel It's not pretty, but it works. The next step is to make it look good.
This commit is contained in:
parent
c7e4281398
commit
11e98b2368
@ -124,6 +124,10 @@ func readTokensToUsers() {
|
||||
log.Println("Found", len(tmp), "active sessions")
|
||||
}
|
||||
|
||||
func SaveUserDatabase() error {
|
||||
return dumpRegistrationCredentials()
|
||||
}
|
||||
|
||||
func dumpRegistrationCredentials() error {
|
||||
tmp := []*User{}
|
||||
|
||||
|
@ -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`.
|
||||
|
17
user/user.go
17
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",
|
||||
|
@ -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
|
||||
|
@ -5,7 +5,7 @@
|
||||
<main class="main-width">
|
||||
<h1>Manage users</h1>
|
||||
|
||||
<form action="/admin/reindex-users" method="get">
|
||||
<form action="/admin/reindex-users" method="post">
|
||||
<button class="btn btn_accent" type="submit">Reindex users</button>
|
||||
</form>
|
||||
|
||||
@ -17,14 +17,18 @@
|
||||
<th>Name</th>
|
||||
<th>Group</th>
|
||||
<th>Registered at</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for _, u := range userList %}
|
||||
<tr>
|
||||
<td>{%s= u.Name %}</td>
|
||||
<td>{%s= u.Group %}</td>
|
||||
<td>{%s= u.RegisteredAt.Format("2006-01-02 15:04:05-0700") %}</td>
|
||||
<td>{%s u.Name %}</td>
|
||||
<td>{%s u.Group %}</td>
|
||||
<td>{%s u.RegisteredAt.Format("2006-01-02 15:04:05-0700") %}</td>
|
||||
<td>
|
||||
<a href="/admin/users/{%u u.Name %}/edit">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@ -32,3 +36,26 @@
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
||||
{% func AdminUsersUserHTML(u *user.User) %}
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<h1>{%s u.Name %}</h1>
|
||||
|
||||
<form action="" method="post">
|
||||
<label for="group">Group:</label>
|
||||
<select id="group" name="group">
|
||||
<option{% if u.Group == "anon" %} selected{% endif %}>anon</option>
|
||||
<option{% if u.Group == "editor" %} selected{% endif %}>editor</option>
|
||||
<option{% if u.Group == "trusted" %} selected{% endif %}>trusted</option>
|
||||
<option{% if u.Group == "moderator" %} selected{% endif %}>moderator</option>
|
||||
<option{% if u.Group == "admin" %} selected{% endif %}>admin</option>
|
||||
</select>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<button class="btn btn_accent" type="submit">Update</button>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
@ -28,7 +28,7 @@ func StreamAdminUsersPanelHTML(qw422016 *qt422016.Writer, userList []*user.User)
|
||||
<main class="main-width">
|
||||
<h1>Manage users</h1>
|
||||
|
||||
<form action="/admin/reindex-users" method="get">
|
||||
<form action="/admin/reindex-users" method="post">
|
||||
<button class="btn btn_accent" type="submit">Reindex users</button>
|
||||
</form>
|
||||
|
||||
@ -40,66 +40,172 @@ func StreamAdminUsersPanelHTML(qw422016 *qt422016.Writer, userList []*user.User)
|
||||
<th>Name</th>
|
||||
<th>Group</th>
|
||||
<th>Registered at</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
`)
|
||||
//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(`
|
||||
<tr>
|
||||
<td>`)
|
||||
//line views/admin.qtpl:25
|
||||
qw422016.N().S(u.Name)
|
||||
//line views/admin.qtpl:25
|
||||
qw422016.N().S(`</td>
|
||||
<td>`)
|
||||
//line views/admin.qtpl:26
|
||||
qw422016.N().S(u.Group)
|
||||
qw422016.E().S(u.Name)
|
||||
//line views/admin.qtpl:26
|
||||
qw422016.N().S(`</td>
|
||||
<td>`)
|
||||
//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(`</td>
|
||||
<td>`)
|
||||
//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(`</td>
|
||||
<td>
|
||||
<a href="/admin/users/`)
|
||||
//line views/admin.qtpl:30
|
||||
qw422016.N().U(u.Name)
|
||||
//line views/admin.qtpl:30
|
||||
qw422016.N().S(`/edit">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
`)
|
||||
//line views/admin.qtpl:29
|
||||
//line views/admin.qtpl:33
|
||||
}
|
||||
//line views/admin.qtpl:29
|
||||
//line views/admin.qtpl:33
|
||||
qw422016.N().S(`
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//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(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<h1>`)
|
||||
//line views/admin.qtpl:43
|
||||
qw422016.E().S(u.Name)
|
||||
//line views/admin.qtpl:43
|
||||
qw422016.N().S(`</h1>
|
||||
|
||||
<form action="" method="post">
|
||||
<label for="group">Group:</label>
|
||||
<select id="group" name="group">
|
||||
<option`)
|
||||
//line views/admin.qtpl:48
|
||||
if u.Group == "anon" {
|
||||
//line views/admin.qtpl:48
|
||||
qw422016.N().S(` selected`)
|
||||
//line views/admin.qtpl:48
|
||||
}
|
||||
//line views/admin.qtpl:48
|
||||
qw422016.N().S(`>anon</option>
|
||||
<option`)
|
||||
//line views/admin.qtpl:49
|
||||
if u.Group == "editor" {
|
||||
//line views/admin.qtpl:49
|
||||
qw422016.N().S(` selected`)
|
||||
//line views/admin.qtpl:49
|
||||
}
|
||||
//line views/admin.qtpl:49
|
||||
qw422016.N().S(`>editor</option>
|
||||
<option`)
|
||||
//line views/admin.qtpl:50
|
||||
if u.Group == "trusted" {
|
||||
//line views/admin.qtpl:50
|
||||
qw422016.N().S(` selected`)
|
||||
//line views/admin.qtpl:50
|
||||
}
|
||||
//line views/admin.qtpl:50
|
||||
qw422016.N().S(`>trusted</option>
|
||||
<option`)
|
||||
//line views/admin.qtpl:51
|
||||
if u.Group == "moderator" {
|
||||
//line views/admin.qtpl:51
|
||||
qw422016.N().S(` selected`)
|
||||
//line views/admin.qtpl:51
|
||||
}
|
||||
//line views/admin.qtpl:51
|
||||
qw422016.N().S(`>moderator</option>
|
||||
<option`)
|
||||
//line views/admin.qtpl:52
|
||||
if u.Group == "admin" {
|
||||
//line views/admin.qtpl:52
|
||||
qw422016.N().S(` selected`)
|
||||
//line views/admin.qtpl:52
|
||||
}
|
||||
//line views/admin.qtpl:52
|
||||
qw422016.N().S(`>admin</option>
|
||||
</select>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<button class="btn btn_accent" type="submit">Update</button>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//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
|
||||
}
|
||||
|
83
web/admin.go
83
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")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user