start user editing
This commit is contained in:
parent
c7c76b413c
commit
245dd909d4
BIN
data/dk.db
BIN
data/dk.db
Binary file not shown.
@ -2,14 +2,19 @@ package routes
|
||||
|
||||
import (
|
||||
"dk/internal/components"
|
||||
"dk/internal/database"
|
||||
"dk/internal/helpers"
|
||||
"dk/internal/models/news"
|
||||
"dk/internal/models/users"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sushi "git.sharkk.net/Sharkk/Sushi"
|
||||
"git.sharkk.net/Sharkk/Sushi/auth"
|
||||
"git.sharkk.net/Sharkk/Sushi/password"
|
||||
)
|
||||
|
||||
func RegisterAdminRoutes(app *sushi.App) {
|
||||
@ -26,6 +31,9 @@ func RegisterAdminRoutes(app *sushi.App) {
|
||||
group.Get("/", adminIndex)
|
||||
group.Get("/news", adminNewsForm)
|
||||
group.Post("/news", adminNewsCreate)
|
||||
group.Get("/users", adminUsersIndex)
|
||||
group.Get("/users/:id", adminUserEdit)
|
||||
group.Post("/users/:id", adminUserUpdate)
|
||||
}
|
||||
|
||||
func adminIndex(ctx sushi.Ctx) {
|
||||
@ -78,6 +86,131 @@ func adminNewsCreate(ctx sushi.Ctx) {
|
||||
ctx.Redirect("/admin")
|
||||
}
|
||||
|
||||
func adminUsersIndex(ctx sushi.Ctx) {
|
||||
pagination := helpers.Pagination{
|
||||
Page: max(int(ctx.QueryArgs().GetUintOrZero("page")), 1),
|
||||
PerPage: 30,
|
||||
}
|
||||
|
||||
type UserData struct {
|
||||
ID int
|
||||
Username string
|
||||
Email string
|
||||
Level int
|
||||
Auth int
|
||||
ClassID int
|
||||
ClassName string
|
||||
HP int
|
||||
MaxHP int
|
||||
Registered int64
|
||||
LastOnline int64
|
||||
}
|
||||
|
||||
var userList []*UserData
|
||||
err := database.Select(&userList, `
|
||||
SELECT u.id, u.username, u.email, u.level, u.auth, u.class_id,
|
||||
COALESCE(c.name, 'Unknown') as class_name,
|
||||
u.hp, u.max_hp, u.registered, u.last_online
|
||||
FROM users u
|
||||
LEFT JOIN classes c ON u.class_id = c.id
|
||||
ORDER BY u.id ASC
|
||||
LIMIT %d OFFSET %d`, pagination.PerPage, pagination.Offset())
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting user list for admin index: %s", err.Error())
|
||||
userList = make([]*UserData, 0)
|
||||
}
|
||||
|
||||
type CountResult struct{ Count int }
|
||||
var result CountResult
|
||||
database.Get(&result, "SELECT COUNT(*) as count FROM users")
|
||||
pagination.Total = result.Count
|
||||
|
||||
components.RenderAdminPage(ctx, "User Management", "admin/users/index.html", map[string]any{
|
||||
"users": userList,
|
||||
"currentPage": pagination.Page,
|
||||
"totalPages": pagination.TotalPages(),
|
||||
"hasNext": pagination.HasNext(),
|
||||
"hasPrev": pagination.HasPrev(),
|
||||
})
|
||||
}
|
||||
|
||||
func adminUserEdit(ctx sushi.Ctx) {
|
||||
sess := ctx.GetCurrentSession()
|
||||
id := ctx.Param("id").Int()
|
||||
|
||||
user, err := users.Find(id)
|
||||
if err != nil {
|
||||
sess.SetFlash("error", fmt.Sprintf("User %d not found", id))
|
||||
ctx.Redirect("/admin/users")
|
||||
return
|
||||
}
|
||||
|
||||
components.RenderAdminPage(ctx, fmt.Sprintf("Edit User: %s", user.Username), "admin/users/edit.html", map[string]any{
|
||||
"user": user,
|
||||
})
|
||||
}
|
||||
|
||||
func adminUserUpdate(ctx sushi.Ctx) {
|
||||
sess := ctx.GetCurrentSession()
|
||||
id := ctx.Param("id").Int()
|
||||
|
||||
user, err := users.Find(id)
|
||||
if err != nil {
|
||||
sess.SetFlash("error", fmt.Sprintf("User %d not found", id))
|
||||
ctx.Redirect("/admin/users")
|
||||
return
|
||||
}
|
||||
|
||||
// Update fields
|
||||
username := strings.TrimSpace(ctx.Form("username").String())
|
||||
email := strings.TrimSpace(ctx.Form("email").String())
|
||||
level, _ := strconv.Atoi(ctx.Form("level").String())
|
||||
auth, _ := strconv.Atoi(ctx.Form("auth").String())
|
||||
hp, _ := strconv.Atoi(ctx.Form("hp").String())
|
||||
maxHP, _ := strconv.Atoi(ctx.Form("max_hp").String())
|
||||
newPassword := strings.TrimSpace(ctx.Form("new_password").String())
|
||||
|
||||
if username == "" || email == "" {
|
||||
sess.SetFlash("error", "Username and email are required")
|
||||
ctx.Redirect(fmt.Sprintf("/admin/users/%d", id))
|
||||
return
|
||||
}
|
||||
|
||||
user.Username = username
|
||||
user.Email = email
|
||||
user.Level = level
|
||||
user.Auth = auth
|
||||
user.HP = hp
|
||||
user.MaxHP = maxHP
|
||||
|
||||
if newPassword != "" {
|
||||
user.Password = password.HashPassword(newPassword)
|
||||
}
|
||||
|
||||
fields := map[string]any{
|
||||
"username": user.Username,
|
||||
"email": user.Email,
|
||||
"level": user.Level,
|
||||
"auth": user.Auth,
|
||||
"hp": user.HP,
|
||||
"max_hp": user.MaxHP,
|
||||
}
|
||||
|
||||
if newPassword != "" {
|
||||
fields["password"] = user.Password
|
||||
}
|
||||
|
||||
if err := database.Update("users", fields, "id", id); err != nil {
|
||||
sess.SetFlash("error", "Failed to update user")
|
||||
ctx.Redirect(fmt.Sprintf("/admin/users/%d", id))
|
||||
return
|
||||
}
|
||||
|
||||
sess.SetFlash("success", fmt.Sprintf("User %s updated successfully", user.Username))
|
||||
ctx.Redirect("/admin/users")
|
||||
}
|
||||
|
||||
func bToMb(b uint64) uint64 {
|
||||
return b / 1024 / 1024
|
||||
}
|
||||
|
46
templates/admin/users/edit.html
Normal file
46
templates/admin/users/edit.html
Normal file
@ -0,0 +1,46 @@
|
||||
{include "admin/layout.html"}
|
||||
|
||||
{block "content"}
|
||||
<h1>Edit User: {user.Username}</h1>
|
||||
|
||||
<form class="standard" method="post">
|
||||
{csrf}
|
||||
<div>
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" name="username" id="username" value="{user.Username}" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="email">Email:</label>
|
||||
<input type="email" name="email" id="email" value="{user.Email}" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="level">Level:</label>
|
||||
<input type="number" name="level" id="level" value="{user.Level}" min="1">
|
||||
</div>
|
||||
<div>
|
||||
<label for="auth">Auth Level:</label>
|
||||
<select name="auth" id="auth">
|
||||
<option value="1"{if user.Auth == 1} selected{/if}>User</option>
|
||||
<option value="2"{if user.Auth == 2} selected{/if}>Moderator</option>
|
||||
<option value="3"{if user.Auth == 3} selected{/if}>Admin</option>
|
||||
<option value="4"{if user.Auth == 4} selected{/if}>Super Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="hp">Current HP:</label>
|
||||
<input type="number" name="hp" id="hp" value="{user.HP}" min="0">
|
||||
</div>
|
||||
<div>
|
||||
<label for="max_hp">Max HP:</label>
|
||||
<input type="number" name="max_hp" id="max_hp" value="{user.MaxHP}" min="1">
|
||||
</div>
|
||||
<div>
|
||||
<label for="new_password">New Password (leave blank to keep current):</label>
|
||||
<input type="password" name="new_password" id="new_password" placeholder="Enter new password">
|
||||
</div>
|
||||
<div>
|
||||
<a href="/admin/users"><button type="button" class="btn">Cancel</button></a>
|
||||
<button type="submit" class="btn btn-primary">Update User</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
58
templates/admin/users/index.html
Normal file
58
templates/admin/users/index.html
Normal file
@ -0,0 +1,58 @@
|
||||
{include "admin/layout.html"}
|
||||
|
||||
{block "content"}
|
||||
<h1>User Management</h1>
|
||||
|
||||
<p>
|
||||
Total users: {#users} | Page {currentPage} of {totalPages}
|
||||
</p>
|
||||
|
||||
{if #users > 0}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>Level</th>
|
||||
<th>Class</th>
|
||||
<th>Auth</th>
|
||||
<th>HP</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{for user in users}
|
||||
<tr>
|
||||
<td>{user.ID}</td>
|
||||
<td>{user.Username}</td>
|
||||
<td>{user.Email}</td>
|
||||
<td>{user.Level}</td>
|
||||
<td>{user.ClassName}</td>
|
||||
<td>{user.Auth}</td>
|
||||
<td>{user.HP}/{user.MaxHP}</td>
|
||||
<td>
|
||||
<a href="/admin/users/{user.ID}">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/for}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{if totalPages > 1}
|
||||
<div class="pagination">
|
||||
{if hasPrev}
|
||||
<a href="/admin/users?page={currentPage - 1}">← Previous</a>
|
||||
{/if}
|
||||
{if hasNext}
|
||||
<a href="/admin/users?page={currentPage + 1}">Next →</a>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{else}
|
||||
<div>
|
||||
No users found.
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
Loading…
x
Reference in New Issue
Block a user