Files
query-orchestration/internal/cognitoauth/permitio.go
T
Jay Brown 2ff6e05ffc Merged in feature/permit-integration-1 (pull request #172)
Permit integration - part 1

* WIP permit integration

* slim down build

* Merge branch 'main' of bitbucket.org:aarete/query-orchestration into feature/permit-integration-1

* omit swagger from auth

* clean build

* comment

* part 1 completed

this is the initial permitio parts and tests without integration. Also testing.md since we have a new test target `task test:permitio`

* feature flag for no jwt validation

* permit integration

* fix ci unit tests

* ci fix

* build fix

* fix home handler

* fix redirect

* test fix

* update docs for auth
2025-07-11 19:27:14 +00:00

101 lines
2.6 KiB
Go

package cognitoauth
import (
"log/slog"
"sync"
"github.com/permitio/permit-golang/pkg/config"
"github.com/permitio/permit-golang/pkg/enforcement"
"github.com/permitio/permit-golang/pkg/permit"
)
// clientKey represents the unique identifier for a PermitIO client configuration
type clientKey struct {
apiKey string
pdpURL string
}
// PermitIOClient wraps the Permit.io client with logging
type PermitIOClient struct {
client *permit.Client
logger *slog.Logger
}
var (
// clientCache stores cached PermitIO clients by their configuration
clientCache = make(map[clientKey]*PermitIOClient)
// clientMutex protects concurrent access to the cache
clientMutex sync.RWMutex
)
// NewPermitIOClient creates or returns a cached Permit.io client instance
// Uses caching based on the combination of apiKey and pdpURL to avoid creating
// duplicate clients for the same configuration.
func NewPermitIOClient(apiKey, pdpURL string, logger *slog.Logger) *PermitIOClient {
key := clientKey{
apiKey: apiKey,
pdpURL: pdpURL,
}
// First, try to get existing client with read lock
clientMutex.RLock()
if existingClient, exists := clientCache[key]; exists {
clientMutex.RUnlock()
return existingClient
}
clientMutex.RUnlock()
// If not found, acquire write lock and check again (double-checked locking)
clientMutex.Lock()
defer clientMutex.Unlock()
// Check again in case another goroutine created it while we were waiting
if existingClient, exists := clientCache[key]; exists {
return existingClient
}
// Create new client
newClient := &PermitIOClient{
client: permit.NewPermit(
config.NewConfigBuilder(apiKey).
WithPdpUrl(pdpURL).
Build(),
),
logger: logger,
}
// Cache the new client
clientCache[key] = newClient
return newClient
}
// CheckPermission verifies if a user has permission to perform an action on a resource
func (p *PermitIOClient) CheckPermission(userID, action, resourceType string) (bool, error) {
user := enforcement.UserBuilder(userID).Build()
resource := enforcement.ResourceBuilder(resourceType).Build()
p.logger.Debug("Sending permission check to PDP",
"user_id", userID,
"action", action,
"resource_type", resourceType)
permitted, err := p.client.Check(user, enforcement.Action(action), resource)
if err != nil {
p.logger.Error("Permit.io authorization check failed",
"user", userID,
"action", action,
"resource", resourceType,
"error", err)
return false, err
}
p.logger.Debug("Permit.io authorization check",
"user", userID,
"action", action,
"resource", resourceType,
"permitted", permitted)
return permitted, nil
}