@@ -16,7 +16,6 @@ package coredata
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
@@ -26,7 +25,6 @@ import (
|
|||||||
"github.com/jackc/pgx/v5/pgconn"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
"go.gearno.de/kit/pg"
|
"go.gearno.de/kit/pg"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/mail"
|
|
||||||
"go.probo.inc/probo/pkg/page"
|
"go.probo.inc/probo/pkg/page"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,12 +33,8 @@ type (
|
|||||||
ID gid.GID `db:"id"`
|
ID gid.GID `db:"id"`
|
||||||
OrganizationID gid.GID `db:"organization_id"`
|
OrganizationID gid.GID `db:"organization_id"`
|
||||||
TenantID gid.TenantID `db:"tenant_id"`
|
TenantID gid.TenantID `db:"tenant_id"`
|
||||||
|
IdentityID gid.GID `db:"identity_id"`
|
||||||
TrustCenterID gid.GID `db:"trust_center_id"`
|
TrustCenterID gid.GID `db:"trust_center_id"`
|
||||||
Email mail.Addr `db:"email"`
|
|
||||||
Name string `db:"name"`
|
|
||||||
State TrustCenterAccessState `db:"state"`
|
|
||||||
HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"`
|
|
||||||
HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"`
|
|
||||||
NDAFileID *gid.GID `db:"nda_file_id"`
|
NDAFileID *gid.GID `db:"nda_file_id"`
|
||||||
ElectronicSignatureID *gid.GID `db:"electronic_signature_id"`
|
ElectronicSignatureID *gid.GID `db:"electronic_signature_id"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
@@ -85,11 +79,6 @@ SELECT
|
|||||||
organization_id,
|
organization_id,
|
||||||
tenant_id,
|
tenant_id,
|
||||||
trust_center_id,
|
trust_center_id,
|
||||||
email,
|
|
||||||
name,
|
|
||||||
state,
|
|
||||||
has_accepted_non_disclosure_agreement,
|
|
||||||
has_accepted_non_disclosure_agreement_metadata,
|
|
||||||
nda_file_id,
|
nda_file_id,
|
||||||
electronic_signature_id,
|
electronic_signature_id,
|
||||||
created_at,
|
created_at,
|
||||||
@@ -126,12 +115,12 @@ LIMIT 1;
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tca *TrustCenterAccess) LoadByTrustCenterIDAndEmail(
|
func (tca *TrustCenterAccess) LoadByTrustCenterIDAndIdentityID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
conn pg.Conn,
|
conn pg.Conn,
|
||||||
scope Scoper,
|
scope Scoper,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
SELECT
|
SELECT
|
||||||
@@ -139,11 +128,6 @@ SELECT
|
|||||||
organization_id,
|
organization_id,
|
||||||
tenant_id,
|
tenant_id,
|
||||||
trust_center_id,
|
trust_center_id,
|
||||||
email,
|
|
||||||
name,
|
|
||||||
state,
|
|
||||||
has_accepted_non_disclosure_agreement,
|
|
||||||
has_accepted_non_disclosure_agreement_metadata,
|
|
||||||
nda_file_id,
|
nda_file_id,
|
||||||
electronic_signature_id,
|
electronic_signature_id,
|
||||||
created_at,
|
created_at,
|
||||||
@@ -153,7 +137,7 @@ FROM
|
|||||||
WHERE
|
WHERE
|
||||||
%s
|
%s
|
||||||
AND trust_center_id = @trust_center_id
|
AND trust_center_id = @trust_center_id
|
||||||
AND email = @email
|
AND identity_id = @identity_id
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -161,7 +145,7 @@ LIMIT 1;
|
|||||||
|
|
||||||
args := pgx.StrictNamedArgs{
|
args := pgx.StrictNamedArgs{
|
||||||
"trust_center_id": trustCenterID,
|
"trust_center_id": trustCenterID,
|
||||||
"email": email,
|
"identity_id": identityID,
|
||||||
}
|
}
|
||||||
maps.Copy(args, scope.SQLArguments())
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
@@ -195,10 +179,6 @@ INSERT INTO trust_center_accesses (
|
|||||||
tenant_id,
|
tenant_id,
|
||||||
organization_id,
|
organization_id,
|
||||||
trust_center_id,
|
trust_center_id,
|
||||||
email,
|
|
||||||
name,
|
|
||||||
state,
|
|
||||||
has_accepted_non_disclosure_agreement,
|
|
||||||
electronic_signature_id,
|
electronic_signature_id,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at
|
updated_at
|
||||||
@@ -207,10 +187,6 @@ INSERT INTO trust_center_accesses (
|
|||||||
@tenant_id,
|
@tenant_id,
|
||||||
@organization_id,
|
@organization_id,
|
||||||
@trust_center_id,
|
@trust_center_id,
|
||||||
@email,
|
|
||||||
@name,
|
|
||||||
@state,
|
|
||||||
@has_accepted_non_disclosure_agreement,
|
|
||||||
@electronic_signature_id,
|
@electronic_signature_id,
|
||||||
@created_at,
|
@created_at,
|
||||||
@updated_at
|
@updated_at
|
||||||
@@ -222,10 +198,6 @@ INSERT INTO trust_center_accesses (
|
|||||||
"tenant_id": tca.TenantID,
|
"tenant_id": tca.TenantID,
|
||||||
"organization_id": tca.OrganizationID,
|
"organization_id": tca.OrganizationID,
|
||||||
"trust_center_id": tca.TrustCenterID,
|
"trust_center_id": tca.TrustCenterID,
|
||||||
"email": tca.Email,
|
|
||||||
"name": tca.Name,
|
|
||||||
"state": tca.State,
|
|
||||||
"has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement,
|
|
||||||
"electronic_signature_id": tca.ElectronicSignatureID,
|
"electronic_signature_id": tca.ElectronicSignatureID,
|
||||||
"created_at": tca.CreatedAt,
|
"created_at": tca.CreatedAt,
|
||||||
"updated_at": tca.UpdatedAt,
|
"updated_at": tca.UpdatedAt,
|
||||||
@@ -252,11 +224,7 @@ func (tca *TrustCenterAccess) Update(
|
|||||||
) error {
|
) error {
|
||||||
q := `
|
q := `
|
||||||
UPDATE trust_center_accesses SET
|
UPDATE trust_center_accesses SET
|
||||||
name = @name,
|
|
||||||
state = @state,
|
|
||||||
updated_at = @updated_at,
|
updated_at = @updated_at,
|
||||||
has_accepted_non_disclosure_agreement = @has_accepted_non_disclosure_agreement,
|
|
||||||
has_accepted_non_disclosure_agreement_metadata = @has_accepted_non_disclosure_agreement_metadata,
|
|
||||||
nda_file_id = @nda_file_id,
|
nda_file_id = @nda_file_id,
|
||||||
electronic_signature_id = @electronic_signature_id
|
electronic_signature_id = @electronic_signature_id
|
||||||
WHERE
|
WHERE
|
||||||
@@ -268,11 +236,7 @@ WHERE
|
|||||||
|
|
||||||
args := pgx.StrictNamedArgs{
|
args := pgx.StrictNamedArgs{
|
||||||
"id": tca.ID,
|
"id": tca.ID,
|
||||||
"name": tca.Name,
|
|
||||||
"state": tca.State,
|
|
||||||
"updated_at": tca.UpdatedAt,
|
"updated_at": tca.UpdatedAt,
|
||||||
"has_accepted_non_disclosure_agreement": tca.HasAcceptedNonDisclosureAgreement,
|
|
||||||
"has_accepted_non_disclosure_agreement_metadata": tca.HasAcceptedNonDisclosureAgreementMetadata,
|
|
||||||
"nda_file_id": tca.NDAFileID,
|
"nda_file_id": tca.NDAFileID,
|
||||||
"electronic_signature_id": tca.ElectronicSignatureID,
|
"electronic_signature_id": tca.ElectronicSignatureID,
|
||||||
}
|
}
|
||||||
@@ -326,11 +290,6 @@ SELECT
|
|||||||
organization_id,
|
organization_id,
|
||||||
tenant_id,
|
tenant_id,
|
||||||
trust_center_id,
|
trust_center_id,
|
||||||
email,
|
|
||||||
name,
|
|
||||||
state,
|
|
||||||
has_accepted_non_disclosure_agreement,
|
|
||||||
has_accepted_non_disclosure_agreement_metadata,
|
|
||||||
nda_file_id,
|
nda_file_id,
|
||||||
electronic_signature_id,
|
electronic_signature_id,
|
||||||
created_at,
|
created_at,
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ type (
|
|||||||
|
|
||||||
CreateTrustCenterAccessRequest struct {
|
CreateTrustCenterAccessRequest struct {
|
||||||
TrustCenterID gid.GID
|
TrustCenterID gid.GID
|
||||||
Email mail.Addr
|
IdentityID gid.GID
|
||||||
FullName string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTrustCenterDocumentAccessRequest struct {
|
UpdateTrustCenterDocumentAccessRequest struct {
|
||||||
@@ -49,8 +48,6 @@ type (
|
|||||||
|
|
||||||
UpdateTrustCenterAccessRequest struct {
|
UpdateTrustCenterAccessRequest struct {
|
||||||
ID gid.GID
|
ID gid.GID
|
||||||
Name *string
|
|
||||||
State *coredata.TrustCenterAccessState
|
|
||||||
DocumentAccesses []UpdateTrustCenterDocumentAccessRequest
|
DocumentAccesses []UpdateTrustCenterDocumentAccessRequest
|
||||||
ReportAccesses []UpdateTrustCenterDocumentAccessRequest
|
ReportAccesses []UpdateTrustCenterDocumentAccessRequest
|
||||||
TrustCenterFileAccesses []UpdateTrustCenterDocumentAccessRequest
|
TrustCenterFileAccesses []UpdateTrustCenterDocumentAccessRequest
|
||||||
@@ -66,9 +63,6 @@ func (ctcar *CreateTrustCenterAccessRequest) Validate() error {
|
|||||||
v := validator.New()
|
v := validator.New()
|
||||||
|
|
||||||
v.Check(ctcar.TrustCenterID, "trust_center_id", validator.Required(), validator.GID(coredata.TrustCenterEntityType))
|
v.Check(ctcar.TrustCenterID, "trust_center_id", validator.Required(), validator.GID(coredata.TrustCenterEntityType))
|
||||||
v.Check(ctcar.Email, "email", validator.Required(), validator.NotEmpty())
|
|
||||||
v.Check(ctcar.Email.Domain(), "email", validator.NotBlacklisted())
|
|
||||||
v.Check(ctcar.FullName, "name", validator.SafeTextNoNewLine(TitleMaxLength))
|
|
||||||
|
|
||||||
return v.Error()
|
return v.Error()
|
||||||
}
|
}
|
||||||
@@ -77,7 +71,6 @@ func (utcar *UpdateTrustCenterAccessRequest) Validate() error {
|
|||||||
v := validator.New()
|
v := validator.New()
|
||||||
|
|
||||||
v.Check(utcar.ID, "id", validator.Required(), validator.GID(coredata.TrustCenterAccessEntityType))
|
v.Check(utcar.ID, "id", validator.Required(), validator.GID(coredata.TrustCenterAccessEntityType))
|
||||||
v.Check(utcar.Name, "name", validator.SafeTextNoNewLine(TitleMaxLength))
|
|
||||||
for i, docAccess := range utcar.DocumentAccesses {
|
for i, docAccess := range utcar.DocumentAccesses {
|
||||||
v.Check(docAccess.ID, fmt.Sprintf("documentAccesses[%d].ID", i), validator.Required(), validator.GID(coredata.DocumentEntityType))
|
v.Check(docAccess.ID, fmt.Sprintf("documentAccesses[%d].ID", i), validator.Required(), validator.GID(coredata.DocumentEntityType))
|
||||||
}
|
}
|
||||||
@@ -237,15 +230,23 @@ func (s TrustCenterAccessService) Create(
|
|||||||
return fmt.Errorf("cannot load trust center: %w", err)
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: need to change UX
|
||||||
|
profile := &coredata.MembershipProfile{}
|
||||||
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, s.svc.scope, trustCenter.OrganizationID, req.IdentityID); err != nil {
|
||||||
|
if !errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := profile.Insert(ctx, tx); err != nil {
|
||||||
|
return fmt.Errorf("cannot insert profile: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
access = &coredata.TrustCenterAccess{
|
access = &coredata.TrustCenterAccess{
|
||||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
||||||
OrganizationID: trustCenter.OrganizationID,
|
OrganizationID: trustCenter.OrganizationID,
|
||||||
TenantID: s.svc.scope.GetTenantID(),
|
TenantID: s.svc.scope.GetTenantID(),
|
||||||
TrustCenterID: req.TrustCenterID,
|
TrustCenterID: req.TrustCenterID,
|
||||||
Email: req.Email,
|
|
||||||
Name: req.FullName,
|
|
||||||
State: coredata.TrustCenterAccessStateActive,
|
|
||||||
HasAcceptedNonDisclosureAgreement: false,
|
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
}
|
}
|
||||||
@@ -258,7 +259,7 @@ func (s TrustCenterAccessService) Create(
|
|||||||
OrganizationID: access.OrganizationID,
|
OrganizationID: access.OrganizationID,
|
||||||
DocumentType: coredata.ElectronicSignatureDocumentTypeNDA,
|
DocumentType: coredata.ElectronicSignatureDocumentTypeNDA,
|
||||||
FileID: *trustCenter.NonDisclosureAgreementFileID,
|
FileID: *trustCenter.NonDisclosureAgreementFileID,
|
||||||
SignerEmail: access.Email,
|
SignerEmail: profile.EmailAddress,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -292,9 +293,13 @@ func (s TrustCenterAccessService) Update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
var access *coredata.TrustCenterAccess
|
var (
|
||||||
var trustCenterAcessActivated bool
|
access *coredata.TrustCenterAccess
|
||||||
var shouldUpdateSlackMessage bool
|
profile *coredata.MembershipProfile
|
||||||
|
trustCenterAcessActivated bool
|
||||||
|
shouldUpdateSlackMessage bool
|
||||||
|
)
|
||||||
|
|
||||||
err := s.svc.pg.WithTx(
|
err := s.svc.pg.WithTx(
|
||||||
ctx,
|
ctx,
|
||||||
func(tx pg.Conn) error {
|
func(tx pg.Conn) error {
|
||||||
@@ -304,19 +309,24 @@ func (s TrustCenterAccessService) Update(
|
|||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trustCenterAcessActivated = req.State != nil && *req.State == coredata.TrustCenterAccessStateActive && access.State != coredata.TrustCenterAccessStateActive
|
|
||||||
if req.Name != nil {
|
|
||||||
access.Name = *req.Name
|
|
||||||
}
|
|
||||||
if req.State != nil {
|
|
||||||
access.State = *req.State
|
|
||||||
}
|
|
||||||
access.UpdatedAt = now
|
access.UpdatedAt = now
|
||||||
|
|
||||||
if err := access.Update(ctx, tx, s.svc.scope); err != nil {
|
if err := access.Update(ctx, tx, s.svc.scope); err != nil {
|
||||||
return fmt.Errorf("cannot update trust center access: %w", err)
|
return fmt.Errorf("cannot update trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: need to change UX
|
||||||
|
profile = &coredata.MembershipProfile{}
|
||||||
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, s.svc.scope, access.OrganizationID, access.IdentityID); err != nil {
|
||||||
|
if !errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := profile.Insert(ctx, tx); err != nil {
|
||||||
|
return fmt.Errorf("cannot insert profile: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var tcdas coredata.TrustCenterDocumentAccesses
|
var tcdas coredata.TrustCenterDocumentAccesses
|
||||||
|
|
||||||
if len(req.DocumentAccesses) > 0 {
|
if len(req.DocumentAccesses) > 0 {
|
||||||
@@ -370,8 +380,7 @@ func (s TrustCenterAccessService) Update(
|
|||||||
shouldUpdateSlackMessage = trustCenterAcessActivated ||
|
shouldUpdateSlackMessage = trustCenterAcessActivated ||
|
||||||
len(req.DocumentAccesses) > 0 ||
|
len(req.DocumentAccesses) > 0 ||
|
||||||
len(req.ReportAccesses) > 0 ||
|
len(req.ReportAccesses) > 0 ||
|
||||||
len(req.TrustCenterFileAccesses) > 0 ||
|
len(req.TrustCenterFileAccesses) > 0
|
||||||
req.Name != nil
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@@ -382,7 +391,7 @@ func (s TrustCenterAccessService) Update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if shouldUpdateSlackMessage {
|
if shouldUpdateSlackMessage {
|
||||||
if err := s.svc.SlackMessages.QueueSlackNotification(ctx, access.Email, access.TrustCenterID); err != nil {
|
if err := s.svc.SlackMessages.QueueSlackNotification(ctx, profile.IdentityID, access.TrustCenterID); err != nil {
|
||||||
if !errors.Is(err, slack.ErrNoSlackConnector) {
|
if !errors.Is(err, slack.ErrNoSlackConnector) {
|
||||||
return nil, fmt.Errorf("cannot queue slack notification: %w", err)
|
return nil, fmt.Errorf("cannot queue slack notification: %w", err)
|
||||||
}
|
}
|
||||||
@@ -429,12 +438,23 @@ func (s TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Con
|
|||||||
return fmt.Errorf("cannot update trust center access with expiration: %w", err)
|
return fmt.Errorf("cannot update trust center access with expiration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profile := &coredata.MembershipProfile{}
|
||||||
|
if err := profile.LoadByIdentityIDAndOrganizationID(
|
||||||
|
ctx,
|
||||||
|
tx,
|
||||||
|
s.svc.scope,
|
||||||
|
access.IdentityID,
|
||||||
|
access.OrganizationID,
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
emailPresenterCfg, err := s.svc.TrustCenters.EmailPresenterConfig(ctx, access.TrustCenterID)
|
emailPresenterCfg, err := s.svc.TrustCenters.EmailPresenterConfig(ctx, access.TrustCenterID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
|
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
emailPresenter := emails.NewPresenterFromConfig(s.svc.fileManager, emailPresenterCfg, access.Name)
|
emailPresenter := emails.NewPresenterFromConfig(s.svc.fileManager, emailPresenterCfg, profile.FullName)
|
||||||
|
|
||||||
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name)
|
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -442,8 +462,8 @@ func (s TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
accessEmail := coredata.NewEmail(
|
accessEmail := coredata.NewEmail(
|
||||||
access.Name,
|
profile.FullName,
|
||||||
access.Email,
|
profile.EmailAddress,
|
||||||
subject,
|
subject,
|
||||||
textBody,
|
textBody,
|
||||||
htmlBody,
|
htmlBody,
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
package compliancepage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
|
||||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
|
||||||
"go.gearno.de/kit/httpserver"
|
|
||||||
"go.gearno.de/kit/log"
|
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
|
||||||
"go.probo.inc/probo/pkg/server/api/authn"
|
|
||||||
"go.probo.inc/probo/pkg/server/gqlutils"
|
|
||||||
"go.probo.inc/probo/pkg/trust"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewMembershipMiddleware(trustSvc *trust.Service, logger *log.Logger) func(next http.Handler) http.Handler {
|
|
||||||
return func(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ctx := r.Context()
|
|
||||||
|
|
||||||
identity := authn.IdentityFromContext(r.Context())
|
|
||||||
if identity == nil {
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
compliancePage := CompliancePageFromContext(ctx)
|
|
||||||
|
|
||||||
membership, err := trustSvc.GetMembershipByCompliancePageIDAndEmail(ctx, compliancePage.ID, identity.EmailAddress)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) {
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.ErrorCtx(ctx, "cannot get membership by page id and email", log.Error(err))
|
|
||||||
httpserver.RenderJSON(
|
|
||||||
w,
|
|
||||||
http.StatusInternalServerError,
|
|
||||||
&graphql.Response{
|
|
||||||
Errors: gqlerror.List{
|
|
||||||
gqlutils.Internal(ctx),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if membership.State == coredata.TrustCenterAccessStateActive {
|
|
||||||
ctx = context.WithValue(ctx, complianceMembershipKey, membership)
|
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -46,10 +46,6 @@ func NewTrustCenterAccessEdge(tca *coredata.TrustCenterAccess, orderBy coredata.
|
|||||||
func NewTrustCenterAccess(tca *coredata.TrustCenterAccess) *TrustCenterAccess {
|
func NewTrustCenterAccess(tca *coredata.TrustCenterAccess) *TrustCenterAccess {
|
||||||
return &TrustCenterAccess{
|
return &TrustCenterAccess{
|
||||||
ID: tca.ID,
|
ID: tca.ID,
|
||||||
Email: tca.Email,
|
|
||||||
Name: tca.Name,
|
|
||||||
State: tca.State,
|
|
||||||
HasAcceptedNonDisclosureAgreement: tca.HasAcceptedNonDisclosureAgreement,
|
|
||||||
CreatedAt: tca.CreatedAt,
|
CreatedAt: tca.CreatedAt,
|
||||||
UpdatedAt: tca.UpdatedAt,
|
UpdatedAt: tca.UpdatedAt,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1940,8 +1940,7 @@ func (r *mutationResolver) CreateTrustCenterAccess(ctx context.Context, input ty
|
|||||||
ctx,
|
ctx,
|
||||||
&probo.CreateTrustCenterAccessRequest{
|
&probo.CreateTrustCenterAccessRequest{
|
||||||
TrustCenterID: input.TrustCenterID,
|
TrustCenterID: input.TrustCenterID,
|
||||||
Email: identity.EmailAddress,
|
IdentityID: identity.ID,
|
||||||
FullName: identity.FullName,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1991,8 +1990,6 @@ func (r *mutationResolver) UpdateTrustCenterAccess(ctx context.Context, input ty
|
|||||||
ctx,
|
ctx,
|
||||||
&probo.UpdateTrustCenterAccessRequest{
|
&probo.UpdateTrustCenterAccessRequest{
|
||||||
ID: input.ID,
|
ID: input.ID,
|
||||||
Name: input.Name,
|
|
||||||
State: input.State,
|
|
||||||
DocumentAccesses: documentAccesses,
|
DocumentAccesses: documentAccesses,
|
||||||
ReportAccesses: reportAccesses,
|
ReportAccesses: reportAccesses,
|
||||||
TrustCenterFileAccesses: fileAccesses,
|
TrustCenterFileAccesses: fileAccesses,
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func NewGraphQLHandler(iamSvc *iam.Service, trustSvc *trust.Service, esignSvc *e
|
|||||||
sessionCookie: authn.NewCookie(&cookieConfig),
|
sessionCookie: authn.NewCookie(&cookieConfig),
|
||||||
},
|
},
|
||||||
Directives: schema.DirectiveRoot{
|
Directives: schema.DirectiveRoot{
|
||||||
Nda: newNDADirective(logger, esignSvc),
|
Nda: newNDADirective(logger, trustSvc, esignSvc),
|
||||||
Session: session.Directive,
|
Session: session.Directive,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package trust_v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql"
|
"github.com/99designs/gqlgen/graphql"
|
||||||
"go.gearno.de/kit/log"
|
"go.gearno.de/kit/log"
|
||||||
@@ -24,10 +25,12 @@ import (
|
|||||||
"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/gqlutils"
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||||
|
"go.probo.inc/probo/pkg/trust"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newNDADirective(
|
func newNDADirective(
|
||||||
logger *log.Logger,
|
logger *log.Logger,
|
||||||
|
trustSvc *trust.Service,
|
||||||
esignSvc *esign.Service,
|
esignSvc *esign.Service,
|
||||||
) func(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
|
) func(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
|
||||||
return func(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
|
return func(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
|
||||||
@@ -36,11 +39,22 @@ func newNDADirective(
|
|||||||
return next(ctx)
|
return next(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
membership := compliancepage.ComplianceMembershipFromContext(ctx)
|
compliancePage := compliancepage.CompliancePageFromContext(ctx)
|
||||||
if membership == nil {
|
if compliancePage == nil {
|
||||||
|
logger.ErrorCtx(ctx, "cannot get compliance page from context")
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
membership, err := trustSvc.GetMembershipByCompliancePageIDAndIdentityID(ctx, compliancePage.ID, identity.ID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, trust.ErrMembershipNotFound) {
|
||||||
return nil, gqlutils.Unauthenticatedf(ctx, "authentication needed")
|
return nil, gqlutils.Unauthenticatedf(ctx, "authentication needed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.ErrorCtx(ctx, "cannot get compliance page membership", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
if membership.ElectronicSignatureID == nil {
|
if membership.ElectronicSignatureID == nil {
|
||||||
return next(ctx)
|
return next(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ func NewMux(
|
|||||||
|
|
||||||
r.Use(compliancepage.NewCompliancePagePresenceMiddleware())
|
r.Use(compliancepage.NewCompliancePagePresenceMiddleware())
|
||||||
r.Use(authn.NewSessionMiddleware(iamSvc, cookieConfig))
|
r.Use(authn.NewSessionMiddleware(iamSvc, cookieConfig))
|
||||||
r.Use(compliancepage.NewMembershipMiddleware(trustSvc, logger))
|
|
||||||
|
|
||||||
graphqlHandler := NewGraphQLHandler(iamSvc, trustSvc, esignSvc, logger, baseURL, cookieConfig)
|
graphqlHandler := NewGraphQLHandler(iamSvc, trustSvc, esignSvc, logger, baseURL, cookieConfig)
|
||||||
|
|
||||||
|
|||||||
@@ -107,17 +107,14 @@ func (r *documentResolver) IsUserAuthorized(ctx context.Context, obj *types.Docu
|
|||||||
documentAccess, err := trustService.TrustCenterAccesses.GetDocumentAccess(
|
documentAccess, err := trustService.TrustCenterAccesses.GetDocumentAccess(
|
||||||
ctx,
|
ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
obj.ID,
|
obj.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) {
|
if errors.Is(err, trust.ErrMembershipNotFound) ||
|
||||||
return false, nil
|
errors.Is(err, trust.ErrUserNotFound) ||
|
||||||
}
|
errors.Is(err, trust.ErrUserInactive) ||
|
||||||
if errors.Is(err, trust.ErrMembershipInactive) {
|
errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
if errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,15 +138,17 @@ func (r *documentResolver) Access(ctx context.Context, obj *types.Document) (*ty
|
|||||||
access, err := trustService.TrustCenterAccesses.GetDocumentAccess(
|
access, err := trustService.TrustCenterAccesses.GetDocumentAccess(
|
||||||
ctx,
|
ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
obj.ID,
|
obj.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) || errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
if errors.Is(err, trust.ErrMembershipNotFound) ||
|
||||||
|
errors.Is(err, trust.ErrUserNotFound) ||
|
||||||
|
errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, trust.ErrMembershipInactive) {
|
if errors.Is(err, trust.ErrUserInactive) {
|
||||||
return nil, gqlutils.Forbidden(ctx, err)
|
return nil, gqlutils.Forbidden(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +261,7 @@ func (r *mutationResolver) VerifyMagicLink(ctx context.Context, input types.Veri
|
|||||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||||
|
|
||||||
if _, err := trustService.TrustCenterAccesses.EnsureAccess(ctx, trustCenter.ID, identity.EmailAddress, identity.FullName); err != nil {
|
if _, err := trustService.TrustCenterAccesses.EnsureAccess(ctx, trustCenter.ID, identity.ID); err != nil {
|
||||||
r.logger.ErrorCtx(ctx, "cannot ensure trust center access", log.Error(err))
|
r.logger.ErrorCtx(ctx, "cannot ensure trust center access", log.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,8 +287,7 @@ func (r *mutationResolver) RequestAllAccesses(ctx context.Context) (*types.Reque
|
|||||||
ctx,
|
ctx,
|
||||||
&trust.TrustCenterAccessRequest{
|
&trust.TrustCenterAccessRequest{
|
||||||
TrustCenterID: trustCenter.ID,
|
TrustCenterID: trustCenter.ID,
|
||||||
Email: identity.EmailAddress,
|
IdentityID: identity.ID,
|
||||||
FullName: identity.FullName,
|
|
||||||
DocumentIDs: nil,
|
DocumentIDs: nil,
|
||||||
ReportIDs: nil,
|
ReportIDs: nil,
|
||||||
},
|
},
|
||||||
@@ -302,8 +300,6 @@ func (r *mutationResolver) RequestAllAccesses(ctx context.Context) (*types.Reque
|
|||||||
return &types.RequestAccessesPayload{
|
return &types.RequestAccessesPayload{
|
||||||
TrustCenterAccess: &types.TrustCenterAccess{
|
TrustCenterAccess: &types.TrustCenterAccess{
|
||||||
ID: access.ID,
|
ID: access.ID,
|
||||||
Email: access.Email,
|
|
||||||
Name: access.Name,
|
|
||||||
CreatedAt: access.CreatedAt,
|
CreatedAt: access.CreatedAt,
|
||||||
UpdatedAt: access.UpdatedAt,
|
UpdatedAt: access.UpdatedAt,
|
||||||
},
|
},
|
||||||
@@ -341,7 +337,7 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex
|
|||||||
documentAccess, err := trustService.TrustCenterAccesses.GetDocumentAccess(
|
documentAccess, err := trustService.TrustCenterAccesses.GetDocumentAccess(
|
||||||
ctx,
|
ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
input.DocumentID,
|
input.DocumentID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -395,7 +391,7 @@ func (r *mutationResolver) ExportReportPDF(ctx context.Context, input types.Expo
|
|||||||
reportAccess, err := trustService.TrustCenterAccesses.GetReportAccess(
|
reportAccess, err := trustService.TrustCenterAccesses.GetReportAccess(
|
||||||
ctx,
|
ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
input.ReportID,
|
input.ReportID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -447,7 +443,7 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type
|
|||||||
|
|
||||||
fileAccess, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx,
|
fileAccess, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
input.TrustCenterFileID,
|
input.TrustCenterFileID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -495,8 +491,7 @@ func (r *mutationResolver) RequestDocumentAccess(ctx context.Context, input type
|
|||||||
ctx,
|
ctx,
|
||||||
&trust.TrustCenterAccessRequest{
|
&trust.TrustCenterAccessRequest{
|
||||||
TrustCenterID: trustCenter.ID,
|
TrustCenterID: trustCenter.ID,
|
||||||
Email: identity.EmailAddress,
|
IdentityID: identity.ID,
|
||||||
FullName: identity.FullName,
|
|
||||||
DocumentIDs: []gid.GID{input.DocumentID},
|
DocumentIDs: []gid.GID{input.DocumentID},
|
||||||
ReportIDs: []gid.GID{},
|
ReportIDs: []gid.GID{},
|
||||||
TrustCenterFileIDs: []gid.GID{},
|
TrustCenterFileIDs: []gid.GID{},
|
||||||
@@ -538,8 +533,7 @@ func (r *mutationResolver) RequestReportAccess(ctx context.Context, input types.
|
|||||||
ctx,
|
ctx,
|
||||||
&trust.TrustCenterAccessRequest{
|
&trust.TrustCenterAccessRequest{
|
||||||
TrustCenterID: trustCenter.ID,
|
TrustCenterID: trustCenter.ID,
|
||||||
Email: identity.EmailAddress,
|
IdentityID: identity.ID,
|
||||||
FullName: identity.FullName,
|
|
||||||
DocumentIDs: []gid.GID{},
|
DocumentIDs: []gid.GID{},
|
||||||
ReportIDs: []gid.GID{input.ReportID},
|
ReportIDs: []gid.GID{input.ReportID},
|
||||||
TrustCenterFileIDs: []gid.GID{},
|
TrustCenterFileIDs: []gid.GID{},
|
||||||
@@ -581,8 +575,7 @@ func (r *mutationResolver) RequestTrustCenterFileAccess(ctx context.Context, inp
|
|||||||
ctx,
|
ctx,
|
||||||
&trust.TrustCenterAccessRequest{
|
&trust.TrustCenterAccessRequest{
|
||||||
TrustCenterID: trustCenter.ID,
|
TrustCenterID: trustCenter.ID,
|
||||||
Email: identity.EmailAddress,
|
IdentityID: identity.ID,
|
||||||
FullName: identity.FullName,
|
|
||||||
DocumentIDs: []gid.GID{},
|
DocumentIDs: []gid.GID{},
|
||||||
ReportIDs: []gid.GID{},
|
ReportIDs: []gid.GID{},
|
||||||
TrustCenterFileIDs: []gid.GID{input.TrustCenterFileID},
|
TrustCenterFileIDs: []gid.GID{input.TrustCenterFileID},
|
||||||
@@ -676,7 +669,7 @@ func (r *nonDisclosureAgreementResolver) FileURL(ctx context.Context, obj *types
|
|||||||
if identity := authn.IdentityFromContext(ctx); identity != nil && r.esign != nil {
|
if identity := authn.IdentityFromContext(ctx); identity != nil && r.esign != nil {
|
||||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||||
|
|
||||||
access, err := trustService.TrustCenterAccesses.GetAccess(ctx, trustCenter.ID, identity.EmailAddress)
|
access, err := trustService.TrustCenterAccesses.GetAccess(ctx, trustCenter.ID, identity.ID)
|
||||||
if err == nil && access.ElectronicSignatureID != nil {
|
if err == nil && access.ElectronicSignatureID != nil {
|
||||||
fileURL, err := r.esign.GenerateSignatureFileURL(ctx, *access.ElectronicSignatureID, 15*time.Minute)
|
fileURL, err := r.esign.GenerateSignatureFileURL(ctx, *access.ElectronicSignatureID, 15*time.Minute)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -707,7 +700,7 @@ func (r *nonDisclosureAgreementResolver) ViewerSignature(ctx context.Context, ob
|
|||||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||||
|
|
||||||
access, err := trustService.TrustCenterAccesses.GetAccess(ctx, trustCenter.ID, identity.EmailAddress)
|
access, err := trustService.TrustCenterAccesses.GetAccess(ctx, trustCenter.ID, identity.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -868,17 +861,14 @@ func (r *reportResolver) IsUserAuthorized(ctx context.Context, obj *types.Report
|
|||||||
|
|
||||||
reportAccess, err := trustService.TrustCenterAccesses.GetReportAccess(ctx,
|
reportAccess, err := trustService.TrustCenterAccesses.GetReportAccess(ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
obj.ID,
|
obj.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) {
|
if errors.Is(err, trust.ErrMembershipNotFound) ||
|
||||||
return false, nil
|
errors.Is(err, trust.ErrUserNotFound) ||
|
||||||
}
|
errors.Is(err, trust.ErrUserInactive) ||
|
||||||
if errors.Is(err, trust.ErrMembershipInactive) {
|
errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
if errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,15 +892,17 @@ func (r *reportResolver) Access(ctx context.Context, obj *types.Report) (*types.
|
|||||||
access, err := trustService.TrustCenterAccesses.GetReportAccess(
|
access, err := trustService.TrustCenterAccesses.GetReportAccess(
|
||||||
ctx,
|
ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
obj.ID,
|
obj.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) || errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
if errors.Is(err, trust.ErrMembershipNotFound) ||
|
||||||
|
errors.Is(err, trust.ErrUserNotFound) ||
|
||||||
|
errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, trust.ErrMembershipInactive) {
|
if errors.Is(err, trust.ErrUserInactive) {
|
||||||
return nil, gqlutils.Forbidden(ctx, err)
|
return nil, gqlutils.Forbidden(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1107,17 +1099,14 @@ func (r *trustCenterFileResolver) IsUserAuthorized(ctx context.Context, obj *typ
|
|||||||
|
|
||||||
fileAccess, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx,
|
fileAccess, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
obj.ID,
|
obj.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) {
|
if errors.Is(err, trust.ErrMembershipNotFound) ||
|
||||||
return false, nil
|
errors.Is(err, trust.ErrUserNotFound) ||
|
||||||
}
|
errors.Is(err, trust.ErrUserInactive) ||
|
||||||
if errors.Is(err, trust.ErrMembershipInactive) {
|
errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
if errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1141,15 +1130,17 @@ func (r *trustCenterFileResolver) Access(ctx context.Context, obj *types.TrustCe
|
|||||||
access, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(
|
access, err := trustService.TrustCenterAccesses.GetTrustCenterFileAccess(
|
||||||
ctx,
|
ctx,
|
||||||
trustCenter.ID,
|
trustCenter.ID,
|
||||||
identity.EmailAddress,
|
identity.ID,
|
||||||
obj.ID,
|
obj.ID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, trust.ErrMembershipNotFound) || errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
if errors.Is(err, trust.ErrMembershipNotFound) ||
|
||||||
|
errors.Is(err, trust.ErrUserNotFound) ||
|
||||||
|
errors.Is(err, trust.ErrDocumentAccessNotFound) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, trust.ErrMembershipInactive) {
|
if errors.Is(err, trust.ErrUserInactive) {
|
||||||
return nil, gqlutils.Forbidden(ctx, err)
|
return nil, gqlutils.Forbidden(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,8 +118,13 @@ func (s *SlackMessageService) UpdateSlackAccessMessage(
|
|||||||
return fmt.Errorf("cannot load trust center: %w", err)
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identity := &coredata.Identity{}
|
||||||
|
if err := identity.LoadByEmail(ctx, tx, requesterEmail); err != nil {
|
||||||
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var trustCenterAccess coredata.TrustCenterAccess
|
var trustCenterAccess coredata.TrustCenterAccess
|
||||||
if err := trustCenterAccess.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenter.ID, requesterEmail); err != nil {
|
if err := trustCenterAccess.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, trustCenter.ID, identity.ID); err != nil {
|
||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +137,7 @@ func (s *SlackMessageService) UpdateSlackAccessMessage(
|
|||||||
|
|
||||||
updatedBody, err := s.buildAccessRequestMessage(
|
updatedBody, err := s.buildAccessRequestMessage(
|
||||||
newSlackMessageID,
|
newSlackMessageID,
|
||||||
trustCenterAccess.Name,
|
identity.FullName,
|
||||||
requesterEmail,
|
requesterEmail,
|
||||||
trustCenter.OrganizationID,
|
trustCenter.OrganizationID,
|
||||||
documents,
|
documents,
|
||||||
@@ -179,12 +184,21 @@ func (s *SlackMessageService) UpdateSlackAccessMessage(
|
|||||||
|
|
||||||
func (s *SlackMessageService) QueueSlackNotification(
|
func (s *SlackMessageService) QueueSlackNotification(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
requesterEmail mail.Addr,
|
identityID gid.GID,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
) error {
|
) error {
|
||||||
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||||
var trustCenterAccess coredata.TrustCenterAccess
|
var (
|
||||||
if err := trustCenterAccess.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenterID, requesterEmail); err != nil {
|
identity = &coredata.Identity{}
|
||||||
|
trustCenterAccess *coredata.TrustCenterAccess
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := identity.LoadByID(ctx, tx, identityID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
trustCenterAccess = &coredata.TrustCenterAccess{}
|
||||||
|
if err := trustCenterAccess.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, trustCenterID, identityID); err != nil {
|
||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,8 +238,8 @@ func (s *SlackMessageService) QueueSlackNotification(
|
|||||||
|
|
||||||
body, err := s.buildAccessRequestMessage(
|
body, err := s.buildAccessRequestMessage(
|
||||||
slackMessageID,
|
slackMessageID,
|
||||||
trustCenterAccess.Name,
|
identity.FullName,
|
||||||
requesterEmail,
|
identity.EmailAddress,
|
||||||
trustCenter.OrganizationID,
|
trustCenter.OrganizationID,
|
||||||
documents,
|
documents,
|
||||||
reports,
|
reports,
|
||||||
@@ -247,7 +261,7 @@ func (s *SlackMessageService) QueueSlackNotification(
|
|||||||
OrganizationID: trustCenter.OrganizationID,
|
OrganizationID: trustCenter.OrganizationID,
|
||||||
Type: coredata.SlackMessageTypeTrustCenterAccessRequest,
|
Type: coredata.SlackMessageTypeTrustCenterAccessRequest,
|
||||||
Body: body,
|
Body: body,
|
||||||
RequesterEmail: &requesterEmail,
|
RequesterEmail: &identity.EmailAddress,
|
||||||
Metadata: metadata.toMap(),
|
Metadata: metadata.toMap(),
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
@@ -261,7 +275,7 @@ func (s *SlackMessageService) QueueSlackNotification(
|
|||||||
tx,
|
tx,
|
||||||
s.svc.scope,
|
s.svc.scope,
|
||||||
trustCenter.OrganizationID,
|
trustCenter.OrganizationID,
|
||||||
requesterEmail,
|
identity.EmailAddress,
|
||||||
coredata.SlackMessageTypeTrustCenterAccessRequest,
|
coredata.SlackMessageTypeTrustCenterAccessRequest,
|
||||||
sevenDaysAgo,
|
sevenDaysAgo,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ var (
|
|||||||
ErrCustomDomainNotFound = errors.New("custom domain not found")
|
ErrCustomDomainNotFound = errors.New("custom domain not found")
|
||||||
ErrPageNotFound = errors.New("page not found")
|
ErrPageNotFound = errors.New("page not found")
|
||||||
ErrMembershipNotFound = errors.New("membership not found")
|
ErrMembershipNotFound = errors.New("membership not found")
|
||||||
ErrMembershipInactive = errors.New("membership inactive")
|
ErrUserNotFound = errors.New("user not found")
|
||||||
|
ErrUserInactive = errors.New("user inactive")
|
||||||
ErrDocumentAccessNotFound = errors.New("document access not found")
|
ErrDocumentAccessNotFound = errors.New("document access not found")
|
||||||
ErrNDAFileNotFound = errors.New("NDA file not found")
|
ErrNDAFileNotFound = errors.New("NDA file not found")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import (
|
|||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
"go.probo.inc/probo/pkg/html2pdf"
|
"go.probo.inc/probo/pkg/html2pdf"
|
||||||
"go.probo.inc/probo/pkg/iam"
|
"go.probo.inc/probo/pkg/iam"
|
||||||
"go.probo.inc/probo/pkg/mail"
|
|
||||||
"go.probo.inc/probo/pkg/probo"
|
"go.probo.inc/probo/pkg/probo"
|
||||||
"go.probo.inc/probo/pkg/slack"
|
"go.probo.inc/probo/pkg/slack"
|
||||||
)
|
)
|
||||||
@@ -277,18 +276,18 @@ func (s *Service) EmailPresenterConfigByOrganizationID(ctx context.Context, orgI
|
|||||||
return s.WithTenant(orgID.TenantID()).TrustCenters.EmailPresenterConfig(ctx, trustCenter.ID)
|
return s.WithTenant(orgID.TenantID()).TrustCenters.EmailPresenterConfig(ctx, trustCenter.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) GetMembershipByCompliancePageIDAndEmail(ctx context.Context, compliancePageID gid.GID, email mail.Addr) (*coredata.TrustCenterAccess, error) {
|
func (s *Service) GetMembershipByCompliancePageIDAndIdentityID(ctx context.Context, compliancePageID gid.GID, identityID gid.GID) (*coredata.TrustCenterAccess, error) {
|
||||||
membership := &coredata.TrustCenterAccess{}
|
membership := &coredata.TrustCenterAccess{}
|
||||||
|
|
||||||
err := s.pg.WithConn(
|
err := s.pg.WithConn(
|
||||||
ctx,
|
ctx,
|
||||||
func(conn pg.Conn) error {
|
func(conn pg.Conn) error {
|
||||||
return membership.LoadByTrustCenterIDAndEmail(
|
return membership.LoadByTrustCenterIDAndIdentityID(
|
||||||
ctx,
|
ctx,
|
||||||
conn,
|
conn,
|
||||||
coredata.NewScopeFromObjectID(compliancePageID),
|
coredata.NewScopeFromObjectID(compliancePageID),
|
||||||
compliancePageID,
|
compliancePageID,
|
||||||
email,
|
identityID,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
"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/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -40,8 +39,7 @@ type (
|
|||||||
|
|
||||||
TrustCenterAccessRequest struct {
|
TrustCenterAccessRequest struct {
|
||||||
TrustCenterID gid.GID
|
TrustCenterID gid.GID
|
||||||
Email mail.Addr
|
IdentityID gid.GID
|
||||||
FullName string
|
|
||||||
DocumentIDs []gid.GID
|
DocumentIDs []gid.GID
|
||||||
ReportIDs []gid.GID
|
ReportIDs []gid.GID
|
||||||
TrustCenterFileIDs []gid.GID
|
TrustCenterFileIDs []gid.GID
|
||||||
@@ -52,20 +50,11 @@ const (
|
|||||||
TrustCenterAccessURLFormat = "https://%s/organizations/%s/trust-center/access"
|
TrustCenterAccessURLFormat = "https://%s/organizations/%s/trust-center/access"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tcar *TrustCenterAccessRequest) Validate() error {
|
|
||||||
v := validator.New()
|
|
||||||
|
|
||||||
v.Check(tcar.Email.Domain(), "email", validator.NotBlacklisted())
|
|
||||||
|
|
||||||
return v.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s TrustCenterAccessService) ensureAccessInTx(
|
func (s TrustCenterAccessService) ensureAccessInTx(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
tx pg.Conn,
|
tx pg.Conn,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
fullName string,
|
|
||||||
) (*coredata.TrustCenterAccess, *coredata.TrustCenter, error) {
|
) (*coredata.TrustCenterAccess, *coredata.TrustCenter, error) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
@@ -74,8 +63,13 @@ func (s TrustCenterAccessService) ensureAccessInTx(
|
|||||||
return nil, nil, fmt.Errorf("cannot load trust center: %w", err)
|
return nil, nil, fmt.Errorf("cannot load trust center: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identity := &coredata.Identity{}
|
||||||
|
if err := identity.LoadByID(ctx, tx, identityID); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
existingAccess := &coredata.TrustCenterAccess{}
|
existingAccess := &coredata.TrustCenterAccess{}
|
||||||
err := existingAccess.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenterID, email)
|
err := existingAccess.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, trustCenterID, identityID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return existingAccess, trustCenter, nil
|
return existingAccess, trustCenter, nil
|
||||||
}
|
}
|
||||||
@@ -89,10 +83,6 @@ func (s TrustCenterAccessService) ensureAccessInTx(
|
|||||||
OrganizationID: trustCenter.OrganizationID,
|
OrganizationID: trustCenter.OrganizationID,
|
||||||
TenantID: s.svc.scope.GetTenantID(),
|
TenantID: s.svc.scope.GetTenantID(),
|
||||||
TrustCenterID: trustCenterID,
|
TrustCenterID: trustCenterID,
|
||||||
Email: email,
|
|
||||||
Name: fullName,
|
|
||||||
State: coredata.TrustCenterAccessStateActive,
|
|
||||||
HasAcceptedNonDisclosureAgreement: false,
|
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
}
|
}
|
||||||
@@ -105,7 +95,7 @@ func (s TrustCenterAccessService) ensureAccessInTx(
|
|||||||
OrganizationID: access.OrganizationID,
|
OrganizationID: access.OrganizationID,
|
||||||
DocumentType: coredata.ElectronicSignatureDocumentTypeNDA,
|
DocumentType: coredata.ElectronicSignatureDocumentTypeNDA,
|
||||||
FileID: *trustCenter.NonDisclosureAgreementFileID,
|
FileID: *trustCenter.NonDisclosureAgreementFileID,
|
||||||
SignerEmail: access.Email,
|
SignerEmail: identity.EmailAddress,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -124,8 +114,7 @@ func (s TrustCenterAccessService) ensureAccessInTx(
|
|||||||
func (s TrustCenterAccessService) EnsureAccess(
|
func (s TrustCenterAccessService) EnsureAccess(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
fullName string,
|
|
||||||
) (*coredata.TrustCenterAccess, error) {
|
) (*coredata.TrustCenterAccess, error) {
|
||||||
var access *coredata.TrustCenterAccess
|
var access *coredata.TrustCenterAccess
|
||||||
|
|
||||||
@@ -133,7 +122,7 @@ func (s TrustCenterAccessService) EnsureAccess(
|
|||||||
ctx,
|
ctx,
|
||||||
func(tx pg.Conn) error {
|
func(tx pg.Conn) error {
|
||||||
var err error
|
var err error
|
||||||
access, _, err = s.ensureAccessInTx(ctx, tx, trustCenterID, email, fullName)
|
access, _, err = s.ensureAccessInTx(ctx, tx, trustCenterID, identityID)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -145,10 +134,6 @@ func (s TrustCenterAccessService) Request(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *TrustCenterAccessRequest,
|
req *TrustCenterAccessRequest,
|
||||||
) (*coredata.TrustCenterAccess, error) {
|
) (*coredata.TrustCenterAccess, error) {
|
||||||
if err := req.Validate(); err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid request arguments: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
access *coredata.TrustCenterAccess
|
access *coredata.TrustCenterAccess
|
||||||
@@ -160,7 +145,7 @@ func (s TrustCenterAccessService) Request(
|
|||||||
var trustCenter *coredata.TrustCenter
|
var trustCenter *coredata.TrustCenter
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
access, trustCenter, err = s.ensureAccessInTx(ctx, tx, req.TrustCenterID, req.Email, req.FullName)
|
access, trustCenter, err = s.ensureAccessInTx(ctx, tx, req.TrustCenterID, req.IdentityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -272,7 +257,7 @@ func (s TrustCenterAccessService) Request(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.svc.SlackMessages.QueueSlackNotification(ctx, access.Email, req.TrustCenterID); err != nil {
|
if err := s.svc.SlackMessages.QueueSlackNotification(ctx, req.IdentityID, req.TrustCenterID); err != nil {
|
||||||
s.logger.ErrorCtx(ctx, "cannot queue slack notification", log.Error(err))
|
s.logger.ErrorCtx(ctx, "cannot queue slack notification", log.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,12 +267,12 @@ func (s TrustCenterAccessService) Request(
|
|||||||
func (s TrustCenterAccessService) GetAccess(
|
func (s TrustCenterAccessService) GetAccess(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
) (coredata.TrustCenterAccess, error) {
|
) (coredata.TrustCenterAccess, error) {
|
||||||
var access coredata.TrustCenterAccess
|
var access coredata.TrustCenterAccess
|
||||||
|
|
||||||
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||||
return access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
return access.LoadByTrustCenterIDAndIdentityID(ctx, conn, s.svc.scope, trustCenterID, identityID)
|
||||||
})
|
})
|
||||||
|
|
||||||
return access, err
|
return access, err
|
||||||
@@ -296,14 +281,14 @@ func (s TrustCenterAccessService) GetAccess(
|
|||||||
func (s TrustCenterAccessService) GetDocumentAccess(
|
func (s TrustCenterAccessService) GetDocumentAccess(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
documentID gid.GID,
|
documentID gid.GID,
|
||||||
) (*coredata.TrustCenterDocumentAccess, error) {
|
) (*coredata.TrustCenterDocumentAccess, error) {
|
||||||
var documentAccess *coredata.TrustCenterDocumentAccess
|
var documentAccess *coredata.TrustCenterDocumentAccess
|
||||||
|
|
||||||
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||||
access := &coredata.TrustCenterAccess{}
|
access := &coredata.TrustCenterAccess{}
|
||||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, s.svc.scope, trustCenterID, identityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
return ErrMembershipNotFound
|
return ErrMembershipNotFound
|
||||||
@@ -312,8 +297,15 @@ func (s TrustCenterAccessService) GetDocumentAccess(
|
|||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if access.State != coredata.TrustCenterAccessStateActive {
|
profile := &coredata.MembershipProfile{}
|
||||||
return ErrMembershipInactive
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, conn, s.svc.scope, identityID, access.OrganizationID); err != nil {
|
||||||
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return ErrUserNotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.State != coredata.ProfileStateActive {
|
||||||
|
return ErrUserInactive
|
||||||
}
|
}
|
||||||
|
|
||||||
documentAccess = &coredata.TrustCenterDocumentAccess{}
|
documentAccess = &coredata.TrustCenterDocumentAccess{}
|
||||||
@@ -339,14 +331,14 @@ func (s TrustCenterAccessService) GetDocumentAccess(
|
|||||||
func (s TrustCenterAccessService) GetReportAccess(
|
func (s TrustCenterAccessService) GetReportAccess(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
reportID gid.GID,
|
reportID gid.GID,
|
||||||
) (*coredata.TrustCenterDocumentAccess, error) {
|
) (*coredata.TrustCenterDocumentAccess, error) {
|
||||||
var reportAccess *coredata.TrustCenterDocumentAccess
|
var reportAccess *coredata.TrustCenterDocumentAccess
|
||||||
|
|
||||||
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||||
access := &coredata.TrustCenterAccess{}
|
access := &coredata.TrustCenterAccess{}
|
||||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, s.svc.scope, trustCenterID, identityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
return ErrMembershipNotFound
|
return ErrMembershipNotFound
|
||||||
@@ -355,8 +347,15 @@ func (s TrustCenterAccessService) GetReportAccess(
|
|||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if access.State != coredata.TrustCenterAccessStateActive {
|
profile := &coredata.MembershipProfile{}
|
||||||
return ErrMembershipInactive
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, conn, s.svc.scope, identityID, access.OrganizationID); err != nil {
|
||||||
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return ErrUserNotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.State != coredata.ProfileStateActive {
|
||||||
|
return ErrUserInactive
|
||||||
}
|
}
|
||||||
|
|
||||||
reportAccess = &coredata.TrustCenterDocumentAccess{}
|
reportAccess = &coredata.TrustCenterDocumentAccess{}
|
||||||
@@ -382,14 +381,14 @@ func (s TrustCenterAccessService) GetReportAccess(
|
|||||||
func (s TrustCenterAccessService) GetTrustCenterFileAccess(
|
func (s TrustCenterAccessService) GetTrustCenterFileAccess(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
email mail.Addr,
|
identityID gid.GID,
|
||||||
trustCenterFileID gid.GID,
|
trustCenterFileID gid.GID,
|
||||||
) (*coredata.TrustCenterDocumentAccess, error) {
|
) (*coredata.TrustCenterDocumentAccess, error) {
|
||||||
var fileAccess *coredata.TrustCenterDocumentAccess
|
var fileAccess *coredata.TrustCenterDocumentAccess
|
||||||
|
|
||||||
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||||
access := &coredata.TrustCenterAccess{}
|
access := &coredata.TrustCenterAccess{}
|
||||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
err := access.LoadByTrustCenterIDAndIdentityID(ctx, conn, s.svc.scope, trustCenterID, identityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, coredata.ErrResourceNotFound) {
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
return ErrMembershipNotFound
|
return ErrMembershipNotFound
|
||||||
@@ -398,8 +397,15 @@ func (s TrustCenterAccessService) GetTrustCenterFileAccess(
|
|||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if access.State != coredata.TrustCenterAccessStateActive {
|
profile := &coredata.MembershipProfile{}
|
||||||
return ErrMembershipInactive
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, conn, s.svc.scope, identityID, access.OrganizationID); err != nil {
|
||||||
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return ErrUserNotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.State != coredata.ProfileStateActive {
|
||||||
|
return ErrUserInactive
|
||||||
}
|
}
|
||||||
|
|
||||||
fileAccess = &coredata.TrustCenterDocumentAccess{}
|
fileAccess = &coredata.TrustCenterDocumentAccess{}
|
||||||
@@ -436,12 +442,28 @@ func (s *TrustCenterAccessService) GrantByIDs(
|
|||||||
return fmt.Errorf("cannot load trust center: %w", err)
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identity := &coredata.Identity{}
|
||||||
|
if err := identity.LoadByEmail(ctx, tx, email); err != nil {
|
||||||
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
access := &coredata.TrustCenterAccess{}
|
access := &coredata.TrustCenterAccess{}
|
||||||
if err := access.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenter.ID, email); err != nil {
|
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, trustCenter.ID, identity.ID); err != nil {
|
||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldSendEmail := access.State != coredata.TrustCenterAccessStateActive
|
profile := &coredata.MembershipProfile{}
|
||||||
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, s.svc.scope, identity.ID, access.OrganizationID); err != nil {
|
||||||
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return ErrUserNotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.State != coredata.ProfileStateActive {
|
||||||
|
return ErrUserInactive
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldSendEmail := profile.State != coredata.ProfileStateActive
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
if len(documentIDs) > 0 {
|
if len(documentIDs) > 0 {
|
||||||
@@ -461,13 +483,13 @@ func (s *TrustCenterAccessService) GrantByIDs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if shouldSendEmail {
|
if shouldSendEmail {
|
||||||
access.State = coredata.TrustCenterAccessStateActive
|
profile.State = coredata.ProfileStateActive
|
||||||
access.UpdatedAt = now
|
profile.UpdatedAt = now
|
||||||
if err := access.Update(ctx, tx, s.svc.scope); err != nil {
|
if err := profile.Update(ctx, tx, s.svc.scope); err != nil {
|
||||||
return fmt.Errorf("cannot update trust center access: %w", err)
|
return fmt.Errorf("cannot update profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.sendAccessEmail(ctx, tx, access); err != nil {
|
if err := s.sendAccessEmail(ctx, tx, access, profile); err != nil {
|
||||||
return fmt.Errorf("cannot send access email: %w", err)
|
return fmt.Errorf("cannot send access email: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -476,7 +498,7 @@ func (s *TrustCenterAccessService) GrantByIDs(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Conn, access *coredata.TrustCenterAccess) error {
|
func (s *TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Conn, access *coredata.TrustCenterAccess, profile *coredata.MembershipProfile) error {
|
||||||
organization := &coredata.Organization{}
|
organization := &coredata.Organization{}
|
||||||
if err := organization.LoadByID(ctx, tx, s.svc.scope, access.OrganizationID); err != nil {
|
if err := organization.LoadByID(ctx, tx, s.svc.scope, access.OrganizationID); err != nil {
|
||||||
return fmt.Errorf("cannot load organization: %w", err)
|
return fmt.Errorf("cannot load organization: %w", err)
|
||||||
@@ -494,7 +516,7 @@ func (s *TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Co
|
|||||||
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
|
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
emailPresenter := emails.NewPresenterFromConfig(s.svc.fileManager, emailPresenterCfg, access.Name)
|
emailPresenter := emails.NewPresenterFromConfig(s.svc.fileManager, emailPresenterCfg, profile.FullName)
|
||||||
|
|
||||||
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name)
|
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterAccess(ctx, organization.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -502,8 +524,8 @@ func (s *TrustCenterAccessService) sendAccessEmail(ctx context.Context, tx pg.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
accessEmail := coredata.NewEmail(
|
accessEmail := coredata.NewEmail(
|
||||||
access.Name,
|
profile.FullName,
|
||||||
access.Email,
|
profile.EmailAddress,
|
||||||
subject,
|
subject,
|
||||||
textBody,
|
textBody,
|
||||||
htmlBody,
|
htmlBody,
|
||||||
@@ -529,11 +551,21 @@ func (s *TrustCenterAccessService) RejectOrRevokeByIDs(
|
|||||||
return fmt.Errorf("cannot load trust center: %w", err)
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identity := &coredata.Identity{}
|
||||||
|
if err := identity.LoadByEmail(ctx, tx, email); err != nil {
|
||||||
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
access := &coredata.TrustCenterAccess{}
|
access := &coredata.TrustCenterAccess{}
|
||||||
if err := access.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenter.ID, email); err != nil {
|
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, trustCenter.ID, identity.ID); err != nil {
|
||||||
return fmt.Errorf("cannot load trust center access: %w", err)
|
return fmt.Errorf("cannot load trust center access: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profile := &coredata.MembershipProfile{}
|
||||||
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, s.svc.scope, identity.ID, access.OrganizationID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
shouldSendEmail := false
|
shouldSendEmail := false
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
@@ -557,7 +589,7 @@ func (s *TrustCenterAccessService) RejectOrRevokeByIDs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if shouldSendEmail {
|
if shouldSendEmail {
|
||||||
if err := s.sendDocumentAccessRejectedEmail(ctx, tx, access, documentIDs, reportIDs, fileIDs); err != nil {
|
if err := s.sendDocumentAccessRejectedEmail(ctx, tx, access, profile, documentIDs, reportIDs, fileIDs); err != nil {
|
||||||
return fmt.Errorf("cannot send access email: %w", err)
|
return fmt.Errorf("cannot send access email: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,6 +602,7 @@ func (s *TrustCenterAccessService) sendDocumentAccessRejectedEmail(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
tx pg.Conn,
|
tx pg.Conn,
|
||||||
access *coredata.TrustCenterAccess,
|
access *coredata.TrustCenterAccess,
|
||||||
|
profile *coredata.MembershipProfile,
|
||||||
documentIDs []gid.GID,
|
documentIDs []gid.GID,
|
||||||
reportIDs []gid.GID,
|
reportIDs []gid.GID,
|
||||||
fileIDs []gid.GID,
|
fileIDs []gid.GID,
|
||||||
@@ -613,11 +646,7 @@ func (s *TrustCenterAccessService) sendDocumentAccessRejectedEmail(
|
|||||||
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
|
return fmt.Errorf("cannot get compliance page email presenter config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fullName := access.Name
|
emailPresenter := emails.NewPresenterFromConfig(s.svc.fileManager, emailPresenterCfg, profile.FullName)
|
||||||
if fullName == "" {
|
|
||||||
fullName = access.Email.Username()
|
|
||||||
}
|
|
||||||
emailPresenter := emails.NewPresenterFromConfig(s.svc.fileManager, emailPresenterCfg, fullName)
|
|
||||||
|
|
||||||
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterDocumentAccessRejected(
|
subject, textBody, htmlBody, err := emailPresenter.RenderTrustCenterDocumentAccessRejected(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -629,8 +658,8 @@ func (s *TrustCenterAccessService) sendDocumentAccessRejectedEmail(
|
|||||||
}
|
}
|
||||||
|
|
||||||
accessEmail := coredata.NewEmail(
|
accessEmail := coredata.NewEmail(
|
||||||
access.Name,
|
profile.FullName,
|
||||||
access.Email,
|
profile.EmailAddress,
|
||||||
subject,
|
subject,
|
||||||
textBody,
|
textBody,
|
||||||
htmlBody,
|
htmlBody,
|
||||||
|
|||||||
Reference in New Issue
Block a user