mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-10 14:15:42 +00:00
284 lines
9.6 KiB
Go
284 lines
9.6 KiB
Go
package main
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
amodels "github.com/abhinavxd/libredesk/internal/auth/models"
|
|
"github.com/abhinavxd/libredesk/internal/envelope"
|
|
vmodels "github.com/abhinavxd/libredesk/internal/view/models"
|
|
"github.com/valyala/fasthttp"
|
|
"github.com/zerodha/fastglue"
|
|
)
|
|
|
|
// handleGetUserViews returns all personal views for a user.
|
|
func handleGetUserViews(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
auser = r.RequestCtx.UserValue("user").(amodels.User)
|
|
)
|
|
user, err := app.user.GetAgentCachedOrLoad(auser.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
v, err := app.view.GetUsersViews(user.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(v)
|
|
}
|
|
|
|
// handleCreateUserView creates a personal view for a user.
|
|
func handleCreateUserView(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
view = vmodels.View{}
|
|
auser = r.RequestCtx.UserValue("user").(amodels.User)
|
|
)
|
|
if err := r.Decode(&view, "json"); err != nil {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("errors.parsingRequest"), err.Error(), envelope.InputError)
|
|
}
|
|
user, err := app.user.GetAgentCachedOrLoad(auser.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
if view.Name == "" {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`Name`"), nil, envelope.InputError)
|
|
}
|
|
if string(view.Filters) == "" {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`Filters`"), nil, envelope.InputError)
|
|
}
|
|
if err := app.conversation.ValidateListFilters(string(view.Filters)); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
createdView, err := app.view.Create(view.Name, view.Filters, user.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(createdView)
|
|
}
|
|
|
|
// handleDeleteUserView deletes a personal view for a user.
|
|
func handleDeleteUserView(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
auser = r.RequestCtx.UserValue("user").(amodels.User)
|
|
)
|
|
id, err := strconv.Atoi(r.RequestCtx.UserValue("id").(string))
|
|
if err != nil || id <= 0 {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.somethingWentWrong"), nil, envelope.InputError)
|
|
}
|
|
user, err := app.user.GetAgentCachedOrLoad(auser.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
view, err := app.view.Get(id)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
// Only allow deletion of personal views owned by the user
|
|
if err := validatePersonalViewOwnership(app, view, user.ID); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
if err = app.view.Delete(id); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(true)
|
|
}
|
|
|
|
// handleUpdateUserView updates a personal view for a user.
|
|
func handleUpdateUserView(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
auser = r.RequestCtx.UserValue("user").(amodels.User)
|
|
view = vmodels.View{}
|
|
)
|
|
id, err := strconv.Atoi(r.RequestCtx.UserValue("id").(string))
|
|
if err != nil || id == 0 {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.somethingWentWrong"), nil, envelope.InputError)
|
|
}
|
|
if err := r.Decode(&view, "json"); err != nil {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("errors.parsingRequest"), err.Error(), envelope.InputError)
|
|
}
|
|
user, err := app.user.GetAgentCachedOrLoad(auser.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
if view.Name == "" {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`name`"), nil, envelope.InputError)
|
|
}
|
|
if string(view.Filters) == "" {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.empty", "name", "`filters`"), nil, envelope.InputError)
|
|
}
|
|
if err := app.conversation.ValidateListFilters(string(view.Filters)); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
v, err := app.view.Get(id)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
// Only allow update of personal views owned by the user
|
|
if err := validatePersonalViewOwnership(app, v, user.ID); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
updatedView, err := app.view.Update(id, view.Name, view.Filters, user.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(updatedView)
|
|
}
|
|
|
|
// handleGetSharedViews returns shared views accessible to the current user.
|
|
func handleGetSharedViews(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
auser = r.RequestCtx.UserValue("user").(amodels.User)
|
|
)
|
|
user, err := app.user.GetAgentCachedOrLoad(auser.ID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
views, err := app.view.GetSharedViewsForUser(user.Teams.IDs())
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(views)
|
|
}
|
|
|
|
// handleGetAllSharedViews returns all shared views (admin only).
|
|
func handleGetAllSharedViews(r *fastglue.Request) error {
|
|
app := r.Context.(*App)
|
|
views, err := app.view.GetAllSharedViews()
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(views)
|
|
}
|
|
|
|
// handleGetSharedView returns a single shared view (admin only).
|
|
func handleGetSharedView(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
id, _ = strconv.Atoi(r.RequestCtx.UserValue("id").(string))
|
|
)
|
|
if id <= 0 {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.somethingWentWrong"), nil, envelope.InputError)
|
|
}
|
|
view, err := app.view.Get(id)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
// Ensure it's a shared view (not a personal view)
|
|
if view.Visibility == vmodels.VisibilityUser {
|
|
return r.SendErrorEnvelope(fasthttp.StatusNotFound, app.i18n.T("validation.notFoundView"), nil, envelope.NotFoundError)
|
|
}
|
|
return r.SendEnvelope(view)
|
|
}
|
|
|
|
// handleCreateSharedView creates a shared view (admin only).
|
|
func handleCreateSharedView(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
view = vmodels.View{}
|
|
)
|
|
if err := r.Decode(&view, "json"); err != nil {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("errors.parsingRequest"), err.Error(), envelope.InputError)
|
|
}
|
|
|
|
// Validation
|
|
if err := validateSharedView(app, view); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
|
|
createdView, err := app.view.CreateSharedView(view.Name, view.Filters, view.Visibility, view.TeamID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(createdView)
|
|
}
|
|
|
|
// handleUpdateSharedView updates a shared view (admin only).
|
|
func handleUpdateSharedView(r *fastglue.Request) error {
|
|
var (
|
|
app = r.Context.(*App)
|
|
view = vmodels.View{}
|
|
id, _ = strconv.Atoi(r.RequestCtx.UserValue("id").(string))
|
|
)
|
|
if id <= 0 {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.somethingWentWrong"), nil, envelope.InputError)
|
|
}
|
|
if err := r.Decode(&view, "json"); err != nil {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("errors.parsingRequest"), err.Error(), envelope.InputError)
|
|
}
|
|
|
|
// Verify view exists and is shared
|
|
existingView, err := app.view.Get(id)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
if existingView.Visibility == vmodels.VisibilityUser {
|
|
return r.SendErrorEnvelope(fasthttp.StatusNotFound, app.i18n.T("validation.notFoundView"), nil, envelope.NotFoundError)
|
|
}
|
|
|
|
// Validation
|
|
if err := validateSharedView(app, view); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
|
|
updatedView, err := app.view.UpdateSharedView(id, view.Name, view.Filters, view.Visibility, view.TeamID)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(updatedView)
|
|
}
|
|
|
|
// handleDeleteSharedView deletes a shared view (admin only).
|
|
func handleDeleteSharedView(r *fastglue.Request) error {
|
|
app := r.Context.(*App)
|
|
id, err := strconv.Atoi(r.RequestCtx.UserValue("id").(string))
|
|
if err != nil || id <= 0 {
|
|
return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.somethingWentWrong"), nil, envelope.InputError)
|
|
}
|
|
|
|
// Verify view exists and is shared
|
|
existingView, err := app.view.Get(id)
|
|
if err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
if existingView.Visibility == vmodels.VisibilityUser {
|
|
return r.SendErrorEnvelope(fasthttp.StatusNotFound, app.i18n.T("validation.notFoundView"), nil, envelope.NotFoundError)
|
|
}
|
|
|
|
if err = app.view.Delete(id); err != nil {
|
|
return sendErrorEnvelope(r, err)
|
|
}
|
|
return r.SendEnvelope(true)
|
|
}
|
|
|
|
// validatePersonalViewOwnership checks if the user owns the personal view.
|
|
func validatePersonalViewOwnership(app *App, view vmodels.View, userID int) error {
|
|
if view.UserID == nil || *view.UserID != userID || view.Visibility != vmodels.VisibilityUser {
|
|
return envelope.NewError(envelope.PermissionError, app.i18n.T("status.deniedPermission"), nil)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateSharedView validates the fields of a shared view.
|
|
func validateSharedView(app *App, view vmodels.View) error {
|
|
if view.Name == "" {
|
|
return envelope.NewError(envelope.InputError, app.i18n.Ts("globals.messages.empty", "name", "`name`"), nil)
|
|
}
|
|
if string(view.Filters) == "" {
|
|
return envelope.NewError(envelope.InputError, app.i18n.Ts("globals.messages.empty", "name", "`filters`"), nil)
|
|
}
|
|
if err := app.conversation.ValidateListFilters(string(view.Filters)); err != nil {
|
|
return err
|
|
}
|
|
if view.Visibility != vmodels.VisibilityAll && view.Visibility != vmodels.VisibilityTeam {
|
|
return envelope.NewError(envelope.InputError, app.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
if view.Visibility == vmodels.VisibilityTeam && (view.TeamID == nil || *view.TeamID <= 0) {
|
|
return envelope.NewError(envelope.InputError, app.i18n.Ts("globals.messages.required", "name", "`team_id`"), nil)
|
|
}
|
|
return nil
|
|
}
|