diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 7191f15..352650a 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,12 +4,12 @@
-
+
+
-
-
-
+
+
@@ -155,7 +155,6 @@
-
@@ -180,7 +179,8 @@
-
+
+
true
diff --git a/pkg/internal/server/admin/factors_api.go b/pkg/internal/server/admin/factors_api.go
new file mode 100644
index 0000000..3de5cc7
--- /dev/null
+++ b/pkg/internal/server/admin/factors_api.go
@@ -0,0 +1,40 @@
+package admin
+
+import (
+ "git.solsynth.dev/hydrogen/passport/pkg/internal/database"
+ "git.solsynth.dev/hydrogen/passport/pkg/internal/models"
+ "git.solsynth.dev/hydrogen/passport/pkg/internal/server/exts"
+ "github.com/gofiber/fiber/v2"
+ jsoniter "github.com/json-iterator/go"
+ "github.com/samber/lo"
+)
+
+func getUserAuthFactors(c *fiber.Ctx) error {
+ userId, _ := c.ParamsInt("user")
+
+ if err := exts.EnsureGrantedPerm(c, "AdminAuthFactors", true); err != nil {
+ return err
+ }
+
+ var factors []models.AuthFactor
+ if err := database.C.Where("account_id = ?", userId).Find(&factors).Error; err != nil {
+ return fiber.NewError(fiber.StatusInternalServerError, err.Error())
+ }
+
+ encodedResp := lo.Map(factors, func(item models.AuthFactor, idx int) map[string]any {
+ var encoded map[string]any
+ raw, _ := jsoniter.Marshal(item)
+ _ = jsoniter.Unmarshal(raw, &encoded)
+
+ // Blur out the secret if it isn't current rolling email one-time-password
+ if item.Type != models.EmailPasswordFactor && len(item.Secret) != 6 {
+ encoded["secret"] = "**CENSORED**"
+ } else {
+ encoded["secret"] = item.Secret
+ }
+
+ return encoded
+ })
+
+ return c.JSON(encodedResp)
+}
diff --git a/pkg/internal/server/admin/index.go b/pkg/internal/server/admin/index.go
index a2bace7..942b1c8 100644
--- a/pkg/internal/server/admin/index.go
+++ b/pkg/internal/server/admin/index.go
@@ -13,6 +13,9 @@ func MapAdminAPIs(app *fiber.App) {
admin.Post("/notify/all", notifyAllUser)
admin.Post("/notify/:user", notifyOneUser)
+ admin.Get("/users", listUser)
+ admin.Get("/users/:user", getUser)
+ admin.Get("/users/:user/factors", getUserAuthFactors)
admin.Put("/users/:user/permissions", editUserPermission)
admin.Post("/users/:user/confirm", forceConfirmAccount)
}
diff --git a/pkg/internal/server/admin/user_api.go b/pkg/internal/server/admin/users_api.go
similarity index 51%
rename from pkg/internal/server/admin/user_api.go
rename to pkg/internal/server/admin/users_api.go
index 84c3277..5629f64 100644
--- a/pkg/internal/server/admin/user_api.go
+++ b/pkg/internal/server/admin/users_api.go
@@ -10,6 +10,44 @@ import (
"github.com/gofiber/fiber/v2"
)
+func listUser(c *fiber.Ctx) error {
+ take := c.QueryInt("take", 0)
+ offset := c.QueryInt("offset", 0)
+
+ if err := exts.EnsureGrantedPerm(c, "AdminUser", true); err != nil {
+ return err
+ }
+
+ var count int64
+ if err := database.C.Model(&models.Account{}).Count(&count).Error; err != nil {
+ return fiber.NewError(fiber.StatusInternalServerError, err.Error())
+ }
+ var items []models.Account
+ if err := database.C.Offset(offset).Limit(take).Find(&items).Error; err != nil {
+ return fiber.NewError(fiber.StatusInternalServerError, err.Error())
+ }
+
+ return c.JSON(fiber.Map{
+ "count": count,
+ "data": items,
+ })
+}
+
+func getUser(c *fiber.Ctx) error {
+ userId, _ := c.ParamsInt("user")
+
+ if err := exts.EnsureGrantedPerm(c, "AdminUser", true); err != nil {
+ return err
+ }
+
+ var user models.Account
+ if err := database.C.Where("id = ?", userId).First(&user).Error; err != nil {
+ return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("account was not found: %v", err))
+ }
+
+ return c.JSON(user)
+}
+
func forceConfirmAccount(c *fiber.Ctx) error {
userId, _ := c.ParamsInt("user")
diff --git a/settings.toml b/settings.toml
index 1bd3f34..945ad7e 100644
--- a/settings.toml
+++ b/settings.toml
@@ -44,10 +44,10 @@ dsn = "host=localhost user=postgres password=password dbname=hy_passport port=54
prefix = "passport_"
[permissions.default]
-CreatePost = true
+CreatePosts = true
CreateAttachments = 1048576
[permissions.verified]
-CreateRealm = true
-CreateArticle = true
+CreateRealms = true
+CreateArticles = true
CreateAttachments = 26214400