feat(auth): integrate portal JWT for enhanced authentication and authorization
CI / changes (push) Successful in 6s
CI / commitlint (push) Skipped
CI / openapi (push) Successful in 27s
CI / web (push) Successful in 51s
CI / go (push) Successful in 2m19s
CI / bird2 (push) Successful in 13s
CI / release (push) Successful in 4m24s
CI / changes (push) Successful in 6s
CI / commitlint (push) Skipped
CI / openapi (push) Successful in 27s
CI / web (push) Successful in 51s
CI / go (push) Successful in 2m19s
CI / bird2 (push) Successful in 13s
CI / release (push) Successful in 4m24s
Added support for portal JWT authentication, enabling single sign-on (SSO) capabilities. Updated the application to handle JWT claims for user permissions and roles, enhancing security and access control. Refactored relevant components and API routes to accommodate the new authentication flow, ensuring a seamless user experience. Updated documentation to reflect the new authentication requirements and configurations. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -80,7 +80,7 @@ func (s *Server) registerCRUDRoutes(m *http.ServeMux) {
|
||||
|
||||
func (s *Server) handlePostModule(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
@@ -99,12 +99,16 @@ func (s *Server) handlePostModule(w http.ResponseWriter, r *http.Request) {
|
||||
writeProblem(w, http.StatusBadRequest, "Bad Request", "invalid json")
|
||||
return
|
||||
}
|
||||
mod, err := s.store.CreateModule(a.TenantID, &store.Module{
|
||||
newModule := &store.Module{
|
||||
Type: body.Type, Name: body.Name, Enabled: body.Enabled, Priority: body.Priority,
|
||||
RefreshIntervalSec: body.RefreshIntervalSec, CronExpr: body.CronExpr,
|
||||
DefaultCommunityID: body.DefaultCommunityID, DohProfileID: body.DohProfileID,
|
||||
DohProfileIDs: body.DohProfileIDs, DohResolverPolicy: body.DohResolverPolicy,
|
||||
})
|
||||
}
|
||||
if a.Kind == AuthKindJWT && strings.TrimSpace(a.UserID) != "" {
|
||||
newModule.CreatedByUserID = a.UserID
|
||||
}
|
||||
mod, err := s.store.CreateModule(a.TenantID, newModule)
|
||||
if err != nil {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
@@ -114,7 +118,7 @@ func (s *Server) handlePostModule(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchModule(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
rawBody, err := io.ReadAll(r.Body)
|
||||
@@ -158,7 +162,14 @@ func (s *Server) handlePatchModule(w http.ResponseWriter, r *http.Request) {
|
||||
body.RefreshIntervalSec = &zero
|
||||
}
|
||||
}
|
||||
mod, err := s.store.UpdateModule(a.TenantID, r.PathValue("module_id"), &body)
|
||||
moduleID := r.PathValue("module_id")
|
||||
if existing, gerr := s.store.GetModule(a.TenantID, moduleID); gerr == nil {
|
||||
if !store.CanAccessOwned(a.Kind, a.IsAdmin, a.UserID, existing.CreatedByUserID) {
|
||||
writeProblem(w, http.StatusNotFound, "Not Found", "module not found")
|
||||
return
|
||||
}
|
||||
}
|
||||
mod, err := s.store.UpdateModule(a.TenantID, moduleID, &body)
|
||||
if err != nil {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
@@ -168,10 +179,17 @@ func (s *Server) handlePatchModule(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteModule(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
if err := s.store.SoftDeleteModule(a.TenantID, r.PathValue("module_id")); err != nil {
|
||||
moduleID := r.PathValue("module_id")
|
||||
if existing, gerr := s.store.GetModule(a.TenantID, moduleID); gerr == nil {
|
||||
if !store.CanAccessOwned(a.Kind, a.IsAdmin, a.UserID, existing.CreatedByUserID) {
|
||||
writeProblem(w, http.StatusNotFound, "Not Found", "module not found")
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := s.store.SoftDeleteModule(a.TenantID, moduleID); err != nil {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
}
|
||||
@@ -215,7 +233,7 @@ func writePostgresStoreErr(w http.ResponseWriter, err error) bool {
|
||||
|
||||
func (s *Server) handleListCDNSources(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:read") {
|
||||
return
|
||||
}
|
||||
list, err := s.store.ListCDNSources(a.TenantID, r.PathValue("module_id"))
|
||||
@@ -248,7 +266,7 @@ func cdnSourceJSON(x *store.CDNSource) map[string]any {
|
||||
|
||||
func (s *Server) handlePreviewCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
@@ -327,7 +345,7 @@ func (s *Server) handlePreviewCDNSource(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
func (s *Server) handlePostCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.CDNSource
|
||||
@@ -357,7 +375,7 @@ func (s *Server) handlePostCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.CDNSourcePatch
|
||||
@@ -387,7 +405,7 @@ func (s *Server) handlePatchCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
mid := r.PathValue("module_id")
|
||||
@@ -401,7 +419,7 @@ func (s *Server) handleDeleteCDNSource(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleListAS(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:read") {
|
||||
return
|
||||
}
|
||||
list, err := s.store.ListASEntries(a.TenantID, r.PathValue("module_id"))
|
||||
@@ -439,7 +457,7 @@ func asEntryJSON(x *store.ASEntry) map[string]any {
|
||||
|
||||
func (s *Server) handlePostAS(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.ASEntry
|
||||
@@ -459,7 +477,7 @@ func (s *Server) handlePostAS(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchAS(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.ASEntryPatch
|
||||
@@ -479,7 +497,7 @@ func (s *Server) handlePatchAS(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteAS(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
mid := r.PathValue("module_id")
|
||||
@@ -493,7 +511,7 @@ func (s *Server) handleDeleteAS(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleListDomain(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:read") {
|
||||
return
|
||||
}
|
||||
list, err := s.store.ListDomainEntries(a.TenantID, r.PathValue("module_id"))
|
||||
@@ -516,7 +534,7 @@ func domainEntryJSON(x *store.DomainEntry) map[string]any {
|
||||
|
||||
func (s *Server) handlePostDomain(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.DomainEntry
|
||||
@@ -536,7 +554,7 @@ func (s *Server) handlePostDomain(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchDomain(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.DomainEntryPatch
|
||||
@@ -556,7 +574,7 @@ func (s *Server) handlePatchDomain(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteDomain(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
mid := r.PathValue("module_id")
|
||||
@@ -570,7 +588,7 @@ func (s *Server) handleDeleteDomain(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleListIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:read") {
|
||||
return
|
||||
}
|
||||
list, err := s.store.ListIPRangeEntries(a.TenantID, r.PathValue("module_id"))
|
||||
@@ -593,7 +611,7 @@ func ipRangeJSON(x *store.IPRangeEntry) map[string]any {
|
||||
|
||||
func (s *Server) handlePostIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.IPRangeEntry
|
||||
@@ -613,7 +631,7 @@ func (s *Server) handlePostIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
var body store.IPRangePatch
|
||||
@@ -633,7 +651,7 @@ func (s *Server) handlePatchIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
mid := r.PathValue("module_id")
|
||||
@@ -647,7 +665,7 @@ func (s *Server) handleDeleteIPRange(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleExportModuleEntriesCSV(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:read") {
|
||||
return
|
||||
}
|
||||
moduleID := r.PathValue("module_id")
|
||||
@@ -730,7 +748,7 @@ func (s *Server) handleExportModuleEntriesCSV(w http.ResponseWriter, r *http.Req
|
||||
|
||||
func (s *Server) handleImportModuleEntriesCSV(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:modules:write") {
|
||||
return
|
||||
}
|
||||
moduleID := r.PathValue("module_id")
|
||||
@@ -774,7 +792,7 @@ func (s *Server) handleImportModuleEntriesCSV(w http.ResponseWriter, r *http.Req
|
||||
|
||||
func (s *Server) handleListDoh(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:read") {
|
||||
return
|
||||
}
|
||||
list, err := s.store.ListDohProfiles(a.TenantID)
|
||||
@@ -806,7 +824,7 @@ func dohJSON(x *store.DohProfile) map[string]any {
|
||||
|
||||
func (s *Server) handleGetDoh(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:read") {
|
||||
return
|
||||
}
|
||||
x, err := s.store.GetDohProfile(a.TenantID, r.PathValue("id"))
|
||||
@@ -819,7 +837,7 @@ func (s *Server) handleGetDoh(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePostDoh(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:write") {
|
||||
return
|
||||
}
|
||||
var body store.DohProfile
|
||||
@@ -837,7 +855,7 @@ func (s *Server) handlePostDoh(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchDoh(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:write") {
|
||||
return
|
||||
}
|
||||
var body store.DohProfilePatch
|
||||
@@ -855,7 +873,7 @@ func (s *Server) handlePatchDoh(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteDoh(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:write") {
|
||||
return
|
||||
}
|
||||
if err := s.store.DeleteDohProfile(a.TenantID, r.PathValue("id")); err != nil {
|
||||
@@ -867,7 +885,7 @@ func (s *Server) handleDeleteDoh(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleListComm(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:read") {
|
||||
return
|
||||
}
|
||||
list, err := s.store.ListCommunities(a.TenantID)
|
||||
@@ -892,7 +910,7 @@ func commJSON(x *store.Community) map[string]any {
|
||||
|
||||
func (s *Server) handleGetComm(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:read") {
|
||||
return
|
||||
}
|
||||
x, err := s.store.GetCommunity(a.TenantID, r.PathValue("id"))
|
||||
@@ -905,7 +923,7 @@ func (s *Server) handleGetComm(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePostComm(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:write") {
|
||||
return
|
||||
}
|
||||
var body store.Community
|
||||
@@ -923,7 +941,7 @@ func (s *Server) handlePostComm(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchComm(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:write") {
|
||||
return
|
||||
}
|
||||
var body store.CommunityPatch
|
||||
@@ -941,7 +959,7 @@ func (s *Server) handlePatchComm(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteComm(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:directories:write") {
|
||||
return
|
||||
}
|
||||
if err := s.store.DeleteCommunity(a.TenantID, r.PathValue("id")); err != nil {
|
||||
@@ -953,7 +971,7 @@ func (s *Server) handleDeleteComm(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePostPeer(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:write") {
|
||||
return
|
||||
}
|
||||
var body store.BGPPeer
|
||||
@@ -962,6 +980,9 @@ func (s *Server) handlePostPeer(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
body.TenantID = a.TenantID
|
||||
if a.Kind == AuthKindJWT && strings.TrimSpace(a.UserID) != "" {
|
||||
body.CreatedByUserID = a.UserID
|
||||
}
|
||||
x, err := s.store.CreatePeer(a.TenantID, &body)
|
||||
if err != nil {
|
||||
writeStoreErr(w, err)
|
||||
@@ -973,7 +994,7 @@ func (s *Server) handlePostPeer(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleGetPeer(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:read") {
|
||||
return
|
||||
}
|
||||
x, err := s.store.GetPeer(a.TenantID, r.PathValue("id"))
|
||||
@@ -981,12 +1002,16 @@ func (s *Server) handleGetPeer(w http.ResponseWriter, r *http.Request) {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
}
|
||||
if !store.CanAccessOwned(a.Kind, a.IsAdmin, a.UserID, x.CreatedByUserID) {
|
||||
writeProblem(w, http.StatusNotFound, "Not Found", "peer not found")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, peerJSON(x))
|
||||
}
|
||||
|
||||
func (s *Server) handlePatchPeer(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:write") {
|
||||
return
|
||||
}
|
||||
var body store.PeerPatch
|
||||
@@ -994,7 +1019,14 @@ func (s *Server) handlePatchPeer(w http.ResponseWriter, r *http.Request) {
|
||||
writeProblem(w, http.StatusBadRequest, "Bad Request", "invalid json")
|
||||
return
|
||||
}
|
||||
x, err := s.store.UpdatePeer(a.TenantID, r.PathValue("id"), &body)
|
||||
peerID := r.PathValue("id")
|
||||
if existing, gerr := s.store.GetPeer(a.TenantID, peerID); gerr == nil {
|
||||
if !store.CanAccessOwned(a.Kind, a.IsAdmin, a.UserID, existing.CreatedByUserID) {
|
||||
writeProblem(w, http.StatusNotFound, "Not Found", "peer not found")
|
||||
return
|
||||
}
|
||||
}
|
||||
x, err := s.store.UpdatePeer(a.TenantID, peerID, &body)
|
||||
if err != nil {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
@@ -1005,10 +1037,17 @@ func (s *Server) handlePatchPeer(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeletePeer(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:write") {
|
||||
return
|
||||
}
|
||||
if err := s.store.DeletePeer(a.TenantID, r.PathValue("id")); err != nil {
|
||||
peerID := r.PathValue("id")
|
||||
if existing, gerr := s.store.GetPeer(a.TenantID, peerID); gerr == nil {
|
||||
if !store.CanAccessOwned(a.Kind, a.IsAdmin, a.UserID, existing.CreatedByUserID) {
|
||||
writeProblem(w, http.StatusNotFound, "Not Found", "peer not found")
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := s.store.DeletePeer(a.TenantID, peerID); err != nil {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
}
|
||||
@@ -1018,7 +1057,7 @@ func (s *Server) handleDeletePeer(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePostSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:write") {
|
||||
return
|
||||
}
|
||||
var body store.Speaker
|
||||
@@ -1044,7 +1083,7 @@ func (s *Server) handlePostSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleGetSpeakerByID(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:read") {
|
||||
return
|
||||
}
|
||||
x, err := s.store.GetSpeaker(a.TenantID, r.PathValue("speaker_id"))
|
||||
@@ -1057,7 +1096,7 @@ func (s *Server) handleGetSpeakerByID(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:write") {
|
||||
return
|
||||
}
|
||||
var body store.SpeakerPatch
|
||||
@@ -1075,7 +1114,7 @@ func (s *Server) handlePatchSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleDeleteSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:network:write") {
|
||||
return
|
||||
}
|
||||
if err := s.store.DeleteSpeaker(a.TenantID, r.PathValue("speaker_id")); err != nil {
|
||||
@@ -1087,7 +1126,7 @@ func (s *Server) handleDeleteSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handleRevisionPrefixes(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:operations:read") {
|
||||
return
|
||||
}
|
||||
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
|
||||
@@ -1111,7 +1150,7 @@ func (s *Server) handleRevisionPrefixes(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
func (s *Server) handleGetSettings(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:tenant_settings:admin") {
|
||||
return
|
||||
}
|
||||
m, err := s.store.ListGlobalSettings(a.TenantID)
|
||||
@@ -1124,7 +1163,7 @@ func (s *Server) handleGetSettings(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Server) handlePatchSettings(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "operator") {
|
||||
if !ok || !s.requirePerm(w, a, "bgp:tenant_settings:admin") {
|
||||
return
|
||||
}
|
||||
var body map[string]any
|
||||
|
||||
Reference in New Issue
Block a user