From efea8ce2fcd0cb52f9532abaa2b0cdabd4f2e9a7 Mon Sep 17 00:00:00 2001 From: RonniSkansing Date: Thu, 1 Oct 2026 20:25:18 +0200 Subject: [PATCH] add preemtive permission handlers Signed-off-by: RonniSkansing --- backend/controller/geoip.go | 10 ++++++++-- backend/controller/ipdata.go | 15 ++++++++++++--- backend/controller/utils.go | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/backend/controller/geoip.go b/backend/controller/geoip.go index 6f24f630..2fa9a8ba 100644 --- a/backend/controller/geoip.go +++ b/backend/controller/geoip.go @@ -12,10 +12,13 @@ type GeoIP struct { // GetMetadata returns the available country codes for the filter UI func (c *GeoIP) GetMetadata(g *gin.Context) { - _, _, ok := c.handleSession(g) + session, _, ok := c.handleSession(g) if !ok { return } + if !c.handleGlobalAuthorization(g, session) { + return + } codes := ipdata.Get().CountryCodes() @@ -28,10 +31,13 @@ func (c *GeoIP) GetMetadata(g *gin.Context) { // Lookup performs a country lookup for the provided IP address func (c *GeoIP) Lookup(g *gin.Context) { - _, _, ok := c.handleSession(g) + session, _, ok := c.handleSession(g) if !ok { return } + if !c.handleGlobalAuthorization(g, session) { + return + } ip := g.Query("ip") if ip == "" { diff --git a/backend/controller/ipdata.go b/backend/controller/ipdata.go index f9cfe1a3..b25b2530 100644 --- a/backend/controller/ipdata.go +++ b/backend/controller/ipdata.go @@ -58,10 +58,13 @@ func (c *IPData) Remove(g *gin.Context) { // SearchASN returns ASNs matching the query for the filter typeahead func (c *IPData) SearchASN(g *gin.Context) { - _, _, ok := c.handleSession(g) + session, _, ok := c.handleSession(g) if !ok { return } + if !c.handleGlobalAuthorization(g, session) { + return + } q := g.Query("q") limit := 25 if v := g.Query("limit"); v != "" { @@ -75,10 +78,13 @@ func (c *IPData) SearchASN(g *gin.Context) { // LookupASN returns the autonomous systems that announce the given IP address func (c *IPData) LookupASN(g *gin.Context) { - _, _, ok := c.handleSession(g) + session, _, ok := c.handleSession(g) if !ok { return } + if !c.handleGlobalAuthorization(g, session) { + return + } ip := g.Query("ip") if ip == "" { c.Response.BadRequest(g) @@ -102,10 +108,13 @@ type ResolveASNRequest struct { // ResolveASNs returns the details of the given ASNs that exist in the dataset. // ASNs that are absent are left out, which lets the UI flag orphaned entries. func (c *IPData) ResolveASNs(g *gin.Context) { - _, _, ok := c.handleSession(g) + session, _, ok := c.handleSession(g) if !ok { return } + if !c.handleGlobalAuthorization(g, session) { + return + } var req ResolveASNRequest if ok := c.handleParseRequest(g, &req); !ok { return diff --git a/backend/controller/utils.go b/backend/controller/utils.go index 23c0459d..97a7a349 100644 --- a/backend/controller/utils.go +++ b/backend/controller/utils.go @@ -15,6 +15,7 @@ import ( "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/phishingclub/phishingclub/api" + "github.com/phishingclub/phishingclub/data" "github.com/phishingclub/phishingclub/errs" "github.com/phishingclub/phishingclub/model" "github.com/phishingclub/phishingclub/service" @@ -58,6 +59,25 @@ func (c *Common) handleSession( return session, user, true } +// handleGlobalAuthorization checks the session holds the global permission. +// On a server error or a failed authorization it writes the response and +// returns false. +func (c *Common) handleGlobalAuthorization( + g *gin.Context, + session *model.Session, +) bool { + isAuthorized, err := service.IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL) + if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) { + _ = handleServerError(g, c.Response, err) + return false + } + if !isAuthorized { + c.Response.Unauthorized(g) + return false + } + return true +} + // HandleParseRequest parses the request and returns true if successful // if the request is not parsable, a 400 response is sent func (c *Common) handleParseRequest(