- embedded React admin UI at /admin/ui (go:embed), login with ADMIN_SECRET via signed HttpOnly session cookie, X-ADMIN-KEY still works for scripts - admin API: overview stats, indexing queue, addon management (priority, reindex, delete/restore/purge, bulk), whitelist CRUD, duplicate hashes, traffic, metrics explorer, services, events/audit log, system info - built-in metrics: request latency per route, visitors, top addons and searches, indexer/scraper counters; minute buckets in the DB with hourly rollups and retention; optional Prometheus /metrics (METRICS_TOKEN) - POST /back/telemetry for indexers/scrapers (metrics, events, heartbeat) and a stdlib-only Go client in telemetry/ - auth hardening: empty secrets no longer allow access, constant-time compare, CORS not applied to /admin and /back, TRUSTED_PROXIES setting - Dockerfile builds the UI and no longer bakes config.yaml into the image; CI builds the UI, runs tests and builds arm64 with CGO
This commit is contained in:
1 parent
0ef27b0072
commit
56d9e10621
79 files changed
+13146
-118
No files matched your search
@@ -4,6 +4,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"gitea.tbdevent.eu/TBD/reforger_crawler_main/initializers"
|
||||
"gitea.tbdevent.eu/TBD/reforger_crawler_main/metrics"
|
||||
"gitea.tbdevent.eu/TBD/reforger_crawler_main/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
@@ -53,6 +54,8 @@ func SetAddonDependencies(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
metrics.DependencyReports.Inc()
|
||||
metrics.DependencyEdges.Add(float64(len(edges)))
|
||||
c.JSON(200, gin.H{"status": "success", "stored": len(edges)})
|
||||
}
|
||||
|
||||
@@ -69,7 +72,7 @@ func GetDependents(c *gin.Context) {
|
||||
limit := parseLimit(c.Query("limit"))
|
||||
offset := parseOffset(c.Query("offset"))
|
||||
|
||||
dependents, total, err := queryRelatedAddons(addonID, "ad.addon_id", "ad.dependency_id", limit, offset)
|
||||
dependents, total, err := QueryRelatedAddons(addonID, "ad.addon_id", "ad.dependency_id", limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
return
|
||||
@@ -97,7 +100,7 @@ func GetDependencies(c *gin.Context) {
|
||||
limit := parseLimit(c.Query("limit"))
|
||||
offset := parseOffset(c.Query("offset"))
|
||||
|
||||
dependencies, total, err := queryRelatedAddons(addonID, "ad.dependency_id", "ad.addon_id", limit, offset)
|
||||
dependencies, total, err := QueryRelatedAddons(addonID, "ad.dependency_id", "ad.addon_id", limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
return
|
||||
@@ -112,7 +115,7 @@ func GetDependencies(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// queryRelatedAddons returns one page of addons linked to addonID through the
|
||||
// QueryRelatedAddons returns one page of addons linked to addonID through the
|
||||
// addon_dependencies edge table, plus the total number of matches.
|
||||
//
|
||||
// joinCol is the edge column joined to addons.id; filterCol is the edge column
|
||||
@@ -120,7 +123,7 @@ func GetDependencies(c *gin.Context) {
|
||||
//
|
||||
// The addons.id tiebreaker in the ORDER BY is required: subscriber_count alone
|
||||
// is not a unique ordering, so without it paging could repeat or skip rows.
|
||||
func queryRelatedAddons(addonID, joinCol, filterCol string, limit, offset int) ([]models.AddonSearchResult, int, error) {
|
||||
func QueryRelatedAddons(addonID, joinCol, filterCol string, limit, offset int) ([]models.AddonSearchResult, int, error) {
|
||||
base := func() *gorm.DB {
|
||||
return initializers.DB.Model(&models.Addon{}).
|
||||
Joins("JOIN addon_dependencies ad ON "+joinCol+" = addons.id").
|
||||
|
||||
Reference in new issue
Block a user