Slim base.graphql to directives, scalars, Query, Node, and Mutation
Move Identity, Organization, Viewer, PageInfo, OrderDirection, CountryCode, OIDCProviderInfo, File, and ReauthenticationReason out of base.graphql into their own dedicated files across all three APIs. base.graphql now only contains directives, scalars, Node interface, Query type, and an empty Mutation type (required by Relay schemaExtensions). Entity files use extend type Mutation for their mutations. Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -12,628 +12,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
"github.com/99designs/gqlgen/graphql"
|
||||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
|
||||||
"go.gearno.de/kit/log"
|
"go.gearno.de/kit/log"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/iam"
|
"go.probo.inc/probo/pkg/iam"
|
||||||
"go.probo.inc/probo/pkg/mail"
|
"go.probo.inc/probo/pkg/mail"
|
||||||
"go.probo.inc/probo/pkg/page"
|
|
||||||
"go.probo.inc/probo/pkg/server/api/authn"
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
"go.probo.inc/probo/pkg/server/api/authz"
|
|
||||||
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
||||||
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
||||||
"go.probo.inc/probo/pkg/server/gqlutils"
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||||
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Profiles is the resolver for the profiles field.
|
|
||||||
func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
|
|
||||||
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList, authz.WithSkipAssumptionCheck()); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
|
||||||
if filter != nil {
|
|
||||||
filters = coredata.NewMembershipProfileFilter(filter.ExcludeContractEnded).WithMembership()
|
|
||||||
if filter.State != nil {
|
|
||||||
filters.WithState(*filter.State)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
|
||||||
return &types.ProfileConnection{
|
|
||||||
Resolver: r,
|
|
||||||
ParentID: obj.ID,
|
|
||||||
Filters: filters,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
|
||||||
Field: coredata.MembershipProfileOrderFieldFullName,
|
|
||||||
Direction: page.OrderDirectionAsc,
|
|
||||||
}
|
|
||||||
if orderBy != nil {
|
|
||||||
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
|
|
||||||
Field: orderBy.Field,
|
|
||||||
Direction: orderBy.Direction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
|
||||||
|
|
||||||
page, err := r.iam.AccountService.ListProfilesForIdentity(ctx, obj.ID, cursor, filters)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return types.NewProfileConnection(page, r, obj.ID, filters), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sessions is the resolver for the sessions field.
|
|
||||||
func (r *identityResolver) Sessions(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SessionOrder) (*types.SessionConnection, error) {
|
|
||||||
if err := r.authorize(ctx, obj.ID, iam.ActionSessionList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
|
||||||
return &types.SessionConnection{
|
|
||||||
Resolver: r,
|
|
||||||
ParentID: obj.ID,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pageOrderBy := page.OrderBy[coredata.SessionOrderField]{
|
|
||||||
Field: coredata.SessionOrderFieldCreatedAt,
|
|
||||||
Direction: page.OrderDirectionDesc,
|
|
||||||
}
|
|
||||||
if orderBy != nil {
|
|
||||||
pageOrderBy = page.OrderBy[coredata.SessionOrderField]{
|
|
||||||
Field: orderBy.Field,
|
|
||||||
Direction: orderBy.Direction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
|
||||||
|
|
||||||
page, err := r.iam.AccountService.ListSessions(ctx, obj.ID, cursor)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list sessions", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return types.NewSessionConnection(page, r, obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PersonalAPIKeys is the resolver for the personalAPIKeys field.
|
|
||||||
func (r *identityResolver) PersonalAPIKeys(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.PersonalAPIKeyConnection, error) {
|
|
||||||
if err := r.authorize(ctx, obj.ID, iam.ActionPersonalAPIKeyList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
|
||||||
return &types.PersonalAPIKeyConnection{
|
|
||||||
Resolver: r,
|
|
||||||
ParentID: obj.ID,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pageOrderBy := page.OrderBy[coredata.PersonalAPIKeyOrderField]{
|
|
||||||
Field: coredata.PersonalAPIKeyOrderFieldCreatedAt,
|
|
||||||
Direction: page.OrderDirectionDesc,
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
|
||||||
|
|
||||||
page, err := r.iam.AccountService.ListPersonalAPIKeys(ctx, obj.ID, cursor)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list personal api keys", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return types.NewPersonalAPIKeyConnection(page, r, obj.ID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SsoLoginURL is the resolver for the ssoLoginURL field.
|
|
||||||
func (r *identityResolver) SsoLoginURL(ctx context.Context, obj *types.Identity) (*string, error) {
|
|
||||||
if err := r.authorize(ctx, obj.ID, iam.ActionIdentityGet); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
count, err := r.iam.AccountService.CountSAMLConfigurationsForEmail(ctx, identity.EmailAddress)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot count SAML configurations for email", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if count != 1 {
|
|
||||||
if count == 0 {
|
|
||||||
return nil, graphql.ErrorOnPath(
|
|
||||||
ctx,
|
|
||||||
fmt.Errorf("no SAML configuration for email"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, graphql.ErrorOnPath(
|
|
||||||
ctx,
|
|
||||||
fmt.Errorf("multiple SSO configurations found for this domain. Please use your organization-specific SSO login URL"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
samlConfigs, err := r.iam.AccountService.ListSAMLConfigurationsForEmail(ctx, identity.EmailAddress)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list SAML configurations for email", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(samlConfigs) == 0 {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot find SAML config")
|
|
||||||
return nil, gqlutils.NotFoundf(ctx, "cannot find SAML config")
|
|
||||||
}
|
|
||||||
samlConfig := samlConfigs[0]
|
|
||||||
|
|
||||||
loginURL := r.SSOLoginURL(samlConfig.ID)
|
|
||||||
return &loginURL, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Permission is the resolver for the permission field.
|
|
||||||
func (r *identityResolver) Permission(ctx context.Context, obj *types.Identity, action string) (bool, error) {
|
|
||||||
return r.Resolver.Permission(ctx, obj, action)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignIn is the resolver for the signIn field.
|
|
||||||
func (r *mutationResolver) SignIn(ctx context.Context, input types.SignInInput) (*types.SignInPayload, error) {
|
|
||||||
identity, err := r.iam.AuthService.CheckCredentials(ctx, input.Email, input.Password)
|
|
||||||
if err != nil {
|
|
||||||
var errInvalidPassword *iam.ErrInvalidPassword
|
|
||||||
if errors.As(err, &errInvalidPassword) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidCredentials *iam.ErrInvalidCredentials
|
|
||||||
if errors.As(err, &errInvalidCredentials) {
|
|
||||||
return nil, &gqlerror.Error{
|
|
||||||
Message: err.Error(),
|
|
||||||
Extensions: map[string]any{
|
|
||||||
"code": "INVALID_CREDENTIALS",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot check credentials", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
session := authn.SessionFromContext(ctx)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case session == nil:
|
|
||||||
var err error
|
|
||||||
session, err = r.iam.AuthService.OpenSessionWithPassword(
|
|
||||||
ctx,
|
|
||||||
identity.ID,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot create session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
case session.IdentityID != identity.ID:
|
|
||||||
if err := r.iam.SessionService.CloseSession(ctx, session.ID); err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
session, err = r.iam.AuthService.OpenSessionWithPassword(
|
|
||||||
ctx,
|
|
||||||
identity.ID,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot create session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
||||||
r.sessionCookie.Set(w, session)
|
|
||||||
|
|
||||||
if input.OrganizationID != nil {
|
|
||||||
var err error
|
|
||||||
_, _, err = r.iam.SessionService.OpenPasswordChildSessionForOrganization(ctx, session.ID, *input.OrganizationID)
|
|
||||||
if err != nil {
|
|
||||||
// Here session middleware already took care of expired/nil root session so we only handle membership related errors
|
|
||||||
var errMembershipNotFound *iam.ErrMembershipNotFound
|
|
||||||
var errUserInactive *iam.ErrUserInactive
|
|
||||||
|
|
||||||
if errors.As(err, &errMembershipNotFound) || errors.As(err, &errUserInactive) {
|
|
||||||
return nil, gqlutils.Forbiddenf(ctx, "forbidden")
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot assume organization", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.SignInPayload{
|
|
||||||
Identity: types.NewIdentity(identity),
|
|
||||||
Session: types.NewSession(session),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignUp is the resolver for the signUp field.
|
|
||||||
func (r *mutationResolver) SignUp(ctx context.Context, input types.SignUpInput) (*types.SignUpPayload, error) {
|
|
||||||
identity, session, err := r.iam.AuthService.CreateIdentityWithPassword(
|
|
||||||
ctx,
|
|
||||||
&iam.CreateIdentityWithPasswordRequest{
|
|
||||||
Email: input.Email,
|
|
||||||
Password: input.Password,
|
|
||||||
FullName: input.FullName,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
var errIdentityAlreadyExists *iam.ErrIdentityAlreadyExists
|
|
||||||
if errors.As(err, &errIdentityAlreadyExists) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errSignupDisabled *iam.ErrSignupDisabled
|
|
||||||
if errors.As(err, &errSignupDisabled) {
|
|
||||||
return nil, gqlutils.Forbidden(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot create identity with password", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
||||||
r.sessionCookie.Set(w, session)
|
|
||||||
|
|
||||||
return &types.SignUpPayload{
|
|
||||||
Identity: types.NewIdentity(identity),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignOut is the resolver for the signOut field.
|
|
||||||
func (r *mutationResolver) SignOut(ctx context.Context) (*types.SignOutPayload, error) {
|
|
||||||
session := authn.SessionFromContext(ctx)
|
|
||||||
|
|
||||||
err := r.iam.SessionService.CloseSession(ctx, session.ID)
|
|
||||||
if err != nil {
|
|
||||||
var ErrSessionNotFound *iam.ErrSessionNotFound
|
|
||||||
if errors.As(err, &ErrSessionNotFound) {
|
|
||||||
return &types.SignOutPayload{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
||||||
r.sessionCookie.Clear(w)
|
|
||||||
|
|
||||||
return &types.SignOutPayload{Success: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ActivateAccount is the resolver for the activateAccount field.
|
|
||||||
func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.ActivateAccountInput) (*types.ActivateAccountPayload, error) {
|
|
||||||
session := authn.SessionFromContext(ctx)
|
|
||||||
|
|
||||||
if session != nil {
|
|
||||||
// Sign out any other account before activating a new one
|
|
||||||
err := r.iam.SessionService.CloseSession(ctx, session.ID)
|
|
||||||
if err != nil {
|
|
||||||
var ErrSessionNotFound *iam.ErrSessionNotFound
|
|
||||||
if !errors.As(err, &ErrSessionNotFound) {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
||||||
r.sessionCookie.Clear(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
identity, user, err := r.iam.AuthService.ActivateAccount(
|
|
||||||
ctx,
|
|
||||||
&iam.ActivateAccountRequest{
|
|
||||||
InvitationToken: input.Token,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
var (
|
|
||||||
errInvalidToken *iam.ErrInvalidToken
|
|
||||||
errInvitationNotFound *iam.ErrInvitationNotFound
|
|
||||||
errInvitationExpired *iam.ErrInvitationExpired
|
|
||||||
|
|
||||||
isInvalidErr = errors.As(err, &errInvalidToken) ||
|
|
||||||
errors.As(err, &errInvitationNotFound) ||
|
|
||||||
errors.As(err, &errInvitationExpired)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isInvalidErr {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := errors.AsType[*iam.ErrInvitationAlreadyAccepted](err); ok {
|
|
||||||
return nil, gqlutils.AccountAlreadyActivated(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot activate account from invitation", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ssoLoginURL *string
|
|
||||||
samlConfigs, err := r.iam.AccountService.ListSAMLConfigurationsForEmail(ctx, user.EmailAddress)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list saml configurations", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, samlConfig := range samlConfigs {
|
|
||||||
if samlConfig.OrganizationID != user.OrganizationID {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ssoLoginURL = new(r.SSOLoginURL(samlConfig.ID))
|
|
||||||
}
|
|
||||||
|
|
||||||
if ssoLoginURL != nil {
|
|
||||||
return &types.ActivateAccountPayload{
|
|
||||||
CreatePasswordToken: nil,
|
|
||||||
SsoLoginURL: ssoLoginURL,
|
|
||||||
Profile: types.NewProfile(user),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var createPasswordToken *string
|
|
||||||
if identity.HashedPassword == nil {
|
|
||||||
token, err := r.iam.AuthService.GetResetPasswordToken(ctx, identity.EmailAddress)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot generate password create token", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
createPasswordToken = &token
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ActivateAccountPayload{
|
|
||||||
CreatePasswordToken: createPasswordToken,
|
|
||||||
SsoLoginURL: nil,
|
|
||||||
Profile: types.NewProfile(user),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForgotPassword is the resolver for the forgotPassword field.
|
|
||||||
func (r *mutationResolver) ForgotPassword(ctx context.Context, input types.ForgotPasswordInput) (*types.ForgotPasswordPayload, error) {
|
|
||||||
err := r.iam.AuthService.SendPasswordResetInstructionByEmail(
|
|
||||||
ctx,
|
|
||||||
input.Email,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot send password reset instruction by email", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ForgotPasswordPayload{
|
|
||||||
Success: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetPassword is the resolver for the resetPassword field.
|
|
||||||
func (r *mutationResolver) ResetPassword(ctx context.Context, input types.ResetPasswordInput) (*types.ResetPasswordPayload, error) {
|
|
||||||
err := r.iam.AuthService.ResetPassword(
|
|
||||||
ctx,
|
|
||||||
&iam.ResetPasswordRequest{
|
|
||||||
Token: input.Token,
|
|
||||||
Password: input.Password,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
var errInvalidToken *iam.ErrInvalidToken
|
|
||||||
if errors.As(err, &errInvalidToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot reset password", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ResetPasswordPayload{
|
|
||||||
Success: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyEmail is the resolver for the verifyEmail field.
|
|
||||||
func (r *mutationResolver) VerifyEmail(ctx context.Context, input types.VerifyEmailInput) (*types.VerifyEmailPayload, error) {
|
|
||||||
err := r.iam.AccountService.VerifyEmail(ctx, input.Token)
|
|
||||||
if err != nil {
|
|
||||||
var (
|
|
||||||
errInvalidToken *iam.ErrInvalidToken
|
|
||||||
errIdentityNotFound *iam.ErrIdentityNotFound
|
|
||||||
errEmailAlreadyVerified *iam.ErrEmailAlreadyVerified
|
|
||||||
errEmailVerificationMismatch *iam.ErrEmailVerificationMismatch
|
|
||||||
|
|
||||||
isInvalidErr = errors.As(err, &errInvalidToken) ||
|
|
||||||
errors.As(err, &errEmailVerificationMismatch)
|
|
||||||
)
|
|
||||||
|
|
||||||
if isInvalidErr {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.As(err, &errEmailAlreadyVerified) {
|
|
||||||
return nil, gqlutils.Conflict(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.As(err, &errIdentityNotFound) {
|
|
||||||
return nil, gqlutils.NotFound(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot verify email", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.VerifyEmailPayload{
|
|
||||||
Success: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangePassword is the resolver for the changePassword field.
|
|
||||||
func (r *mutationResolver) ChangePassword(ctx context.Context, input types.ChangePasswordInput) (*types.ChangePasswordPayload, error) {
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
err := r.iam.AccountService.ChangePassword(
|
|
||||||
ctx,
|
|
||||||
identity.ID,
|
|
||||||
&iam.ChangePasswordRequest{
|
|
||||||
CurrentPassword: input.CurrentPassword,
|
|
||||||
NewPassword: input.NewPassword,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
var (
|
|
||||||
errInvalidPassword *iam.ErrInvalidPassword
|
|
||||||
errIdentityNotFound *iam.ErrIdentityNotFound
|
|
||||||
)
|
|
||||||
|
|
||||||
if errors.As(err, &errInvalidPassword) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.As(err, &errIdentityNotFound) {
|
|
||||||
return nil, gqlutils.NotFound(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot change password", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ChangePasswordPayload{
|
|
||||||
Success: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeEmail is the resolver for the changeEmail field.
|
|
||||||
func (r *mutationResolver) ChangeEmail(ctx context.Context, input types.ChangeEmailInput) (*types.ChangeEmailPayload, error) {
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
err := r.iam.AccountService.ChangeEmail(
|
|
||||||
ctx,
|
|
||||||
identity.ID,
|
|
||||||
&iam.ChangeEmailRequest{
|
|
||||||
NewEmail: input.NewEmail,
|
|
||||||
Password: input.Password,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
var (
|
|
||||||
errInvalidPassword *iam.ErrInvalidPassword
|
|
||||||
errIdentityNotFound *iam.ErrIdentityNotFound
|
|
||||||
)
|
|
||||||
|
|
||||||
if errors.As(err, &errInvalidPassword) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.As(err, &errIdentityNotFound) {
|
|
||||||
return nil, gqlutils.NotFound(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot change email", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.ChangeEmailPayload{
|
|
||||||
Success: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssumeOrganizationSession is the resolver for the assumeOrganizationSession field.
|
|
||||||
func (r *mutationResolver) AssumeOrganizationSession(ctx context.Context, input types.AssumeOrganizationSessionInput) (*types.AssumeOrganizationSessionPayload, error) {
|
|
||||||
rootSession := authn.SessionFromContext(ctx)
|
|
||||||
|
|
||||||
childSession, membership, err := r.iam.SessionService.AssumeOrganizationSession(ctx, rootSession.ID, input.OrganizationID, input.Continue)
|
|
||||||
if err != nil {
|
|
||||||
var (
|
|
||||||
errMembershipNotFound *iam.ErrMembershipNotFound
|
|
||||||
errPasswordAuthenticationRequired *iam.ErrPasswordAuthenticationRequired
|
|
||||||
errSAMLAuthenticationRequired *iam.ErrSAMLAuthenticationRequired
|
|
||||||
)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case errors.As(err, &errMembershipNotFound):
|
|
||||||
return nil, gqlutils.NotFound(ctx, err)
|
|
||||||
|
|
||||||
case errors.As(err, &errPasswordAuthenticationRequired):
|
|
||||||
return &types.AssumeOrganizationSessionPayload{
|
|
||||||
Result: types.PasswordRequired{
|
|
||||||
Reason: types.ReauthenticationReason(errPasswordAuthenticationRequired.Reason),
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
case errors.As(err, &errSAMLAuthenticationRequired):
|
|
||||||
return &types.AssumeOrganizationSessionPayload{
|
|
||||||
Result: types.SAMLAuthenticationRequired{
|
|
||||||
Reason: types.ReauthenticationReason(errSAMLAuthenticationRequired.Reason),
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot assume organization session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.AssumeOrganizationSessionPayload{
|
|
||||||
Result: types.OrganizationSessionCreated{
|
|
||||||
Session: types.NewSession(childSession),
|
|
||||||
Membership: types.NewMembership(membership),
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevokeSession is the resolver for the revokeSession field.
|
|
||||||
func (r *mutationResolver) RevokeSession(ctx context.Context, input types.RevokeSessionInput) (*types.RevokeSessionPayload, error) {
|
|
||||||
if err := r.authorize(ctx, input.SessionID, iam.ActionSessionRevoke); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
err := r.iam.SessionService.RevokeSession(ctx, identity.ID, input.SessionID)
|
|
||||||
if err != nil {
|
|
||||||
var ErrSessionExpired *iam.ErrSessionExpired
|
|
||||||
if errors.As(err, &ErrSessionExpired) {
|
|
||||||
return &types.RevokeSessionPayload{Success: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot revoke session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.RevokeSessionPayload{Success: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevokeAllSessions is the resolver for the revokeAllSessions field.
|
|
||||||
func (r *mutationResolver) RevokeAllSessions(ctx context.Context) (*types.RevokeAllSessionsPayload, error) {
|
|
||||||
if err := r.authorize(ctx, authn.SessionFromContext(ctx).ID, iam.ActionSessionRevokeAll); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
session := authn.SessionFromContext(ctx)
|
|
||||||
|
|
||||||
revokedCount, err := r.iam.SessionService.RevokeAllSessions(ctx, session.ID)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot revoke all sessions", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.RevokeAllSessionsPayload{RevokedCount: int(revokedCount)}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node is the resolver for the node field.
|
// Node is the resolver for the node field.
|
||||||
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
|
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
|
||||||
var (
|
var (
|
||||||
@@ -843,15 +232,11 @@ func (r *queryResolver) SignUpEnabled(ctx context.Context) (bool, error) {
|
|||||||
return r.iam.IsSignUpEnabled(), nil
|
return r.iam.IsSignUpEnabled(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identity returns schema.IdentityResolver implementation.
|
|
||||||
func (r *Resolver) Identity() schema.IdentityResolver { return &identityResolver{r} }
|
|
||||||
|
|
||||||
// Mutation returns schema.MutationResolver implementation.
|
// Mutation returns schema.MutationResolver implementation.
|
||||||
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
||||||
|
|
||||||
// Query returns schema.QueryResolver implementation.
|
// Query returns schema.QueryResolver implementation.
|
||||||
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
||||||
|
|
||||||
type identityResolver struct{ *Resolver }
|
|
||||||
type mutationResolver struct{ *Resolver }
|
type mutationResolver struct{ *Resolver }
|
||||||
type queryResolver struct{ *Resolver }
|
type queryResolver struct{ *Resolver }
|
||||||
|
|||||||
@@ -16,34 +16,10 @@ scalar Datetime
|
|||||||
scalar Upload
|
scalar Upload
|
||||||
scalar EmailAddr
|
scalar EmailAddr
|
||||||
|
|
||||||
enum OrderDirection
|
|
||||||
@goModel(model: "go.probo.inc/probo/pkg/page.OrderDirection") {
|
|
||||||
ASC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionAsc")
|
|
||||||
DESC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionDesc")
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Node {
|
interface Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageInfo {
|
|
||||||
hasNextPage: Boolean!
|
|
||||||
hasPreviousPage: Boolean!
|
|
||||||
startCursor: CursorKey
|
|
||||||
endCursor: CursorKey
|
|
||||||
}
|
|
||||||
|
|
||||||
type OIDCProviderInfo {
|
|
||||||
name: String!
|
|
||||||
loginURL: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ReauthenticationReason {
|
|
||||||
SESSION_EXPIRED
|
|
||||||
SENSITIVE_ACTION
|
|
||||||
POLICY_REQUIREMENT
|
|
||||||
}
|
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
node(id: ID!): Node @session(required: PRESENT)
|
node(id: ID!): Node @session(required: PRESENT)
|
||||||
viewer: Identity @session(required: PRESENT)
|
viewer: Identity @session(required: PRESENT)
|
||||||
@@ -58,69 +34,4 @@ type Query {
|
|||||||
@session(required: OPTIONAL)
|
@session(required: OPTIONAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Identity implements Node {
|
type Mutation
|
||||||
id: ID!
|
|
||||||
email: EmailAddr!
|
|
||||||
fullName: String!
|
|
||||||
emailVerified: Boolean!
|
|
||||||
createdAt: Datetime!
|
|
||||||
updatedAt: Datetime!
|
|
||||||
|
|
||||||
profiles(
|
|
||||||
first: Int
|
|
||||||
after: CursorKey
|
|
||||||
last: Int
|
|
||||||
before: CursorKey
|
|
||||||
orderBy: ProfileOrder
|
|
||||||
filter: ProfileFilter
|
|
||||||
): ProfileConnection @goField(forceResolver: true)
|
|
||||||
|
|
||||||
sessions(
|
|
||||||
first: Int
|
|
||||||
after: CursorKey
|
|
||||||
last: Int
|
|
||||||
before: CursorKey
|
|
||||||
orderBy: SessionOrder
|
|
||||||
): SessionConnection @goField(forceResolver: true)
|
|
||||||
|
|
||||||
personalAPIKeys(
|
|
||||||
first: Int
|
|
||||||
after: CursorKey
|
|
||||||
last: Int
|
|
||||||
before: CursorKey
|
|
||||||
): PersonalAPIKeyConnection @goField(forceResolver: true)
|
|
||||||
|
|
||||||
ssoLoginURL: String
|
|
||||||
@goField(forceResolver: true)
|
|
||||||
@session(required: PRESENT)
|
|
||||||
|
|
||||||
permission(action: String!): Boolean!
|
|
||||||
@goField(forceResolver: true)
|
|
||||||
@session(required: PRESENT)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mutation {
|
|
||||||
signIn(input: SignInInput!): SignInPayload @session(required: OPTIONAL)
|
|
||||||
signUp(input: SignUpInput!): SignUpPayload @session(required: NONE)
|
|
||||||
signOut: SignOutPayload @session(required: PRESENT)
|
|
||||||
activateAccount(
|
|
||||||
input: ActivateAccountInput!
|
|
||||||
): ActivateAccountPayload @session(required: OPTIONAL)
|
|
||||||
forgotPassword(input: ForgotPasswordInput!): ForgotPasswordPayload
|
|
||||||
@session(required: NONE)
|
|
||||||
resetPassword(input: ResetPasswordInput!): ResetPasswordPayload
|
|
||||||
@session(required: NONE)
|
|
||||||
verifyEmail(input: VerifyEmailInput!): VerifyEmailPayload
|
|
||||||
@session(required: OPTIONAL)
|
|
||||||
changePassword(input: ChangePasswordInput!): ChangePasswordPayload
|
|
||||||
@session(required: PRESENT)
|
|
||||||
changeEmail(input: ChangeEmailInput!): ChangeEmailPayload
|
|
||||||
@session(required: PRESENT)
|
|
||||||
assumeOrganizationSession(
|
|
||||||
input: AssumeOrganizationSessionInput!
|
|
||||||
): AssumeOrganizationSessionPayload @session(required: PRESENT)
|
|
||||||
|
|
||||||
revokeSession(input: RevokeSessionInput!): RevokeSessionPayload!
|
|
||||||
@session(required: PRESENT)
|
|
||||||
revokeAllSessions: RevokeAllSessionsPayload @session(required: PRESENT)
|
|
||||||
}
|
|
||||||
|
|||||||
40
pkg/server/api/connect/v1/graphql/identity.graphql
Normal file
40
pkg/server/api/connect/v1/graphql/identity.graphql
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
type Identity implements Node {
|
||||||
|
id: ID!
|
||||||
|
email: EmailAddr!
|
||||||
|
fullName: String!
|
||||||
|
emailVerified: Boolean!
|
||||||
|
createdAt: Datetime!
|
||||||
|
updatedAt: Datetime!
|
||||||
|
|
||||||
|
profiles(
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
orderBy: ProfileOrder
|
||||||
|
filter: ProfileFilter
|
||||||
|
): ProfileConnection @goField(forceResolver: true)
|
||||||
|
|
||||||
|
sessions(
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
orderBy: SessionOrder
|
||||||
|
): SessionConnection @goField(forceResolver: true)
|
||||||
|
|
||||||
|
personalAPIKeys(
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
): PersonalAPIKeyConnection @goField(forceResolver: true)
|
||||||
|
|
||||||
|
ssoLoginURL: String
|
||||||
|
@goField(forceResolver: true)
|
||||||
|
@session(required: PRESENT)
|
||||||
|
|
||||||
|
permission(action: String!): Boolean!
|
||||||
|
@goField(forceResolver: true)
|
||||||
|
@session(required: PRESENT)
|
||||||
|
}
|
||||||
4
pkg/server/api/connect/v1/graphql/oidc.graphql
Normal file
4
pkg/server/api/connect/v1/graphql/oidc.graphql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
type OIDCProviderInfo {
|
||||||
|
name: String!
|
||||||
|
loginURL: String!
|
||||||
|
}
|
||||||
12
pkg/server/api/connect/v1/graphql/pagination.graphql
Normal file
12
pkg/server/api/connect/v1/graphql/pagination.graphql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
type PageInfo {
|
||||||
|
hasNextPage: Boolean!
|
||||||
|
hasPreviousPage: Boolean!
|
||||||
|
startCursor: CursorKey
|
||||||
|
endCursor: CursorKey
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OrderDirection
|
||||||
|
@goModel(model: "go.probo.inc/probo/pkg/page.OrderDirection") {
|
||||||
|
ASC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionAsc")
|
||||||
|
DESC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionDesc")
|
||||||
|
}
|
||||||
@@ -1,3 +1,35 @@
|
|||||||
|
enum ReauthenticationReason {
|
||||||
|
SESSION_EXPIRED
|
||||||
|
SENSITIVE_ACTION
|
||||||
|
POLICY_REQUIREMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
extend type Mutation {
|
||||||
|
signIn(input: SignInInput!): SignInPayload @session(required: OPTIONAL)
|
||||||
|
signUp(input: SignUpInput!): SignUpPayload @session(required: NONE)
|
||||||
|
signOut: SignOutPayload @session(required: PRESENT)
|
||||||
|
activateAccount(
|
||||||
|
input: ActivateAccountInput!
|
||||||
|
): ActivateAccountPayload @session(required: OPTIONAL)
|
||||||
|
forgotPassword(input: ForgotPasswordInput!): ForgotPasswordPayload
|
||||||
|
@session(required: NONE)
|
||||||
|
resetPassword(input: ResetPasswordInput!): ResetPasswordPayload
|
||||||
|
@session(required: NONE)
|
||||||
|
verifyEmail(input: VerifyEmailInput!): VerifyEmailPayload
|
||||||
|
@session(required: OPTIONAL)
|
||||||
|
changePassword(input: ChangePasswordInput!): ChangePasswordPayload
|
||||||
|
@session(required: PRESENT)
|
||||||
|
changeEmail(input: ChangeEmailInput!): ChangeEmailPayload
|
||||||
|
@session(required: PRESENT)
|
||||||
|
assumeOrganizationSession(
|
||||||
|
input: AssumeOrganizationSessionInput!
|
||||||
|
): AssumeOrganizationSessionPayload @session(required: PRESENT)
|
||||||
|
|
||||||
|
revokeSession(input: RevokeSessionInput!): RevokeSessionPayload!
|
||||||
|
@session(required: PRESENT)
|
||||||
|
revokeAllSessions: RevokeAllSessionsPayload @session(required: PRESENT)
|
||||||
|
}
|
||||||
|
|
||||||
enum SessionOrderField
|
enum SessionOrderField
|
||||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.SessionOrderField") {
|
@goModel(model: "go.probo.inc/probo/pkg/coredata.SessionOrderField") {
|
||||||
CREATED_AT
|
CREATED_AT
|
||||||
|
|||||||
185
pkg/server/api/connect/v1/identity.resolvers.go
Normal file
185
pkg/server/api/connect/v1/identity.resolvers.go
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package connect_v1
|
||||||
|
|
||||||
|
// This file will be automatically regenerated based on the schema, any resolver
|
||||||
|
// implementations
|
||||||
|
// will be copied through when generating and any unknown code will be moved to the end.
|
||||||
|
// Code generated by github.com/99designs/gqlgen version v0.17.87
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/graphql"
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
|
"go.probo.inc/probo/pkg/iam"
|
||||||
|
"go.probo.inc/probo/pkg/page"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/authz"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
||||||
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||||
|
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Profiles is the resolver for the profiles field.
|
||||||
|
func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
|
||||||
|
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList, authz.WithSkipAssumptionCheck()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
||||||
|
if filter != nil {
|
||||||
|
filters = coredata.NewMembershipProfileFilter(filter.ExcludeContractEnded).WithMembership()
|
||||||
|
if filter.State != nil {
|
||||||
|
filters.WithState(*filter.State)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||||
|
return &types.ProfileConnection{
|
||||||
|
Resolver: r,
|
||||||
|
ParentID: obj.ID,
|
||||||
|
Filters: filters,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||||
|
Field: coredata.MembershipProfileOrderFieldFullName,
|
||||||
|
Direction: page.OrderDirectionAsc,
|
||||||
|
}
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
page, err := r.iam.AccountService.ListProfilesForIdentity(ctx, obj.ID, cursor, filters)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewProfileConnection(page, r, obj.ID, filters), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sessions is the resolver for the sessions field.
|
||||||
|
func (r *identityResolver) Sessions(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SessionOrder) (*types.SessionConnection, error) {
|
||||||
|
if err := r.authorize(ctx, obj.ID, iam.ActionSessionList); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||||
|
return &types.SessionConnection{
|
||||||
|
Resolver: r,
|
||||||
|
ParentID: obj.ID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.SessionOrderField]{
|
||||||
|
Field: coredata.SessionOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.SessionOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
page, err := r.iam.AccountService.ListSessions(ctx, obj.ID, cursor)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list sessions", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewSessionConnection(page, r, obj.ID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PersonalAPIKeys is the resolver for the personalAPIKeys field.
|
||||||
|
func (r *identityResolver) PersonalAPIKeys(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.PersonalAPIKeyConnection, error) {
|
||||||
|
if err := r.authorize(ctx, obj.ID, iam.ActionPersonalAPIKeyList); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||||
|
return &types.PersonalAPIKeyConnection{
|
||||||
|
Resolver: r,
|
||||||
|
ParentID: obj.ID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.PersonalAPIKeyOrderField]{
|
||||||
|
Field: coredata.PersonalAPIKeyOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
page, err := r.iam.AccountService.ListPersonalAPIKeys(ctx, obj.ID, cursor)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list personal api keys", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewPersonalAPIKeyConnection(page, r, obj.ID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SsoLoginURL is the resolver for the ssoLoginURL field.
|
||||||
|
func (r *identityResolver) SsoLoginURL(ctx context.Context, obj *types.Identity) (*string, error) {
|
||||||
|
if err := r.authorize(ctx, obj.ID, iam.ActionIdentityGet); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
count, err := r.iam.AccountService.CountSAMLConfigurationsForEmail(ctx, identity.EmailAddress)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot count SAML configurations for email", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if count != 1 {
|
||||||
|
if count == 0 {
|
||||||
|
return nil, graphql.ErrorOnPath(
|
||||||
|
ctx,
|
||||||
|
fmt.Errorf("no SAML configuration for email"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, graphql.ErrorOnPath(
|
||||||
|
ctx,
|
||||||
|
fmt.Errorf("multiple SSO configurations found for this domain. Please use your organization-specific SSO login URL"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
samlConfigs, err := r.iam.AccountService.ListSAMLConfigurationsForEmail(ctx, identity.EmailAddress)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list SAML configurations for email", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(samlConfigs) == 0 {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot find SAML config")
|
||||||
|
return nil, gqlutils.NotFoundf(ctx, "cannot find SAML config")
|
||||||
|
}
|
||||||
|
samlConfig := samlConfigs[0]
|
||||||
|
|
||||||
|
loginURL := r.SSOLoginURL(samlConfig.ID)
|
||||||
|
return &loginURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permission is the resolver for the permission field.
|
||||||
|
func (r *identityResolver) Permission(ctx context.Context, obj *types.Identity, action string) (bool, error) {
|
||||||
|
return r.Resolver.Permission(ctx, obj, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity returns schema.IdentityResolver implementation.
|
||||||
|
func (r *Resolver) Identity() schema.IdentityResolver { return &identityResolver{r} }
|
||||||
|
|
||||||
|
type identityResolver struct{ *Resolver }
|
||||||
@@ -7,13 +7,467 @@ package connect_v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||||
"go.gearno.de/kit/log"
|
"go.gearno.de/kit/log"
|
||||||
|
"go.probo.inc/probo/pkg/iam"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
||||||
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
||||||
"go.probo.inc/probo/pkg/server/gqlutils"
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SignIn is the resolver for the signIn field.
|
||||||
|
func (r *mutationResolver) SignIn(ctx context.Context, input types.SignInInput) (*types.SignInPayload, error) {
|
||||||
|
identity, err := r.iam.AuthService.CheckCredentials(ctx, input.Email, input.Password)
|
||||||
|
if err != nil {
|
||||||
|
var errInvalidPassword *iam.ErrInvalidPassword
|
||||||
|
if errors.As(err, &errInvalidPassword) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errInvalidCredentials *iam.ErrInvalidCredentials
|
||||||
|
if errors.As(err, &errInvalidCredentials) {
|
||||||
|
return nil, &gqlerror.Error{
|
||||||
|
Message: err.Error(),
|
||||||
|
Extensions: map[string]any{
|
||||||
|
"code": "INVALID_CREDENTIALS",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot check credentials", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
session := authn.SessionFromContext(ctx)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case session == nil:
|
||||||
|
var err error
|
||||||
|
session, err = r.iam.AuthService.OpenSessionWithPassword(
|
||||||
|
ctx,
|
||||||
|
identity.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot create session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
case session.IdentityID != identity.ID:
|
||||||
|
if err := r.iam.SessionService.CloseSession(ctx, session.ID); err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err = r.iam.AuthService.OpenSessionWithPassword(
|
||||||
|
ctx,
|
||||||
|
identity.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot create session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
||||||
|
r.sessionCookie.Set(w, session)
|
||||||
|
|
||||||
|
if input.OrganizationID != nil {
|
||||||
|
var err error
|
||||||
|
_, _, err = r.iam.SessionService.OpenPasswordChildSessionForOrganization(ctx, session.ID, *input.OrganizationID)
|
||||||
|
if err != nil {
|
||||||
|
// Here session middleware already took care of expired/nil root session so we only handle membership related errors
|
||||||
|
var errMembershipNotFound *iam.ErrMembershipNotFound
|
||||||
|
var errUserInactive *iam.ErrUserInactive
|
||||||
|
|
||||||
|
if errors.As(err, &errMembershipNotFound) || errors.As(err, &errUserInactive) {
|
||||||
|
return nil, gqlutils.Forbiddenf(ctx, "forbidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot assume organization", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.SignInPayload{
|
||||||
|
Identity: types.NewIdentity(identity),
|
||||||
|
Session: types.NewSession(session),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignUp is the resolver for the signUp field.
|
||||||
|
func (r *mutationResolver) SignUp(ctx context.Context, input types.SignUpInput) (*types.SignUpPayload, error) {
|
||||||
|
identity, session, err := r.iam.AuthService.CreateIdentityWithPassword(
|
||||||
|
ctx,
|
||||||
|
&iam.CreateIdentityWithPasswordRequest{
|
||||||
|
Email: input.Email,
|
||||||
|
Password: input.Password,
|
||||||
|
FullName: input.FullName,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
var errIdentityAlreadyExists *iam.ErrIdentityAlreadyExists
|
||||||
|
if errors.As(err, &errIdentityAlreadyExists) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errSignupDisabled *iam.ErrSignupDisabled
|
||||||
|
if errors.As(err, &errSignupDisabled) {
|
||||||
|
return nil, gqlutils.Forbidden(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot create identity with password", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
||||||
|
r.sessionCookie.Set(w, session)
|
||||||
|
|
||||||
|
return &types.SignUpPayload{
|
||||||
|
Identity: types.NewIdentity(identity),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignOut is the resolver for the signOut field.
|
||||||
|
func (r *mutationResolver) SignOut(ctx context.Context) (*types.SignOutPayload, error) {
|
||||||
|
session := authn.SessionFromContext(ctx)
|
||||||
|
|
||||||
|
err := r.iam.SessionService.CloseSession(ctx, session.ID)
|
||||||
|
if err != nil {
|
||||||
|
var ErrSessionNotFound *iam.ErrSessionNotFound
|
||||||
|
if errors.As(err, &ErrSessionNotFound) {
|
||||||
|
return &types.SignOutPayload{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
||||||
|
r.sessionCookie.Clear(w)
|
||||||
|
|
||||||
|
return &types.SignOutPayload{Success: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivateAccount is the resolver for the activateAccount field.
|
||||||
|
func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.ActivateAccountInput) (*types.ActivateAccountPayload, error) {
|
||||||
|
session := authn.SessionFromContext(ctx)
|
||||||
|
|
||||||
|
if session != nil {
|
||||||
|
// Sign out any other account before activating a new one
|
||||||
|
err := r.iam.SessionService.CloseSession(ctx, session.ID)
|
||||||
|
if err != nil {
|
||||||
|
var ErrSessionNotFound *iam.ErrSessionNotFound
|
||||||
|
if !errors.As(err, &ErrSessionNotFound) {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
||||||
|
r.sessionCookie.Clear(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
identity, user, err := r.iam.AuthService.ActivateAccount(
|
||||||
|
ctx,
|
||||||
|
&iam.ActivateAccountRequest{
|
||||||
|
InvitationToken: input.Token,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
var (
|
||||||
|
errInvalidToken *iam.ErrInvalidToken
|
||||||
|
errInvitationNotFound *iam.ErrInvitationNotFound
|
||||||
|
errInvitationExpired *iam.ErrInvitationExpired
|
||||||
|
|
||||||
|
isInvalidErr = errors.As(err, &errInvalidToken) ||
|
||||||
|
errors.As(err, &errInvitationNotFound) ||
|
||||||
|
errors.As(err, &errInvitationExpired)
|
||||||
|
)
|
||||||
|
|
||||||
|
if isInvalidErr {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := errors.AsType[*iam.ErrInvitationAlreadyAccepted](err); ok {
|
||||||
|
return nil, gqlutils.AccountAlreadyActivated(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot activate account from invitation", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ssoLoginURL *string
|
||||||
|
samlConfigs, err := r.iam.AccountService.ListSAMLConfigurationsForEmail(ctx, user.EmailAddress)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list saml configurations", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, samlConfig := range samlConfigs {
|
||||||
|
if samlConfig.OrganizationID != user.OrganizationID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ssoLoginURL = new(r.SSOLoginURL(samlConfig.ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ssoLoginURL != nil {
|
||||||
|
return &types.ActivateAccountPayload{
|
||||||
|
CreatePasswordToken: nil,
|
||||||
|
SsoLoginURL: ssoLoginURL,
|
||||||
|
Profile: types.NewProfile(user),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var createPasswordToken *string
|
||||||
|
if identity.HashedPassword == nil {
|
||||||
|
token, err := r.iam.AuthService.GetResetPasswordToken(ctx, identity.EmailAddress)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot generate password create token", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
createPasswordToken = &token
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ActivateAccountPayload{
|
||||||
|
CreatePasswordToken: createPasswordToken,
|
||||||
|
SsoLoginURL: nil,
|
||||||
|
Profile: types.NewProfile(user),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForgotPassword is the resolver for the forgotPassword field.
|
||||||
|
func (r *mutationResolver) ForgotPassword(ctx context.Context, input types.ForgotPasswordInput) (*types.ForgotPasswordPayload, error) {
|
||||||
|
err := r.iam.AuthService.SendPasswordResetInstructionByEmail(
|
||||||
|
ctx,
|
||||||
|
input.Email,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot send password reset instruction by email", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ForgotPasswordPayload{
|
||||||
|
Success: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetPassword is the resolver for the resetPassword field.
|
||||||
|
func (r *mutationResolver) ResetPassword(ctx context.Context, input types.ResetPasswordInput) (*types.ResetPasswordPayload, error) {
|
||||||
|
err := r.iam.AuthService.ResetPassword(
|
||||||
|
ctx,
|
||||||
|
&iam.ResetPasswordRequest{
|
||||||
|
Token: input.Token,
|
||||||
|
Password: input.Password,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
var errInvalidToken *iam.ErrInvalidToken
|
||||||
|
if errors.As(err, &errInvalidToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot reset password", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ResetPasswordPayload{
|
||||||
|
Success: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyEmail is the resolver for the verifyEmail field.
|
||||||
|
func (r *mutationResolver) VerifyEmail(ctx context.Context, input types.VerifyEmailInput) (*types.VerifyEmailPayload, error) {
|
||||||
|
err := r.iam.AccountService.VerifyEmail(ctx, input.Token)
|
||||||
|
if err != nil {
|
||||||
|
var (
|
||||||
|
errInvalidToken *iam.ErrInvalidToken
|
||||||
|
errIdentityNotFound *iam.ErrIdentityNotFound
|
||||||
|
errEmailAlreadyVerified *iam.ErrEmailAlreadyVerified
|
||||||
|
errEmailVerificationMismatch *iam.ErrEmailVerificationMismatch
|
||||||
|
|
||||||
|
isInvalidErr = errors.As(err, &errInvalidToken) ||
|
||||||
|
errors.As(err, &errEmailVerificationMismatch)
|
||||||
|
)
|
||||||
|
|
||||||
|
if isInvalidErr {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err, &errEmailAlreadyVerified) {
|
||||||
|
return nil, gqlutils.Conflict(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err, &errIdentityNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot verify email", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.VerifyEmailPayload{
|
||||||
|
Success: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangePassword is the resolver for the changePassword field.
|
||||||
|
func (r *mutationResolver) ChangePassword(ctx context.Context, input types.ChangePasswordInput) (*types.ChangePasswordPayload, error) {
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
err := r.iam.AccountService.ChangePassword(
|
||||||
|
ctx,
|
||||||
|
identity.ID,
|
||||||
|
&iam.ChangePasswordRequest{
|
||||||
|
CurrentPassword: input.CurrentPassword,
|
||||||
|
NewPassword: input.NewPassword,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
var (
|
||||||
|
errInvalidPassword *iam.ErrInvalidPassword
|
||||||
|
errIdentityNotFound *iam.ErrIdentityNotFound
|
||||||
|
)
|
||||||
|
|
||||||
|
if errors.As(err, &errInvalidPassword) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err, &errIdentityNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot change password", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ChangePasswordPayload{
|
||||||
|
Success: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeEmail is the resolver for the changeEmail field.
|
||||||
|
func (r *mutationResolver) ChangeEmail(ctx context.Context, input types.ChangeEmailInput) (*types.ChangeEmailPayload, error) {
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
err := r.iam.AccountService.ChangeEmail(
|
||||||
|
ctx,
|
||||||
|
identity.ID,
|
||||||
|
&iam.ChangeEmailRequest{
|
||||||
|
NewEmail: input.NewEmail,
|
||||||
|
Password: input.Password,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
var (
|
||||||
|
errInvalidPassword *iam.ErrInvalidPassword
|
||||||
|
errIdentityNotFound *iam.ErrIdentityNotFound
|
||||||
|
)
|
||||||
|
|
||||||
|
if errors.As(err, &errInvalidPassword) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err, &errIdentityNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot change email", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.ChangeEmailPayload{
|
||||||
|
Success: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssumeOrganizationSession is the resolver for the assumeOrganizationSession field.
|
||||||
|
func (r *mutationResolver) AssumeOrganizationSession(ctx context.Context, input types.AssumeOrganizationSessionInput) (*types.AssumeOrganizationSessionPayload, error) {
|
||||||
|
rootSession := authn.SessionFromContext(ctx)
|
||||||
|
|
||||||
|
childSession, membership, err := r.iam.SessionService.AssumeOrganizationSession(ctx, rootSession.ID, input.OrganizationID, input.Continue)
|
||||||
|
if err != nil {
|
||||||
|
var (
|
||||||
|
errMembershipNotFound *iam.ErrMembershipNotFound
|
||||||
|
errPasswordAuthenticationRequired *iam.ErrPasswordAuthenticationRequired
|
||||||
|
errSAMLAuthenticationRequired *iam.ErrSAMLAuthenticationRequired
|
||||||
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case errors.As(err, &errMembershipNotFound):
|
||||||
|
return nil, gqlutils.NotFound(ctx, err)
|
||||||
|
|
||||||
|
case errors.As(err, &errPasswordAuthenticationRequired):
|
||||||
|
return &types.AssumeOrganizationSessionPayload{
|
||||||
|
Result: types.PasswordRequired{
|
||||||
|
Reason: types.ReauthenticationReason(errPasswordAuthenticationRequired.Reason),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case errors.As(err, &errSAMLAuthenticationRequired):
|
||||||
|
return &types.AssumeOrganizationSessionPayload{
|
||||||
|
Result: types.SAMLAuthenticationRequired{
|
||||||
|
Reason: types.ReauthenticationReason(errSAMLAuthenticationRequired.Reason),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot assume organization session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.AssumeOrganizationSessionPayload{
|
||||||
|
Result: types.OrganizationSessionCreated{
|
||||||
|
Session: types.NewSession(childSession),
|
||||||
|
Membership: types.NewMembership(membership),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeSession is the resolver for the revokeSession field.
|
||||||
|
func (r *mutationResolver) RevokeSession(ctx context.Context, input types.RevokeSessionInput) (*types.RevokeSessionPayload, error) {
|
||||||
|
if err := r.authorize(ctx, input.SessionID, iam.ActionSessionRevoke); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
err := r.iam.SessionService.RevokeSession(ctx, identity.ID, input.SessionID)
|
||||||
|
if err != nil {
|
||||||
|
var ErrSessionExpired *iam.ErrSessionExpired
|
||||||
|
if errors.As(err, &ErrSessionExpired) {
|
||||||
|
return &types.RevokeSessionPayload{Success: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot revoke session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.RevokeSessionPayload{Success: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeAllSessions is the resolver for the revokeAllSessions field.
|
||||||
|
func (r *mutationResolver) RevokeAllSessions(ctx context.Context) (*types.RevokeAllSessionsPayload, error) {
|
||||||
|
if err := r.authorize(ctx, authn.SessionFromContext(ctx).ID, iam.ActionSessionRevokeAll); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
session := authn.SessionFromContext(ctx)
|
||||||
|
|
||||||
|
revokedCount, err := r.iam.SessionService.RevokeAllSessions(ctx, session.ID)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot revoke all sessions", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.RevokeAllSessionsPayload{RevokedCount: int(revokedCount)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Identity is the resolver for the identity field.
|
// Identity is the resolver for the identity field.
|
||||||
func (r *sessionResolver) Identity(ctx context.Context, obj *types.Session) (*types.Identity, error) {
|
func (r *sessionResolver) Identity(ctx context.Context, obj *types.Session) (*types.Identity, error) {
|
||||||
if gqlutils.OnlyIDSelected(ctx) {
|
if gqlutils.OnlyIDSelected(ctx) {
|
||||||
|
|||||||
@@ -9,13 +9,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.gearno.de/kit/log"
|
"go.gearno.de/kit/log"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/iam"
|
"go.probo.inc/probo/pkg/iam"
|
||||||
"go.probo.inc/probo/pkg/page"
|
|
||||||
"go.probo.inc/probo/pkg/probo"
|
"go.probo.inc/probo/pkg/probo"
|
||||||
"go.probo.inc/probo/pkg/server/api/authn"
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
|
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
|
||||||
@@ -24,23 +22,6 @@ import (
|
|||||||
"go.probo.inc/probo/pkg/validator"
|
"go.probo.inc/probo/pkg/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DownloadURL is the resolver for the downloadUrl field.
|
|
||||||
func (r *fileResolver) DownloadURL(ctx context.Context, obj *types.File) (string, error) {
|
|
||||||
if err := r.authorize(ctx, obj.ID, probo.ActionFileDownloadUrl); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
prb := r.ProboService(ctx, obj.ID.TenantID())
|
|
||||||
|
|
||||||
downloadUrl, err := prb.Files.GenerateFileTempURL(ctx, obj.ID, 60*time.Second)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot generate download URL", log.Error(err))
|
|
||||||
return "", gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return downloadUrl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateOrganizationContext is the resolver for the updateOrganizationContext field.
|
// UpdateOrganizationContext is the resolver for the updateOrganizationContext field.
|
||||||
func (r *mutationResolver) UpdateOrganizationContext(ctx context.Context, input types.UpdateOrganizationContextInput) (*types.UpdateOrganizationContextPayload, error) {
|
func (r *mutationResolver) UpdateOrganizationContext(ctx context.Context, input types.UpdateOrganizationContextInput) (*types.UpdateOrganizationContextPayload, error) {
|
||||||
if err := r.authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate); err != nil {
|
if err := r.authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate); err != nil {
|
||||||
@@ -431,177 +412,11 @@ func (r *queryResolver) Viewer(ctx context.Context) (*types.Viewer, error) {
|
|||||||
return &types.Viewer{ID: viewerID}, nil
|
return &types.Viewer{ID: viewerID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignableDocuments is the resolver for the signableDocuments field.
|
|
||||||
func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
|
|
||||||
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prb := r.ProboService(ctx, organizationID.TenantID())
|
|
||||||
|
|
||||||
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
||||||
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
||||||
Direction: page.OrderDirectionDesc,
|
|
||||||
}
|
|
||||||
if orderBy != nil {
|
|
||||||
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
||||||
Field: orderBy.Field,
|
|
||||||
Direction: orderBy.Direction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
|
|
||||||
|
|
||||||
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list organization signable documents", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
|
|
||||||
for i, doc := range documentsPage.Data {
|
|
||||||
employeeDocuments[i] = &types.EmployeeDocument{
|
|
||||||
ID: doc.ID,
|
|
||||||
Title: doc.Title,
|
|
||||||
DocumentType: doc.DocumentType,
|
|
||||||
CreatedAt: doc.CreatedAt,
|
|
||||||
UpdatedAt: doc.UpdatedAt,
|
|
||||||
FilterMode: types.EmployeeDocumentFilterModeSignature,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
|
|
||||||
|
|
||||||
return types.NewEmployeeDocumentConnection(page), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignableDocument is the resolver for the signableDocument field.
|
|
||||||
func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
|
|
||||||
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prb := r.ProboService(ctx, id.TenantID())
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
|
|
||||||
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
||||||
return nil, gqlutils.NotFound(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot get signable document", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.EmployeeDocument{
|
|
||||||
ID: document.ID,
|
|
||||||
Title: document.Title,
|
|
||||||
DocumentType: document.DocumentType,
|
|
||||||
CreatedAt: document.CreatedAt,
|
|
||||||
UpdatedAt: document.UpdatedAt,
|
|
||||||
FilterMode: types.EmployeeDocumentFilterModeSignature,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApprovableDocuments is the resolver for the approvableDocuments field.
|
|
||||||
func (r *viewerResolver) ApprovableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
|
|
||||||
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prb := r.ProboService(ctx, organizationID.TenantID())
|
|
||||||
|
|
||||||
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
||||||
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
||||||
Direction: page.OrderDirectionDesc,
|
|
||||||
}
|
|
||||||
if orderBy != nil {
|
|
||||||
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
||||||
Field: orderBy.Field,
|
|
||||||
Direction: orderBy.Direction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
|
|
||||||
|
|
||||||
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot list organization approvable documents", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
|
|
||||||
for i, doc := range documentsPage.Data {
|
|
||||||
employeeDocuments[i] = &types.EmployeeDocument{
|
|
||||||
ID: doc.ID,
|
|
||||||
Title: doc.Title,
|
|
||||||
DocumentType: doc.DocumentType,
|
|
||||||
CreatedAt: doc.CreatedAt,
|
|
||||||
UpdatedAt: doc.UpdatedAt,
|
|
||||||
FilterMode: types.EmployeeDocumentFilterModeApproval,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
|
|
||||||
|
|
||||||
return types.NewEmployeeDocumentConnection(page), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApprovableDocument is the resolver for the approvableDocument field.
|
|
||||||
func (r *viewerResolver) ApprovableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
|
|
||||||
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prb := r.ProboService(ctx, id.TenantID())
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
|
|
||||||
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
||||||
return nil, gqlutils.NotFound(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot get approvable document", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.EmployeeDocument{
|
|
||||||
ID: document.ID,
|
|
||||||
Title: document.Title,
|
|
||||||
DocumentType: document.DocumentType,
|
|
||||||
CreatedAt: document.CreatedAt,
|
|
||||||
UpdatedAt: document.UpdatedAt,
|
|
||||||
FilterMode: types.EmployeeDocumentFilterModeApproval,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// File returns schema.FileResolver implementation.
|
|
||||||
func (r *Resolver) File() schema.FileResolver { return &fileResolver{r} }
|
|
||||||
|
|
||||||
// Mutation returns schema.MutationResolver implementation.
|
// Mutation returns schema.MutationResolver implementation.
|
||||||
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
||||||
|
|
||||||
// Query returns schema.QueryResolver implementation.
|
// Query returns schema.QueryResolver implementation.
|
||||||
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
||||||
|
|
||||||
// Viewer returns schema.ViewerResolver implementation.
|
|
||||||
func (r *Resolver) Viewer() schema.ViewerResolver { return &viewerResolver{r} }
|
|
||||||
|
|
||||||
type fileResolver struct{ *Resolver }
|
|
||||||
type mutationResolver struct{ *Resolver }
|
type mutationResolver struct{ *Resolver }
|
||||||
type queryResolver struct{ *Resolver }
|
type queryResolver struct{ *Resolver }
|
||||||
type viewerResolver struct{ *Resolver }
|
|
||||||
|
|||||||
39
pkg/server/api/console/v1/file.resolvers.go
Normal file
39
pkg/server/api/console/v1/file.resolvers.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package console_v1
|
||||||
|
|
||||||
|
// This file will be automatically regenerated based on the schema, any resolver
|
||||||
|
// implementations
|
||||||
|
// will be copied through when generating and any unknown code will be moved to the end.
|
||||||
|
// Code generated by github.com/99designs/gqlgen version v0.17.87
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
|
"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/gqlutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DownloadURL is the resolver for the downloadUrl field.
|
||||||
|
func (r *fileResolver) DownloadURL(ctx context.Context, obj *types.File) (string, error) {
|
||||||
|
if err := r.authorize(ctx, obj.ID, probo.ActionFileDownloadUrl); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
|
downloadUrl, err := prb.Files.GenerateFileTempURL(ctx, obj.ID, 60*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot generate download URL", log.Error(err))
|
||||||
|
return "", gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return downloadUrl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// File returns schema.FileResolver implementation.
|
||||||
|
func (r *Resolver) File() schema.FileResolver { return &fileResolver{r} }
|
||||||
|
|
||||||
|
type fileResolver struct{ *Resolver }
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
# Directives
|
|
||||||
directive @goField(
|
directive @goField(
|
||||||
forceResolver: Boolean
|
forceResolver: Boolean
|
||||||
name: String
|
name: String
|
||||||
@@ -12,7 +11,6 @@ directive @goModel(
|
|||||||
|
|
||||||
directive @goEnum(value: String) on ENUM_VALUE
|
directive @goEnum(value: String) on ENUM_VALUE
|
||||||
|
|
||||||
# Scalars
|
|
||||||
scalar CursorKey
|
scalar CursorKey
|
||||||
scalar Datetime
|
scalar Datetime
|
||||||
scalar Upload
|
scalar Upload
|
||||||
@@ -20,321 +18,15 @@ scalar Duration
|
|||||||
scalar BigInt
|
scalar BigInt
|
||||||
scalar EmailAddr
|
scalar EmailAddr
|
||||||
|
|
||||||
# Interfaces
|
|
||||||
interface Node {
|
interface Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
# Pagination
|
|
||||||
type PageInfo {
|
|
||||||
hasNextPage: Boolean!
|
|
||||||
hasPreviousPage: Boolean!
|
|
||||||
startCursor: CursorKey
|
|
||||||
endCursor: CursorKey
|
|
||||||
}
|
|
||||||
|
|
||||||
# Enums
|
|
||||||
enum OrderDirection
|
|
||||||
@goModel(model: "go.probo.inc/probo/pkg/page.OrderDirection") {
|
|
||||||
ASC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionAsc")
|
|
||||||
DESC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionDesc")
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CountryCode
|
|
||||||
@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")
|
|
||||||
}
|
|
||||||
|
|
||||||
type File {
|
|
||||||
id: ID!
|
|
||||||
mimeType: String!
|
|
||||||
fileName: String!
|
|
||||||
size: BigInt!
|
|
||||||
downloadUrl: String! @goField(forceResolver: true)
|
|
||||||
createdAt: Datetime!
|
|
||||||
updatedAt: Datetime!
|
|
||||||
}
|
|
||||||
|
|
||||||
# Root Types
|
|
||||||
type Query {
|
type Query {
|
||||||
node(id: ID!): Node!
|
node(id: ID!): Node!
|
||||||
viewer: Viewer!
|
viewer: Viewer!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Viewer {
|
|
||||||
id: ID!
|
|
||||||
|
|
||||||
signableDocuments(
|
|
||||||
organizationId: ID!
|
|
||||||
first: Int
|
|
||||||
after: CursorKey
|
|
||||||
last: Int
|
|
||||||
before: CursorKey
|
|
||||||
orderBy: DocumentOrder
|
|
||||||
): EmployeeDocumentConnection! @goField(forceResolver: true)
|
|
||||||
|
|
||||||
signableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
|
|
||||||
|
|
||||||
approvableDocuments(
|
|
||||||
organizationId: ID!
|
|
||||||
first: Int
|
|
||||||
after: CursorKey
|
|
||||||
last: Int
|
|
||||||
before: CursorKey
|
|
||||||
orderBy: DocumentOrder
|
|
||||||
): EmployeeDocumentConnection! @goField(forceResolver: true)
|
|
||||||
|
|
||||||
approvableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
updateOrganizationContext(
|
updateOrganizationContext(
|
||||||
input: UpdateOrganizationContextInput!
|
input: UpdateOrganizationContextInput!
|
||||||
|
|||||||
253
pkg/server/api/console/v1/graphql/country_code.graphql
Normal file
253
pkg/server/api/console/v1/graphql/country_code.graphql
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
enum CountryCode
|
||||||
|
@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")
|
||||||
|
}
|
||||||
|
|
||||||
9
pkg/server/api/console/v1/graphql/file.graphql
Normal file
9
pkg/server/api/console/v1/graphql/file.graphql
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
type File {
|
||||||
|
id: ID!
|
||||||
|
mimeType: String!
|
||||||
|
fileName: String!
|
||||||
|
size: BigInt!
|
||||||
|
downloadUrl: String! @goField(forceResolver: true)
|
||||||
|
createdAt: Datetime!
|
||||||
|
updatedAt: Datetime!
|
||||||
|
}
|
||||||
12
pkg/server/api/console/v1/graphql/pagination.graphql
Normal file
12
pkg/server/api/console/v1/graphql/pagination.graphql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
type PageInfo {
|
||||||
|
hasNextPage: Boolean!
|
||||||
|
hasPreviousPage: Boolean!
|
||||||
|
startCursor: CursorKey
|
||||||
|
endCursor: CursorKey
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OrderDirection
|
||||||
|
@goModel(model: "go.probo.inc/probo/pkg/page.OrderDirection") {
|
||||||
|
ASC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionAsc")
|
||||||
|
DESC @goEnum(value: "go.probo.inc/probo/pkg/page.OrderDirectionDesc")
|
||||||
|
}
|
||||||
25
pkg/server/api/console/v1/graphql/viewer.graphql
Normal file
25
pkg/server/api/console/v1/graphql/viewer.graphql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
type Viewer {
|
||||||
|
id: ID!
|
||||||
|
|
||||||
|
signableDocuments(
|
||||||
|
organizationId: ID!
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
orderBy: DocumentOrder
|
||||||
|
): EmployeeDocumentConnection! @goField(forceResolver: true)
|
||||||
|
|
||||||
|
signableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
|
||||||
|
|
||||||
|
approvableDocuments(
|
||||||
|
organizationId: ID!
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
orderBy: DocumentOrder
|
||||||
|
): EmployeeDocumentConnection! @goField(forceResolver: true)
|
||||||
|
|
||||||
|
approvableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
|
||||||
|
}
|
||||||
184
pkg/server/api/console/v1/viewer.resolvers.go
Normal file
184
pkg/server/api/console/v1/viewer.resolvers.go
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
package console_v1
|
||||||
|
|
||||||
|
// This file will be automatically regenerated based on the schema, any resolver
|
||||||
|
// implementations
|
||||||
|
// will be copied through when generating and any unknown code will be moved to the end.
|
||||||
|
// Code generated by github.com/99designs/gqlgen version v0.17.87
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
|
"go.probo.inc/probo/pkg/gid"
|
||||||
|
"go.probo.inc/probo/pkg/page"
|
||||||
|
"go.probo.inc/probo/pkg/probo"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
|
"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/gqlutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SignableDocuments is the resolver for the signableDocuments field.
|
||||||
|
func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
|
||||||
|
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, organizationID.TenantID())
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
||||||
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
|
||||||
|
|
||||||
|
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list organization signable documents", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
|
||||||
|
for i, doc := range documentsPage.Data {
|
||||||
|
employeeDocuments[i] = &types.EmployeeDocument{
|
||||||
|
ID: doc.ID,
|
||||||
|
Title: doc.Title,
|
||||||
|
DocumentType: doc.DocumentType,
|
||||||
|
CreatedAt: doc.CreatedAt,
|
||||||
|
UpdatedAt: doc.UpdatedAt,
|
||||||
|
FilterMode: types.EmployeeDocumentFilterModeSignature,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
|
||||||
|
|
||||||
|
return types.NewEmployeeDocumentConnection(page), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignableDocument is the resolver for the signableDocument field.
|
||||||
|
func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
|
||||||
|
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, id.TenantID())
|
||||||
|
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
|
||||||
|
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot get signable document", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.EmployeeDocument{
|
||||||
|
ID: document.ID,
|
||||||
|
Title: document.Title,
|
||||||
|
DocumentType: document.DocumentType,
|
||||||
|
CreatedAt: document.CreatedAt,
|
||||||
|
UpdatedAt: document.UpdatedAt,
|
||||||
|
FilterMode: types.EmployeeDocumentFilterModeSignature,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApprovableDocuments is the resolver for the approvableDocuments field.
|
||||||
|
func (r *viewerResolver) ApprovableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
|
||||||
|
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, organizationID.TenantID())
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
||||||
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
|
||||||
|
|
||||||
|
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list organization approvable documents", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
|
||||||
|
for i, doc := range documentsPage.Data {
|
||||||
|
employeeDocuments[i] = &types.EmployeeDocument{
|
||||||
|
ID: doc.ID,
|
||||||
|
Title: doc.Title,
|
||||||
|
DocumentType: doc.DocumentType,
|
||||||
|
CreatedAt: doc.CreatedAt,
|
||||||
|
UpdatedAt: doc.UpdatedAt,
|
||||||
|
FilterMode: types.EmployeeDocumentFilterModeApproval,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
|
||||||
|
|
||||||
|
return types.NewEmployeeDocumentConnection(page), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApprovableDocument is the resolver for the approvableDocument field.
|
||||||
|
func (r *viewerResolver) ApprovableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
|
||||||
|
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, id.TenantID())
|
||||||
|
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
|
||||||
|
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot get approvable document", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.EmployeeDocument{
|
||||||
|
ID: document.ID,
|
||||||
|
Title: document.Title,
|
||||||
|
DocumentType: document.DocumentType,
|
||||||
|
CreatedAt: document.CreatedAt,
|
||||||
|
UpdatedAt: document.UpdatedAt,
|
||||||
|
FilterMode: types.EmployeeDocumentFilterModeApproval,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Viewer returns schema.ViewerResolver implementation.
|
||||||
|
func (r *Resolver) Viewer() schema.ViewerResolver { return &viewerResolver{r} }
|
||||||
|
|
||||||
|
type viewerResolver struct{ *Resolver }
|
||||||
179
pkg/server/api/trust/v1/auth.resolvers.go
Normal file
179
pkg/server/api/trust/v1/auth.resolvers.go
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
package trust_v1
|
||||||
|
|
||||||
|
// This file will be automatically regenerated based on the schema, any resolver
|
||||||
|
// implementations
|
||||||
|
// will be copied through when generating and any unknown code will be moved to the end.
|
||||||
|
// Code generated by github.com/99designs/gqlgen version v0.17.87
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/log"
|
||||||
|
"go.probo.inc/probo/pkg/baseurl"
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
|
"go.probo.inc/probo/pkg/iam"
|
||||||
|
"go.probo.inc/probo/pkg/saferedirect"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/compliancepage"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
|
||||||
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SendMagicLink is the resolver for the sendMagicLink field.
|
||||||
|
func (r *mutationResolver) SendMagicLink(ctx context.Context, input types.SendMagicLinkInput) (*types.SendMagicLinkPayload, error) {
|
||||||
|
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||||
|
|
||||||
|
baseURL := compliancepage.CompliancePageBaseURLFromContext(ctx)
|
||||||
|
|
||||||
|
safeRedirect := saferedirect.New(saferedirect.StaticHosts(baseurl.MustParse(*baseURL).Host()))
|
||||||
|
|
||||||
|
if input.Continue != nil {
|
||||||
|
_, ok := safeRedirect.Validate(ctx, *input.Continue)
|
||||||
|
if !ok {
|
||||||
|
return nil, gqlutils.Invalidf(ctx, "invalid continue URL")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &iam.SendMagicLinkRequest{
|
||||||
|
Email: input.Email,
|
||||||
|
CompliancePageID: &trustCenter.ID,
|
||||||
|
OrganizationID: trustCenter.OrganizationID,
|
||||||
|
URLPath: "verify-magic-link",
|
||||||
|
Continue: input.Continue,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.iam.AuthService.SendMagicLink(ctx, req); err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot send magic link", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyMagicLink is the resolver for the verifyMagicLink field.
|
||||||
|
func (r *mutationResolver) VerifyMagicLink(ctx context.Context, input types.VerifyMagicLinkInput) (*types.VerifyMagicLinkPayload, error) {
|
||||||
|
session := authn.SessionFromContext(ctx)
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
|
||||||
|
email, err := r.iam.AuthService.GetMagicLinkEmail(ctx, input.Token)
|
||||||
|
if err != nil {
|
||||||
|
var errExpiredToken *iam.ErrExpiredToken
|
||||||
|
if errors.As(err, &errExpiredToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errInvalidToken *iam.ErrInvalidToken
|
||||||
|
if errors.As(err, &errInvalidToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot get magic link email", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
var continueURL *string
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case session == nil:
|
||||||
|
var err error
|
||||||
|
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
||||||
|
if err != nil {
|
||||||
|
var errExpiredToken *iam.ErrExpiredToken
|
||||||
|
if errors.As(err, &errExpiredToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errInvalidToken *iam.ErrInvalidToken
|
||||||
|
if errors.As(err, &errInvalidToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
case identity.EmailAddress != email:
|
||||||
|
if err := r.iam.SessionService.CloseSession(ctx, session.ID); err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
||||||
|
if err != nil {
|
||||||
|
var errExpiredToken *iam.ErrExpiredToken
|
||||||
|
if errors.As(err, &errExpiredToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errInvalidToken *iam.ErrInvalidToken
|
||||||
|
if errors.As(err, &errInvalidToken) {
|
||||||
|
return nil, gqlutils.Invalid(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||||
|
|
||||||
|
if _, err := r.trust.ProvisionMember(ctx, trustCenter.ID, identity.ID); err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot provision member", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
||||||
|
r.sessionCookie.Set(w, session)
|
||||||
|
|
||||||
|
return &types.VerifyMagicLinkPayload{
|
||||||
|
Continue: continueURL,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFullName is the resolver for the updateFullName field.
|
||||||
|
func (r *mutationResolver) UpdateFullName(ctx context.Context, input types.UpdateFullNameInput) (*types.UpdateFullNamePayload, error) {
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
if identity == nil {
|
||||||
|
return nil, gqlutils.Unauthenticatedf(ctx, "authentication is required to request access")
|
||||||
|
}
|
||||||
|
|
||||||
|
identity, err := r.iam.AccountService.UpdateIdentity(
|
||||||
|
ctx,
|
||||||
|
identity.ID,
|
||||||
|
&iam.UpdateIdentityRequest{
|
||||||
|
FullName: input.FullName,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot update identity", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
compliancePage := compliancepage.CompliancePageFromContext(ctx)
|
||||||
|
|
||||||
|
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, compliancePage.OrganizationID)
|
||||||
|
if err != nil {
|
||||||
|
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); !ok {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.Source == coredata.ProfileSourceManual {
|
||||||
|
if _, err := r.iam.OrganizationService.UpdateUser(ctx, &iam.UpdateUserRequest{
|
||||||
|
ID: profile.ID,
|
||||||
|
FullName: identity.FullName,
|
||||||
|
AdditionalEmailAddresses: profile.AdditionalEmailAddresses,
|
||||||
|
Kind: profile.Kind,
|
||||||
|
Position: profile.Position,
|
||||||
|
ContractStartDate: &profile.ContractStartDate,
|
||||||
|
ContractEndDate: &profile.ContractEndDate,
|
||||||
|
}); err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot update profile", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.UpdateFullNamePayload{Success: true}, nil
|
||||||
|
}
|
||||||
@@ -9,14 +9,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.gearno.de/kit/log"
|
"go.gearno.de/kit/log"
|
||||||
"go.probo.inc/probo/pkg/baseurl"
|
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/iam"
|
|
||||||
"go.probo.inc/probo/pkg/saferedirect"
|
|
||||||
"go.probo.inc/probo/pkg/server/api/authn"
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
"go.probo.inc/probo/pkg/server/api/compliancepage"
|
"go.probo.inc/probo/pkg/server/api/compliancepage"
|
||||||
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
|
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
|
||||||
@@ -25,171 +21,6 @@ import (
|
|||||||
"go.probo.inc/probo/pkg/trust"
|
"go.probo.inc/probo/pkg/trust"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SendMagicLink is the resolver for the sendMagicLink field.
|
|
||||||
func (r *mutationResolver) SendMagicLink(ctx context.Context, input types.SendMagicLinkInput) (*types.SendMagicLinkPayload, error) {
|
|
||||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
|
||||||
|
|
||||||
baseURL := compliancepage.CompliancePageBaseURLFromContext(ctx)
|
|
||||||
|
|
||||||
safeRedirect := saferedirect.New(saferedirect.StaticHosts(baseurl.MustParse(*baseURL).Host()))
|
|
||||||
|
|
||||||
if input.Continue != nil {
|
|
||||||
_, ok := safeRedirect.Validate(ctx, *input.Continue)
|
|
||||||
if !ok {
|
|
||||||
return nil, gqlutils.Invalidf(ctx, "invalid continue URL")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &iam.SendMagicLinkRequest{
|
|
||||||
Email: input.Email,
|
|
||||||
CompliancePageID: &trustCenter.ID,
|
|
||||||
OrganizationID: trustCenter.OrganizationID,
|
|
||||||
URLPath: "verify-magic-link",
|
|
||||||
Continue: input.Continue,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := r.iam.AuthService.SendMagicLink(ctx, req); err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot send magic link", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyMagicLink is the resolver for the verifyMagicLink field.
|
|
||||||
func (r *mutationResolver) VerifyMagicLink(ctx context.Context, input types.VerifyMagicLinkInput) (*types.VerifyMagicLinkPayload, error) {
|
|
||||||
session := authn.SessionFromContext(ctx)
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
|
|
||||||
email, err := r.iam.AuthService.GetMagicLinkEmail(ctx, input.Token)
|
|
||||||
if err != nil {
|
|
||||||
var errExpiredToken *iam.ErrExpiredToken
|
|
||||||
if errors.As(err, &errExpiredToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidToken *iam.ErrInvalidToken
|
|
||||||
if errors.As(err, &errInvalidToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot get magic link email", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
var continueURL *string
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case session == nil:
|
|
||||||
var err error
|
|
||||||
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
|
||||||
if err != nil {
|
|
||||||
var errExpiredToken *iam.ErrExpiredToken
|
|
||||||
if errors.As(err, &errExpiredToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidToken *iam.ErrInvalidToken
|
|
||||||
if errors.As(err, &errInvalidToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
case identity.EmailAddress != email:
|
|
||||||
if err := r.iam.SessionService.CloseSession(ctx, session.ID); err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
|
||||||
if err != nil {
|
|
||||||
var errExpiredToken *iam.ErrExpiredToken
|
|
||||||
if errors.As(err, &errExpiredToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidToken *iam.ErrInvalidToken
|
|
||||||
if errors.As(err, &errInvalidToken) {
|
|
||||||
return nil, gqlutils.Invalid(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
|
||||||
|
|
||||||
if _, err := r.trust.ProvisionMember(ctx, trustCenter.ID, identity.ID); err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot provision member", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
||||||
r.sessionCookie.Set(w, session)
|
|
||||||
|
|
||||||
return &types.VerifyMagicLinkPayload{
|
|
||||||
Continue: continueURL,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateFullName is the resolver for the updateFullName field.
|
|
||||||
func (r *mutationResolver) UpdateFullName(ctx context.Context, input types.UpdateFullNameInput) (*types.UpdateFullNamePayload, error) {
|
|
||||||
identity := authn.IdentityFromContext(ctx)
|
|
||||||
if identity == nil {
|
|
||||||
return nil, gqlutils.Unauthenticatedf(ctx, "authentication is required to request access")
|
|
||||||
}
|
|
||||||
|
|
||||||
identity, err := r.iam.AccountService.UpdateIdentity(
|
|
||||||
ctx,
|
|
||||||
identity.ID,
|
|
||||||
&iam.UpdateIdentityRequest{
|
|
||||||
FullName: input.FullName,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot update identity", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
compliancePage := compliancepage.CompliancePageFromContext(ctx)
|
|
||||||
|
|
||||||
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, compliancePage.OrganizationID)
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); !ok {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if profile.Source == coredata.ProfileSourceManual {
|
|
||||||
if _, err := r.iam.OrganizationService.UpdateUser(ctx, &iam.UpdateUserRequest{
|
|
||||||
ID: profile.ID,
|
|
||||||
FullName: identity.FullName,
|
|
||||||
AdditionalEmailAddresses: profile.AdditionalEmailAddresses,
|
|
||||||
Kind: profile.Kind,
|
|
||||||
Position: profile.Position,
|
|
||||||
ContractStartDate: &profile.ContractStartDate,
|
|
||||||
ContractEndDate: &profile.ContractEndDate,
|
|
||||||
}); err != nil {
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot update profile", log.Error(err))
|
|
||||||
return nil, gqlutils.Internal(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.UpdateFullNamePayload{Success: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LogoURL is the resolver for the logoUrl field.
|
|
||||||
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
|
|
||||||
trustService := r.TrustService(ctx, obj.ID.TenantID())
|
|
||||||
|
|
||||||
return trustService.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Viewer is the resolver for the viewer field.
|
// Viewer is the resolver for the viewer field.
|
||||||
func (r *queryResolver) Viewer(ctx context.Context) (*types.Identity, error) {
|
func (r *queryResolver) Viewer(ctx context.Context) (*types.Identity, error) {
|
||||||
identity := authn.IdentityFromContext(ctx)
|
identity := authn.IdentityFromContext(ctx)
|
||||||
@@ -352,12 +183,8 @@ func (r *queryResolver) OidcProviders(ctx context.Context) ([]*types.OIDCProvide
|
|||||||
// Mutation returns schema.MutationResolver implementation.
|
// Mutation returns schema.MutationResolver implementation.
|
||||||
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
|
||||||
|
|
||||||
// Organization returns schema.OrganizationResolver implementation.
|
|
||||||
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
|
|
||||||
|
|
||||||
// Query returns schema.QueryResolver implementation.
|
// Query returns schema.QueryResolver implementation.
|
||||||
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
||||||
|
|
||||||
type mutationResolver struct{ *Resolver }
|
type mutationResolver struct{ *Resolver }
|
||||||
type organizationResolver struct{ *Resolver }
|
|
||||||
type queryResolver struct{ *Resolver }
|
type queryResolver struct{ *Resolver }
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
extend type Mutation {
|
||||||
|
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
|
||||||
|
@session(required: OPTIONAL)
|
||||||
|
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
||||||
|
@session(required: OPTIONAL)
|
||||||
|
updateFullName(input: UpdateFullNameInput!): UpdateFullNamePayload
|
||||||
|
@session(required: PRESENT)
|
||||||
|
}
|
||||||
|
|
||||||
input SendMagicLinkInput {
|
input SendMagicLinkInput {
|
||||||
email: EmailAddr!
|
email: EmailAddr!
|
||||||
continue: String
|
continue: String
|
||||||
|
|||||||
@@ -21,291 +21,6 @@ interface Node {
|
|||||||
id: ID!
|
id: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageInfo {
|
|
||||||
hasNextPage: Boolean!
|
|
||||||
hasPreviousPage: Boolean!
|
|
||||||
startCursor: CursorKey
|
|
||||||
endCursor: CursorKey
|
|
||||||
}
|
|
||||||
|
|
||||||
type Identity implements Node {
|
|
||||||
id: ID!
|
|
||||||
email: EmailAddr!
|
|
||||||
fullName: String!
|
|
||||||
emailVerified: Boolean!
|
|
||||||
createdAt: Datetime!
|
|
||||||
updatedAt: Datetime!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Organization implements Node {
|
|
||||||
id: ID!
|
|
||||||
name: String!
|
|
||||||
logoUrl: String @goField(forceResolver: true)
|
|
||||||
|
|
||||||
description: String
|
|
||||||
websiteUrl: String
|
|
||||||
email: String
|
|
||||||
headquarterAddress: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type OIDCProviderInfo {
|
|
||||||
name: String!
|
|
||||||
loginURL: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CountryCode
|
|
||||||
@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")
|
|
||||||
}
|
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
viewer: Identity
|
viewer: Identity
|
||||||
node(id: ID!): Node
|
node(id: ID!): Node
|
||||||
@@ -315,11 +30,4 @@ type Query {
|
|||||||
@session(required: OPTIONAL)
|
@session(required: OPTIONAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation
|
||||||
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
|
|
||||||
@session(required: OPTIONAL)
|
|
||||||
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
|
||||||
@session(required: OPTIONAL)
|
|
||||||
updateFullName(input: UpdateFullNameInput!): UpdateFullNamePayload
|
|
||||||
@session(required: PRESENT)
|
|
||||||
}
|
|
||||||
|
|||||||
253
pkg/server/api/trust/v1/graphql/country_code.graphql
Normal file
253
pkg/server/api/trust/v1/graphql/country_code.graphql
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
enum CountryCode
|
||||||
|
@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")
|
||||||
|
}
|
||||||
|
|
||||||
8
pkg/server/api/trust/v1/graphql/identity.graphql
Normal file
8
pkg/server/api/trust/v1/graphql/identity.graphql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
type Identity implements Node {
|
||||||
|
id: ID!
|
||||||
|
email: EmailAddr!
|
||||||
|
fullName: String!
|
||||||
|
emailVerified: Boolean!
|
||||||
|
createdAt: Datetime!
|
||||||
|
updatedAt: Datetime!
|
||||||
|
}
|
||||||
4
pkg/server/api/trust/v1/graphql/oidc.graphql
Normal file
4
pkg/server/api/trust/v1/graphql/oidc.graphql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
type OIDCProviderInfo {
|
||||||
|
name: String!
|
||||||
|
loginURL: String!
|
||||||
|
}
|
||||||
10
pkg/server/api/trust/v1/graphql/organization.graphql
Normal file
10
pkg/server/api/trust/v1/graphql/organization.graphql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
type Organization implements Node {
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
logoUrl: String @goField(forceResolver: true)
|
||||||
|
|
||||||
|
description: String
|
||||||
|
websiteUrl: String
|
||||||
|
email: String
|
||||||
|
headquarterAddress: String
|
||||||
|
}
|
||||||
6
pkg/server/api/trust/v1/graphql/pagination.graphql
Normal file
6
pkg/server/api/trust/v1/graphql/pagination.graphql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
type PageInfo {
|
||||||
|
hasNextPage: Boolean!
|
||||||
|
hasPreviousPage: Boolean!
|
||||||
|
startCursor: CursorKey
|
||||||
|
endCursor: CursorKey
|
||||||
|
}
|
||||||
26
pkg/server/api/trust/v1/organization.resolvers.go
Normal file
26
pkg/server/api/trust/v1/organization.resolvers.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package trust_v1
|
||||||
|
|
||||||
|
// This file will be automatically regenerated based on the schema, any resolver
|
||||||
|
// implementations
|
||||||
|
// will be copied through when generating and any unknown code will be moved to the end.
|
||||||
|
// Code generated by github.com/99designs/gqlgen version v0.17.87
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
|
||||||
|
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LogoURL is the resolver for the logoUrl field.
|
||||||
|
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
|
||||||
|
trustService := r.TrustService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
|
return trustService.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Organization returns schema.OrganizationResolver implementation.
|
||||||
|
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
|
||||||
|
|
||||||
|
type organizationResolver struct{ *Resolver }
|
||||||
Reference in New Issue
Block a user