74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"linkport/internal/model"
|
|
)
|
|
|
|
type ScopeIndex map[string]model.ResourceScope
|
|
|
|
// Use current ownership, or the last saved ownership for deleted resources.
|
|
// Read sealed metadata without resolving asset contents or target credentials.
|
|
func (s *Store) ResourceScopes(ctx context.Context) (ScopeIndex, error) {
|
|
tx, err := s.db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback()
|
|
index := ScopeIndex{}
|
|
for _, kind := range []string{"gateways", "targets", "outbounds", "assets"} {
|
|
query := "SELECT id,config,0 FROM " + kind + " UNION ALL SELECT h.id,h.config,h.revision FROM config_history h WHERE h.kind=? AND NOT EXISTS(SELECT 1 FROM " + kind + " c WHERE c.id=h.id) AND h.revision=(SELECT MAX(revision) FROM config_history WHERE kind=h.kind AND id=h.id)"
|
|
rows, err := tx.QueryContext(ctx, query, kind)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for rows.Next() {
|
|
var id string
|
|
var blob []byte
|
|
var revision int64
|
|
if err := rows.Scan(&id, &blob, &revision); err != nil {
|
|
rows.Close()
|
|
return nil, err
|
|
}
|
|
purpose, _ := configPurpose(kind, id)
|
|
if revision > 0 {
|
|
purpose = fmt.Sprintf("history:%s:%s:%d", kind, id, revision)
|
|
}
|
|
scope := model.ResourceScope{Project: model.DefaultProject, Environment: model.DefaultEnvironment}
|
|
if err := s.unseal(blob, purpose, &scope); err != nil {
|
|
rows.Close()
|
|
return nil, err
|
|
}
|
|
if kind == "assets" {
|
|
scope.Project = ""
|
|
}
|
|
index[kind+":"+id] = scope
|
|
}
|
|
err = rows.Err()
|
|
rows.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return index, tx.Commit()
|
|
}
|
|
|
|
func (index ScopeIndex) Matches(kind, id string, filter model.ResourceScope) bool {
|
|
scope := index[kind+":"+id]
|
|
return filter.Matches(scope.Project, scope.Environment)
|
|
}
|
|
|
|
func (index ScopeIndex) MatchesResource(id string, filter model.ResourceScope) bool {
|
|
found := false
|
|
for _, kind := range []string{"gateways", "targets", "outbounds", "assets"} {
|
|
if scope, ok := index[kind+":"+id]; ok {
|
|
found = true
|
|
if filter.Matches(scope.Project, scope.Environment) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return !found && filter.Matches("", "")
|
|
}
|