feat(kol): KOL workspace HTTP handlers + route registration
This commit is contained in:
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/geo-platform/tenant-api/internal/shared/response"
|
"github.com/geo-platform/tenant-api/internal/shared/response"
|
||||||
"github.com/geo-platform/tenant-api/internal/shared/retrieval"
|
"github.com/geo-platform/tenant-api/internal/shared/retrieval"
|
||||||
"github.com/geo-platform/tenant-api/internal/shared/stream"
|
"github.com/geo-platform/tenant-api/internal/shared/stream"
|
||||||
|
tenantapp "github.com/geo-platform/tenant-api/internal/tenant/app"
|
||||||
"github.com/geo-platform/tenant-api/internal/tenant/prompts"
|
"github.com/geo-platform/tenant-api/internal/tenant/prompts"
|
||||||
"github.com/geo-platform/tenant-api/internal/tenant/repository"
|
"github.com/geo-platform/tenant-api/internal/tenant/repository"
|
||||||
)
|
)
|
||||||
@@ -47,6 +48,9 @@ type App struct {
|
|||||||
GenerationStreams *stream.GenerationHub
|
GenerationStreams *stream.GenerationHub
|
||||||
Cache cache.Cache
|
Cache cache.Cache
|
||||||
KolProfiles repository.KolProfileRepository
|
KolProfiles repository.KolProfileRepository
|
||||||
|
KolPackages repository.KolPackageRepository
|
||||||
|
KolPrompts repository.KolPromptRepository
|
||||||
|
KolPromptAsset *tenantapp.KolPromptAsset
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(configPath string) (*App, error) {
|
func New(configPath string) (*App, error) {
|
||||||
@@ -99,6 +103,9 @@ func New(configPath string) (*App, error) {
|
|||||||
generationStreams := stream.NewGenerationHub(mqClient)
|
generationStreams := stream.NewGenerationHub(mqClient)
|
||||||
appCache := cache.New(cfg.Cache.Driver, rdb)
|
appCache := cache.New(cfg.Cache.Driver, rdb)
|
||||||
kolProfiles := repository.NewKolProfileRepository(pool)
|
kolProfiles := repository.NewKolProfileRepository(pool)
|
||||||
|
kolPackages := repository.NewKolPackageRepository(pool)
|
||||||
|
kolPrompts := repository.NewKolPromptRepository(pool)
|
||||||
|
kolPromptAsset := tenantapp.NewKolPromptAsset(objectStorageClient)
|
||||||
|
|
||||||
if cfg.Server.Mode == "release" {
|
if cfg.Server.Mode == "release" {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
@@ -153,6 +160,9 @@ func New(configPath string) (*App, error) {
|
|||||||
GenerationStreams: generationStreams,
|
GenerationStreams: generationStreams,
|
||||||
Cache: appCache,
|
Cache: appCache,
|
||||||
KolProfiles: kolProfiles,
|
KolProfiles: kolProfiles,
|
||||||
|
KolPackages: kolPackages,
|
||||||
|
KolPrompts: kolPrompts,
|
||||||
|
KolPromptAsset: kolPromptAsset,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,340 @@
|
|||||||
|
package transport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"github.com/geo-platform/tenant-api/internal/bootstrap"
|
||||||
|
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
||||||
|
"github.com/geo-platform/tenant-api/internal/shared/response"
|
||||||
|
"github.com/geo-platform/tenant-api/internal/tenant/app"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KolManageHandler struct {
|
||||||
|
profileSvc *app.KolProfileService
|
||||||
|
pkgSvc *app.KolPackageService
|
||||||
|
promptSvc *app.KolPromptService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKolManageHandler(a *bootstrap.App) *KolManageHandler {
|
||||||
|
profileSvc := app.NewKolProfileService(a.KolProfiles)
|
||||||
|
|
||||||
|
return &KolManageHandler{
|
||||||
|
profileSvc: profileSvc,
|
||||||
|
pkgSvc: app.NewKolPackageService(profileSvc, a.KolPackages, a.KolPrompts),
|
||||||
|
promptSvc: app.NewKolPromptService(a.DB, profileSvc, a.KolPackages, a.KolPrompts, a.KolPromptAsset),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) GetProfile(c *gin.Context) {
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
profile, err := h.profileSvc.RequireActiveKol(c.Request.Context(), actor)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, app.NewKolProfileResponse(profile))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) ListPackages(c *gin.Context) {
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.pkgSvc.List(c.Request.Context(), actor)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) CreatePackage(c *gin.Context) {
|
||||||
|
var req app.CreateKolPackageInput
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.pkgSvc.Create(c.Request.Context(), actor, req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) UpdatePackage(c *gin.Context) {
|
||||||
|
id, ok := parseInt64Param(c, "id", "package id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req app.UpdateKolPackageInput
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.pkgSvc.Update(c.Request.Context(), actor, id, req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) DeletePackage(c *gin.Context) {
|
||||||
|
id, ok := parseInt64Param(c, "id", "package id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.pkgSvc.Delete(c.Request.Context(), actor, id); err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) PublishPackage(c *gin.Context) {
|
||||||
|
id, ok := parseInt64Param(c, "id", "package id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.pkgSvc.Publish(c.Request.Context(), actor, id)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) ArchivePackage(c *gin.Context) {
|
||||||
|
id, ok := parseInt64Param(c, "id", "package id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.pkgSvc.Archive(c.Request.Context(), actor, id)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) ListPrompts(c *gin.Context) {
|
||||||
|
packageID, ok := parseInt64Param(c, "id", "package id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.promptSvc.ListByPackage(c.Request.Context(), actor, packageID)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) CreatePrompt(c *gin.Context) {
|
||||||
|
packageID, ok := parseInt64Param(c, "id", "package id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req app.CreatePromptInput
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.PackageID = packageID
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.promptSvc.CreatePrompt(c.Request.Context(), actor, req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) GetPromptLatest(c *gin.Context) {
|
||||||
|
promptID, ok := parseInt64Param(c, "id", "prompt id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.promptSvc.GetForOwner(c.Request.Context(), actor, promptID)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) UpdatePromptMetadata(c *gin.Context) {
|
||||||
|
promptID, ok := parseInt64Param(c, "id", "prompt id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req app.UpdateKolPromptInput
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.promptSvc.UpdateMetadata(c.Request.Context(), actor, promptID, req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) DeletePrompt(c *gin.Context) {
|
||||||
|
promptID, ok := parseInt64Param(c, "id", "prompt id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.promptSvc.Delete(c.Request.Context(), actor, promptID); err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) SaveDraft(c *gin.Context) {
|
||||||
|
promptID, ok := parseInt64Param(c, "id", "prompt id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req app.SaveDraftInput
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.PromptID = promptID
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := h.promptSvc.SaveDraft(c.Request.Context(), actor, req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *KolManageHandler) PublishPrompt(c *gin.Context) {
|
||||||
|
promptID, ok := parseInt64Param(c, "id", "prompt id")
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actor, ok := actorFromRequest(c)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.promptSvc.Publish(c.Request.Context(), actor, promptID); err != nil {
|
||||||
|
response.Error(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, gin.H{"ok": true})
|
||||||
|
}
|
||||||
|
|
||||||
|
func actorFromRequest(c *gin.Context) (auth.Actor, bool) {
|
||||||
|
actor, ok := auth.ActorFromCtx(c.Request.Context())
|
||||||
|
if !ok {
|
||||||
|
response.Error(c, response.ErrUnauthorized(40100, "not_authenticated", "not authenticated"))
|
||||||
|
return auth.Actor{}, false
|
||||||
|
}
|
||||||
|
return actor, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInt64Param(c *gin.Context, key, label string) (int64, bool) {
|
||||||
|
id, err := strconv.ParseInt(c.Param(key), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, response.ErrBadRequest(40001, "invalid_id", label+" must be a number"))
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return id, true
|
||||||
|
}
|
||||||
@@ -55,6 +55,23 @@ func RegisterRoutes(app *bootstrap.App) {
|
|||||||
templates.GET("/:id/gen_outline_task_result", tplHandler.GetOutlineTaskResult)
|
templates.GET("/:id/gen_outline_task_result", tplHandler.GetOutlineTaskResult)
|
||||||
templates.POST("/:id/generate", tplHandler.Generate)
|
templates.POST("/:id/generate", tplHandler.Generate)
|
||||||
|
|
||||||
|
kolManage := protected.Group("/tenant/kol/manage")
|
||||||
|
kolManageHandler := NewKolManageHandler(app)
|
||||||
|
kolManage.GET("/profile", kolManageHandler.GetProfile)
|
||||||
|
kolManage.GET("/packages", kolManageHandler.ListPackages)
|
||||||
|
kolManage.POST("/packages", kolManageHandler.CreatePackage)
|
||||||
|
kolManage.PUT("/packages/:id", kolManageHandler.UpdatePackage)
|
||||||
|
kolManage.DELETE("/packages/:id", kolManageHandler.DeletePackage)
|
||||||
|
kolManage.PUT("/packages/:id/publish", kolManageHandler.PublishPackage)
|
||||||
|
kolManage.PUT("/packages/:id/archive", kolManageHandler.ArchivePackage)
|
||||||
|
kolManage.GET("/packages/:id/prompts", kolManageHandler.ListPrompts)
|
||||||
|
kolManage.POST("/packages/:id/prompts", kolManageHandler.CreatePrompt)
|
||||||
|
kolManage.GET("/prompts/:id", kolManageHandler.GetPromptLatest)
|
||||||
|
kolManage.PUT("/prompts/:id", kolManageHandler.UpdatePromptMetadata)
|
||||||
|
kolManage.DELETE("/prompts/:id", kolManageHandler.DeletePrompt)
|
||||||
|
kolManage.POST("/prompts/:id/draft", kolManageHandler.SaveDraft)
|
||||||
|
kolManage.POST("/prompts/:id/publish", kolManageHandler.PublishPrompt)
|
||||||
|
|
||||||
articles := protected.Group("/tenant/articles")
|
articles := protected.Group("/tenant/articles")
|
||||||
artHandler := NewArticleHandler(app)
|
artHandler := NewArticleHandler(app)
|
||||||
articles.GET("", artHandler.List)
|
articles.GET("", artHandler.List)
|
||||||
|
|||||||
Reference in New Issue
Block a user