131 lines
4.3 KiB
Go
131 lines
4.3 KiB
Go
package channel
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"git.dustin.coffee/hobokenchicken/dumpsterChat/internal/middleware"
|
|
"git.dustin.coffee/hobokenchicken/dumpsterChat/internal/permissions"
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
type overrideRequest struct {
|
|
Allow int64 `json:"allow"`
|
|
Deny int64 `json:"deny"`
|
|
}
|
|
|
|
type overrideResponse struct {
|
|
ID string `json:"id"`
|
|
ChannelID string `json:"channel_id"`
|
|
TargetType string `json:"target_type"`
|
|
TargetID string `json:"target_id"`
|
|
Allow int64 `json:"allow_bitflags"`
|
|
Deny int64 `json:"deny_bitflags"`
|
|
}
|
|
|
|
func (h *Handler) registerOverrideRoutes(r chi.Router) {
|
|
r.Put("/{channelID}/permissions/{targetType}/{targetID}", h.SetOverride)
|
|
r.Get("/{channelID}/permissions", h.ListOverrides)
|
|
r.Delete("/{channelID}/permissions/{targetType}/{targetID}", h.DeleteOverride)
|
|
}
|
|
|
|
func (h *Handler) requireChannelManager(w http.ResponseWriter, r *http.Request, channelID string) (userID, serverID string, ok bool) {
|
|
userID, authOK := middleware.UserIDFromContext(r.Context())
|
|
if !authOK {
|
|
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
|
|
return "", "", false
|
|
}
|
|
serverID, err := h.serverIDForChannel(r.Context(), channelID)
|
|
if err != nil {
|
|
http.Error(w, `{"error":"channel not found"}`, http.StatusNotFound)
|
|
return "", "", false
|
|
}
|
|
allowed, err := h.checker.CheckPermission(r.Context(), serverID, userID, permissions.MANAGE_CHANNELS)
|
|
if err != nil || !allowed {
|
|
http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
|
|
return "", "", false
|
|
}
|
|
return userID, serverID, true
|
|
}
|
|
|
|
func (h *Handler) SetOverride(w http.ResponseWriter, r *http.Request) {
|
|
channelID := chi.URLParam(r, "channelID")
|
|
_, _, ok := h.requireChannelManager(w, r, channelID)
|
|
if !ok {
|
|
return
|
|
}
|
|
targetType := chi.URLParam(r, "targetType")
|
|
targetID := chi.URLParam(r, "targetID")
|
|
if targetType != "role" && targetType != "user" {
|
|
http.Error(w, `{"error":"invalid target_type"}`, http.StatusBadRequest)
|
|
return
|
|
}
|
|
var req overrideRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var res overrideResponse
|
|
err := h.db.QueryRowContext(r.Context(), `
|
|
INSERT INTO channel_overrides (channel_id, target_type, target_id, allow_bitflags, deny_bitflags)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
ON CONFLICT (channel_id, target_type, target_id)
|
|
DO UPDATE SET allow_bitflags = EXCLUDED.allow_bitflags, deny_bitflags = EXCLUDED.deny_bitflags, updated_at = NOW()
|
|
RETURNING id, channel_id, target_type, target_id, allow_bitflags, deny_bitflags
|
|
`, channelID, targetType, targetID, req.Allow, req.Deny).Scan(&res.ID, &res.ChannelID, &res.TargetType, &res.TargetID, &res.Allow, &res.Deny)
|
|
if err != nil {
|
|
http.Error(w, `{"error":"failed to set override"}`, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(res)
|
|
}
|
|
|
|
func (h *Handler) ListOverrides(w http.ResponseWriter, r *http.Request) {
|
|
channelID := chi.URLParam(r, "channelID")
|
|
_, _, ok := h.requireChannelManager(w, r, channelID)
|
|
if !ok {
|
|
return
|
|
}
|
|
rows, err := h.db.QueryContext(r.Context(), `
|
|
SELECT id, channel_id, target_type, target_id, allow_bitflags, deny_bitflags
|
|
FROM channel_overrides
|
|
WHERE channel_id = $1
|
|
ORDER BY target_type, target_id
|
|
`, channelID)
|
|
if err != nil {
|
|
http.Error(w, `{"error":"server error"}`, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
overrides := make([]overrideResponse, 0)
|
|
for rows.Next() {
|
|
var o overrideResponse
|
|
if err := rows.Scan(&o.ID, &o.ChannelID, &o.TargetType, &o.TargetID, &o.Allow, &o.Deny); err != nil {
|
|
continue
|
|
}
|
|
overrides = append(overrides, o)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(overrides)
|
|
}
|
|
|
|
func (h *Handler) DeleteOverride(w http.ResponseWriter, r *http.Request) {
|
|
channelID := chi.URLParam(r, "channelID")
|
|
_, _, ok := h.requireChannelManager(w, r, channelID)
|
|
if !ok {
|
|
return
|
|
}
|
|
targetType := chi.URLParam(r, "targetType")
|
|
targetID := chi.URLParam(r, "targetID")
|
|
_, err := h.db.ExecContext(r.Context(), `
|
|
DELETE FROM channel_overrides WHERE channel_id = $1 AND target_type = $2 AND target_id = $3
|
|
`, channelID, targetType, targetID)
|
|
if err != nil {
|
|
http.Error(w, `{"error":"failed to delete override"}`, http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|