Align console references and OAuth branding with the compliance-page model, and fix certificate cache eviction, portal OAuth handlers, and magic-link edge cases left after the trust-center rename. Signed-off-by: Bryan Frimin <bryan@probo.com>
120 lines
4.1 KiB
Go
120 lines
4.1 KiB
Go
package complianceportal_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.93
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"go.gearno.de/kit/log"
|
|
"go.probo.inc/probo/pkg/coredata"
|
|
"go.probo.inc/probo/pkg/iam"
|
|
"go.probo.inc/probo/pkg/server/api/authn"
|
|
"go.probo.inc/probo/pkg/server/api/complianceportal"
|
|
"go.probo.inc/probo/pkg/server/api/complianceportal/v1/types"
|
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
|
"go.probo.inc/probo/pkg/validator"
|
|
)
|
|
|
|
// 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")
|
|
}
|
|
|
|
compliancePage := complianceportal.CompliancePageFromContext(ctx)
|
|
|
|
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, compliancePage.OrganizationID)
|
|
if err != nil {
|
|
// External trust-center visitors have no organization profile; only
|
|
// their identity needs updating.
|
|
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); !ok {
|
|
r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
profile = nil
|
|
}
|
|
|
|
// The identity and profile full names are validated by different rules.
|
|
// Validate the profile update up front so it cannot fail after the
|
|
// identity has already been mutated, keeping the two in sync.
|
|
var updateUserRequest *iam.UpdateUserRequest
|
|
if profile != nil && profile.Source == coredata.ProfileSourceManual {
|
|
updateUserRequest = &iam.UpdateUserRequest{
|
|
ID: profile.ID,
|
|
FullName: input.FullName,
|
|
AdditionalEmailAddresses: profile.AdditionalEmailAddresses,
|
|
Kind: profile.Kind,
|
|
Position: profile.Position,
|
|
ContractStartDate: &profile.ContractStartDate,
|
|
ContractEndDate: &profile.ContractEndDate,
|
|
}
|
|
|
|
if err := updateUserRequest.Validate(); err != nil {
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot validate profile update", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
}
|
|
|
|
if _, err := r.iam.AccountService.UpdateIdentity(
|
|
ctx,
|
|
identity.ID,
|
|
&iam.UpdateIdentityRequest{
|
|
FullName: input.FullName,
|
|
},
|
|
); err != nil {
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot update identity", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
if updateUserRequest != nil {
|
|
if _, err := r.iam.OrganizationService.UpdateUser(ctx, updateUserRequest); err != nil {
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot update profile", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
}
|
|
|
|
return &types.UpdateFullNamePayload{Success: true}, 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 {
|
|
_, notFound := errors.AsType[*iam.ErrSessionNotFound](err)
|
|
|
|
_, expired := errors.AsType[*iam.ErrSessionExpired](err)
|
|
if !notFound && !expired {
|
|
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
// Already closed or missing — still clear the cookie so the browser
|
|
// drops the stale session on concurrent / retried logout.
|
|
}
|
|
|
|
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
r.sessionCookie.Clear(w)
|
|
|
|
return &types.SignOutPayload{Success: true}, nil
|
|
}
|