DEVELOPMENT ENVIRONMENT

~liljamo/felu

79db2da35d2967df71aca3c29c28b3157122cd5a — Jonni Liljamo 11 months ago c097efe
feat: ability add new users as admin
5 files changed, 98 insertions(+), 13 deletions(-)

M components/manageadmin.templ
M components/manageadmin_templ.go
M felu.go
A handlers/users.go
M static/styles.css
M components/manageadmin.templ => components/manageadmin.templ +11 -3
@@ 15,10 15,18 @@ templ ManageAdmin() {

templ ManageAdminUsers() {
	@ManageBase("ManageAdmin") {
		<div>
			list of users here, with also the ability to add new users
		<div class="bg-yellow-200">
			<form class="flex flex-col p-2 gap-2" hx-post="/manage/admin/users" hx-target="#add_user_error">
				<label for="email">Email</label>
				<input class="border" type="text" placeholder="name@example.com" name="email" id="email"/>
				<label for="initial_pwd">Initial Password</label>
				<input class="border" type="password" placeholder="..." name="initial_pwd" id="initial_pwd"/>
				<div class="text-rose-600 text-center" id="add_user_error"></div>
				<button class="border p-1" type="submit">Add</button>
			</form>
		</div>
		<div hx-get="/manage/admin/partials/users_list" hx-trigger="load" hx-target="this">

		<div hx-get="/manage/admin/partials/users_list" hx-trigger="load, update-user-list from:body" hx-target="this">
		</div>
	}
}

M components/manageadmin_templ.go => components/manageadmin_templ.go +28 -10
@@ 103,16 103,34 @@ func ManageAdminUsers() templ.Component {
				templBuffer = templ.GetBuffer()
				defer templ.ReleaseBuffer(templBuffer)
			}
			_, err = templBuffer.WriteString("<div>")
			_, err = templBuffer.WriteString("<div class=\"bg-yellow-200\"><form class=\"flex flex-col p-2 gap-2\" hx-post=\"/manage/admin/users\" hx-target=\"#add_user_error\"><label for=\"email\">")
			if err != nil {
				return err
			}
			var_9 := `list of users here, with also the ability to add new users`
			var_9 := `Email`
			_, err = templBuffer.WriteString(var_9)
			if err != nil {
				return err
			}
			_, err = templBuffer.WriteString("</div> <div hx-get=\"/manage/admin/partials/users_list\" hx-trigger=\"load\" hx-target=\"this\"></div>")
			_, err = templBuffer.WriteString("</label><input class=\"border\" type=\"text\" placeholder=\"name@example.com\" name=\"email\" id=\"email\"><label for=\"initial_pwd\">")
			if err != nil {
				return err
			}
			var_10 := `Initial Password`
			_, err = templBuffer.WriteString(var_10)
			if err != nil {
				return err
			}
			_, err = templBuffer.WriteString("</label><input class=\"border\" type=\"password\" placeholder=\"...\" name=\"initial_pwd\" id=\"initial_pwd\"><div class=\"text-rose-600 text-center\" id=\"add_user_error\"></div><button class=\"border p-1\" type=\"submit\">")
			if err != nil {
				return err
			}
			var_11 := `Add`
			_, err = templBuffer.WriteString(var_11)
			if err != nil {
				return err
			}
			_, err = templBuffer.WriteString("</button></form></div> <div hx-get=\"/manage/admin/partials/users_list\" hx-trigger=\"load, update-user-list from:body\" hx-target=\"this\"></div>")
			if err != nil {
				return err
			}


@@ 140,12 158,12 @@ func ManageAdminDomains() templ.Component {
			defer templ.ReleaseBuffer(templBuffer)
		}
		ctx = templ.InitializeContext(ctx)
		var_10 := templ.GetChildren(ctx)
		if var_10 == nil {
			var_10 = templ.NopComponent
		var_12 := templ.GetChildren(ctx)
		if var_12 == nil {
			var_12 = templ.NopComponent
		}
		ctx = templ.ClearChildren(ctx)
		var_11 := templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
		var_13 := templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
			templBuffer, templIsBuffer := w.(*bytes.Buffer)
			if !templIsBuffer {
				templBuffer = templ.GetBuffer()


@@ 155,8 173,8 @@ func ManageAdminDomains() templ.Component {
			if err != nil {
				return err
			}
			var_12 := `list of all domains on the instance, with owner details and such`
			_, err = templBuffer.WriteString(var_12)
			var_14 := `list of all domains on the instance, with owner details and such`
			_, err = templBuffer.WriteString(var_14)
			if err != nil {
				return err
			}


@@ 169,7 187,7 @@ func ManageAdminDomains() templ.Component {
			}
			return err
		})
		err = ManageBase("ManageAdmin").Render(templ.WithChildren(ctx, var_11), templBuffer)
		err = ManageBase("ManageAdmin").Render(templ.WithChildren(ctx, var_13), templBuffer)
		if err != nil {
			return err
		}

M felu.go => felu.go +2 -0
@@ 101,6 101,8 @@ func setupFrontendRouter() *gin.Engine {
		manageAdmin.GET("/users", handlers.ManageAdminUsers())
		manageAdmin.GET("/domains", handlers.ManageAdminDomains())

		manageAdmin.POST("/users", handlers.PostUser())

		manageAdmin.GET("/partials/users_list", handlers.AdminPartialsUsersList())
	}


A handlers/users.go => handlers/users.go +52 -0
@@ 0,0 1,52 @@
/*
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for
 * more information.
 */
package handlers

import (
	"log"
	"net/http"

	"git.src.quest/~skye/felu-ddns/db"
	"github.com/gin-gonic/gin"
)

type postUserData struct {
	Email      string `form:"email"`
	InitialPwd string `form:"initial_pwd"`
}

func PostUser() gin.HandlerFunc {
	return func(c *gin.Context) {
		data := &postUserData{}
		if err := c.Bind(data); err != nil {
			log.Printf("[felu] ERROR: Could not bind user data: %v", err)
			c.String(http.StatusBadRequest, "Could not bind user data")
			return
		}

		if data.Email == "" {
			c.String(http.StatusBadRequest, "Email can't be empty")
			c.Abort()
			return
		}
		if len(data.InitialPwd) < 10 {
			c.String(http.StatusBadRequest, "Initial password should be at least 10 chars")
			c.Abort()
			return
		}

		err := db.CreateUser(data.Email, data.InitialPwd)
		if err != nil {
			// FIXME: Handle better
			c.String(http.StatusInternalServerError, "Something went wrong while creating a new user")
			c.Abort()
			return
		}

		c.Header("HX-Trigger", "update-user-list")
	}
}

M static/styles.css => static/styles.css +5 -0
@@ 589,6 589,11 @@ video {
  background-color: rgb(153 246 228 / var(--tw-bg-opacity));
}

.bg-yellow-200 {
  --tw-bg-opacity: 1;
  background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}

.p-1 {
  padding: 0.25rem;
}