✨ List, create & delete auth factor apis
This commit is contained in:
parent
a43e89a5a3
commit
dc2de65245
@ -16,6 +16,8 @@ type AuthFactorType = int8
|
|||||||
const (
|
const (
|
||||||
PasswordAuthFactor = AuthFactorType(iota)
|
PasswordAuthFactor = AuthFactorType(iota)
|
||||||
EmailPasswordFactor
|
EmailPasswordFactor
|
||||||
|
InAppNotifyFactor
|
||||||
|
TimeOtpFactor
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthFactor struct {
|
type AuthFactor struct {
|
||||||
|
@ -83,39 +83,7 @@ func getUserinfo(c *fiber.Ctx) error {
|
|||||||
return c.JSON(resp)
|
return c.JSON(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEvents(c *fiber.Ctx) error {
|
func updateUserinfo(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 {
|
|
||||||
if err := exts.EnsureAuthenticated(c); err != nil {
|
if err := exts.EnsureAuthenticated(c); err != nil {
|
||||||
return err
|
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 (
|
import (
|
||||||
"fmt"
|
"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/http/exts"
|
||||||
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
|
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getAvailableFactors(c *fiber.Ctx) error {
|
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 {
|
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 {
|
if err := exts.BindAndValidate(c, &data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := services.GetAccount(data.UserID)
|
typeWhitelist := []models.AuthFactorType{
|
||||||
if err != nil {
|
models.EmailPasswordFactor,
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
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 {
|
// Currently, each type of factor can only be created once
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
var currentCount int64
|
||||||
} else if err = services.RequestResetPassword(user); err != nil {
|
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 fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
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.Put("/banner", setBanner)
|
||||||
|
|
||||||
me.Get("/", getUserinfo)
|
me.Get("/", getUserinfo)
|
||||||
me.Put("/", editUserinfo)
|
me.Put("/", updateUserinfo)
|
||||||
me.Get("/events", getEvents)
|
me.Get("/events", getEvents)
|
||||||
me.Get("/tickets", getTickets)
|
me.Get("/tickets", getTickets)
|
||||||
me.Delete("/tickets/:ticketId", killTicket)
|
me.Delete("/tickets/:ticketId", killTicket)
|
||||||
@ -72,6 +72,13 @@ func MapAPIs(app *fiber.App, baseURL string) {
|
|||||||
me.Put("/status", editStatus)
|
me.Put("/status", editStatus)
|
||||||
me.Delete("/status", clearStatus)
|
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 := me.Group("/relations").Name("Relations")
|
||||||
{
|
{
|
||||||
relations.Post("/", makeFriendship)
|
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