feat(tenant/kol): let KOLs self-subscribe to their own published packages
Add /kol/manage/packages/:id/self-subscription POST/DELETE on the tenant side so a KOL can grant themselves access to their own published package without going through the marketplace approval flow. Reject self-subscribe through the marketplace with a clear error, expose owned_by_current_tenant on package responses, and surface a self_subscription block on KolPackage Response. The admin-web KOL workspace gets 订阅自己 / 取消订阅 entries with matching messaging in the marketplace detail view. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ func NewKolManageHandler(a *bootstrap.App, assets *AssetHandler) *KolManageHandl
|
||||
|
||||
return &KolManageHandler{
|
||||
profileSvc: profileSvc,
|
||||
pkgSvc: app.NewKolPackageService(profileSvc, a.KolPackages, a.KolPrompts).WithCache(a.Cache),
|
||||
pkgSvc: app.NewKolPackageService(profileSvc, a.KolPackages, a.KolPrompts, a.KolSubscriptions).WithCache(a.Cache),
|
||||
promptSvc: app.NewKolPromptService(a.DB, profileSvc, a.KolPackages, a.KolPrompts, a.KolSubscriptions, a.KolPromptAsset).WithCache(a.Cache),
|
||||
assistSvc: app.NewKolAssistService(a.DB, profileSvc, a.KolAssists, a.LLM, a.RabbitMQ, a.Config.LLM, a.Logger).WithCache(a.Cache),
|
||||
assets: assets,
|
||||
@@ -249,6 +249,46 @@ func (h *KolManageHandler) ArchivePackage(c *gin.Context) {
|
||||
response.Success(c, data)
|
||||
}
|
||||
|
||||
func (h *KolManageHandler) SelfSubscribePackage(c *gin.Context) {
|
||||
id, ok := parseInt64Param(c, "id", "package id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
actor, ok := actorFromRequest(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := h.pkgSvc.SelfSubscribe(c.Request.Context(), actor, id)
|
||||
if err != nil {
|
||||
response.Error(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, data)
|
||||
}
|
||||
|
||||
func (h *KolManageHandler) CancelSelfSubscription(c *gin.Context) {
|
||||
id, ok := parseInt64Param(c, "id", "package id")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
actor, ok := actorFromRequest(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := h.pkgSvc.CancelSelfSubscription(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 {
|
||||
|
||||
@@ -108,6 +108,8 @@ func RegisterRoutes(app *bootstrap.App) {
|
||||
kolManage.DELETE("/packages/:id", kolManageHandler.DeletePackage)
|
||||
kolManage.PUT("/packages/:id/publish", kolManageHandler.PublishPackage)
|
||||
kolManage.PUT("/packages/:id/archive", kolManageHandler.ArchivePackage)
|
||||
kolManage.POST("/packages/:id/self-subscription", kolManageHandler.SelfSubscribePackage)
|
||||
kolManage.DELETE("/packages/:id/self-subscription", kolManageHandler.CancelSelfSubscription)
|
||||
kolManage.GET("/packages/:id/prompts", kolManageHandler.ListPrompts)
|
||||
kolManage.POST("/packages/:id/prompts", kolManageHandler.CreatePrompt)
|
||||
kolManage.GET("/prompts/:id", kolManageHandler.GetPromptLatest)
|
||||
@@ -139,14 +141,6 @@ func RegisterRoutes(app *bootstrap.App) {
|
||||
kolSubscriptions.GET("/subscription-prompts/:id/schema", kolMarketplaceHandler.SubscriptionPromptSchema)
|
||||
kolSubscriptions.POST("/subscription-prompts/:id/generate", kolMarketplaceHandler.Generate)
|
||||
|
||||
// V1 compromise: these admin operations live on tenant-api and are gated by
|
||||
// tenant_role=tenant_admin until the platform-api/module is built.
|
||||
kolAdmin := tenantProtected.Group("/kol/admin")
|
||||
kolAdminHandler := NewKolAdminHandler(app)
|
||||
kolAdmin.PUT("/subscriptions/:id/approve", kolAdminHandler.ApproveSubscription)
|
||||
kolAdmin.POST("/subscriptions", kolAdminHandler.ManualBind)
|
||||
kolAdmin.PUT("/subscriptions/:id/revoke", kolAdminHandler.RevokeSubscription)
|
||||
|
||||
articles := tenantProtected.Group("/articles")
|
||||
artHandler := NewArticleHandler(app)
|
||||
articles.GET("", artHandler.List)
|
||||
|
||||
Reference in New Issue
Block a user