Add api keys

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-11-03 09:15:14 +01:00
parent 845652c382
commit 5212d0c18f
47 changed files with 6009 additions and 3648 deletions

View File

@@ -20,16 +20,16 @@ call_argument_directives_with_null: true
models:
ID:
model:
- "github.com/getprobo/probo/pkg/server/graphql/types/gid.GIDScalar"
- "go.probo.inc/probo/pkg/server/gqlutils/types/gid.GIDScalar"
Datetime:
model:
- "github.com/99designs/gqlgen/graphql.Time"
CursorKey:
model:
- "github.com/getprobo/probo/pkg/server/graphql/types/cursor.CursorKeyScalar"
- "go.probo.inc/probo/pkg/server/gqlutils/types/cursor.CursorKeyScalar"
Duration:
model:
- "github.com/99designs/gqlgen/graphql.Duration"
BigInt:
model:
- "github.com/getprobo/probo/pkg/server/graphql/types/bigint.BigIntScalar"
- "go.probo.inc/probo/pkg/server/gqlutils/types/bigint.BigIntScalar"

View File

@@ -30,6 +30,11 @@ import (
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/go-chi/chi/v5"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.gearno.de/crypto/uuid"
"go.gearno.de/kit/httpserver"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
"go.probo.inc/probo/pkg/connector"
@@ -38,14 +43,9 @@ import (
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/saferedirect"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
gqlutils "go.probo.inc/probo/pkg/server/graphql"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/session"
"go.probo.inc/probo/pkg/statelesstoken"
"github.com/go-chi/chi/v5"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.gearno.de/crypto/uuid"
"go.gearno.de/kit/httpserver"
"go.gearno.de/kit/log"
)
type (
@@ -77,6 +77,7 @@ var (
sessionContextKey = &ctxKey{name: "session"}
userContextKey = &ctxKey{name: "user"}
userTenantContextKey = &ctxKey{name: "user_tenants"}
userAPIKeyContextKey = &ctxKey{name: "user_api_key"}
)
func SessionFromContext(ctx context.Context) *coredata.Session {
@@ -89,6 +90,11 @@ func UserFromContext(ctx context.Context) *coredata.User {
return user
}
func UserAPIKeyFromContext(ctx context.Context) *coredata.UserAPIKey {
userAPIKey, _ := ctx.Value(userAPIKeyContextKey).(*coredata.UserAPIKey)
return userAPIKey
}
func NewMux(
logger *log.Logger,
proboSvc *probo.Service,
@@ -357,6 +363,11 @@ func WithSession(authSvc *auth.Service, authzSvc *authz.Service, authCfg AuthCon
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
if authCtx := tryAPIKeyAuth(ctx, r, authSvc, authzSvc); authCtx != nil {
next(w, r.WithContext(authCtx))
return
}
sessionAuthCfg := session.AuthConfig{
CookieName: authCfg.CookieName,
CookieSecret: authCfg.CookieSecret,
@@ -402,6 +413,43 @@ func WithSession(authSvc *auth.Service, authzSvc *authz.Service, authCfg AuthCon
}
}
func tryAPIKeyAuth(ctx context.Context, r *http.Request, authSvc *auth.Service, authzSvc *authz.Service) context.Context {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
return nil
}
if !strings.HasPrefix(authHeader, "Bearer ") {
return nil
}
apiKeyString := strings.TrimPrefix(authHeader, "Bearer ")
user, userAPIKey, err := authSvc.ValidateUserAPIKey(ctx, apiKeyString)
if err != nil {
return nil
}
organizations, err := authzSvc.GetAllOrganizationsForUserAPIKeyId(ctx, userAPIKey.ID)
if err != nil {
return nil
}
tenantIDs := make([]gid.TenantID, 0, len(organizations))
for _, org := range organizations {
tenantIDs = append(tenantIDs, org.ID.TenantID())
}
ctx = context.WithValue(ctx, userContextKey, user)
ctx = context.WithValue(ctx, userAPIKeyContextKey, userAPIKey)
ctx = context.WithValue(ctx, userTenantContextKey, &userTenantAccess{
tenantIDs: tenantIDs,
authErrors: make(map[gid.TenantID]error),
})
return ctx
}
func (r *Resolver) ProboService(ctx context.Context, tenantID gid.TenantID) *probo.TenantService {
return GetTenantService(ctx, r.proboSvc, tenantID)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ package types
import (
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/graphql/types/cursor"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
func NewCursor[O page.OrderField](

View File

@@ -16,7 +16,7 @@ package types
import (
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/graphql/types/pageinfo"
"go.probo.inc/probo/pkg/server/gqlutils/types/pageinfo"
)
func NewPageInfo[T page.Paginable[O], O page.OrderField](p *page.Page[T, O]) *PageInfo {

View File

@@ -13,6 +13,8 @@ import (
"strings"
"time"
pgx "github.com/jackc/pgx/v5"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
@@ -20,9 +22,7 @@ import (
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
"go.probo.inc/probo/pkg/server/graphql"
pgx "github.com/jackc/pgx/v5"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.probo.inc/probo/pkg/server/gqlutils"
)
// Owner is the resolver for the owner field.
@@ -33,7 +33,7 @@ func (r *assetResolver) Owner(ctx context.Context, obj *types.Asset) (*types.Peo
if err != nil {
var errNotFound *coredata.ErrAssetNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get asset: %w", err))
}
@@ -42,7 +42,7 @@ func (r *assetResolver) Owner(ctx context.Context, obj *types.Asset) (*types.Peo
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
@@ -103,7 +103,7 @@ func (r *assetResolver) Organization(ctx context.Context, obj *types.Asset) (*ty
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -140,7 +140,7 @@ func (r *auditResolver) Organization(ctx context.Context, obj *types.Audit) (*ty
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
@@ -149,7 +149,7 @@ func (r *auditResolver) Organization(ctx context.Context, obj *types.Audit) (*ty
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load organization: %w", err))
}
@@ -165,7 +165,7 @@ func (r *auditResolver) Framework(ctx context.Context, obj *types.Audit) (*types
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
@@ -174,7 +174,7 @@ func (r *auditResolver) Framework(ctx context.Context, obj *types.Audit) (*types
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load framework: %w", err))
}
@@ -190,7 +190,7 @@ func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Re
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load audit: %w", err))
}
@@ -277,7 +277,7 @@ func (r *continualImprovementResolver) Organization(ctx context.Context, obj *ty
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get continual improvement organization: %w", err))
}
@@ -298,7 +298,7 @@ func (r *continualImprovementResolver) Owner(ctx context.Context, obj *types.Con
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get continual improvement owner: %w", err))
}
@@ -335,7 +335,7 @@ func (r *controlResolver) Framework(ctx context.Context, obj *types.Control) (*t
if err != nil {
var errNotFound *coredata.ErrControlNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get control: %w", err))
}
@@ -344,7 +344,7 @@ func (r *controlResolver) Framework(ctx context.Context, obj *types.Control) (*t
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get framework: %w", err))
}
@@ -516,7 +516,7 @@ func (r *datumResolver) Owner(ctx context.Context, obj *types.Datum) (*types.Peo
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
return nil, fmt.Errorf("cannot get owner: %w", err)
}
@@ -557,7 +557,7 @@ func (r *datumResolver) Organization(ctx context.Context, obj *types.Datum) (*ty
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -594,7 +594,7 @@ func (r *documentResolver) Owner(ctx context.Context, obj *types.Document) (*typ
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
@@ -604,7 +604,7 @@ func (r *documentResolver) Owner(ctx context.Context, obj *types.Document) (*typ
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
@@ -620,7 +620,7 @@ func (r *documentResolver) Organization(ctx context.Context, obj *types.Document
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
@@ -629,7 +629,7 @@ func (r *documentResolver) Organization(ctx context.Context, obj *types.Document
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -733,7 +733,7 @@ func (r *documentVersionResolver) Document(ctx context.Context, obj *types.Docum
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
@@ -754,7 +754,7 @@ func (r *documentVersionResolver) Owner(ctx context.Context, obj *types.Document
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
@@ -823,7 +823,7 @@ func (r *documentVersionSignatureResolver) SignedBy(ctx context.Context, obj *ty
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get people: %w", err))
}
@@ -848,7 +848,7 @@ func (r *evidenceResolver) File(ctx context.Context, obj *types.Evidence) (*type
if err != nil {
var errNotFound *coredata.ErrFileNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load evidence file: %w", err))
}
@@ -873,7 +873,7 @@ func (r *evidenceResolver) Task(ctx context.Context, obj *types.Evidence) (*type
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load task: %w", err))
}
@@ -894,7 +894,7 @@ func (r *evidenceResolver) Measure(ctx context.Context, obj *types.Evidence) (*t
if err != nil {
var errNotFound *coredata.ErrMeasureNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load measure: %w", err))
}
@@ -944,7 +944,7 @@ func (r *frameworkResolver) Organization(ctx context.Context, obj *types.Framewo
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load framework: %w", err))
}
@@ -953,7 +953,7 @@ func (r *frameworkResolver) Organization(ctx context.Context, obj *types.Framewo
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load organization: %w", err))
}
@@ -1227,11 +1227,11 @@ func (r *mutationResolver) CreateOrganization(ctx context.Context, input types.C
if err != nil {
var errAlreadyExists *coredata.ErrOrganizationAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
var errTrustCenterAlreadyExists *coredata.ErrTrustCenterAlreadyExists
if errors.As(err, &errTrustCenterAlreadyExists) {
return nil, graphql.Conflict(errTrustCenterAlreadyExists)
return nil, gqlutils.Conflict(errTrustCenterAlreadyExists)
}
panic(fmt.Errorf("cannot create organization: %w", err))
}
@@ -1260,7 +1260,7 @@ func (r *mutationResolver) CreateOrganization(ctx context.Context, input types.C
if err != nil {
var errAlreadyExists *coredata.ErrPeopleAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create people: %w", err))
}
@@ -1408,7 +1408,7 @@ func (r *mutationResolver) CreateTrustCenterAccess(ctx context.Context, input ty
if err != nil {
var errAlreadyExists *coredata.ErrTrustCenterAccessAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create trust center access: %w", err))
}
@@ -1632,7 +1632,7 @@ func (r *mutationResolver) InviteUser(ctx context.Context, input types.InviteUse
if err != nil {
var errAlreadyExists *coredata.ErrPeopleAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
return nil, fmt.Errorf("cannot create people record: %w", err)
}
@@ -1697,7 +1697,7 @@ func (r *mutationResolver) CreatePeople(ctx context.Context, input types.CreateP
if err != nil {
var errAlreadyExists *coredata.ErrPeopleAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create people: %w", err))
}
@@ -1776,7 +1776,7 @@ func (r *mutationResolver) CreateVendor(ctx context.Context, input types.CreateV
if err != nil {
var errAlreadyExists *coredata.ErrVendorAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
return nil, fmt.Errorf("cannot create vendor: %w", err)
}
@@ -2079,7 +2079,7 @@ func (r *mutationResolver) CreateControl(ctx context.Context, input types.Create
if err != nil {
var errAlreadyExists *coredata.ErrControlAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create control: %w", err))
}
@@ -2105,7 +2105,7 @@ func (r *mutationResolver) UpdateControl(ctx context.Context, input types.Update
if err != nil {
var errAlreadyExists *coredata.ErrControlAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot update control: %w", err))
}
@@ -2142,7 +2142,7 @@ func (r *mutationResolver) CreateMeasure(ctx context.Context, input types.Create
if err != nil {
var errAlreadyExists *coredata.ErrMeasureAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create measure: %w", err))
}
@@ -2233,7 +2233,7 @@ func (r *mutationResolver) CreateControlDocumentMapping(ctx context.Context, inp
if err != nil {
var errMappingExists *coredata.ErrControlDocumentMappingAlreadyExists
if errors.As(err, &errMappingExists) {
return nil, graphql.Conflict(errMappingExists)
return nil, gqlutils.Conflict(errMappingExists)
}
panic(fmt.Errorf("cannot create control document mapping: %w", err))
}
@@ -2349,7 +2349,7 @@ func (r *mutationResolver) CreateTask(ctx context.Context, input types.CreateTas
if err != nil {
var errAlreadyExists *coredata.ErrTaskAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create task: %w", err))
}
@@ -2445,7 +2445,7 @@ func (r *mutationResolver) CreateRisk(ctx context.Context, input types.CreateRis
if err != nil {
var errAlreadyExists *coredata.ErrRiskAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create risk: %w", err))
}
@@ -2799,7 +2799,7 @@ func (r *mutationResolver) CreateDocument(ctx context.Context, input types.Creat
if err != nil {
var errAlreadyExists *coredata.ErrDocumentAlreadyExists
if errors.As(err, &errAlreadyExists) {
return nil, graphql.Conflict(errAlreadyExists)
return nil, gqlutils.Conflict(errAlreadyExists)
}
panic(fmt.Errorf("cannot create document: %w", err))
}
@@ -2858,7 +2858,7 @@ func (r *mutationResolver) PublishDocumentVersion(ctx context.Context, input typ
if err != nil {
var errNoChanges *coredata.ErrDocumentVersionNoChanges
if errors.As(err, &errNoChanges) {
return nil, graphql.Invalid(errNoChanges)
return nil, gqlutils.Invalid(errNoChanges)
}
panic(fmt.Errorf("cannot publish document version: %w", err))
}
@@ -3939,7 +3939,7 @@ func (r *nonconformityResolver) Organization(ctx context.Context, obj *types.Non
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get nonconformity organization: %w", err))
}
@@ -3960,7 +3960,7 @@ func (r *nonconformityResolver) Audit(ctx context.Context, obj *types.Nonconform
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get nonconformity audit: %w", err))
}
@@ -3981,7 +3981,7 @@ func (r *nonconformityResolver) Owner(ctx context.Context, obj *types.Nonconform
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get nonconformity owner: %w", err))
}
@@ -4023,7 +4023,7 @@ func (r *obligationResolver) Organization(ctx context.Context, obj *types.Obliga
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get obligation organization: %w", err))
}
@@ -4044,7 +4044,7 @@ func (r *obligationResolver) Owner(ctx context.Context, obj *types.Obligation) (
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get obligation owner: %w", err))
}
@@ -4742,7 +4742,7 @@ func (r *processingActivityResolver) Organization(ctx context.Context, obj *type
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -4806,7 +4806,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -4817,7 +4817,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get people: %w", err))
}
@@ -4828,7 +4828,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -4839,7 +4839,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrFrameworkNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get framework: %w", err))
}
@@ -4850,7 +4850,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrMeasureNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get measure: %w", err))
}
@@ -4861,7 +4861,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
@@ -4879,7 +4879,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get document: %w", err))
}
@@ -4889,7 +4889,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrControlNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get control: %w", err))
}
@@ -4900,7 +4900,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrRiskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get risk: %w", err))
}
@@ -4940,7 +4940,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrAssetNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get asset: %w", err))
}
@@ -4956,7 +4956,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
if err != nil {
var errNotFound *coredata.ErrAuditNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get audit: %w", err))
}
@@ -5021,9 +5021,19 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
func (r *queryResolver) Viewer(ctx context.Context) (*types.Viewer, error) {
user := UserFromContext(ctx)
session := SessionFromContext(ctx)
apiKey := UserAPIKeyFromContext(ctx)
var viewerID gid.GID
if session != nil {
viewerID = session.ID
} else if apiKey != nil {
viewerID = apiKey.ID
} else {
viewerID = user.ID
}
return &types.Viewer{
ID: session.ID,
ID: viewerID,
User: types.NewUser(user),
}, nil
}
@@ -5060,7 +5070,7 @@ func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.Peopl
if err != nil {
var errNotFound *coredata.ErrRiskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get risk: %w", err))
}
@@ -5073,7 +5083,7 @@ func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.Peopl
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get owner: %w", err))
}
@@ -5089,7 +5099,7 @@ func (r *riskResolver) Organization(ctx context.Context, obj *types.Risk) (*type
if err != nil {
var errNotFound *coredata.ErrRiskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get risk: %w", err))
}
@@ -5098,7 +5108,7 @@ func (r *riskResolver) Organization(ctx context.Context, obj *types.Risk) (*type
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -5296,7 +5306,7 @@ func (r *snapshotResolver) Organization(ctx context.Context, obj *types.Snapshot
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -5358,7 +5368,7 @@ func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types.
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
@@ -5371,7 +5381,7 @@ func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types.
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get assigned to: %w", err))
}
@@ -5387,7 +5397,7 @@ func (r *taskResolver) Organization(ctx context.Context, obj *types.Task) (*type
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
@@ -5396,7 +5406,7 @@ func (r *taskResolver) Organization(ctx context.Context, obj *types.Task) (*type
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -5412,7 +5422,7 @@ func (r *taskResolver) Measure(ctx context.Context, obj *types.Task) (*types.Mea
if err != nil {
var errNotFound *coredata.ErrTaskNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get task: %w", err))
}
@@ -5421,7 +5431,7 @@ func (r *taskResolver) Measure(ctx context.Context, obj *types.Task) (*types.Mea
if err != nil {
var errNotFound *coredata.ErrMeasureNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get measure: %w", err))
}
@@ -5495,7 +5505,7 @@ func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.Trust
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -5614,7 +5624,7 @@ func (r *trustCenterDocumentAccessResolver) Document(ctx context.Context, obj *t
if err != nil {
var errNotFound *coredata.ErrDocumentNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
return nil, fmt.Errorf("cannot load document: %w", err)
}
@@ -5691,7 +5701,7 @@ func (r *trustCenterFileResolver) Organization(ctx context.Context, obj *types.T
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -5756,7 +5766,7 @@ func (r *vendorResolver) Organization(ctx context.Context, obj *types.Vendor) (*
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -5765,7 +5775,7 @@ func (r *vendorResolver) Organization(ctx context.Context, obj *types.Vendor) (*
if err != nil {
var errNotFound *coredata.ErrOrganizationNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get organization: %w", err))
}
@@ -5913,7 +5923,7 @@ func (r *vendorResolver) BusinessOwner(ctx context.Context, obj *types.Vendor) (
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -5926,7 +5936,7 @@ func (r *vendorResolver) BusinessOwner(ctx context.Context, obj *types.Vendor) (
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get business owner: %w", err))
}
@@ -5941,7 +5951,7 @@ func (r *vendorResolver) SecurityOwner(ctx context.Context, obj *types.Vendor) (
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -5954,7 +5964,7 @@ func (r *vendorResolver) SecurityOwner(ctx context.Context, obj *types.Vendor) (
if err != nil {
var errNotFound *coredata.ErrPeopleNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get security owner: %w", err))
}
@@ -5970,7 +5980,7 @@ func (r *vendorBusinessAssociateAgreementResolver) Vendor(ctx context.Context, o
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
return nil, fmt.Errorf("cannot get vendor: %w", err)
}
@@ -5998,7 +6008,7 @@ func (r *vendorComplianceReportResolver) Vendor(ctx context.Context, obj *types.
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -6023,7 +6033,7 @@ func (r *vendorComplianceReportResolver) File(ctx context.Context, obj *types.Ve
if err != nil {
var errNotFound *coredata.ErrFileNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot load evidence file: %w", err))
}
@@ -6073,7 +6083,7 @@ func (r *vendorContactResolver) Vendor(ctx context.Context, obj *types.VendorCon
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -6089,7 +6099,7 @@ func (r *vendorDataPrivacyAgreementResolver) Vendor(ctx context.Context, obj *ty
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -6117,7 +6127,7 @@ func (r *vendorRiskAssessmentResolver) Vendor(ctx context.Context, obj *types.Ve
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}
@@ -6139,7 +6149,7 @@ func (r *vendorServiceResolver) Vendor(ctx context.Context, obj *types.VendorSer
if err != nil {
var errNotFound *coredata.ErrVendorNotFound
if errors.As(err, &errNotFound) {
return nil, graphql.NotFound(errNotFound)
return nil, gqlutils.NotFound(errNotFound)
}
panic(fmt.Errorf("cannot get vendor: %w", err))
}

View File

@@ -20,10 +20,10 @@ call_argument_directives_with_null: true
models:
ID:
model:
- "github.com/getprobo/probo/pkg/server/graphql/types/gid.GIDScalar"
- "go.probo.inc/probo/pkg/server/gqlutils/types/gid.GIDScalar"
Datetime:
model:
- "github.com/99designs/gqlgen/graphql.Time"
CursorKey:
model:
- "github.com/getprobo/probo/pkg/server/graphql/types/cursor.CursorKeyScalar"
- "go.probo.inc/probo/pkg/server/gqlutils/types/cursor.CursorKeyScalar"

View File

@@ -26,6 +26,8 @@ import (
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/go-chi/chi/v5"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
"go.probo.inc/probo/pkg/coredata"
@@ -34,12 +36,10 @@ import (
console_v1 "go.probo.inc/probo/pkg/server/api/console/v1"
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
"go.probo.inc/probo/pkg/server/api/trust/v1/trustauth"
gqlutils "go.probo.inc/probo/pkg/server/graphql"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/session"
"go.probo.inc/probo/pkg/statelesstoken"
"go.probo.inc/probo/pkg/trust"
"github.com/go-chi/chi/v5"
"go.gearno.de/kit/log"
)
type (

View File

@@ -45,14 +45,14 @@ type Organization implements Node {
}
enum DocumentType
@goModel(model: "github.com/getprobo/probo/pkg/coredata.DocumentType") {
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
OTHER
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DocumentTypeOther")
ISMS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.DocumentTypeISMS")
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
ISMS @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeISMS")
POLICY
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DocumentTypePolicy")
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
PROCEDURE
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.DocumentTypeProcedure")
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeProcedure")
}
type Document implements Node {
@@ -102,340 +102,340 @@ type AuditEdge {
}
enum CountryCode
@goModel(model: "github.com/getprobo/probo/pkg/coredata.CountryCode") {
AD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAD")
AE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAE")
AF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAF")
AG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAG")
AI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAI")
AL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAL")
AM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAM")
AO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAO")
AQ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAQ")
AR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAR")
AS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAS")
AT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAT")
AU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAU")
AW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAW")
AX @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAX")
AZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeAZ")
BA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBA")
BB @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBB")
BD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBD")
BE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBE")
BF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBF")
BG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBG")
BH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBH")
BI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBI")
BJ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBJ")
BL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBL")
BM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBM")
BN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBN")
BO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBO")
BQ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBQ")
BR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBR")
BS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBS")
BT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBT")
BV @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBV")
BW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBW")
BY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBY")
BZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeBZ")
CA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCA")
CC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCC")
CD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCD")
CF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCF")
CG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCG")
CH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCH")
CI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCI")
CK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCK")
CL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCL")
CM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCM")
CN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCN")
CO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCO")
CR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCR")
CU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCU")
CV @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCV")
CW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCW")
CX @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCX")
CY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCY")
CZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeCZ")
DE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeDE")
DJ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeDJ")
DK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeDK")
DM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeDM")
DO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeDO")
DZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeDZ")
EC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeEC")
EE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeEE")
EG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeEG")
EH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeEH")
ER @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeER")
ES @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeES")
ET @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeET")
EU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeEU")
FI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeFI")
FJ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeFJ")
FK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeFK")
FM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeFM")
FO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeFO")
FR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeFR")
GA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGA")
GB @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGB")
GD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGD")
GE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGE")
GF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGF")
GG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGG")
GH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGH")
GI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGI")
GL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGL")
GM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGM")
GN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGN")
GP @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGP")
GQ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGQ")
GR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGR")
GT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGT")
GU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGU")
GW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGW")
GY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeGY")
HK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeHK")
HM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeHM")
HN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeHN")
HR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeHR")
HT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeHT")
HU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeHU")
ID @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeID")
IE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIE")
IL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIL")
IM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIM")
IN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIN")
IO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIO")
IQ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIQ")
IR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIR")
IS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIS")
IT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeIT")
JE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeJE")
JM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeJM")
JO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeJO")
JP @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeJP")
KE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKE")
KG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKG")
KH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKH")
KI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKI")
KM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKM")
KN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKN")
KP @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKP")
KR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKR")
KW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKW")
KY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKY")
KZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeKZ")
LA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLA")
LB @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLB")
LC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLC")
LI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLI")
LK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLK")
LR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLR")
LS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLS")
LT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLT")
LU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLU")
LV @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLV")
LY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeLY")
MA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMA")
MC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMC")
MD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMD")
ME @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeME")
MF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMF")
MG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMG")
MH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMH")
MK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMK")
ML @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeML")
MM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMM")
MN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMN")
MO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMO")
MP @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMP")
MQ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMQ")
MR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMR")
MS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMS")
MT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMT")
MU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMU")
MV @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMV")
MW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMW")
MX @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMX")
MY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMY")
MZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeMZ")
NA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNA")
NC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNC")
NE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNE")
NF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNF")
NG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNG")
NI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNI")
NL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNL")
NO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNO")
NP @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNP")
NR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNR")
NU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNU")
NZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeNZ")
OM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeOM")
PA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePA")
PE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePE")
PF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePF")
PG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePG")
PH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePH")
PK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePK")
PL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePL")
PM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePM")
PN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePN")
PR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePR")
PS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePS")
PT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePT")
PW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePW")
PY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodePY")
QA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeQA")
RE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeRE")
RO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeRO")
RS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeRS")
RU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeRU")
RW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeRW")
SA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSA")
SB @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSB")
SC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSC")
SD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSD")
SE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSE")
SG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSG")
SH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSH")
SI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSI")
SJ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSJ")
SK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSK")
SL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSL")
SM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSM")
SN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSN")
SO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSO")
SR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSR")
SS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSS")
ST @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeST")
SV @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSV")
SX @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSX")
SY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSY")
SZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeSZ")
TC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTC")
TD @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTD")
TF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTF")
TG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTG")
TH @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTH")
TJ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTJ")
TK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTK")
TL @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTL")
TM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTM")
TN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTN")
TO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTO")
TR @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTR")
TT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTT")
TV @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTV")
TW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTW")
TZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeTZ")
UA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeUA")
UG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeUG")
UM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeUM")
US @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeUS")
UY @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeUY")
UZ @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeUZ")
VA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVA")
VC @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVC")
VE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVE")
VG @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVG")
VI @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVI")
VN @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVN")
VU @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeVU")
WF @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeWF")
WS @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeWS")
YE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeYE")
YT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeYT")
ZA @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeZA")
ZM @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeZM")
ZW @goEnum(value: "github.com/getprobo/probo/pkg/coredata.CountryCodeZW")
@goModel(model: "go.probo.inc/probo/pkg/coredata.CountryCode") {
AD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAD")
AE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAE")
AF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAF")
AG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAG")
AI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAI")
AL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAL")
AM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAM")
AO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAO")
AQ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAQ")
AR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAR")
AS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAS")
AT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAT")
AU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAU")
AW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAW")
AX @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAX")
AZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeAZ")
BA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBA")
BB @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBB")
BD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBD")
BE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBE")
BF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBF")
BG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBG")
BH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBH")
BI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBI")
BJ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBJ")
BL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBL")
BM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBM")
BN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBN")
BO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBO")
BQ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBQ")
BR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBR")
BS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBS")
BT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBT")
BV @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBV")
BW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBW")
BY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBY")
BZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeBZ")
CA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCA")
CC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCC")
CD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCD")
CF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCF")
CG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCG")
CH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCH")
CI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCI")
CK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCK")
CL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCL")
CM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCM")
CN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCN")
CO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCO")
CR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCR")
CU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCU")
CV @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCV")
CW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCW")
CX @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCX")
CY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCY")
CZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeCZ")
DE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeDE")
DJ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeDJ")
DK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeDK")
DM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeDM")
DO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeDO")
DZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeDZ")
EC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeEC")
EE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeEE")
EG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeEG")
EH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeEH")
ER @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeER")
ES @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeES")
ET @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeET")
EU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeEU")
FI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeFI")
FJ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeFJ")
FK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeFK")
FM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeFM")
FO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeFO")
FR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeFR")
GA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGA")
GB @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGB")
GD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGD")
GE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGE")
GF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGF")
GG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGG")
GH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGH")
GI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGI")
GL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGL")
GM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGM")
GN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGN")
GP @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGP")
GQ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGQ")
GR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGR")
GT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGT")
GU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGU")
GW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGW")
GY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeGY")
HK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeHK")
HM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeHM")
HN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeHN")
HR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeHR")
HT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeHT")
HU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeHU")
ID @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeID")
IE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIE")
IL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIL")
IM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIM")
IN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIN")
IO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIO")
IQ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIQ")
IR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIR")
IS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIS")
IT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeIT")
JE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeJE")
JM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeJM")
JO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeJO")
JP @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeJP")
KE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKE")
KG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKG")
KH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKH")
KI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKI")
KM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKM")
KN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKN")
KP @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKP")
KR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKR")
KW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKW")
KY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKY")
KZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeKZ")
LA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLA")
LB @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLB")
LC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLC")
LI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLI")
LK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLK")
LR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLR")
LS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLS")
LT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLT")
LU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLU")
LV @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLV")
LY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeLY")
MA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMA")
MC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMC")
MD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMD")
ME @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeME")
MF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMF")
MG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMG")
MH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMH")
MK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMK")
ML @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeML")
MM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMM")
MN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMN")
MO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMO")
MP @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMP")
MQ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMQ")
MR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMR")
MS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMS")
MT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMT")
MU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMU")
MV @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMV")
MW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMW")
MX @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMX")
MY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMY")
MZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeMZ")
NA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNA")
NC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNC")
NE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNE")
NF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNF")
NG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNG")
NI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNI")
NL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNL")
NO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNO")
NP @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNP")
NR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNR")
NU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNU")
NZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeNZ")
OM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeOM")
PA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePA")
PE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePE")
PF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePF")
PG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePG")
PH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePH")
PK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePK")
PL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePL")
PM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePM")
PN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePN")
PR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePR")
PS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePS")
PT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePT")
PW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePW")
PY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodePY")
QA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeQA")
RE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeRE")
RO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeRO")
RS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeRS")
RU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeRU")
RW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeRW")
SA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSA")
SB @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSB")
SC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSC")
SD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSD")
SE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSE")
SG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSG")
SH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSH")
SI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSI")
SJ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSJ")
SK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSK")
SL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSL")
SM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSM")
SN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSN")
SO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSO")
SR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSR")
SS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSS")
ST @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeST")
SV @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSV")
SX @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSX")
SY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSY")
SZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeSZ")
TC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTC")
TD @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTD")
TF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTF")
TG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTG")
TH @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTH")
TJ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTJ")
TK @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTK")
TL @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTL")
TM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTM")
TN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTN")
TO @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTO")
TR @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTR")
TT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTT")
TV @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTV")
TW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTW")
TZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeTZ")
UA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeUA")
UG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeUG")
UM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeUM")
US @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeUS")
UY @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeUY")
UZ @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeUZ")
VA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVA")
VC @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVC")
VE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVE")
VG @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVG")
VI @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVI")
VN @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVN")
VU @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeVU")
WF @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeWF")
WS @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeWS")
YE @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeYE")
YT @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeYT")
ZA @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeZA")
ZM @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeZM")
ZW @goEnum(value: "go.probo.inc/probo/pkg/coredata.CountryCodeZW")
}
enum VendorCategory
@goModel(model: "github.com/getprobo/probo/pkg/coredata.VendorCategory") {
@goModel(model: "go.probo.inc/probo/pkg/coredata.VendorCategory") {
ANALYTICS
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryAnalytics"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryAnalytics"
)
CLOUD_MONITORING
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryCloudMonitoring"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryCloudMonitoring"
)
CLOUD_PROVIDER
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryCloudProvider"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryCloudProvider"
)
COLLABORATION
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryCollaboration"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryCollaboration"
)
CUSTOMER_SUPPORT
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryCustomerSupport"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryCustomerSupport"
)
DATA_STORAGE_AND_PROCESSING
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryDataStorageAndProcessing"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryDataStorageAndProcessing"
)
DOCUMENT_MANAGEMENT
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryDocumentManagement"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryDocumentManagement"
)
EMPLOYEE_MANAGEMENT
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryEmployeeManagement"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEmployeeManagement"
)
ENGINEERING
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryEngineering"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEngineering"
)
FINANCE
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryFinance"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryFinance"
)
IDENTITY_PROVIDER
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryIdentityProvider"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryIdentityProvider"
)
IT @goEnum(value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryIT")
IT @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryIT")
MARKETING
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryMarketing"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryMarketing"
)
OFFICE_OPERATIONS
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryOfficeOperations"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOfficeOperations"
)
OTHER
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryOther")
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOther")
PASSWORD_MANAGEMENT
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryPasswordManagement"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryPasswordManagement"
)
PRODUCT_AND_DESIGN
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryProductAndDesign"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryProductAndDesign"
)
PROFESSIONAL_SERVICES
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryProfessionalServices"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryProfessionalServices"
)
RECRUITING
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryRecruiting"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryRecruiting"
)
SALES
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.VendorCategorySales")
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySales")
SECURITY
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategorySecurity"
value: "go.probo.inc/probo/pkg/coredata.VendorCategorySecurity"
)
VERSION_CONTROL
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.VendorCategoryVersionControl"
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryVersionControl"
)
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,13 +21,13 @@ import (
"net/http"
"time"
"go.gearno.de/kit/httpserver"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/probo"
console_v1 "go.probo.inc/probo/pkg/server/api/console/v1"
"go.probo.inc/probo/pkg/server/session"
"go.probo.inc/probo/pkg/statelesstoken"
"go.probo.inc/probo/pkg/trust"
"go.gearno.de/kit/httpserver"
)
var (

View File

@@ -16,7 +16,7 @@ package types
import (
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/graphql/types/cursor"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
func NewCursor[O page.OrderField](

View File

@@ -16,7 +16,7 @@ package types
import (
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/graphql/types/pageinfo"
"go.probo.inc/probo/pkg/server/gqlutils/types/pageinfo"
)
func NewPageInfo[T page.Paginable[O], O page.OrderField](p *page.Page[T, O]) *PageInfo {

View File

@@ -10,13 +10,13 @@ import (
"fmt"
"time"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
"go.probo.inc/probo/pkg/trust"
"github.com/vektah/gqlparser/v2/gqlerror"
)
// Framework is the resolver for the framework field.

View File

@@ -18,11 +18,11 @@ import (
"net/http"
"time"
"github.com/go-chi/chi/v5"
"go.gearno.de/kit/log"
authsvc "go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
"go.probo.inc/probo/pkg/filemanager"
"github.com/go-chi/chi/v5"
"go.gearno.de/kit/log"
)
type Config struct {
@@ -56,6 +56,12 @@ func NewServer(cfg Config) (*Server, error) {
router.Get("/invitations", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, ListInvitationsHandler(cfg.Authz)))
router.Post("/invitations/accept", AcceptInvitationHandler(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret))
router.Get("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, ListUserAPIKeysHandler(cfg.Auth, cfg.Authz)))
router.Post("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, CreateUserAPIKeyHandler(cfg.Auth)))
router.Get("/api-keys/{id}", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, GetUserAPIKeyHandler(cfg.Auth)))
router.Put("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, UpdateUserAPIKeyHandler(cfg.Auth)))
router.Delete("/api-keys", RequireAuth(cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, DeleteUserAPIKeyHandler(cfg.Auth)))
router.Get("/saml/login/{samlConfigID}", SAMLLoginHandler(cfg.SAML, cfg.Auth, cfg.Logger))
router.Post("/saml/consume", SAMLACSHandler(cfg.SAML, cfg.Auth, cfg.Authz, cfg.CookieName, cfg.CookieSecret, cfg.SessionDuration, cfg.Logger))
router.Get("/saml/metadata", SAMLMetadataHandler(cfg.SAML))

View File

@@ -0,0 +1,126 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package auth
import (
"encoding/json"
"fmt"
"net/http"
"time"
"go.gearno.de/kit/httpserver"
authsvc "go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
)
type (
CreateUserAPIKeyRequest struct {
Name string `json:"name"`
ExpiresAt time.Time `json:"expiresAt"`
Organizations []UserAPIKeyOrganizationMembershipRequest `json:"organizations"`
}
UserAPIKeyOrganizationMembershipRequest struct {
OrganizationID string `json:"organizationId"`
Role string `json:"role"`
}
CreateUserAPIKeyResponse struct {
UserAPIKey UserAPIKeyResponse `json:"apiKey"`
Key string `json:"key"`
}
)
func CreateUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := UserFromContext(ctx)
var req CreateUserAPIKeyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid request body",
})
return
}
if req.ExpiresAt.IsZero() {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "expiresAt is required",
})
return
}
if req.ExpiresAt.Before(time.Now()) {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "expiration date must be in the future",
})
return
}
if len(req.Organizations) == 0 {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "at least one organization is required",
})
return
}
name := req.Name
if name == "" {
name = time.Now().Format("2006-01-02")
}
orgInputs := make([]authsvc.UserAPIKeyOrganizationRequest, len(req.Organizations))
for i, org := range req.Organizations {
orgID, err := gid.ParseGID(org.OrganizationID)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid organization id",
})
return
}
orgInputs[i] = authsvc.UserAPIKeyOrganizationRequest{
OrganizationID: orgID,
Role: coredata.APIRole(org.Role),
}
}
memberships, err := authSvc.ValidateAndBuildUserAPIKeyMemberships(ctx, user.ID, orgInputs)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid organizations",
})
return
}
userAPIKey, key, err := authSvc.CreateUserAPIKey(ctx, user.ID, name, req.ExpiresAt, memberships)
if err != nil {
panic(fmt.Errorf("cannot create user api key: %w", err))
}
response := CreateUserAPIKeyResponse{
UserAPIKey: UserAPIKeyResponse{
ID: userAPIKey.ID,
Name: userAPIKey.Name,
ExpiresAt: userAPIKey.ExpiresAt,
CreatedAt: userAPIKey.CreatedAt,
},
Key: key,
}
httpserver.RenderJSON(w, http.StatusCreated, response)
}
}

View File

@@ -0,0 +1,84 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package auth
import (
"encoding/json"
"errors"
"net/http"
"go.gearno.de/kit/httpserver"
authsvc "go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
)
type DeleteUserAPIKeyRequest struct {
ID string `json:"id"`
}
type DeleteUserAPIKeyResponse struct {
ID string `json:"id"`
}
func DeleteUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := UserFromContext(ctx)
var req DeleteUserAPIKeyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid request body",
})
return
}
if req.ID == "" {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "user api key id is required",
})
return
}
userAPIKeyID, err := gid.ParseGID(req.ID)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid user api key id",
})
return
}
if err := authSvc.DeleteUserAPIKey(ctx, userAPIKeyID, user.ID); err != nil {
var errNotFound *coredata.ErrUserAPIKeyNotFound
if errors.As(err, &errNotFound) {
httpserver.RenderJSON(w, http.StatusNotFound, map[string]string{
"error": "user api key not found",
})
return
}
httpserver.RenderJSON(w, http.StatusInternalServerError, map[string]string{
"error": "failed to delete user api key",
})
return
}
response := DeleteUserAPIKeyResponse{
ID: req.ID,
}
httpserver.RenderJSON(w, http.StatusOK, response)
}
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package auth
import (
"net/http"
"github.com/go-chi/chi/v5"
"go.gearno.de/kit/httpserver"
authsvc "go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/gid"
)
type GetUserAPIKeyResponse struct {
Key string `json:"key"`
}
func GetUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := UserFromContext(ctx)
userAPIKeyIDStr := chi.URLParam(r, "id")
if userAPIKeyIDStr == "" {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "user api key id is required",
})
return
}
userAPIKeyID, err := gid.ParseGID(userAPIKeyIDStr)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid user api key id",
})
return
}
key, err := authSvc.GetUserAPIKey(ctx, userAPIKeyID, user.ID)
if err != nil {
httpserver.RenderJSON(w, http.StatusNotFound, map[string]string{
"error": "user api key not found",
})
return
}
response := GetUserAPIKeyResponse{
Key: key,
}
httpserver.RenderJSON(w, http.StatusOK, response)
}
}

View File

@@ -0,0 +1,93 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package auth
import (
"fmt"
"net/http"
"time"
"go.gearno.de/kit/httpserver"
authsvc "go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
"go.probo.inc/probo/pkg/gid"
)
type (
ListUserAPIKeysResponse struct {
UserAPIKeys []UserAPIKeyResponse `json:"apiKeys"`
}
UserAPIKeyResponse struct {
ID gid.GID `json:"id"`
Name string `json:"name"`
ExpiresAt time.Time `json:"expiresAt"`
CreatedAt time.Time `json:"createdAt"`
Organizations []UserAPIKeyOrganizationMembership `json:"organizations"`
}
UserAPIKeyOrganizationMembership struct {
OrganizationID gid.GID `json:"organizationId"`
OrganizationName string `json:"organizationName"`
Role string `json:"role"`
}
)
func ListUserAPIKeysHandler(authSvc *authsvc.Service, authzSvc *authz.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := UserFromContext(ctx)
organizations, err := authzSvc.GetAllUserOrganizations(ctx, user.ID)
if err != nil {
panic(fmt.Errorf("cannot list organizations for user: %w", err))
}
tenantIDs := make([]gid.TenantID, 0, len(organizations))
for _, org := range organizations {
tenantIDs = append(tenantIDs, org.ID.TenantID())
}
userAPIKeysWithMemberships, err := authSvc.ListUserAPIKeysWithMemberships(ctx, user.ID, tenantIDs)
if err != nil {
panic(fmt.Errorf("cannot list user api keys: %w", err))
}
response := ListUserAPIKeysResponse{
UserAPIKeys: make([]UserAPIKeyResponse, 0, len(userAPIKeysWithMemberships)),
}
for _, keyWithMemberships := range userAPIKeysWithMemberships {
organizations := make([]UserAPIKeyOrganizationMembership, 0, len(keyWithMemberships.Memberships))
for _, membership := range keyWithMemberships.Memberships {
organizations = append(organizations, UserAPIKeyOrganizationMembership{
OrganizationID: membership.OrganizationID,
OrganizationName: membership.OrganizationName,
Role: membership.Role.String(),
})
}
response.UserAPIKeys = append(response.UserAPIKeys, UserAPIKeyResponse{
ID: keyWithMemberships.UserAPIKey.ID,
Name: keyWithMemberships.UserAPIKey.Name,
ExpiresAt: keyWithMemberships.UserAPIKey.ExpiresAt,
CreatedAt: keyWithMemberships.UserAPIKey.CreatedAt,
Organizations: organizations,
})
}
httpserver.RenderJSON(w, http.StatusOK, response)
}
}

View File

@@ -0,0 +1,142 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package auth
import (
"encoding/json"
"errors"
"net/http"
"strings"
"go.gearno.de/kit/httpserver"
authsvc "go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
)
type UpdateUserAPIKeyRequest struct {
ID string `json:"id"`
Name *string `json:"name,omitempty"`
Organizations []UserAPIKeyOrganizationMembershipRequest `json:"organizations"`
}
func UpdateUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := UserFromContext(ctx)
var req UpdateUserAPIKeyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid request body",
})
return
}
if req.ID == "" {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "user api key id is required",
})
return
}
userAPIKeyID, err := gid.ParseGID(req.ID)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid user api key id",
})
return
}
if req.Name == nil && len(req.Organizations) == 0 {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "at least one field must be provided for update",
})
return
}
if req.Name != nil && *req.Name != "" {
if err := authSvc.UpdateUserAPIKeyName(ctx, userAPIKeyID, user.ID, *req.Name); err != nil {
var errNotFound *coredata.ErrUserAPIKeyNotFound
if errors.As(err, &errNotFound) {
httpserver.RenderJSON(w, http.StatusNotFound, map[string]string{
"error": "user api key not found",
})
return
}
if strings.Contains(err.Error(), "does not belong to user") {
httpserver.RenderJSON(w, http.StatusForbidden, map[string]string{
"error": "access denied",
})
return
}
httpserver.RenderJSON(w, http.StatusInternalServerError, map[string]string{
"error": "failed to update user api key name",
})
return
}
}
if len(req.Organizations) > 0 {
orgInputs := make([]authsvc.UserAPIKeyOrganizationRequest, len(req.Organizations))
for i, org := range req.Organizations {
orgID, err := gid.ParseGID(org.OrganizationID)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid organization id",
})
return
}
orgInputs[i] = authsvc.UserAPIKeyOrganizationRequest{
OrganizationID: orgID,
Role: coredata.APIRole(org.Role),
}
}
memberships, err := authSvc.ValidateAndBuildUserAPIKeyMemberships(ctx, user.ID, orgInputs)
if err != nil {
httpserver.RenderJSON(w, http.StatusBadRequest, map[string]string{
"error": "invalid organizations",
})
return
}
if err := authSvc.UpdateUserAPIKeyMemberships(ctx, userAPIKeyID, user.ID, memberships); err != nil {
var errNotFound *coredata.ErrUserAPIKeyNotFound
if errors.As(err, &errNotFound) {
httpserver.RenderJSON(w, http.StatusNotFound, map[string]string{
"error": "user api key not found",
})
return
}
if strings.Contains(err.Error(), "does not belong to user") {
httpserver.RenderJSON(w, http.StatusForbidden, map[string]string{
"error": "access denied",
})
return
}
httpserver.RenderJSON(w, http.StatusInternalServerError, map[string]string{
"error": "failed to update user api key",
})
return
}
}
httpserver.RenderJSON(w, http.StatusOK, map[string]string{
"message": "User API key updated successfully",
})
}
}

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package graphql
package gqlutils
import (
"maps"

View File

@@ -12,18 +12,18 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package graphql
package gqlutils
import (
"context"
"errors"
"runtime/debug"
"go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.gearno.de/kit/httpserver"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/auth"
"go.probo.inc/probo/pkg/authz"
)
func RecoverFunc(ctx context.Context, err any) error {

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package graphql
package gqlutils
import (
"context"