✨ List, create & delete auth factor apis
This commit is contained in:
parent
a43e89a5a3
commit
dc2de65245
@ -16,6 +16,8 @@ type AuthFactorType = int8
|
||||
const (
|
||||
PasswordAuthFactor = AuthFactorType(iota)
|
||||
EmailPasswordFactor
|
||||
InAppNotifyFactor
|
||||
TimeOtpFactor
|
||||
)
|
||||
|
||||
type AuthFactor struct {
|
||||
|
@ -83,39 +83,7 @@ func getUserinfo(c *fiber.Ctx) error {
|
||||
return c.JSON(resp)
|
||||
}
|
||||
|
||||
func getEvents(c *fiber.Ctx) error {
|
||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
user := c.Locals("user").(models.Account)
|
||||
take := c.QueryInt("take", 0)
|
||||
offset := c.QueryInt("offset", 0)
|
||||
|
||||
var count int64
|
||||
var events []models.ActionEvent
|
||||
if err := database.C.
|
||||
Where(&models.ActionEvent{AccountID: user.ID}).
|
||||
Model(&models.ActionEvent{}).
|
||||
Count(&count).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
if err := database.C.
|
||||
Order("created_at desc").
|
||||
Where(&models.ActionEvent{AccountID: user.ID}).
|
||||
Limit(take).
|
||||
Offset(offset).
|
||||
Find(&events).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"count": count,
|
||||
"data": events,
|
||||
})
|
||||
}
|
||||
|
||||
func editUserinfo(c *fiber.Ctx) error {
|
||||
func updateUserinfo(c *fiber.Ctx) error {
|
||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
40
pkg/internal/http/api/events_api.go
Normal file
40
pkg/internal/http/api/events_api.go
Normal file
@ -0,0 +1,40 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/http/exts"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func getEvents(c *fiber.Ctx) error {
|
||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
user := c.Locals("user").(models.Account)
|
||||
take := c.QueryInt("take", 0)
|
||||
offset := c.QueryInt("offset", 0)
|
||||
|
||||
var count int64
|
||||
var events []models.ActionEvent
|
||||
if err := database.C.
|
||||
Where(&models.ActionEvent{AccountID: user.ID}).
|
||||
Model(&models.ActionEvent{}).
|
||||
Count(&count).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
if err := database.C.
|
||||
Order("created_at desc").
|
||||
Where(&models.ActionEvent{AccountID: user.ID}).
|
||||
Limit(take).
|
||||
Offset(offset).
|
||||
Find(&events).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"count": count,
|
||||
"data": events,
|
||||
})
|
||||
}
|
@ -2,9 +2,13 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/http/exts"
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func getAvailableFactors(c *fiber.Ctx) error {
|
||||
@ -42,42 +46,87 @@ func requestFactorToken(c *fiber.Ctx) error {
|
||||
}
|
||||
}
|
||||
|
||||
func requestResetPassword(c *fiber.Ctx) error {
|
||||
func listFactor(c *fiber.Ctx) error {
|
||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
user := c.Locals("user").(models.Account)
|
||||
|
||||
var factors []models.AuthFactor
|
||||
if err := database.C.Where("account_id = ?", user.ID).Find(&factors).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return c.JSON(factors)
|
||||
}
|
||||
|
||||
func createFactor(c *fiber.Ctx) error {
|
||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
user := c.Locals("user").(models.Account)
|
||||
|
||||
var data struct {
|
||||
UserID uint `json:"user_id" validate:"required"`
|
||||
Type models.AuthFactorType `json:"type"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
if err := exts.BindAndValidate(c, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := services.GetAccount(data.UserID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
typeWhitelist := []models.AuthFactorType{
|
||||
models.EmailPasswordFactor,
|
||||
models.InAppNotifyFactor,
|
||||
models.TimeOtpFactor,
|
||||
}
|
||||
if !lo.Contains(typeWhitelist, data.Type) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "invalid factor type")
|
||||
}
|
||||
|
||||
if err = services.CheckAbleToResetPassword(user); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
} else if err = services.RequestResetPassword(user); err != nil {
|
||||
// Currently, each type of factor can only be created once
|
||||
var currentCount int64
|
||||
if err := database.C.Model(&models.AuthFactor{}).
|
||||
Where("account_id = ? AND type = ?", user.ID, data.Type).
|
||||
Count(¤tCount).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("unable to check current factor count: %v", err))
|
||||
} else if currentCount > 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "this type of factor already exists")
|
||||
}
|
||||
|
||||
factor := models.AuthFactor{
|
||||
Type: data.Type,
|
||||
Secret: data.Secret,
|
||||
Account: user,
|
||||
AccountID: user.ID,
|
||||
}
|
||||
if err := database.C.Create(&factor).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return c.JSON(factor)
|
||||
}
|
||||
|
||||
func deleteFactor(c *fiber.Ctx) error {
|
||||
id, _ := c.ParamsInt("factorId", 0)
|
||||
|
||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}
|
||||
user := c.Locals("user").(models.Account)
|
||||
|
||||
var factor models.AuthFactor
|
||||
if err := database.C.Where("id = ? AND account_id = ?", id, user.ID).First(&factor).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||
}
|
||||
|
||||
if factor.Type == models.PasswordAuthFactor {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "unable to delete password factor")
|
||||
}
|
||||
|
||||
if err := database.C.Delete(&factor).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func confirmResetPassword(c *fiber.Ctx) error {
|
||||
var data struct {
|
||||
Code string `json:"code" validate:"required"`
|
||||
NewPassword string `json:"new_password" validate:"required"`
|
||||
}
|
||||
|
||||
if err := exts.BindAndValidate(c, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := services.ConfirmResetPassword(data.Code, data.NewPassword); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func MapAPIs(app *fiber.App, baseURL string) {
|
||||
me.Put("/banner", setBanner)
|
||||
|
||||
me.Get("/", getUserinfo)
|
||||
me.Put("/", editUserinfo)
|
||||
me.Put("/", updateUserinfo)
|
||||
me.Get("/events", getEvents)
|
||||
me.Get("/tickets", getTickets)
|
||||
me.Delete("/tickets/:ticketId", killTicket)
|
||||
@ -72,6 +72,13 @@ func MapAPIs(app *fiber.App, baseURL string) {
|
||||
me.Put("/status", editStatus)
|
||||
me.Delete("/status", clearStatus)
|
||||
|
||||
factors := me.Group("/factors").Name("Factors")
|
||||
{
|
||||
factors.Get("/", listFactor)
|
||||
factors.Post("/", createFactor)
|
||||
factors.Delete("/:factorId", deleteFactor)
|
||||
}
|
||||
|
||||
relations := me.Group("/relations").Name("Relations")
|
||||
{
|
||||
relations.Post("/", makeFriendship)
|
||||
|
47
pkg/internal/http/api/password_api.go
Normal file
47
pkg/internal/http/api/password_api.go
Normal file
@ -0,0 +1,47 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/http/exts"
|
||||
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func requestResetPassword(c *fiber.Ctx) error {
|
||||
var data struct {
|
||||
UserID uint `json:"user_id" validate:"required"`
|
||||
}
|
||||
|
||||
if err := exts.BindAndValidate(c, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := services.GetAccount(data.UserID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
if err = services.CheckAbleToResetPassword(user); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
} else if err = services.RequestResetPassword(user); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func confirmResetPassword(c *fiber.Ctx) error {
|
||||
var data struct {
|
||||
Code string `json:"code" validate:"required"`
|
||||
NewPassword string `json:"new_password" validate:"required"`
|
||||
}
|
||||
|
||||
if err := exts.BindAndValidate(c, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := services.ConfirmResetPassword(data.Code, data.NewPassword); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user