second commit
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/pkg/response"
|
||||
)
|
||||
|
||||
// PlatformAgentBotHandler handles Platform API agent bot endpoints (AccessToken auth).
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController — AccessToken authenticated
|
||||
//
|
||||
// Distinct from account-level AgentBotHandler: this uses AccessToken authentication
|
||||
// + Permissible system for resource-level access control.
|
||||
// Platform-level bots (account_id == nil) and account-scoped bots are both accessible.
|
||||
type PlatformAgentBotHandler struct {
|
||||
agentBotRepo *repository.AgentBotRepo
|
||||
permissibleRepo *repository.PermissibleRepo
|
||||
}
|
||||
|
||||
// NewPlatformAgentBotHandler creates a new PlatformAgentBot handler.
|
||||
func NewPlatformAgentBotHandler(
|
||||
agentBotRepo *repository.AgentBotRepo,
|
||||
permissibleRepo *repository.PermissibleRepo,
|
||||
) *PlatformAgentBotHandler {
|
||||
return &PlatformAgentBotHandler{
|
||||
agentBotRepo: agentBotRepo,
|
||||
permissibleRepo: permissibleRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// List returns all agent bots the PlatformApp has permissible access to.
|
||||
// GET /platform/api/v1/agent_bots
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController#index
|
||||
func (h *PlatformAgentBotHandler) List(c *gin.Context) {
|
||||
platformAppID := getPlatformAppID(c)
|
||||
|
||||
permissibles, err := h.permissibleRepo.FindByPlatformAppID(c.Request.Context(), platformAppID)
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var bots []model.AgentBot
|
||||
for _, perm := range permissibles {
|
||||
if perm.PermissibleType == model.PermissibleTypeAgentBot {
|
||||
bot, err := h.agentBotRepo.FindByID(c.Request.Context(), perm.PermissibleID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
bots = append(bots, *bot)
|
||||
}
|
||||
}
|
||||
|
||||
response.OK(c, bots)
|
||||
}
|
||||
|
||||
// Show retrieves an agent bot by ID.
|
||||
// GET /platform/api/v1/agent_bots/:id
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController#show
|
||||
// Requires: Permissible verification
|
||||
func (h *PlatformAgentBotHandler) Show(c *gin.Context) {
|
||||
botID, err := parseUintParam(c, "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid bot ID")
|
||||
return
|
||||
}
|
||||
|
||||
platformAppID := getPlatformAppID(c)
|
||||
|
||||
// Verify Permissible access
|
||||
perm, err := h.permissibleRepo.FindByPlatformAppAndResource(c.Request.Context(), platformAppID, model.PermissibleTypeAgentBot, botID)
|
||||
if err != nil || perm == nil {
|
||||
response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "non permissible resource")
|
||||
return
|
||||
}
|
||||
|
||||
bot, err := h.agentBotRepo.FindByID(c.Request.Context(), botID)
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusNotFound, response.ErrNotFound, "agent bot not found")
|
||||
return
|
||||
}
|
||||
|
||||
response.OK(c, bot)
|
||||
}
|
||||
|
||||
// Create creates a new agent bot and auto-creates Permissible record.
|
||||
// POST /platform/api/v1/agent_bots
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController#create
|
||||
// Auto-permissible: PlatformApp automatically gets access to the created bot.
|
||||
func (h *PlatformAgentBotHandler) Create(c *gin.Context) {
|
||||
platformAppID := getPlatformAppID(c)
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description,omitempty"`
|
||||
AvatarURL string `json:"avatar_url,omitempty"`
|
||||
AccountID *uint `json:"account_id,omitempty"`
|
||||
Config model.AgentBot `json:"config,omitempty"` // Embedded struct for bot config
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
bot := &model.AgentBot{
|
||||
AccountID: req.AccountID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
AvatarURL: req.AvatarURL,
|
||||
}
|
||||
|
||||
if err := h.agentBotRepo.Create(c.Request.Context(), bot); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Auto-create Permissible
|
||||
perm := &model.Permissible{
|
||||
PlatformAppID: platformAppID,
|
||||
PermissibleType: model.PermissibleTypeAgentBot,
|
||||
PermissibleID: bot.ID,
|
||||
}
|
||||
if err := h.permissibleRepo.Create(c.Request.Context(), perm); err != nil {
|
||||
// Non-critical
|
||||
}
|
||||
|
||||
response.Created(c, bot)
|
||||
}
|
||||
|
||||
// Update updates an agent bot.
|
||||
// PUT /platform/api/v1/agent_bots/:id
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController#update
|
||||
// Requires: Permissible verification
|
||||
func (h *PlatformAgentBotHandler) Update(c *gin.Context) {
|
||||
botID, err := parseUintParam(c, "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid bot ID")
|
||||
return
|
||||
}
|
||||
|
||||
platformAppID := getPlatformAppID(c)
|
||||
|
||||
// Verify Permissible access
|
||||
perm, err := h.permissibleRepo.FindByPlatformAppAndResource(c.Request.Context(), platformAppID, model.PermissibleTypeAgentBot, botID)
|
||||
if err != nil || perm == nil {
|
||||
response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "non permissible resource")
|
||||
return
|
||||
}
|
||||
|
||||
bot, err := h.agentBotRepo.FindByID(c.Request.Context(), botID)
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusNotFound, response.ErrNotFound, "agent bot not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
AvatarURL string `json:"avatar_url,omitempty"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
bot.Name = req.Name
|
||||
}
|
||||
if req.Description != "" {
|
||||
bot.Description = req.Description
|
||||
}
|
||||
if req.AvatarURL != "" {
|
||||
bot.AvatarURL = req.AvatarURL
|
||||
}
|
||||
|
||||
if err := h.agentBotRepo.Update(c.Request.Context(), bot); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.OK(c, bot)
|
||||
}
|
||||
|
||||
// Destroy deletes an agent bot.
|
||||
// DELETE /platform/api/v1/agent_bots/:id
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController#destroy
|
||||
// Requires: Permissible verification
|
||||
func (h *PlatformAgentBotHandler) Destroy(c *gin.Context) {
|
||||
botID, err := parseUintParam(c, "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid bot ID")
|
||||
return
|
||||
}
|
||||
|
||||
platformAppID := getPlatformAppID(c)
|
||||
|
||||
// Verify Permissible access
|
||||
perm, err := h.permissibleRepo.FindByPlatformAppAndResource(c.Request.Context(), platformAppID, model.PermissibleTypeAgentBot, botID)
|
||||
if err != nil || perm == nil {
|
||||
response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "non permissible resource")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.agentBotRepo.Delete(c.Request.Context(), botID); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.NoContent(c)
|
||||
}
|
||||
|
||||
// DeleteAvatar removes the avatar of an agent bot.
|
||||
// POST /platform/api/v1/agent_bots/:id/delete_avatar
|
||||
// Reference: Chatwoot Platform::Api::V1::AgentBotsController#delete_avatar
|
||||
// Requires: Permissible verification
|
||||
func (h *PlatformAgentBotHandler) DeleteAvatar(c *gin.Context) {
|
||||
botID, err := parseUintParam(c, "id")
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid bot ID")
|
||||
return
|
||||
}
|
||||
|
||||
platformAppID := getPlatformAppID(c)
|
||||
|
||||
// Verify Permissible access
|
||||
perm, err := h.permissibleRepo.FindByPlatformAppAndResource(c.Request.Context(), platformAppID, model.PermissibleTypeAgentBot, botID)
|
||||
if err != nil || perm == nil {
|
||||
response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "non permissible resource")
|
||||
return
|
||||
}
|
||||
|
||||
bot, err := h.agentBotRepo.FindByID(c.Request.Context(), botID)
|
||||
if err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusNotFound, response.ErrNotFound, "agent bot not found")
|
||||
return
|
||||
}
|
||||
|
||||
bot.AvatarURL = ""
|
||||
if err := h.agentBotRepo.Update(c.Request.Context(), bot); err != nil {
|
||||
response.AbortWithStatusError(c, http.StatusInternalServerError, response.ErrInternal, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.OK(c, bot)
|
||||
}
|
||||
Reference in New Issue
Block a user