[#31] replaced the initial admin create interactive cli with Installer web page
This commit is contained in:
parent
460c684caa
commit
0739e90ff2
|
@ -24,7 +24,7 @@ func BindAdminApi(app core.App, rg *echo.Group) {
|
||||||
subGroup.POST("/confirm-password-reset", api.confirmPasswordReset)
|
subGroup.POST("/confirm-password-reset", api.confirmPasswordReset)
|
||||||
subGroup.POST("/refresh", api.refresh, RequireAdminAuth())
|
subGroup.POST("/refresh", api.refresh, RequireAdminAuth())
|
||||||
subGroup.GET("", api.list, RequireAdminAuth())
|
subGroup.GET("", api.list, RequireAdminAuth())
|
||||||
subGroup.POST("", api.create, RequireAdminAuth())
|
subGroup.POST("", api.create, RequireAdminAuthOnlyIfAny(app))
|
||||||
subGroup.GET("/:id", api.view, RequireAdminAuth())
|
subGroup.GET("/:id", api.view, RequireAdminAuth())
|
||||||
subGroup.PATCH("/:id", api.update, RequireAdminAuth())
|
subGroup.PATCH("/:id", api.update, RequireAdminAuth())
|
||||||
subGroup.DELETE("/:id", api.delete, RequireAdminAuth())
|
subGroup.DELETE("/:id", api.delete, RequireAdminAuth())
|
||||||
|
|
|
@ -456,12 +456,37 @@ func TestAdminDelete(t *testing.T) {
|
||||||
func TestAdminCreate(t *testing.T) {
|
func TestAdminCreate(t *testing.T) {
|
||||||
scenarios := []tests.ApiScenario{
|
scenarios := []tests.ApiScenario{
|
||||||
{
|
{
|
||||||
Name: "unauthorized",
|
Name: "unauthorized (while having at least 1 existing admin)",
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Url: "/api/admins",
|
Url: "/api/admins",
|
||||||
ExpectedStatus: 401,
|
ExpectedStatus: 401,
|
||||||
ExpectedContent: []string{`"data":{}`},
|
ExpectedContent: []string{`"data":{}`},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "unauthorized (while having 0 existing admins)",
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Url: "/api/admins",
|
||||||
|
Body: strings.NewReader(`{"email":"testnew@example.com","password":"1234567890","passwordConfirm":"1234567890","avatar":3}`),
|
||||||
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
||||||
|
// delete all admins
|
||||||
|
_, err := app.Dao().DB().NewQuery("DELETE FROM {{_admins}}").Execute()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ExpectedStatus: 200,
|
||||||
|
ExpectedContent: []string{
|
||||||
|
`"id":`,
|
||||||
|
`"email":"testnew@example.com"`,
|
||||||
|
`"avatar":3`,
|
||||||
|
},
|
||||||
|
ExpectedEvents: map[string]int{
|
||||||
|
"OnModelBeforeCreate": 1,
|
||||||
|
"OnModelAfterCreate": 1,
|
||||||
|
"OnAdminBeforeCreateRequest": 1,
|
||||||
|
"OnAdminAfterCreateRequest": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as user",
|
Name: "authorized as user",
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
|
|
85
apis/base.go
85
apis/base.go
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/tools/rest"
|
"github.com/pocketbase/pocketbase/tools/rest"
|
||||||
"github.com/pocketbase/pocketbase/ui"
|
"github.com/pocketbase/pocketbase/ui"
|
||||||
|
"github.com/spf13/cast"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitApi creates a configured echo instance with registered
|
// InitApi creates a configured echo instance with registered
|
||||||
|
@ -71,13 +72,8 @@ func InitApi(app core.App) (*echo.Echo, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// serves /ui/dist/index.html file
|
// admin ui routes
|
||||||
// (explicit route is used to avoid conflicts with `RemoveTrailingSlash` middleware)
|
bindStaticAdminUI(app, e)
|
||||||
e.FileFS("/_", "index.html", ui.DistIndexHTML, middleware.Gzip())
|
|
||||||
|
|
||||||
// serves static files from the /ui/dist directory
|
|
||||||
// (similar to echo.StaticFS but with gzip middleware enabled)
|
|
||||||
e.GET("/_/*", StaticDirectoryHandler(ui.DistDirFS, false), middleware.Gzip())
|
|
||||||
|
|
||||||
// default routes
|
// default routes
|
||||||
api := e.Group("/api")
|
api := e.Group("/api")
|
||||||
|
@ -129,3 +125,78 @@ func StaticDirectoryHandler(fileSystem fs.FS, disablePathUnescaping bool) echo.H
|
||||||
return c.FileFS(name, fileSystem)
|
return c.FileFS(name, fileSystem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bindStaticAdminUI registers the endpoints that serves the static admin UI.
|
||||||
|
func bindStaticAdminUI(app core.App, e *echo.Echo) error {
|
||||||
|
// serves /ui/dist/index.html file
|
||||||
|
// (explicit route is used to avoid conflicts with `RemoveTrailingSlash` middleware)
|
||||||
|
e.FileFS(
|
||||||
|
"/_",
|
||||||
|
"index.html",
|
||||||
|
ui.DistIndexHTML,
|
||||||
|
middleware.Gzip(),
|
||||||
|
installerRedirect(app),
|
||||||
|
)
|
||||||
|
|
||||||
|
// serves static files from the /ui/dist directory
|
||||||
|
// (similar to echo.StaticFS but with gzip middleware enabled)
|
||||||
|
e.GET(
|
||||||
|
"/_/*",
|
||||||
|
StaticDirectoryHandler(ui.DistDirFS, false),
|
||||||
|
middleware.Gzip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalAdminsCacheKey = "totalAdmins"
|
||||||
|
|
||||||
|
func updateTotalAdminsCache(app core.App) error {
|
||||||
|
total, err := app.Dao().TotalAdmins()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Cache().Set(totalAdminsCacheKey, total)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// installerRedirect redirects the user to the installer admin UI page
|
||||||
|
// when the application needs some preliminary configurations to be done.
|
||||||
|
func installerRedirect(app core.App) echo.MiddlewareFunc {
|
||||||
|
// keep totalAdminsCacheKey value up-to-date
|
||||||
|
app.OnAdminAfterCreateRequest().Add(func(data *core.AdminCreateEvent) error {
|
||||||
|
return updateTotalAdminsCache(app)
|
||||||
|
})
|
||||||
|
app.OnAdminAfterDeleteRequest().Add(func(data *core.AdminDeleteEvent) error {
|
||||||
|
return updateTotalAdminsCache(app)
|
||||||
|
})
|
||||||
|
|
||||||
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
// load into cache (if not already)
|
||||||
|
if !app.Cache().Has(totalAdminsCacheKey) {
|
||||||
|
if err := updateTotalAdminsCache(app); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
totalAdmins := cast.ToInt(app.Cache().Get(totalAdminsCacheKey))
|
||||||
|
|
||||||
|
_, hasInstallerParam := c.Request().URL.Query()["installer"]
|
||||||
|
|
||||||
|
if totalAdmins == 0 && !hasInstallerParam {
|
||||||
|
// redirect to the installer page
|
||||||
|
return c.Redirect(http.StatusTemporaryRedirect, "/_/?installer#")
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalAdmins != 0 && hasInstallerParam {
|
||||||
|
// redirect to the home page
|
||||||
|
return c.Redirect(http.StatusTemporaryRedirect, "/_/#/")
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -77,6 +77,28 @@ func RequireAdminAuth() echo.MiddlewareFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequireAdminAuthIfAny middleware requires a request to have
|
||||||
|
// a valid admin Authorization header set (aka. `Authorization: Admin ...`)
|
||||||
|
// ONLY if the application has at least 1 existing Admin model.
|
||||||
|
func RequireAdminAuthOnlyIfAny(app core.App) echo.MiddlewareFunc {
|
||||||
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
totalAdmins, err := app.Dao().TotalAdmins()
|
||||||
|
if err != nil {
|
||||||
|
return rest.NewBadRequestError("Failed to fetch admins info.", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
admin, _ := c.Get(ContextAdminKey).(*models.Admin)
|
||||||
|
|
||||||
|
if admin != nil || totalAdmins == 0 {
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rest.NewUnauthorizedError("The request requires admin authorization token to be set.", nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RequireAdminOrUserAuth middleware requires a request to have
|
// RequireAdminOrUserAuth middleware requires a request to have
|
||||||
// a valid admin or user Authorization header set
|
// a valid admin or user Authorization header set
|
||||||
// (aka. `Authorization: Admin ...` or `Authorization: User ...`).
|
// (aka. `Authorization: Admin ...` or `Authorization: User ...`).
|
||||||
|
|
|
@ -291,6 +291,125 @@ func TestRequireAdminAuth(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRequireAdminAuthOnlyIfAny(t *testing.T) {
|
||||||
|
scenarios := []tests.ApiScenario{
|
||||||
|
{
|
||||||
|
Name: "guest (while having at least 1 existing admin)",
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Url: "/my/test",
|
||||||
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
||||||
|
e.AddRoute(echo.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/my/test",
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
return c.String(200, "test123")
|
||||||
|
},
|
||||||
|
Middlewares: []echo.MiddlewareFunc{
|
||||||
|
apis.RequireAdminAuthOnlyIfAny(app),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ExpectedStatus: 401,
|
||||||
|
ExpectedContent: []string{`"data":{}`},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "guest (while having 0 existing admins)",
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Url: "/my/test",
|
||||||
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
||||||
|
// delete all admins
|
||||||
|
_, err := app.Dao().DB().NewQuery("DELETE FROM {{_admins}}").Execute()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.AddRoute(echo.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/my/test",
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
return c.String(200, "test123")
|
||||||
|
},
|
||||||
|
Middlewares: []echo.MiddlewareFunc{
|
||||||
|
apis.RequireAdminAuthOnlyIfAny(app),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ExpectedStatus: 200,
|
||||||
|
ExpectedContent: []string{"test123"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "expired/invalid token",
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Url: "/my/test",
|
||||||
|
RequestHeaders: map[string]string{
|
||||||
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTY0MTAxMzIwMH0.Gp_1b5WVhqjj2o3nJhNUlJmpdiwFLXN72LbMP-26gjA",
|
||||||
|
},
|
||||||
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
||||||
|
e.AddRoute(echo.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/my/test",
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
return c.String(200, "test123")
|
||||||
|
},
|
||||||
|
Middlewares: []echo.MiddlewareFunc{
|
||||||
|
apis.RequireAdminAuthOnlyIfAny(app),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ExpectedStatus: 401,
|
||||||
|
ExpectedContent: []string{`"data":{}`},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "valid user token",
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Url: "/my/test",
|
||||||
|
RequestHeaders: map[string]string{
|
||||||
|
"Authorization": "User eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjRkMDE5N2NjLTJiNGEtM2Y4My1hMjZiLWQ3N2JjODQyM2QzYyIsInR5cGUiOiJ1c2VyIiwiZXhwIjoxODkzNDc0MDAwfQ.Wq5ac1q1f5WntIzEngXk22ydMj-eFgvfSRg7dhmPKic",
|
||||||
|
},
|
||||||
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
||||||
|
e.AddRoute(echo.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/my/test",
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
return c.String(200, "test123")
|
||||||
|
},
|
||||||
|
Middlewares: []echo.MiddlewareFunc{
|
||||||
|
apis.RequireAdminAuthOnlyIfAny(app),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ExpectedStatus: 401,
|
||||||
|
ExpectedContent: []string{`"data":{}`},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "valid admin token",
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Url: "/my/test",
|
||||||
|
RequestHeaders: map[string]string{
|
||||||
|
"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
|
||||||
|
},
|
||||||
|
BeforeFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
|
||||||
|
e.AddRoute(echo.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/my/test",
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
return c.String(200, "test123")
|
||||||
|
},
|
||||||
|
Middlewares: []echo.MiddlewareFunc{
|
||||||
|
apis.RequireAdminAuthOnlyIfAny(app),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ExpectedStatus: 200,
|
||||||
|
ExpectedContent: []string{"test123"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
scenario.Test(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRequireAdminOrUserAuth(t *testing.T) {
|
func TestRequireAdminOrUserAuth(t *testing.T) {
|
||||||
scenarios := []tests.ApiScenario{
|
scenarios := []tests.ApiScenario{
|
||||||
{
|
{
|
||||||
|
|
93
cmd/serve.go
93
cmd/serve.go
|
@ -2,7 +2,6 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
@ -10,14 +9,10 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2"
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/go-ozzo/ozzo-validation/v4/is"
|
|
||||||
"github.com/labstack/echo/v5/middleware"
|
"github.com/labstack/echo/v5/middleware"
|
||||||
"github.com/pocketbase/pocketbase/apis"
|
"github.com/pocketbase/pocketbase/apis"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/forms"
|
|
||||||
"github.com/pocketbase/pocketbase/models"
|
|
||||||
"github.com/pocketbase/pocketbase/tools/migrate"
|
"github.com/pocketbase/pocketbase/tools/migrate"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/crypto/acme"
|
"golang.org/x/crypto/acme"
|
||||||
|
@ -35,18 +30,6 @@ func NewServeCommand(app core.App, showStartBanner bool) *cobra.Command {
|
||||||
Use: "serve",
|
Use: "serve",
|
||||||
Short: "Starts the web server (default to localhost:8090)",
|
Short: "Starts the web server (default to localhost:8090)",
|
||||||
Run: func(command *cobra.Command, args []string) {
|
Run: func(command *cobra.Command, args []string) {
|
||||||
router, err := apis.InitApi(app)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure cors
|
|
||||||
router.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
|
||||||
Skipper: middleware.DefaultSkipper,
|
|
||||||
AllowOrigins: allowedOrigins,
|
|
||||||
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
|
||||||
}))
|
|
||||||
|
|
||||||
// ensure that the latest migrations are applied before starting the server
|
// ensure that the latest migrations are applied before starting the server
|
||||||
if err := runMigrations(app); err != nil {
|
if err := runMigrations(app); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -61,19 +44,18 @@ func NewServeCommand(app core.App, showStartBanner bool) *cobra.Command {
|
||||||
color.Yellow("=====================================")
|
color.Yellow("=====================================")
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no admins are found, create the first one
|
router, err := apis.InitApi(app)
|
||||||
totalAdmins, err := app.Dao().TotalAdmins()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
panic(err)
|
||||||
return
|
|
||||||
}
|
|
||||||
if totalAdmins == 0 {
|
|
||||||
if err := promptCreateAdmin(app); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// configure cors
|
||||||
|
router.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||||
|
Skipper: middleware.DefaultSkipper,
|
||||||
|
AllowOrigins: allowedOrigins,
|
||||||
|
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
||||||
|
}))
|
||||||
|
|
||||||
// start http server
|
// start http server
|
||||||
// ---
|
// ---
|
||||||
mainAddr := httpAddr
|
mainAddr := httpAddr
|
||||||
|
@ -149,7 +131,7 @@ func NewServeCommand(app core.App, showStartBanner bool) *cobra.Command {
|
||||||
&httpsAddr,
|
&httpsAddr,
|
||||||
"https",
|
"https",
|
||||||
"",
|
"",
|
||||||
"api HTTPS server address (auto TLS via Let's Encrypt)\nthe incomming --http address traffic also will be redirected to this address",
|
"api HTTPS server address (auto TLS via Let's Encrypt)\nthe incoming --http address traffic also will be redirected to this address",
|
||||||
)
|
)
|
||||||
|
|
||||||
return command
|
return command
|
||||||
|
@ -171,58 +153,3 @@ func runMigrations(app core.App) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func promptCreateAdmin(app core.App) error {
|
|
||||||
color.White("-------------------------------------")
|
|
||||||
color.Cyan("Lets create your first admin account:")
|
|
||||||
color.White("-------------------------------------")
|
|
||||||
|
|
||||||
prompts := []*survey.Question{
|
|
||||||
{
|
|
||||||
Name: "Email",
|
|
||||||
Prompt: &survey.Input{Message: "Email:"},
|
|
||||||
Validate: func(val any) error {
|
|
||||||
if err := survey.Required(val); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := is.Email.Validate(val); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Password",
|
|
||||||
Prompt: &survey.Password{Message: "Pass (min 10 chars):"},
|
|
||||||
Validate: func(val any) error {
|
|
||||||
if str, ok := val.(string); !ok || len(str) < 10 {
|
|
||||||
return errors.New("The password must be at least 10 characters.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
result := struct {
|
|
||||||
Email string
|
|
||||||
Password string
|
|
||||||
}{}
|
|
||||||
if err := survey.Ask(prompts, &result); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
form := forms.NewAdminUpsert(app, &models.Admin{})
|
|
||||||
form.Email = result.Email
|
|
||||||
form.Password = result.Password
|
|
||||||
form.PasswordConfirm = result.Password
|
|
||||||
|
|
||||||
if err := form.Submit(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
color.Green("Successfully created admin %s!", result.Email)
|
|
||||||
fmt.Println("")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,8 +37,6 @@ func NewSmtpClient(
|
||||||
// SmtpClient defines a SMTP mail client structure that implements
|
// SmtpClient defines a SMTP mail client structure that implements
|
||||||
// `mailer.Mailer` interface.
|
// `mailer.Mailer` interface.
|
||||||
type SmtpClient struct {
|
type SmtpClient struct {
|
||||||
mail *mailyak.MailYak
|
|
||||||
|
|
||||||
host string
|
host string
|
||||||
port int
|
port int
|
||||||
username string
|
username string
|
||||||
|
|
1
ui/.env
1
ui/.env
|
@ -2,3 +2,4 @@
|
||||||
PB_BACKEND_URL = /
|
PB_BACKEND_URL = /
|
||||||
PB_PROFILE_COLLECTION = profiles
|
PB_PROFILE_COLLECTION = profiles
|
||||||
PB_RULES_SYNTAX_DOCS = https://pocketbase.io/docs/manage-collections#rules-filters-syntax
|
PB_RULES_SYNTAX_DOCS = https://pocketbase.io/docs/manage-collections#rules-filters-syntax
|
||||||
|
PB_INSTALLER_PARAM = installer
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
||||||
import{S as t,i as n,s as o,K as a}from"./index.0314b5be.js";function l(e){return a("/collections"),[]}class c extends t{constructor(s){super(),n(this,s,l,null,o,{})}}export{c as default};
|
|
|
@ -1,2 +0,0 @@
|
||||||
import{S as I,i as K,s as L,F as W,f as F,m as H,n as B,o as J,q as N,H as M,D as q,e as c,g as u,h as b,j as _,E as O,p as w,z,d as k,A as D,B as T,C as Q,k as U,v as V,I as X,y as E,J as Y,K as Z,G as S}from"./index.0314b5be.js";function G(f){let e,o,s;return{c(){e=q("for "),o=c("strong"),s=q(f[3]),u(o,"class","txt-nowrap")},m(l,t){b(l,e,t),b(l,o,t),_(o,s)},p(l,t){t&8&&O(s,l[3])},d(l){l&&w(e),l&&w(o)}}}function x(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0,t.autofocus=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[0]),t.focus(),p||(d=T(t,"input",f[6]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&1&&t.value!==n[0]&&S(t,n[0])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function ee(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password confirm"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[1]),p||(d=T(t,"input",f[7]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&2&&t.value!==n[1]&&S(t,n[1])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function te(f){let e,o,s,l,t,r,p,d,n,i,g,R,C,v,P,A,h,m=f[3]&&G(f);return r=new z({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),d=new z({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),{c(){e=c("form"),o=c("div"),s=c("h4"),l=q(`Reset your admin password
|
|
||||||
`),m&&m.c(),t=k(),F(r.$$.fragment),p=k(),F(d.$$.fragment),n=k(),i=c("button"),g=c("span"),g.textContent="Set new password",R=k(),C=c("div"),v=c("a"),v.textContent="Back to login",u(s,"class","m-b-xs"),u(o,"class","content txt-center m-b-sm"),u(g,"class","txt"),u(i,"type","submit"),u(i,"class","btn btn-lg btn-block"),i.disabled=f[2],D(i,"btn-loading",f[2]),u(e,"class","m-b-base"),u(v,"href","/login"),u(v,"class","link-hint"),u(C,"class","content txt-center")},m(a,$){b(a,e,$),_(e,o),_(o,s),_(s,l),m&&m.m(s,null),_(e,t),H(r,e,null),_(e,p),H(d,e,null),_(e,n),_(e,i),_(i,g),b(a,R,$),b(a,C,$),_(C,v),P=!0,A||(h=[T(e,"submit",Q(f[4])),U(V.call(null,v))],A=!0)},p(a,$){a[3]?m?m.p(a,$):(m=G(a),m.c(),m.m(s,null)):m&&(m.d(1),m=null);const j={};$&769&&(j.$$scope={dirty:$,ctx:a}),r.$set(j);const y={};$&770&&(y.$$scope={dirty:$,ctx:a}),d.$set(y),(!P||$&4)&&(i.disabled=a[2]),$&4&&D(i,"btn-loading",a[2])},i(a){P||(B(r.$$.fragment,a),B(d.$$.fragment,a),P=!0)},o(a){J(r.$$.fragment,a),J(d.$$.fragment,a),P=!1},d(a){a&&w(e),m&&m.d(),N(r),N(d),a&&w(R),a&&w(C),A=!1,X(h)}}}function se(f){let e,o;return e=new W({props:{$$slots:{default:[te]},$$scope:{ctx:f}}}),{c(){F(e.$$.fragment)},m(s,l){H(e,s,l),o=!0},p(s,[l]){const t={};l&527&&(t.$$scope={dirty:l,ctx:s}),e.$set(t)},i(s){o||(B(e.$$.fragment,s),o=!0)},o(s){J(e.$$.fragment,s),o=!1},d(s){N(e,s)}}}function le(f,e,o){let s,{params:l}=e,t="",r="",p=!1;async function d(){if(!p){o(2,p=!0);try{await E.Admins.confirmPasswordReset(l==null?void 0:l.token,t,r),Y("Successfully set a new admin password."),Z("/")}catch(g){E.errorResponseHandler(g)}o(2,p=!1)}}function n(){t=this.value,o(0,t)}function i(){r=this.value,o(1,r)}return f.$$set=g=>{"params"in g&&o(5,l=g.params)},f.$$.update=()=>{f.$$.dirty&32&&o(3,s=M.getJWTPayload(l==null?void 0:l.token).email||"")},[t,r,p,s,d,l,n,i]}class ae extends I{constructor(e){super(),K(this,e,le,se,L,{params:5})}}export{ae as default};
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
import{S as E,i as G,s as I,F as K,c as F,m as B,t as H,a as N,d as T,C as M,w as q,e as c,f as u,g as b,h as _,x as O,o as w,q as J,b as k,r as L,u as h,v as Q,j as U,l as V,A as X,p as W,B as Y,D as Z,z as S}from"./index.c63abb6b.js";function y(f){let e,o,s;return{c(){e=q("for "),o=c("strong"),s=q(f[3]),u(o,"class","txt-nowrap")},m(l,t){b(l,e,t),b(l,o,t),_(o,s)},p(l,t){t&8&&O(s,l[3])},d(l){l&&w(e),l&&w(o)}}}function x(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0,t.autofocus=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[0]),t.focus(),p||(d=h(t,"input",f[6]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&1&&t.value!==n[0]&&S(t,n[0])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function ee(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password confirm"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[1]),p||(d=h(t,"input",f[7]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&2&&t.value!==n[1]&&S(t,n[1])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function te(f){let e,o,s,l,t,r,p,d,n,i,g,R,C,v,P,A,j,m=f[3]&&y(f);return r=new J({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),d=new J({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),{c(){e=c("form"),o=c("div"),s=c("h4"),l=q(`Reset your admin password
|
||||||
|
`),m&&m.c(),t=k(),F(r.$$.fragment),p=k(),F(d.$$.fragment),n=k(),i=c("button"),g=c("span"),g.textContent="Set new password",R=k(),C=c("div"),v=c("a"),v.textContent="Back to login",u(s,"class","m-b-xs"),u(o,"class","content txt-center m-b-sm"),u(g,"class","txt"),u(i,"type","submit"),u(i,"class","btn btn-lg btn-block"),i.disabled=f[2],L(i,"btn-loading",f[2]),u(e,"class","m-b-base"),u(v,"href","/login"),u(v,"class","link-hint"),u(C,"class","content txt-center")},m(a,$){b(a,e,$),_(e,o),_(o,s),_(s,l),m&&m.m(s,null),_(e,t),B(r,e,null),_(e,p),B(d,e,null),_(e,n),_(e,i),_(i,g),b(a,R,$),b(a,C,$),_(C,v),P=!0,A||(j=[h(e,"submit",Q(f[4])),U(V.call(null,v))],A=!0)},p(a,$){a[3]?m?m.p(a,$):(m=y(a),m.c(),m.m(s,null)):m&&(m.d(1),m=null);const z={};$&769&&(z.$$scope={dirty:$,ctx:a}),r.$set(z);const D={};$&770&&(D.$$scope={dirty:$,ctx:a}),d.$set(D),(!P||$&4)&&(i.disabled=a[2]),$&4&&L(i,"btn-loading",a[2])},i(a){P||(H(r.$$.fragment,a),H(d.$$.fragment,a),P=!0)},o(a){N(r.$$.fragment,a),N(d.$$.fragment,a),P=!1},d(a){a&&w(e),m&&m.d(),T(r),T(d),a&&w(R),a&&w(C),A=!1,X(j)}}}function se(f){let e,o;return e=new K({props:{$$slots:{default:[te]},$$scope:{ctx:f}}}),{c(){F(e.$$.fragment)},m(s,l){B(e,s,l),o=!0},p(s,[l]){const t={};l&527&&(t.$$scope={dirty:l,ctx:s}),e.$set(t)},i(s){o||(H(e.$$.fragment,s),o=!0)},o(s){N(e.$$.fragment,s),o=!1},d(s){T(e,s)}}}function le(f,e,o){let s,{params:l}=e,t="",r="",p=!1;async function d(){if(!p){o(2,p=!0);try{await W.Admins.confirmPasswordReset(l==null?void 0:l.token,t,r),Y("Successfully set a new admin password."),Z("/")}catch(g){W.errorResponseHandler(g)}o(2,p=!1)}}function n(){t=this.value,o(0,t)}function i(){r=this.value,o(1,r)}return f.$$set=g=>{"params"in g&&o(5,l=g.params)},f.$$.update=()=>{f.$$.dirty&32&&o(3,s=M.getJWTPayload(l==null?void 0:l.token).email||"")},[t,r,p,s,d,l,n,i]}class ae extends E{constructor(e){super(),G(this,e,le,se,I,{params:5})}}export{ae as default};
|
|
@ -1,2 +1,2 @@
|
||||||
import{S,i as B,s as M,F as T,f as A,m as E,n as w,o as y,q as H,d as g,e as _,g as p,h as k,j as d,k as j,v as z,w as D,x as G,p as v,y as C,z as N,A as F,B as L,C as I,D as h,E as J,u as P,G as R}from"./index.0314b5be.js";function K(c){let e,s,n,l,t,o,f,m,i,a,b,u;return l=new N({props:{class:"form-field required",name:"email",$$slots:{default:[Q,({uniqueId:r})=>({5:r}),({uniqueId:r})=>r?32:0]},$$scope:{ctx:c}}}),{c(){e=_("form"),s=_("div"),s.innerHTML=`<h4 class="m-b-xs">Forgotten admin password</h4>
|
import{S as E,i as M,s as T,F as j,c as H,m as L,t as w,a as y,d as S,b as g,e as _,f as p,g as k,h as d,j as z,l as B,k as N,n as D,o as v,p as C,q as G,r as F,u as A,v as I,w as h,x as J,y as P,z as R}from"./index.c63abb6b.js";function K(c){let e,s,n,l,t,o,f,m,i,a,b,u;return l=new G({props:{class:"form-field required",name:"email",$$slots:{default:[Q,({uniqueId:r})=>({5:r}),({uniqueId:r})=>r?32:0]},$$scope:{ctx:c}}}),{c(){e=_("form"),s=_("div"),s.innerHTML=`<h4 class="m-b-xs">Forgotten admin password</h4>
|
||||||
<p>Enter the email associated with your account and we\u2019ll send you a recovery link:</p>`,n=g(),A(l.$$.fragment),t=g(),o=_("button"),f=_("i"),m=g(),i=_("span"),i.textContent="Send recovery link",p(s,"class","content txt-center m-b-sm"),p(f,"class","ri-mail-send-line"),p(i,"class","txt"),p(o,"type","submit"),p(o,"class","btn btn-lg btn-block"),o.disabled=c[1],F(o,"btn-loading",c[1]),p(e,"class","m-b-base")},m(r,$){k(r,e,$),d(e,s),d(e,n),E(l,e,null),d(e,t),d(e,o),d(o,f),d(o,m),d(o,i),a=!0,b||(u=L(e,"submit",I(c[3])),b=!0)},p(r,$){const q={};$&97&&(q.$$scope={dirty:$,ctx:r}),l.$set(q),(!a||$&2)&&(o.disabled=r[1]),$&2&&F(o,"btn-loading",r[1])},i(r){a||(w(l.$$.fragment,r),a=!0)},o(r){y(l.$$.fragment,r),a=!1},d(r){r&&v(e),H(l),b=!1,u()}}}function O(c){let e,s,n,l,t,o,f,m,i;return{c(){e=_("div"),s=_("div"),s.innerHTML='<i class="ri-checkbox-circle-line"></i>',n=g(),l=_("div"),t=_("p"),o=h("Check "),f=_("strong"),m=h(c[0]),i=h(" for the recovery link."),p(s,"class","icon"),p(f,"class","txt-nowrap"),p(l,"class","content"),p(e,"class","alert alert-success")},m(a,b){k(a,e,b),d(e,s),d(e,n),d(e,l),d(l,t),d(t,o),d(t,f),d(f,m),d(t,i)},p(a,b){b&1&&J(m,a[0])},i:P,o:P,d(a){a&&v(e)}}}function Q(c){let e,s,n,l,t,o,f,m;return{c(){e=_("label"),s=h("Email"),l=g(),t=_("input"),p(e,"for",n=c[5]),p(t,"type","email"),p(t,"id",o=c[5]),t.required=!0,t.autofocus=!0},m(i,a){k(i,e,a),d(e,s),k(i,l,a),k(i,t,a),R(t,c[0]),t.focus(),f||(m=L(t,"input",c[4]),f=!0)},p(i,a){a&32&&n!==(n=i[5])&&p(e,"for",n),a&32&&o!==(o=i[5])&&p(t,"id",o),a&1&&t.value!==i[0]&&R(t,i[0])},d(i){i&&v(e),i&&v(l),i&&v(t),f=!1,m()}}}function U(c){let e,s,n,l,t,o,f,m;const i=[O,K],a=[];function b(u,r){return u[2]?0:1}return e=b(c),s=a[e]=i[e](c),{c(){s.c(),n=g(),l=_("div"),t=_("a"),t.textContent="Back to login",p(t,"href","/login"),p(t,"class","link-hint"),p(l,"class","content txt-center")},m(u,r){a[e].m(u,r),k(u,n,r),k(u,l,r),d(l,t),o=!0,f||(m=j(z.call(null,t)),f=!0)},p(u,r){let $=e;e=b(u),e===$?a[e].p(u,r):(D(),y(a[$],1,1,()=>{a[$]=null}),G(),s=a[e],s?s.p(u,r):(s=a[e]=i[e](u),s.c()),w(s,1),s.m(n.parentNode,n))},i(u){o||(w(s),o=!0)},o(u){y(s),o=!1},d(u){a[e].d(u),u&&v(n),u&&v(l),f=!1,m()}}}function V(c){let e,s;return e=new T({props:{$$slots:{default:[U]},$$scope:{ctx:c}}}),{c(){A(e.$$.fragment)},m(n,l){E(e,n,l),s=!0},p(n,[l]){const t={};l&71&&(t.$$scope={dirty:l,ctx:n}),e.$set(t)},i(n){s||(w(e.$$.fragment,n),s=!0)},o(n){y(e.$$.fragment,n),s=!1},d(n){H(e,n)}}}function W(c,e,s){let n="",l=!1,t=!1;async function o(){if(!l){s(1,l=!0);try{await C.Admins.requestPasswordReset(n),s(2,t=!0)}catch(m){C.errorResponseHandler(m)}s(1,l=!1)}}function f(){n=this.value,s(0,n)}return[n,l,t,o,f]}class Y extends S{constructor(e){super(),B(this,e,W,V,M,{})}}export{Y as default};
|
<p>Enter the email associated with your account and we\u2019ll send you a recovery link:</p>`,n=g(),H(l.$$.fragment),t=g(),o=_("button"),f=_("i"),m=g(),i=_("span"),i.textContent="Send recovery link",p(s,"class","content txt-center m-b-sm"),p(f,"class","ri-mail-send-line"),p(i,"class","txt"),p(o,"type","submit"),p(o,"class","btn btn-lg btn-block"),o.disabled=c[1],F(o,"btn-loading",c[1]),p(e,"class","m-b-base")},m(r,$){k(r,e,$),d(e,s),d(e,n),L(l,e,null),d(e,t),d(e,o),d(o,f),d(o,m),d(o,i),a=!0,b||(u=A(e,"submit",I(c[3])),b=!0)},p(r,$){const q={};$&97&&(q.$$scope={dirty:$,ctx:r}),l.$set(q),(!a||$&2)&&(o.disabled=r[1]),$&2&&F(o,"btn-loading",r[1])},i(r){a||(w(l.$$.fragment,r),a=!0)},o(r){y(l.$$.fragment,r),a=!1},d(r){r&&v(e),S(l),b=!1,u()}}}function O(c){let e,s,n,l,t,o,f,m,i;return{c(){e=_("div"),s=_("div"),s.innerHTML='<i class="ri-checkbox-circle-line"></i>',n=g(),l=_("div"),t=_("p"),o=h("Check "),f=_("strong"),m=h(c[0]),i=h(" for the recovery link."),p(s,"class","icon"),p(f,"class","txt-nowrap"),p(l,"class","content"),p(e,"class","alert alert-success")},m(a,b){k(a,e,b),d(e,s),d(e,n),d(e,l),d(l,t),d(t,o),d(t,f),d(f,m),d(t,i)},p(a,b){b&1&&J(m,a[0])},i:P,o:P,d(a){a&&v(e)}}}function Q(c){let e,s,n,l,t,o,f,m;return{c(){e=_("label"),s=h("Email"),l=g(),t=_("input"),p(e,"for",n=c[5]),p(t,"type","email"),p(t,"id",o=c[5]),t.required=!0,t.autofocus=!0},m(i,a){k(i,e,a),d(e,s),k(i,l,a),k(i,t,a),R(t,c[0]),t.focus(),f||(m=A(t,"input",c[4]),f=!0)},p(i,a){a&32&&n!==(n=i[5])&&p(e,"for",n),a&32&&o!==(o=i[5])&&p(t,"id",o),a&1&&t.value!==i[0]&&R(t,i[0])},d(i){i&&v(e),i&&v(l),i&&v(t),f=!1,m()}}}function U(c){let e,s,n,l,t,o,f,m;const i=[O,K],a=[];function b(u,r){return u[2]?0:1}return e=b(c),s=a[e]=i[e](c),{c(){s.c(),n=g(),l=_("div"),t=_("a"),t.textContent="Back to login",p(t,"href","/login"),p(t,"class","link-hint"),p(l,"class","content txt-center")},m(u,r){a[e].m(u,r),k(u,n,r),k(u,l,r),d(l,t),o=!0,f||(m=z(B.call(null,t)),f=!0)},p(u,r){let $=e;e=b(u),e===$?a[e].p(u,r):(N(),y(a[$],1,1,()=>{a[$]=null}),D(),s=a[e],s?s.p(u,r):(s=a[e]=i[e](u),s.c()),w(s,1),s.m(n.parentNode,n))},i(u){o||(w(s),o=!0)},o(u){y(s),o=!1},d(u){a[e].d(u),u&&v(n),u&&v(l),f=!1,m()}}}function V(c){let e,s;return e=new j({props:{$$slots:{default:[U]},$$scope:{ctx:c}}}),{c(){H(e.$$.fragment)},m(n,l){L(e,n,l),s=!0},p(n,[l]){const t={};l&71&&(t.$$scope={dirty:l,ctx:n}),e.$set(t)},i(n){s||(w(e.$$.fragment,n),s=!0)},o(n){y(e.$$.fragment,n),s=!1},d(n){S(e,n)}}}function W(c,e,s){let n="",l=!1,t=!1;async function o(){if(!l){s(1,l=!0);try{await C.Admins.requestPasswordReset(n),s(2,t=!0)}catch(m){C.errorResponseHandler(m)}s(1,l=!1)}}function f(){n=this.value,s(0,n)}return[n,l,t,o,f]}class Y extends E{constructor(e){super(),M(this,e,W,V,T,{})}}export{Y as default};
|
|
@ -1,4 +1,4 @@
|
||||||
import{S as z,i as A,s as B,F as D,f as S,m as U,n as $,o as v,q as j,H as G,L as J,h as _,w as M,x as N,p as b,y as P,D as y,e as m,g as d,j as g,E as R,z as W,d as C,A as F,B as E,C as Y,u as h,G as L}from"./index.0314b5be.js";function I(r){let e,s,t,l,n,o,c,a,i,u,k,q,p=r[3]&&T(r);return o=new W({props:{class:"form-field required",name:"password",$$slots:{default:[O,({uniqueId:f})=>({8:f}),({uniqueId:f})=>f?256:0]},$$scope:{ctx:r}}}),{c(){e=m("form"),s=m("div"),t=m("h4"),l=y(`Type your password to confirm changing your email address
|
import{S as J,i as M,s as N,F as R,c as S,m as U,t as $,a as v,d as z,C as W,E as Y,g as _,k as j,n as A,o as b,p as F,w as y,e as m,f as d,h as k,x as B,q as D,b as C,r as H,u as E,v as G,y as h,z as T}from"./index.c63abb6b.js";function I(r){let e,s,t,l,n,o,c,a,i,u,g,q,p=r[3]&&L(r);return o=new D({props:{class:"form-field required",name:"password",$$slots:{default:[O,({uniqueId:f})=>({8:f}),({uniqueId:f})=>f?256:0]},$$scope:{ctx:r}}}),{c(){e=m("form"),s=m("div"),t=m("h4"),l=y(`Type your password to confirm changing your email address
|
||||||
`),p&&p.c(),n=C(),S(o.$$.fragment),c=C(),a=m("button"),i=m("span"),i.textContent="Confirm new email",d(t,"class","m-b-xs"),d(s,"class","content txt-center m-b-sm"),d(i,"class","txt"),d(a,"type","submit"),d(a,"class","btn btn-lg btn-block"),a.disabled=r[1],F(a,"btn-loading",r[1])},m(f,w){_(f,e,w),g(e,s),g(s,t),g(t,l),p&&p.m(t,null),g(e,n),U(o,e,null),g(e,c),g(e,a),g(a,i),u=!0,k||(q=E(e,"submit",Y(r[4])),k=!0)},p(f,w){f[3]?p?p.p(f,w):(p=T(f),p.c(),p.m(t,null)):p&&(p.d(1),p=null);const H={};w&769&&(H.$$scope={dirty:w,ctx:f}),o.$set(H),(!u||w&2)&&(a.disabled=f[1]),w&2&&F(a,"btn-loading",f[1])},i(f){u||($(o.$$.fragment,f),u=!0)},o(f){v(o.$$.fragment,f),u=!1},d(f){f&&b(e),p&&p.d(),j(o),k=!1,q()}}}function K(r){let e,s,t,l,n;return{c(){e=m("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div>
|
`),p&&p.c(),n=C(),S(o.$$.fragment),c=C(),a=m("button"),i=m("span"),i.textContent="Confirm new email",d(t,"class","m-b-xs"),d(s,"class","content txt-center m-b-sm"),d(i,"class","txt"),d(a,"type","submit"),d(a,"class","btn btn-lg btn-block"),a.disabled=r[1],H(a,"btn-loading",r[1])},m(f,w){_(f,e,w),k(e,s),k(s,t),k(t,l),p&&p.m(t,null),k(e,n),U(o,e,null),k(e,c),k(e,a),k(a,i),u=!0,g||(q=E(e,"submit",G(r[4])),g=!0)},p(f,w){f[3]?p?p.p(f,w):(p=L(f),p.c(),p.m(t,null)):p&&(p.d(1),p=null);const P={};w&769&&(P.$$scope={dirty:w,ctx:f}),o.$set(P),(!u||w&2)&&(a.disabled=f[1]),w&2&&H(a,"btn-loading",f[1])},i(f){u||($(o.$$.fragment,f),u=!0)},o(f){v(o.$$.fragment,f),u=!1},d(f){f&&b(e),p&&p.d(),z(o),g=!1,q()}}}function K(r){let e,s,t,l,n;return{c(){e=m("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div>
|
||||||
<div class="content txt-bold"><p>Email address changed</p>
|
<div class="content txt-bold"><p>Email address changed</p>
|
||||||
<p>You can now sign in with your new email address.</p></div>`,s=C(),t=m("button"),t.textContent="Close",d(e,"class","alert alert-success"),d(t,"type","button"),d(t,"class","btn btn-secondary btn-block")},m(o,c){_(o,e,c),_(o,s,c),_(o,t,c),l||(n=E(t,"click",r[6]),l=!0)},p:h,i:h,o:h,d(o){o&&b(e),o&&b(s),o&&b(t),l=!1,n()}}}function T(r){let e,s,t;return{c(){e=y("to "),s=m("strong"),t=y(r[3]),d(s,"class","txt-nowrap")},m(l,n){_(l,e,n),_(l,s,n),g(s,t)},p(l,n){n&8&&R(t,l[3])},d(l){l&&b(e),l&&b(s)}}}function O(r){let e,s,t,l,n,o,c,a;return{c(){e=m("label"),s=y("Password"),l=C(),n=m("input"),d(e,"for",t=r[8]),d(n,"type","password"),d(n,"id",o=r[8]),n.required=!0,n.autofocus=!0},m(i,u){_(i,e,u),g(e,s),_(i,l,u),_(i,n,u),L(n,r[0]),n.focus(),c||(a=E(n,"input",r[7]),c=!0)},p(i,u){u&256&&t!==(t=i[8])&&d(e,"for",t),u&256&&o!==(o=i[8])&&d(n,"id",o),u&1&&n.value!==i[0]&&L(n,i[0])},d(i){i&&b(e),i&&b(l),i&&b(n),c=!1,a()}}}function Q(r){let e,s,t,l;const n=[K,I],o=[];function c(a,i){return a[2]?0:1}return e=c(r),s=o[e]=n[e](r),{c(){s.c(),t=J()},m(a,i){o[e].m(a,i),_(a,t,i),l=!0},p(a,i){let u=e;e=c(a),e===u?o[e].p(a,i):(M(),v(o[u],1,1,()=>{o[u]=null}),N(),s=o[e],s?s.p(a,i):(s=o[e]=n[e](a),s.c()),$(s,1),s.m(t.parentNode,t))},i(a){l||($(s),l=!0)},o(a){v(s),l=!1},d(a){o[e].d(a),a&&b(t)}}}function V(r){let e,s;return e=new D({props:{nobranding:!0,$$slots:{default:[Q]},$$scope:{ctx:r}}}),{c(){S(e.$$.fragment)},m(t,l){U(e,t,l),s=!0},p(t,[l]){const n={};l&527&&(n.$$scope={dirty:l,ctx:t}),e.$set(n)},i(t){s||($(e.$$.fragment,t),s=!0)},o(t){v(e.$$.fragment,t),s=!1},d(t){j(e,t)}}}function X(r,e,s){let t,{params:l}=e,n="",o=!1,c=!1;async function a(){if(!o){s(1,o=!0);try{await P.Users.confirmEmailChange(l==null?void 0:l.token,n),s(2,c=!0)}catch(k){P.errorResponseHandler(k)}s(1,o=!1)}}const i=()=>window.close();function u(){n=this.value,s(0,n)}return r.$$set=k=>{"params"in k&&s(5,l=k.params)},r.$$.update=()=>{r.$$.dirty&32&&s(3,t=G.getJWTPayload(l==null?void 0:l.token).newEmail||"")},[n,o,c,t,a,l,i,u]}class x extends z{constructor(e){super(),A(this,e,X,V,B,{params:5})}}export{x as default};
|
<p>You can now sign in with your new email address.</p></div>`,s=C(),t=m("button"),t.textContent="Close",d(e,"class","alert alert-success"),d(t,"type","button"),d(t,"class","btn btn-secondary btn-block")},m(o,c){_(o,e,c),_(o,s,c),_(o,t,c),l||(n=E(t,"click",r[6]),l=!0)},p:h,i:h,o:h,d(o){o&&b(e),o&&b(s),o&&b(t),l=!1,n()}}}function L(r){let e,s,t;return{c(){e=y("to "),s=m("strong"),t=y(r[3]),d(s,"class","txt-nowrap")},m(l,n){_(l,e,n),_(l,s,n),k(s,t)},p(l,n){n&8&&B(t,l[3])},d(l){l&&b(e),l&&b(s)}}}function O(r){let e,s,t,l,n,o,c,a;return{c(){e=m("label"),s=y("Password"),l=C(),n=m("input"),d(e,"for",t=r[8]),d(n,"type","password"),d(n,"id",o=r[8]),n.required=!0,n.autofocus=!0},m(i,u){_(i,e,u),k(e,s),_(i,l,u),_(i,n,u),T(n,r[0]),n.focus(),c||(a=E(n,"input",r[7]),c=!0)},p(i,u){u&256&&t!==(t=i[8])&&d(e,"for",t),u&256&&o!==(o=i[8])&&d(n,"id",o),u&1&&n.value!==i[0]&&T(n,i[0])},d(i){i&&b(e),i&&b(l),i&&b(n),c=!1,a()}}}function Q(r){let e,s,t,l;const n=[K,I],o=[];function c(a,i){return a[2]?0:1}return e=c(r),s=o[e]=n[e](r),{c(){s.c(),t=Y()},m(a,i){o[e].m(a,i),_(a,t,i),l=!0},p(a,i){let u=e;e=c(a),e===u?o[e].p(a,i):(j(),v(o[u],1,1,()=>{o[u]=null}),A(),s=o[e],s?s.p(a,i):(s=o[e]=n[e](a),s.c()),$(s,1),s.m(t.parentNode,t))},i(a){l||($(s),l=!0)},o(a){v(s),l=!1},d(a){o[e].d(a),a&&b(t)}}}function V(r){let e,s;return e=new R({props:{nobranding:!0,$$slots:{default:[Q]},$$scope:{ctx:r}}}),{c(){S(e.$$.fragment)},m(t,l){U(e,t,l),s=!0},p(t,[l]){const n={};l&527&&(n.$$scope={dirty:l,ctx:t}),e.$set(n)},i(t){s||($(e.$$.fragment,t),s=!0)},o(t){v(e.$$.fragment,t),s=!1},d(t){z(e,t)}}}function X(r,e,s){let t,{params:l}=e,n="",o=!1,c=!1;async function a(){if(!o){s(1,o=!0);try{await F.Users.confirmEmailChange(l==null?void 0:l.token,n),s(2,c=!0)}catch(g){F.errorResponseHandler(g)}s(1,o=!1)}}const i=()=>window.close();function u(){n=this.value,s(0,n)}return r.$$set=g=>{"params"in g&&s(5,l=g.params)},r.$$.update=()=>{r.$$.dirty&32&&s(3,t=W.getJWTPayload(l==null?void 0:l.token).newEmail||"")},[n,o,c,t,a,l,i,u]}class x extends J{constructor(e){super(),M(this,e,X,V,N,{params:5})}}export{x as default};
|
|
@ -0,0 +1,4 @@
|
||||||
|
import{S as W,i as Y,s as j,F as A,c as H,m as N,t as P,a as q,d as S,C as B,E as D,g as _,k as G,n as I,o as m,p as z,w as y,e as b,h as w,x as K,q as E,b as C,f as c,r as J,u as h,v as O,y as F,z as R}from"./index.c63abb6b.js";function Q(i){let e,l,t,n,s,o,p,a,r,u,v,g,k,L,d=i[4]&&M(i);return o=new E({props:{class:"form-field required",name:"password",$$slots:{default:[X,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:i}}}),a=new E({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[Z,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:i}}}),{c(){e=b("form"),l=b("div"),t=b("h4"),n=y(`Reset your user password
|
||||||
|
`),d&&d.c(),s=C(),H(o.$$.fragment),p=C(),H(a.$$.fragment),r=C(),u=b("button"),v=b("span"),v.textContent="Set new password",c(t,"class","m-b-xs"),c(l,"class","content txt-center m-b-sm"),c(v,"class","txt"),c(u,"type","submit"),c(u,"class","btn btn-lg btn-block"),u.disabled=i[2],J(u,"btn-loading",i[2])},m(f,$){_(f,e,$),w(e,l),w(l,t),w(t,n),d&&d.m(t,null),w(e,s),N(o,e,null),w(e,p),N(a,e,null),w(e,r),w(e,u),w(u,v),g=!0,k||(L=h(e,"submit",O(i[5])),k=!0)},p(f,$){f[4]?d?d.p(f,$):(d=M(f),d.c(),d.m(t,null)):d&&(d.d(1),d=null);const T={};$&3073&&(T.$$scope={dirty:$,ctx:f}),o.$set(T);const U={};$&3074&&(U.$$scope={dirty:$,ctx:f}),a.$set(U),(!g||$&4)&&(u.disabled=f[2]),$&4&&J(u,"btn-loading",f[2])},i(f){g||(P(o.$$.fragment,f),P(a.$$.fragment,f),g=!0)},o(f){q(o.$$.fragment,f),q(a.$$.fragment,f),g=!1},d(f){f&&m(e),d&&d.d(),S(o),S(a),k=!1,L()}}}function V(i){let e,l,t,n,s;return{c(){e=b("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div>
|
||||||
|
<div class="content txt-bold"><p>Password changed</p>
|
||||||
|
<p>You can now sign in with your new password.</p></div>`,l=C(),t=b("button"),t.textContent="Close",c(e,"class","alert alert-success"),c(t,"type","button"),c(t,"class","btn btn-secondary btn-block")},m(o,p){_(o,e,p),_(o,l,p),_(o,t,p),n||(s=h(t,"click",i[7]),n=!0)},p:F,i:F,o:F,d(o){o&&m(e),o&&m(l),o&&m(t),n=!1,s()}}}function M(i){let e,l,t;return{c(){e=y("for "),l=b("strong"),t=y(i[4])},m(n,s){_(n,e,s),_(n,l,s),w(l,t)},p(n,s){s&16&&K(t,n[4])},d(n){n&&m(e),n&&m(l)}}}function X(i){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password"),n=C(),s=b("input"),c(e,"for",t=i[10]),c(s,"type","password"),c(s,"id",o=i[10]),s.required=!0,s.autofocus=!0},m(r,u){_(r,e,u),w(e,l),_(r,n,u),_(r,s,u),R(s,i[0]),s.focus(),p||(a=h(s,"input",i[8]),p=!0)},p(r,u){u&1024&&t!==(t=r[10])&&c(e,"for",t),u&1024&&o!==(o=r[10])&&c(s,"id",o),u&1&&s.value!==r[0]&&R(s,r[0])},d(r){r&&m(e),r&&m(n),r&&m(s),p=!1,a()}}}function Z(i){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password confirm"),n=C(),s=b("input"),c(e,"for",t=i[10]),c(s,"type","password"),c(s,"id",o=i[10]),s.required=!0},m(r,u){_(r,e,u),w(e,l),_(r,n,u),_(r,s,u),R(s,i[1]),p||(a=h(s,"input",i[9]),p=!0)},p(r,u){u&1024&&t!==(t=r[10])&&c(e,"for",t),u&1024&&o!==(o=r[10])&&c(s,"id",o),u&2&&s.value!==r[1]&&R(s,r[1])},d(r){r&&m(e),r&&m(n),r&&m(s),p=!1,a()}}}function x(i){let e,l,t,n;const s=[V,Q],o=[];function p(a,r){return a[3]?0:1}return e=p(i),l=o[e]=s[e](i),{c(){l.c(),t=D()},m(a,r){o[e].m(a,r),_(a,t,r),n=!0},p(a,r){let u=e;e=p(a),e===u?o[e].p(a,r):(G(),q(o[u],1,1,()=>{o[u]=null}),I(),l=o[e],l?l.p(a,r):(l=o[e]=s[e](a),l.c()),P(l,1),l.m(t.parentNode,t))},i(a){n||(P(l),n=!0)},o(a){q(l),n=!1},d(a){o[e].d(a),a&&m(t)}}}function ee(i){let e,l;return e=new A({props:{nobranding:!0,$$slots:{default:[x]},$$scope:{ctx:i}}}),{c(){H(e.$$.fragment)},m(t,n){N(e,t,n),l=!0},p(t,[n]){const s={};n&2079&&(s.$$scope={dirty:n,ctx:t}),e.$set(s)},i(t){l||(P(e.$$.fragment,t),l=!0)},o(t){q(e.$$.fragment,t),l=!1},d(t){S(e,t)}}}function te(i,e,l){let t,{params:n}=e,s="",o="",p=!1,a=!1;async function r(){if(!p){l(2,p=!0);try{await z.Users.confirmPasswordReset(n==null?void 0:n.token,s,o),l(3,a=!0)}catch(k){z.errorResponseHandler(k)}l(2,p=!1)}}const u=()=>window.close();function v(){s=this.value,l(0,s)}function g(){o=this.value,l(1,o)}return i.$$set=k=>{"params"in k&&l(6,n=k.params)},i.$$.update=()=>{i.$$.dirty&64&&l(4,t=B.getJWTPayload(n==null?void 0:n.token).email||"")},[s,o,p,a,t,r,n,u,v,g]}class le extends W{constructor(e){super(),Y(this,e,te,ee,j,{params:6})}}export{le as default};
|
|
@ -1,4 +0,0 @@
|
||||||
import{S as D,i as E,s as G,F as J,f as F,m as L,n as P,o as q,q as N,H as M,L as W,h as _,w as Y,x as I,p as m,y as j,D as y,e as b,j as w,E as K,z,d as C,g as c,A,B as R,C as O,u as h,G as H}from"./index.0314b5be.js";function Q(r){let e,l,t,n,s,o,p,a,i,u,v,g,k,S,d=r[4]&&B(r);return o=new z({props:{class:"form-field required",name:"password",$$slots:{default:[X,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:r}}}),a=new z({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[Z,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:r}}}),{c(){e=b("form"),l=b("div"),t=b("h4"),n=y(`Reset your user password
|
|
||||||
`),d&&d.c(),s=C(),F(o.$$.fragment),p=C(),F(a.$$.fragment),i=C(),u=b("button"),v=b("span"),v.textContent="Set new password",c(t,"class","m-b-xs"),c(l,"class","content txt-center m-b-sm"),c(v,"class","txt"),c(u,"type","submit"),c(u,"class","btn btn-lg btn-block"),u.disabled=r[2],A(u,"btn-loading",r[2])},m(f,$){_(f,e,$),w(e,l),w(l,t),w(t,n),d&&d.m(t,null),w(e,s),L(o,e,null),w(e,p),L(a,e,null),w(e,i),w(e,u),w(u,v),g=!0,k||(S=R(e,"submit",O(r[5])),k=!0)},p(f,$){f[4]?d?d.p(f,$):(d=B(f),d.c(),d.m(t,null)):d&&(d.d(1),d=null);const T={};$&3073&&(T.$$scope={dirty:$,ctx:f}),o.$set(T);const U={};$&3074&&(U.$$scope={dirty:$,ctx:f}),a.$set(U),(!g||$&4)&&(u.disabled=f[2]),$&4&&A(u,"btn-loading",f[2])},i(f){g||(P(o.$$.fragment,f),P(a.$$.fragment,f),g=!0)},o(f){q(o.$$.fragment,f),q(a.$$.fragment,f),g=!1},d(f){f&&m(e),d&&d.d(),N(o),N(a),k=!1,S()}}}function V(r){let e,l,t,n,s;return{c(){e=b("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div>
|
|
||||||
<div class="content txt-bold"><p>Password changed</p>
|
|
||||||
<p>You can now sign in with your new password.</p></div>`,l=C(),t=b("button"),t.textContent="Close",c(e,"class","alert alert-success"),c(t,"type","button"),c(t,"class","btn btn-secondary btn-block")},m(o,p){_(o,e,p),_(o,l,p),_(o,t,p),n||(s=R(t,"click",r[7]),n=!0)},p:h,i:h,o:h,d(o){o&&m(e),o&&m(l),o&&m(t),n=!1,s()}}}function B(r){let e,l,t;return{c(){e=y("for "),l=b("strong"),t=y(r[4])},m(n,s){_(n,e,s),_(n,l,s),w(l,t)},p(n,s){s&16&&K(t,n[4])},d(n){n&&m(e),n&&m(l)}}}function X(r){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password"),n=C(),s=b("input"),c(e,"for",t=r[10]),c(s,"type","password"),c(s,"id",o=r[10]),s.required=!0,s.autofocus=!0},m(i,u){_(i,e,u),w(e,l),_(i,n,u),_(i,s,u),H(s,r[0]),s.focus(),p||(a=R(s,"input",r[8]),p=!0)},p(i,u){u&1024&&t!==(t=i[10])&&c(e,"for",t),u&1024&&o!==(o=i[10])&&c(s,"id",o),u&1&&s.value!==i[0]&&H(s,i[0])},d(i){i&&m(e),i&&m(n),i&&m(s),p=!1,a()}}}function Z(r){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password confirm"),n=C(),s=b("input"),c(e,"for",t=r[10]),c(s,"type","password"),c(s,"id",o=r[10]),s.required=!0},m(i,u){_(i,e,u),w(e,l),_(i,n,u),_(i,s,u),H(s,r[1]),p||(a=R(s,"input",r[9]),p=!0)},p(i,u){u&1024&&t!==(t=i[10])&&c(e,"for",t),u&1024&&o!==(o=i[10])&&c(s,"id",o),u&2&&s.value!==i[1]&&H(s,i[1])},d(i){i&&m(e),i&&m(n),i&&m(s),p=!1,a()}}}function x(r){let e,l,t,n;const s=[V,Q],o=[];function p(a,i){return a[3]?0:1}return e=p(r),l=o[e]=s[e](r),{c(){l.c(),t=W()},m(a,i){o[e].m(a,i),_(a,t,i),n=!0},p(a,i){let u=e;e=p(a),e===u?o[e].p(a,i):(Y(),q(o[u],1,1,()=>{o[u]=null}),I(),l=o[e],l?l.p(a,i):(l=o[e]=s[e](a),l.c()),P(l,1),l.m(t.parentNode,t))},i(a){n||(P(l),n=!0)},o(a){q(l),n=!1},d(a){o[e].d(a),a&&m(t)}}}function ee(r){let e,l;return e=new J({props:{nobranding:!0,$$slots:{default:[x]},$$scope:{ctx:r}}}),{c(){F(e.$$.fragment)},m(t,n){L(e,t,n),l=!0},p(t,[n]){const s={};n&2079&&(s.$$scope={dirty:n,ctx:t}),e.$set(s)},i(t){l||(P(e.$$.fragment,t),l=!0)},o(t){q(e.$$.fragment,t),l=!1},d(t){N(e,t)}}}function te(r,e,l){let t,{params:n}=e,s="",o="",p=!1,a=!1;async function i(){if(!p){l(2,p=!0);try{await j.Users.confirmPasswordReset(n==null?void 0:n.token,s,o),l(3,a=!0)}catch(k){j.errorResponseHandler(k)}l(2,p=!1)}}const u=()=>window.close();function v(){s=this.value,l(0,s)}function g(){o=this.value,l(1,o)}return r.$$set=k=>{"params"in k&&l(6,n=k.params)},r.$$.update=()=>{r.$$.dirty&64&&l(4,t=M.getJWTPayload(n==null?void 0:n.token).email||"")},[s,o,p,a,t,i,n,u,v,g]}class le extends D{constructor(e){super(),E(this,e,te,ee,G,{params:6})}}export{le as default};
|
|
|
@ -1,3 +1,3 @@
|
||||||
import{S as k,i as v,s as y,F as w,f as x,m as C,n as g,o as L,q as $,y as H,L as M,h as r,p as a,e as u,d as m,g as f,B as _,u as p}from"./index.0314b5be.js";function P(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-error-warning-line"></i></div>
|
import{S as k,i as v,s as y,F as w,c as x,m as C,t as g,a as $,d as L,p as H,E as M,g as r,o as a,e as u,b as m,f,u as _,y as p}from"./index.c63abb6b.js";function P(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-error-warning-line"></i></div>
|
||||||
<div class="content txt-bold"><p>Invalid or expired verification token.</p></div>`,s=m(),e=u("button"),e.textContent="Close",f(t,"class","alert alert-danger"),f(e,"type","button"),f(e,"class","btn btn-secondary btn-block")},m(l,c){r(l,t,c),r(l,s,c),r(l,e,c),n||(i=_(e,"click",o[4]),n=!0)},p,d(l){l&&a(t),l&&a(s),l&&a(e),n=!1,i()}}}function S(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div>
|
<div class="content txt-bold"><p>Invalid or expired verification token.</p></div>`,s=m(),e=u("button"),e.textContent="Close",f(t,"class","alert alert-danger"),f(e,"type","button"),f(e,"class","btn btn-secondary btn-block")},m(l,c){r(l,t,c),r(l,s,c),r(l,e,c),n||(i=_(e,"click",o[4]),n=!0)},p,d(l){l&&a(t),l&&a(s),l&&a(e),n=!1,i()}}}function S(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div>
|
||||||
<div class="content txt-bold"><p>Successfully verified email address.</p></div>`,s=m(),e=u("button"),e.textContent="Close",f(t,"class","alert alert-success"),f(e,"type","button"),f(e,"class","btn btn-secondary btn-block")},m(l,c){r(l,t,c),r(l,s,c),r(l,e,c),n||(i=_(e,"click",o[3]),n=!0)},p,d(l){l&&a(t),l&&a(s),l&&a(e),n=!1,i()}}}function T(o){let t;return{c(){t=u("div"),t.innerHTML='<div class="loader loader-lg"><em>Please wait...</em></div>',f(t,"class","txt-center")},m(s,e){r(s,t,e)},p,d(s){s&&a(t)}}}function q(o){let t;function s(i,l){return i[1]?T:i[0]?S:P}let e=s(o),n=e(o);return{c(){n.c(),t=M()},m(i,l){n.m(i,l),r(i,t,l)},p(i,l){e===(e=s(i))&&n?n.p(i,l):(n.d(1),n=e(i),n&&(n.c(),n.m(t.parentNode,t)))},d(i){n.d(i),i&&a(t)}}}function F(o){let t,s;return t=new w({props:{nobranding:!0,$$slots:{default:[q]},$$scope:{ctx:o}}}),{c(){x(t.$$.fragment)},m(e,n){C(t,e,n),s=!0},p(e,[n]){const i={};n&67&&(i.$$scope={dirty:n,ctx:e}),t.$set(i)},i(e){s||(g(t.$$.fragment,e),s=!0)},o(e){L(t.$$.fragment,e),s=!1},d(e){$(t,e)}}}function U(o,t,s){let{params:e}=t,n=!1,i=!1;l();async function l(){s(1,i=!0);try{await H.Users.confirmVerification(e==null?void 0:e.token),s(0,n=!0)}catch(d){console.warn(d),s(0,n=!1)}s(1,i=!1)}const c=()=>window.close(),b=()=>window.close();return o.$$set=d=>{"params"in d&&s(2,e=d.params)},[n,i,e,c,b]}class B extends k{constructor(t){super(),v(this,t,U,F,y,{params:2})}}export{B as default};
|
<div class="content txt-bold"><p>Successfully verified email address.</p></div>`,s=m(),e=u("button"),e.textContent="Close",f(t,"class","alert alert-success"),f(e,"type","button"),f(e,"class","btn btn-secondary btn-block")},m(l,c){r(l,t,c),r(l,s,c),r(l,e,c),n||(i=_(e,"click",o[3]),n=!0)},p,d(l){l&&a(t),l&&a(s),l&&a(e),n=!1,i()}}}function T(o){let t;return{c(){t=u("div"),t.innerHTML='<div class="loader loader-lg"><em>Please wait...</em></div>',f(t,"class","txt-center")},m(s,e){r(s,t,e)},p,d(s){s&&a(t)}}}function F(o){let t;function s(i,l){return i[1]?T:i[0]?S:P}let e=s(o),n=e(o);return{c(){n.c(),t=M()},m(i,l){n.m(i,l),r(i,t,l)},p(i,l){e===(e=s(i))&&n?n.p(i,l):(n.d(1),n=e(i),n&&(n.c(),n.m(t.parentNode,t)))},d(i){n.d(i),i&&a(t)}}}function U(o){let t,s;return t=new w({props:{nobranding:!0,$$slots:{default:[F]},$$scope:{ctx:o}}}),{c(){x(t.$$.fragment)},m(e,n){C(t,e,n),s=!0},p(e,[n]){const i={};n&67&&(i.$$scope={dirty:n,ctx:e}),t.$set(i)},i(e){s||(g(t.$$.fragment,e),s=!0)},o(e){$(t.$$.fragment,e),s=!1},d(e){L(t,e)}}}function V(o,t,s){let{params:e}=t,n=!1,i=!1;l();async function l(){s(1,i=!0);try{await H.Users.confirmVerification(e==null?void 0:e.token),s(0,n=!0)}catch(d){console.warn(d),s(0,n=!1)}s(1,i=!1)}const c=()=>window.close(),b=()=>window.close();return o.$$set=d=>{"params"in d&&s(2,e=d.params)},[n,i,e,c,b]}class E extends k{constructor(t){super(),v(this,t,V,U,y,{params:2})}}export{E as default};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -20,8 +20,8 @@
|
||||||
window.Prism = window.Prism || {};
|
window.Prism = window.Prism || {};
|
||||||
window.Prism.manual = true;
|
window.Prism.manual = true;
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/_/assets/index.0314b5be.js"></script>
|
<script type="module" crossorigin src="/_/assets/index.c63abb6b.js"></script>
|
||||||
<link rel="stylesheet" href="/_/assets/index.a5726992.css">
|
<link rel="stylesheet" href="/_/assets/index.d97a62dd.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -16,11 +16,15 @@
|
||||||
|
|
||||||
let oldLocation = undefined;
|
let oldLocation = undefined;
|
||||||
|
|
||||||
|
let showAppSidebar = false;
|
||||||
|
|
||||||
function handleRouteLoading(e) {
|
function handleRouteLoading(e) {
|
||||||
if (e?.detail?.location === oldLocation) {
|
if (e?.detail?.location === oldLocation) {
|
||||||
return; // not an actual change
|
return; // not an actual change
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showAppSidebar = !!e?.detail?.userData?.showAppSidebar;
|
||||||
|
|
||||||
oldLocation = e?.detail?.location;
|
oldLocation = e?.detail?.location;
|
||||||
|
|
||||||
// resets
|
// resets
|
||||||
|
@ -30,11 +34,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRouteFailure() {
|
function handleRouteFailure() {
|
||||||
if (ApiClient.AuthStore.isValid) {
|
replace("/");
|
||||||
replace("/");
|
|
||||||
} else {
|
|
||||||
ApiClient.logout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="app-layout">
|
<div class="app-layout">
|
||||||
{#if $admin?.id}
|
{#if $admin?.id && showAppSidebar}
|
||||||
<aside class="app-sidebar">
|
<aside class="app-sidebar">
|
||||||
<a href="/" class="logo logo-sm" use:link>
|
<a href="/" class="logo logo-sm" use:link>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -1,487 +0,0 @@
|
||||||
<script>
|
|
||||||
import tooltip from "@/actions/tooltip";
|
|
||||||
import ObjectSelect from "@/components/base/ObjectSelect.svelte";
|
|
||||||
import OverlayPanel from "@/components/base/OverlayPanel.svelte";
|
|
||||||
import { addInfoToast } from "@/stores/toasts";
|
|
||||||
|
|
||||||
let popupActive = true;
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
addInfoToast("Hello world");
|
|
||||||
}, 500);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<label for="">EXAMPLE</label>
|
|
||||||
<ObjectSelect multiple searchable items={["test1", "test2"]} />
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
<div class="form-field">
|
|
||||||
<label for="">EXAMPLE</label>
|
|
||||||
<ObjectSelect searchable items={["test1", "test2"]} />
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
<div class="form-field disabled">
|
|
||||||
<label for="">EXAMPLE</label>
|
|
||||||
<ObjectSelect disabled searchable items={["test1", "test2"]} />
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="alert">
|
|
||||||
<div class="icon">
|
|
||||||
<i class="ri-information-line" />
|
|
||||||
</div>
|
|
||||||
<div class="content">Hello world!</div>
|
|
||||||
<div class="close">
|
|
||||||
<i class="ri-close-line" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<div class="icon">
|
|
||||||
<i class="ri-information-line" />
|
|
||||||
</div>
|
|
||||||
<div class="content">Hello world!</div>
|
|
||||||
<div class="close">
|
|
||||||
<i class="ri-close-line" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<div class="icon">
|
|
||||||
<i class="ri-information-line" />
|
|
||||||
</div>
|
|
||||||
<div class="content">Hello world!</div>
|
|
||||||
<div class="close">
|
|
||||||
<i class="ri-close-line" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<div class="icon">
|
|
||||||
<i class="ri-error-warning-line" />
|
|
||||||
</div>
|
|
||||||
<div class="content">Hello world!</div>
|
|
||||||
<div class="close">
|
|
||||||
<i class="ri-close-line" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<div class="icon">
|
|
||||||
<i class="ri-checkbox-circle-line" />
|
|
||||||
</div>
|
|
||||||
<div class="content">Hello world!</div>
|
|
||||||
<div class="close">
|
|
||||||
<i class="ri-close-line" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<h1>H1 title</h1>
|
|
||||||
<p>Lorem Ipsum dolor sit amet...</p>
|
|
||||||
<h2>H2 title</h2>
|
|
||||||
<p>Lorem Ipsum dolor sit amet...</p>
|
|
||||||
<h3>H3 title</h3>
|
|
||||||
<p>Lorem Ipsum dolor sit amet...</p>
|
|
||||||
<h4>H4 title</h4>
|
|
||||||
<p>Lorem Ipsum dolor sit amet...</p>
|
|
||||||
<h5>H5 title</h5>
|
|
||||||
<p>Lorem Ipsum dolor sit amet...</p>
|
|
||||||
<h6>H6 title</h6>
|
|
||||||
<p>Lorem Ipsum dolor sit amet...</p>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<div class="col-6">COL1</div>
|
|
||||||
<div class="col-6">COL2</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Lorem Ipsum is <a href="/">simply dummy</a> text of the printing and typesetting industry. Lorem Ipsum has
|
|
||||||
been the industry's
|
|
||||||
<strong>standard</strong> dummy text ever since the 1500s, when an unknown printer took a galley of type
|
|
||||||
and <em>scrambled</em> it to make a type specimen book. It has survived not only five centuries, but also
|
|
||||||
the leap into electronic typesetting, remaining<sup>1</sup> essentially<sub>2</sub> unchanged.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and
|
|
||||||
more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><small>Option 1</small></li>
|
|
||||||
<li>Option 2</li>
|
|
||||||
<li>Option 3</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>Option 1</li>
|
|
||||||
<li>Option 2</li>
|
|
||||||
<li>Option 3</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<span use:tooltip={"My tooltip"}>Lorem Ipsum</span>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn">Button default</button>
|
|
||||||
<button class="btn btn-danger">Button danger</button>
|
|
||||||
<button class="btn btn-warning">Button warning</button>
|
|
||||||
<button class="btn btn-success">Button success</button>
|
|
||||||
<button class="btn btn-info">Button info</button>
|
|
||||||
<button class="btn btn-hint">Button hint</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn btn-secondary">Button default</button>
|
|
||||||
<button class="btn btn-secondary btn-danger">Button danger</button>
|
|
||||||
<button class="btn btn-secondary btn-warning">Button danger</button>
|
|
||||||
<button class="btn btn-secondary btn-success">Button success</button>
|
|
||||||
<button class="btn btn-secondary btn-info">Button info</button>
|
|
||||||
<button class="btn btn-secondary btn-hint">Button hint</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn btn-outline">Button default</button>
|
|
||||||
<button class="btn btn-outline btn-danger">Button danger</button>
|
|
||||||
<button class="btn btn-outline btn-warning">Button danger</button>
|
|
||||||
<button class="btn btn-outline btn-success">Button success</button>
|
|
||||||
<button class="btn btn-outline btn-info">Button info</button>
|
|
||||||
<button class="btn btn-outline btn-hint">Button hint</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button disabled class="btn">Button default</button>
|
|
||||||
<button disabled class="btn btn-danger">Button danger</button>
|
|
||||||
<button disabled class="btn btn-warning">Button warning</button>
|
|
||||||
<button disabled class="btn btn-success">Button success</button>
|
|
||||||
<button disabled class="btn btn-info">Button info</button>
|
|
||||||
<button disabled class="btn btn-hint">Button hint</button>
|
|
||||||
|
|
||||||
<button disabled class="btn btn-secondary">Button default</button>
|
|
||||||
<button disabled class="btn btn-secondary btn-danger">Button danger</button>
|
|
||||||
<button disabled class="btn btn-secondary btn-warning">Button danger</button>
|
|
||||||
<button disabled class="btn btn-secondary btn-success">Button success</button>
|
|
||||||
<button disabled class="btn btn-secondary btn-info">Button info</button>
|
|
||||||
<button disabled class="btn btn-secondary btn-hint">Button hint</button>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button default</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-danger">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button danger</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-warning">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button warning</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-success">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button success</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-hint">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button hint</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button default</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-danger btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button danger</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-warning btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button warning</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-success btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button success</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-hint btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button hint</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button default</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-danger btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button danger</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-warning btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button warning</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-success btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button success</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-hint btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button hint</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-sm btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-lg btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="btn btn-secondary btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-secondary btn-sm btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-secondary btn-lg btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button class="btn btn-loading">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button Loading</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-loading btn-primary btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button Loading</span>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-loading btn-danger btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button Loading</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="btn btn-loading btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-loading btn-primary btn-sm btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-loading btn-danger btn-lg btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<button disabled class="btn btn-loading">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button Loading</span>
|
|
||||||
</button>
|
|
||||||
<button disabled class="btn btn-loading btn-primary btn-sm">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button Loading</span>
|
|
||||||
</button>
|
|
||||||
<button disabled class="btn btn-loading btn-danger btn-lg">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
<span class="txt">Button Loading</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button disabled class="btn btn-loading btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button disabled class="btn btn-loading btn-primary btn-sm btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
<button disabled class="btn btn-loading btn-danger btn-lg btn-circle">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<input type="text" />
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
<select>
|
|
||||||
<option value="1" selected>Option 1</option>
|
|
||||||
<option value="">Option 2</option>
|
|
||||||
<option value="">Option 3</option>
|
|
||||||
</select>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<textarea cols="30" rows="10" />
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-field required">
|
|
||||||
<label for="field_1">Name</label>
|
|
||||||
<input type="text" id="field_1" placeholder="Name 123" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field required">
|
|
||||||
<label for="field_2">Description</label>
|
|
||||||
<textarea id="field_2" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<label for="field_3">Choose value</label>
|
|
||||||
<select id="field_3">
|
|
||||||
<option value="1" selected>Option 1</option>
|
|
||||||
<option value="">Option 2</option>
|
|
||||||
<option value="">Option 3</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="text" placeholder="Lorem ipsum dolor sit amet..." />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<textarea />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<select>
|
|
||||||
<option value="1" selected>Option 1</option>
|
|
||||||
<option value="">Option 2</option>
|
|
||||||
<option value="">Option 3</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="checkbox" id="field_check" />
|
|
||||||
<label for="field_check">
|
|
||||||
I agree with the <a href="/">terms and conditions</a>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="radio" name="radio_check" id="field_radio1" value="1" />
|
|
||||||
<label for="field_radio1">Radio 1</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="radio" name="radio_check" id="field_radio2" value="2" />
|
|
||||||
<label for="field_radio2">Radio 2</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field form-field-toggle">
|
|
||||||
<input type="checkbox" id="field_toggle" />
|
|
||||||
<label for="field_toggle">Toggle check</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-field error">
|
|
||||||
<label for="field_error">Name + error</label>
|
|
||||||
<input type="text" id="field_error" />
|
|
||||||
<div class="help-block help-block-error">
|
|
||||||
<p>Something went wrong</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<label for="field_hint">Name + hint</label>
|
|
||||||
<input type="text" id="field_hint" />
|
|
||||||
<div class="help-block">
|
|
||||||
<p>Lorem ipsum dolor <a href="/">sit</a> amet</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="checkbox" id="field_check_hint" />
|
|
||||||
<label for="field_check_hint">Checkbox hint</label>
|
|
||||||
<div class="help-block">Lorem ipsum</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field has-error">
|
|
||||||
<input type="checkbox" id="field_check_error" />
|
|
||||||
<label for="field_check_error">Checkbox error</label>
|
|
||||||
<div class="help-block help-error">Lorem ipsum</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-field disabled">
|
|
||||||
<input type="checkbox" id="field_check" disabled />
|
|
||||||
<label for="field_check">
|
|
||||||
I agree with the <a href="/">terms and conditions</a>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="radio" name="radio_check" id="field_radio1" value="1" disabled />
|
|
||||||
<label for="field_radio1">Radio 1</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-field">
|
|
||||||
<input type="radio" name="radio_check" id="field_radio2" value="2" disabled />
|
|
||||||
<label for="field_radio2">Radio 2</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field form-field-toggle disabled">
|
|
||||||
<input type="checkbox" id="field_toggle" disabled />
|
|
||||||
<label for="field_toggle" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-field disabled">
|
|
||||||
<label for="field_addon1">Name</label>
|
|
||||||
<div class="form-field-addon">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</div>
|
|
||||||
<input disabled type="text" id="field_addon1" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-field">
|
|
||||||
<div class="form-field-addon">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</div>
|
|
||||||
<input type="text" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="form-field">
|
|
||||||
<label for="field_group1">Name</label>
|
|
||||||
<div class="form-field-addon">
|
|
||||||
<div class="btn btn-circle btn-secondary">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input type="text" id="field_group1" />
|
|
||||||
</div>
|
|
||||||
<div class="form-field">
|
|
||||||
<label for="field_group2">Password</label>
|
|
||||||
<div class="form-field-addon">
|
|
||||||
<i class="ri-mail-line" />
|
|
||||||
</div>
|
|
||||||
<input type="password" id="field_group2" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<OverlayPanel bind:active={popupActive} popup={false}>
|
|
||||||
<h4 slot="header">My title</h4>
|
|
||||||
<p>Lorem ipsum dolor sit amet...</p>
|
|
||||||
<svelte:fragment slot="footer">
|
|
||||||
<button class="btn btn-secondary">Cancel</button>
|
|
||||||
<button class="btn btn-expanded">Save</button>
|
|
||||||
</svelte:fragment>
|
|
||||||
</OverlayPanel>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<script>
|
|
||||||
import { replace } from "svelte-spa-router";
|
|
||||||
|
|
||||||
replace("/collections");
|
|
||||||
</script>
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<script>
|
||||||
|
import { tick } from "svelte";
|
||||||
|
import { replace } from "svelte-spa-router";
|
||||||
|
import ApiClient from "@/utils/ApiClient";
|
||||||
|
import FullPage from "@/components/base/FullPage.svelte";
|
||||||
|
import Installer from "@/components/base/Installer.svelte";
|
||||||
|
|
||||||
|
let showInstaller = false;
|
||||||
|
|
||||||
|
handler();
|
||||||
|
|
||||||
|
function handler() {
|
||||||
|
showInstaller = false;
|
||||||
|
|
||||||
|
const realQueryParams = new URLSearchParams(window.location.search);
|
||||||
|
if (realQueryParams.has(import.meta.env.PB_INSTALLER_PARAM)) {
|
||||||
|
ApiClient.logout(false);
|
||||||
|
showInstaller = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ApiClient.AuthStore.isValid) {
|
||||||
|
replace("/collections");
|
||||||
|
} else {
|
||||||
|
ApiClient.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if showInstaller}
|
||||||
|
<FullPage>
|
||||||
|
<Installer
|
||||||
|
on:submit={async () => {
|
||||||
|
showInstaller = false;
|
||||||
|
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
// clear the installer param
|
||||||
|
window.location.search = "";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FullPage>
|
||||||
|
{/if}
|
|
@ -0,0 +1,76 @@
|
||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
import ApiClient from "@/utils/ApiClient";
|
||||||
|
import Field from "@/components/base/Field.svelte";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
let email = "";
|
||||||
|
let password = "";
|
||||||
|
let passwordConfirm = "";
|
||||||
|
let isLoading = false;
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
if (isLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await ApiClient.Admins.create({
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
passwordConfirm,
|
||||||
|
});
|
||||||
|
|
||||||
|
await ApiClient.Admins.authViaEmail(email, password);
|
||||||
|
|
||||||
|
dispatch("submit");
|
||||||
|
} catch (err) {
|
||||||
|
ApiClient.errorResponseHandler(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form class="block" autocomplete="off" on:submit|preventDefault={submit}>
|
||||||
|
<div class="content txt-center m-b-base">
|
||||||
|
<h4>Create your first admin account in order to continue</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Field class="form-field required" name="email" let:uniqueId>
|
||||||
|
<label for={uniqueId}>Email</label>
|
||||||
|
<!-- svelte-ignore a11y-autofocus -->
|
||||||
|
<input type="email" autocomplete="off" id={uniqueId} bind:value={email} required autofocus />
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<Field class="form-field required" name="password" let:uniqueId>
|
||||||
|
<label for={uniqueId}>Password</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
autocomplete="new-password"
|
||||||
|
minlength="10"
|
||||||
|
id={uniqueId}
|
||||||
|
bind:value={password}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div class="help-block">Minimum 10 characters.</div>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<Field class="form-field required" name="passwordConfirm" let:uniqueId>
|
||||||
|
<label for={uniqueId}>Password confirm</label>
|
||||||
|
<input type="password" minlength="10" id={uniqueId} bind:value={passwordConfirm} required />
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-lg btn-block btn-next"
|
||||||
|
class:btn-disabled={isLoading}
|
||||||
|
class:btn-loading={isLoading}
|
||||||
|
>
|
||||||
|
<span class="txt">Create and login</span>
|
||||||
|
<i class="ri-arrow-right-line" />
|
||||||
|
</button>
|
||||||
|
</form>
|
|
@ -1,5 +1,7 @@
|
||||||
|
import { replace } from "svelte-spa-router";
|
||||||
import { wrap } from "svelte-spa-router/wrap";
|
import { wrap } from "svelte-spa-router/wrap";
|
||||||
import ApiClient from "@/utils/ApiClient";
|
import ApiClient from "@/utils/ApiClient";
|
||||||
|
import PageIndex from "@/components/PageIndex.svelte";
|
||||||
import PageLogs from "@/components/logs/PageLogs.svelte";
|
import PageLogs from "@/components/logs/PageLogs.svelte";
|
||||||
import PageRecords from "@/components/records/PageRecords.svelte";
|
import PageRecords from "@/components/records/PageRecords.svelte";
|
||||||
import PageUsers from "@/components/users/PageUsers.svelte";
|
import PageUsers from "@/components/users/PageUsers.svelte";
|
||||||
|
@ -11,107 +13,131 @@ import PageStorage from "@/components/settings/PageStorage.svelte";
|
||||||
import PageAuthProviders from "@/components/settings/PageAuthProviders.svelte";
|
import PageAuthProviders from "@/components/settings/PageAuthProviders.svelte";
|
||||||
import PageTokenOptions from "@/components/settings/PageTokenOptions.svelte";
|
import PageTokenOptions from "@/components/settings/PageTokenOptions.svelte";
|
||||||
|
|
||||||
const routes = {
|
const baseConditions = [
|
||||||
"/_elements": wrap({
|
async (details) => {
|
||||||
asyncComponent: () => import("@/components/Elements.svelte"),
|
const realQueryParams = new URLSearchParams(window.location.search);
|
||||||
}),
|
|
||||||
|
|
||||||
|
if (details.location !== "/" && realQueryParams.has(import.meta.env.PB_INSTALLER_PARAM)) {
|
||||||
|
return replace("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const routes = {
|
||||||
"/login": wrap({
|
"/login": wrap({
|
||||||
component: PageAdminLogin,
|
component: PageAdminLogin,
|
||||||
conditions: [(_) => !ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => !ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/request-password-reset": wrap({
|
"/request-password-reset": wrap({
|
||||||
asyncComponent: () => import("@/components/admins/PageAdminRequestPasswordReset.svelte"),
|
asyncComponent: () => import("@/components/admins/PageAdminRequestPasswordReset.svelte"),
|
||||||
conditions: [(_) => !ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => !ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/confirm-password-reset/:token": wrap({
|
"/confirm-password-reset/:token": wrap({
|
||||||
asyncComponent: () => import("@/components/admins/PageAdminConfirmPasswordReset.svelte"),
|
asyncComponent: () => import("@/components/admins/PageAdminConfirmPasswordReset.svelte"),
|
||||||
conditions: [(_) => !ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => !ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/collections": wrap({
|
"/collections": wrap({
|
||||||
component: PageRecords,
|
component: PageRecords,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/logs": wrap({
|
"/logs": wrap({
|
||||||
component: PageLogs,
|
component: PageLogs,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/users": wrap({
|
"/users": wrap({
|
||||||
component: PageUsers,
|
component: PageUsers,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/users/confirm-password-reset/:token": wrap({
|
"/users/confirm-password-reset/:token": wrap({
|
||||||
asyncComponent: () => import("@/components/users/PageUserConfirmPasswordReset.svelte"),
|
asyncComponent: () => import("@/components/users/PageUserConfirmPasswordReset.svelte"),
|
||||||
conditions: [
|
conditions: baseConditions.concat([
|
||||||
() => {
|
() => {
|
||||||
// ensure that there is no authenticated user/admin model
|
// ensure that there is no authenticated user/admin model
|
||||||
ApiClient.logout(false);
|
ApiClient.logout(false);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
],
|
]),
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/users/confirm-verification/:token": wrap({
|
"/users/confirm-verification/:token": wrap({
|
||||||
asyncComponent: () => import("@/components/users/PageUserConfirmVerification.svelte"),
|
asyncComponent: () => import("@/components/users/PageUserConfirmVerification.svelte"),
|
||||||
conditions: [
|
conditions: baseConditions.concat([
|
||||||
() => {
|
() => {
|
||||||
// ensure that there is no authenticated user/admin model
|
// ensure that there is no authenticated user/admin model
|
||||||
ApiClient.logout(false);
|
ApiClient.logout(false);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
],
|
]),
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/users/confirm-email-change/:token": wrap({
|
"/users/confirm-email-change/:token": wrap({
|
||||||
asyncComponent: () => import("@/components/users/PageUserConfirmEmailChange.svelte"),
|
asyncComponent: () => import("@/components/users/PageUserConfirmEmailChange.svelte"),
|
||||||
conditions: [
|
conditions: baseConditions.concat([
|
||||||
() => {
|
() => {
|
||||||
// ensure that there is no authenticated user/admin model
|
// ensure that there is no authenticated user/admin model
|
||||||
ApiClient.logout(false);
|
ApiClient.logout(false);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
],
|
]),
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/settings": wrap({
|
"/settings": wrap({
|
||||||
component: PageApplication,
|
component: PageApplication,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/settings/admins": wrap({
|
"/settings/admins": wrap({
|
||||||
component: PageAdmins,
|
component: PageAdmins,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/settings/mail": wrap({
|
"/settings/mail": wrap({
|
||||||
component: PageMail,
|
component: PageMail,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/settings/storage": wrap({
|
"/settings/storage": wrap({
|
||||||
component: PageStorage,
|
component: PageStorage,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/settings/auth-providers": wrap({
|
"/settings/auth-providers": wrap({
|
||||||
component: PageAuthProviders,
|
component: PageAuthProviders,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"/settings/tokens": wrap({
|
"/settings/tokens": wrap({
|
||||||
component: PageTokenOptions,
|
component: PageTokenOptions,
|
||||||
conditions: [(_) => ApiClient.AuthStore.isValid],
|
conditions: baseConditions.concat([(_) => ApiClient.AuthStore.isValid]),
|
||||||
|
userData: { showAppSidebar: true },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// fallback
|
// fallback
|
||||||
"*": wrap({
|
"*": wrap({
|
||||||
asyncComponent: () => import("@/components/NotFoundPage.svelte"),
|
component: PageIndex,
|
||||||
|
userData: { showAppSidebar: false },
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue