Files
olons_server/internal/httpapi/admin.go
T

250 lines
7.4 KiB
Go

package httpapi
import (
"encoding/json"
"net/http"
"strconv"
"strings"
"time"
"git.118im.com/im_team/im_workbench/internal/store"
)
func (a *API) adminWorkbenchApps(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
page := queryInt(r, "page", 1)
perPage := queryInt(r, "per_page", 20)
var enabled *int
if raw := strings.TrimSpace(r.URL.Query().Get("enabled")); raw != "" {
if value, err := strconv.Atoi(raw); err == nil {
enabled = &value
}
}
items, total, err := a.store.AdminWorkbenchModules(r.Context(), page, perPage, r.URL.Query().Get("code"), r.URL.Query().Get("name"), enabled)
if err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, map[string]any{"items": adminWorkbenchModulePayloads(items), "total": total, "page": page, "per_page": perPage})
case http.MethodPost:
var body adminWorkbenchModuleRequest
if !decodeJSON(w, r, &body) {
return
}
item, err := a.store.UpsertAdminWorkbenchModule(r.Context(), store.AdminWorkbenchModuleInput{
ID: body.ID, Code: body.Code, Name: body.Name, IconFileID: body.IconFileID, Route: body.Route,
SortOrder: body.SortOrder, UnreadKey: body.UnreadKey, Enabled: body.Enabled, Permission: body.Permission,
})
if err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, adminWorkbenchModulePayload(*item))
default:
methodNotAllowed(w, r)
}
}
func (a *API) adminWorkbenchAppDisable(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
methodNotAllowed(w, r)
return
}
var body struct {
ID int64 `json:"id"`
Code string `json:"code"`
}
if !decodeJSON(w, r, &body) {
return
}
if err := a.store.DisableAdminWorkbenchModule(r.Context(), body.ID, body.Code); err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, map[string]any{"ok": true})
}
func (a *API) adminWorkbenchAppsReorder(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
methodNotAllowed(w, r)
return
}
var body struct {
Items []struct {
Code string `json:"code"`
SortOrder int `json:"sort_order"`
} `json:"items"`
}
if !decodeJSON(w, r, &body) {
return
}
items := make([]store.AdminWorkbenchReorderItem, 0, len(body.Items))
for _, item := range body.Items {
items = append(items, store.AdminWorkbenchReorderItem{Code: item.Code, SortOrder: item.SortOrder})
}
if err := a.store.ReorderAdminWorkbenchModules(r.Context(), items); err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, map[string]any{"ok": true})
}
func (a *API) adminMailboxConfig(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
cfg, err := a.store.AdminMailboxConfig(r.Context())
if err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, adminMailboxConfigPayload(*cfg))
case http.MethodPost:
var body adminMailboxConfigRequest
if !decodeJSON(w, r, &body) {
return
}
if err := a.store.UpdateAdminMailboxConfig(r.Context(), store.AdminMailboxConfig{
Enabled: body.Enabled, AllowAnonymous: body.AllowAnonymous, RequiredFields: body.RequiredFields,
MaxLength: body.MaxLength, AttachmentPolicy: body.AttachmentPolicy, NoticeTitle: body.NoticeTitle, NoticeContent: body.NoticeContent,
}); err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, map[string]any{"ok": true})
default:
methodNotAllowed(w, r)
}
}
func (a *API) adminFeedbackConfig(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
cfg, err := a.store.AdminFeedbackConfig(r.Context())
if err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, adminFeedbackConfigPayload(*cfg))
case http.MethodPost:
var body adminFeedbackConfigRequest
if !decodeJSON(w, r, &body) {
return
}
if err := a.store.UpdateAdminFeedbackConfig(r.Context(), store.AdminFeedbackConfig{
Categories: body.Categories, MaxLength: body.MaxLength, AttachmentPolicy: body.AttachmentPolicy,
AllowContact: body.AllowContact, DiagnosticsNotice: body.DiagnosticsNotice,
}); err != nil {
writeStoreError(w, r, err)
return
}
writeSuccess(w, r, map[string]any{"ok": true})
default:
methodNotAllowed(w, r)
}
}
type adminWorkbenchModuleRequest struct {
ID int64 `json:"id"`
Code string `json:"code"`
Name string `json:"name"`
IconFileID string `json:"icon_file_id"`
Route string `json:"route"`
SortOrder int `json:"sort_order"`
UnreadKey string `json:"unread_key"`
Enabled int `json:"enabled"`
Permission string `json:"permission"`
}
type adminMailboxConfigRequest struct {
Enabled int `json:"enabled"`
AllowAnonymous int `json:"allow_anonymous"`
RequiredFields string `json:"required_fields"`
MaxLength int `json:"max_length"`
AttachmentPolicy string `json:"attachment_policy"`
NoticeTitle string `json:"notice_title"`
NoticeContent string `json:"notice_content"`
}
type adminFeedbackConfigRequest struct {
Categories string `json:"categories"`
MaxLength int `json:"max_length"`
AttachmentPolicy string `json:"attachment_policy"`
AllowContact int `json:"allow_contact"`
DiagnosticsNotice string `json:"diagnostics_notice"`
}
func adminWorkbenchModulePayloads(items []store.AdminWorkbenchModule) []map[string]any {
res := make([]map[string]any, 0, len(items))
for _, item := range items {
res = append(res, adminWorkbenchModulePayload(item))
}
return res
}
func adminWorkbenchModulePayload(item store.AdminWorkbenchModule) map[string]any {
return map[string]any{
"id": item.ID,
"code": item.Code,
"name": item.Name,
"iconFileId": item.IconFileID,
"route": item.Route,
"sortOrder": item.SortOrder,
"unreadKey": item.UnreadKey,
"enabled": item.Enabled,
"permission": item.Permission,
"createdAt": formatAdminTime(item.CreatedAt),
"updatedAt": formatAdminTime(item.UpdatedAt),
}
}
func adminMailboxConfigPayload(cfg store.AdminMailboxConfig) map[string]any {
return map[string]any{
"id": cfg.ID,
"enabled": cfg.Enabled,
"allowAnonymous": cfg.AllowAnonymous,
"requiredFields": cfg.RequiredFields,
"maxLength": cfg.MaxLength,
"attachmentPolicy": cfg.AttachmentPolicy,
"noticeTitle": cfg.NoticeTitle,
"noticeContent": cfg.NoticeContent,
"noticeUpdatedAt": formatAdminTime(cfg.NoticeUpdatedAt),
"updatedAt": formatAdminTime(cfg.UpdatedAt),
}
}
func adminFeedbackConfigPayload(cfg store.AdminFeedbackConfig) map[string]any {
return map[string]any{
"id": cfg.ID,
"categories": cfg.Categories,
"maxLength": cfg.MaxLength,
"attachmentPolicy": cfg.AttachmentPolicy,
"allowContact": cfg.AllowContact,
"diagnosticsNotice": cfg.DiagnosticsNotice,
"updatedAt": formatAdminTime(cfg.UpdatedAt),
}
}
func decodeJSON(w http.ResponseWriter, r *http.Request, out any) bool {
if err := json.NewDecoder(r.Body).Decode(out); err != nil {
writeError(w, r, http.StatusBadRequest, 30000, reasonMalformedRequest, "malformed request", nil)
return false
}
return true
}
func queryInt(r *http.Request, key string, fallback int) int {
value, err := strconv.Atoi(strings.TrimSpace(r.URL.Query().Get(key)))
if err != nil || value <= 0 {
return fallback
}
return value
}
func formatAdminTime(t time.Time) string {
if t.IsZero() {
return ""
}
return t.UTC().Format(time.RFC3339Nano)
}