227 lines
7.0 KiB
Go
227 lines
7.0 KiB
Go
package services
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// ShieldClient cliente HTTP para la API de USITE Shield.
|
|
type ShieldClient struct {
|
|
baseURL string
|
|
adminToken string
|
|
http *http.Client
|
|
}
|
|
|
|
func NewShieldClient(baseURL, adminToken string) *ShieldClient {
|
|
if baseURL == "" {
|
|
baseURL = "https://api-shield.u-s.app"
|
|
}
|
|
return &ShieldClient{
|
|
baseURL: baseURL,
|
|
adminToken: adminToken,
|
|
http: &http.Client{Timeout: 15 * time.Second},
|
|
}
|
|
}
|
|
|
|
func (s *ShieldClient) do(method, path string, body interface{}) ([]byte, int, error) {
|
|
var bodyReader io.Reader
|
|
if body != nil {
|
|
b, err := json.Marshal(body)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
bodyReader = bytes.NewReader(b)
|
|
}
|
|
req, err := http.NewRequest(method, s.baseURL+path, bodyReader)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if s.adminToken != "" {
|
|
req.Header.Set("Authorization", "Bearer "+s.adminToken)
|
|
}
|
|
resp, err := s.http.Do(req)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
defer resp.Body.Close()
|
|
data, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, resp.StatusCode, err
|
|
}
|
|
if resp.StatusCode >= 400 {
|
|
// La API puede devolver texto plano en errores; evitamos que el caller intente parsear JSON
|
|
msg := string(data)
|
|
if msg == "" {
|
|
msg = resp.Status
|
|
}
|
|
return nil, resp.StatusCode, fmt.Errorf("shield API error %d: %s", resp.StatusCode, msg)
|
|
}
|
|
return data, resp.StatusCode, nil
|
|
}
|
|
|
|
// ─── Health ──────────────────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) Health() (map[string]interface{}, error) {
|
|
data, _, err := s.do("GET", "/health", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
// ─── Extension version ───────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) ExtensionVersion() (map[string]interface{}, error) {
|
|
data, _, err := s.do("GET", "/api/extension/version", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
// ─── Logs ────────────────────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) Logs(limit int, path, method string) (map[string]interface{}, error) {
|
|
q := fmt.Sprintf("/api/admin/logs?limit=%d", limit)
|
|
if path != "" {
|
|
q += "&path=" + path
|
|
}
|
|
if method != "" {
|
|
q += "&method=" + method
|
|
}
|
|
data, _, err := s.do("GET", q, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
func (s *ShieldClient) LogStats() (map[string]interface{}, error) {
|
|
data, _, err := s.do("GET", "/api/admin/logs/stats", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
// ─── Review requests ─────────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) ReviewRequests(status string) (map[string]interface{}, error) {
|
|
if status == "" {
|
|
status = "pending"
|
|
}
|
|
data, _, err := s.do("GET", "/api/admin/review-requests?status="+status, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
func (s *ShieldClient) ApproveRequest(id, note, reason string) (map[string]interface{}, error) {
|
|
body := map[string]string{"note": note, "reason": reason}
|
|
data, _, err := s.do("PUT", "/api/admin/review-requests/"+id+"/approve", body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
json.Unmarshal(data, &out)
|
|
return out, nil
|
|
}
|
|
|
|
func (s *ShieldClient) RejectRequest(id, note string) (map[string]interface{}, error) {
|
|
body := map[string]string{"note": note}
|
|
data, _, err := s.do("PUT", "/api/admin/review-requests/"+id+"/reject", body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
json.Unmarshal(data, &out)
|
|
return out, nil
|
|
}
|
|
|
|
// ─── Whitelist ───────────────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) Whitelist() (map[string]interface{}, error) {
|
|
data, _, err := s.do("GET", "/api/admin/whitelist", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
func (s *ShieldClient) AddWhitelist(domain, reason, addedBy string) (map[string]interface{}, error) {
|
|
body := map[string]string{"domain": domain, "reason": reason, "added_by": addedBy}
|
|
data, _, err := s.do("POST", "/api/admin/whitelist", body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
json.Unmarshal(data, &out)
|
|
return out, nil
|
|
}
|
|
|
|
func (s *ShieldClient) DeleteWhitelist(domain string) error {
|
|
_, _, err := s.do("DELETE", "/api/admin/whitelist/"+domain, nil)
|
|
return err
|
|
}
|
|
|
|
// ─── Blacklist ───────────────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) Blacklist() (map[string]interface{}, error) {
|
|
data, _, err := s.do("GET", "/api/admin/blacklist", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
func (s *ShieldClient) AddBlacklist(domain, reason, addedBy string) (map[string]interface{}, error) {
|
|
body := map[string]string{"domain": domain, "reason": reason, "added_by": addedBy}
|
|
data, _, err := s.do("POST", "/api/admin/blacklist", body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
json.Unmarshal(data, &out)
|
|
return out, nil
|
|
}
|
|
|
|
func (s *ShieldClient) DeleteBlacklist(domain string) error {
|
|
_, _, err := s.do("DELETE", "/api/admin/blacklist/"+domain, nil)
|
|
return err
|
|
}
|
|
|
|
// ─── Reputación ──────────────────────────────────────────────────────────────
|
|
|
|
func (s *ShieldClient) Reputation(domain string) (map[string]interface{}, error) {
|
|
data, _, err := s.do("GET", "/api/reputation/"+domain, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
return out, json.Unmarshal(data, &out)
|
|
}
|
|
|
|
func (s *ShieldClient) AdjustScore(domain string, votesReal, votesFake int) (map[string]interface{}, error) {
|
|
body := map[string]int{"votes_real": votesReal, "votes_fake": votesFake}
|
|
data, _, err := s.do("PUT", "/api/admin/reputation/"+domain+"/score", body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out map[string]interface{}
|
|
json.Unmarshal(data, &out)
|
|
return out, nil
|
|
}
|