mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 01:39:34 +08:00
107 lines
3.5 KiB
Go
107 lines
3.5 KiB
Go
// Package users handles user-related custom functionality.
|
|
package users
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/henrygd/beszel/src/migrations"
|
|
|
|
"github.com/pocketbase/dbx"
|
|
"github.com/pocketbase/pocketbase/core"
|
|
)
|
|
|
|
type UserManager struct {
|
|
app core.App
|
|
}
|
|
|
|
func NewUserManager(app core.App) *UserManager {
|
|
return &UserManager{
|
|
app: app,
|
|
}
|
|
}
|
|
|
|
// Initialize user role if not set
|
|
func (um *UserManager) InitializeUserRole(e *core.RecordEvent) error {
|
|
if e.Record.GetString("role") == "" {
|
|
e.Record.Set("role", "user")
|
|
}
|
|
return e.Next()
|
|
}
|
|
|
|
// Initialize user settings with defaults if not set
|
|
func (um *UserManager) InitializeUserSettings(e *core.RecordEvent) error {
|
|
record := e.Record
|
|
// intialize settings with defaults (zero values can be ignored)
|
|
settings := struct {
|
|
ChartTime string `json:"chartTime"`
|
|
Emails []string `json:"emails"`
|
|
}{
|
|
ChartTime: "1h",
|
|
}
|
|
record.UnmarshalJSONField("settings", &settings)
|
|
// get user email from auth record
|
|
var user struct {
|
|
Email string `db:"email"`
|
|
}
|
|
err := e.App.DB().NewQuery("SELECT email FROM users WHERE id = {:id}").Bind(dbx.Params{
|
|
"id": record.GetString("user"),
|
|
}).One(&user)
|
|
if err != nil {
|
|
log.Println("failed to get user email", "err", err)
|
|
return err
|
|
}
|
|
settings.Emails = []string{user.Email}
|
|
record.Set("settings", settings)
|
|
return e.Next()
|
|
}
|
|
|
|
// Custom API endpoint to create the first user.
|
|
// Mimics previous default behavior in PocketBase < 0.23.0 allowing user to be created through the Beszel UI.
|
|
func (um *UserManager) CreateFirstUser(e *core.RequestEvent) error {
|
|
// check that there are no users
|
|
totalUsers, err := um.app.CountRecords("users")
|
|
if err != nil || totalUsers > 0 {
|
|
return e.JSON(http.StatusForbidden, map[string]string{"err": "Forbidden"})
|
|
}
|
|
// check that there is only one superuser and the email matches the email of the superuser we set up in initial-settings.go
|
|
adminUsers, err := um.app.FindAllRecords(core.CollectionNameSuperusers)
|
|
if err != nil || len(adminUsers) != 1 || adminUsers[0].GetString("email") != migrations.TempAdminEmail {
|
|
return e.JSON(http.StatusForbidden, map[string]string{"err": "Forbidden"})
|
|
}
|
|
// create first user using supplied email and password in request body
|
|
data := struct {
|
|
Email string `json:"email"`
|
|
Password string `json:"password"`
|
|
}{}
|
|
if err := e.BindBody(&data); err != nil {
|
|
return e.JSON(http.StatusBadRequest, map[string]string{"err": err.Error()})
|
|
}
|
|
if data.Email == "" || data.Password == "" {
|
|
return e.JSON(http.StatusBadRequest, map[string]string{"err": "Bad request"})
|
|
}
|
|
|
|
collection, _ := um.app.FindCollectionByNameOrId("users")
|
|
user := core.NewRecord(collection)
|
|
user.SetEmail(data.Email)
|
|
user.SetPassword(data.Password)
|
|
user.Set("role", "admin")
|
|
user.Set("verified", true)
|
|
if err := um.app.Save(user); err != nil {
|
|
return e.JSON(http.StatusInternalServerError, map[string]string{"err": err.Error()})
|
|
}
|
|
// create superuser using the email of the first user
|
|
collection, _ = um.app.FindCollectionByNameOrId(core.CollectionNameSuperusers)
|
|
adminUser := core.NewRecord(collection)
|
|
adminUser.SetEmail(data.Email)
|
|
adminUser.SetPassword(data.Password)
|
|
if err := um.app.Save(adminUser); err != nil {
|
|
return e.JSON(http.StatusInternalServerError, map[string]string{"err": err.Error()})
|
|
}
|
|
// delete the intial superuser
|
|
if err := um.app.Delete(adminUsers[0]); err != nil {
|
|
return e.JSON(http.StatusInternalServerError, map[string]string{"err": err.Error()})
|
|
}
|
|
return e.JSON(http.StatusOK, map[string]string{"msg": "User created"})
|
|
}
|