Remove legacy document signing endpoints

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-03-09 16:22:45 +04:00
parent fec4696aeb
commit 0a532f17c5
4 changed files with 3 additions and 228 deletions

View File

@@ -13,7 +13,6 @@ import (
"unicode"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/jackc/pgx/v5"
"go.gearno.de/crypto/uuid"
"go.gearno.de/kit/pg"
"go.probo.inc/probo/packages/emails"
@@ -23,7 +22,6 @@ import (
"go.probo.inc/probo/pkg/html2pdf"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/statelesstoken"
"go.probo.inc/probo/pkg/validator"
"go.probo.inc/probo/pkg/watermarkpdf"
)
@@ -79,11 +77,6 @@ type (
SignatoryIDs []gid.GID
}
SigningRequestData struct {
OrganizationID gid.GID `json:"organization_id"`
PeopleID gid.GID `json:"people_id"`
}
BulkPublishVersionsRequest struct {
DocumentIDs []gid.GID
PublishedBy gid.GID
@@ -137,8 +130,6 @@ func (udvr *UpdateDocumentVersionRequest) Validate() error {
}
const (
TokenTypeSigningRequest = "signing_request"
documentExportEmailExpiresIn = 24 * time.Hour
maxFilenameLength = 200
@@ -593,59 +584,6 @@ func (s *DocumentService) Create(
return document, documentVersion, nil
}
func (s *DocumentService) ListSigningRequests(
ctx context.Context,
organizationID gid.GID,
profileID gid.GID,
) ([]map[string]any, error) {
q := `
SELECT
p.title,
pv.id AS document_version_id,
o.name AS organization_name
FROM
documents p
INNER JOIN document_versions pv ON pv.document_id = p.id
INNER JOIN document_version_signatures pvs ON pvs.document_version_id = pv.id
INNER JOIN organizations o ON o.id = p.organization_id
WHERE
p.tenant_id = $1
AND pvs.signed_by_profile_id = $2
AND pvs.signed_at IS NULL
AND pv.status = 'PUBLISHED'
AND pv.version_number = (
SELECT MAX(pv2.version_number)
FROM document_versions pv2
WHERE pv2.document_id = pv.document_id
AND pv2.status = 'PUBLISHED'
)
`
var results []map[string]any
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
rows, err := conn.Query(ctx, q, s.svc.scope.GetTenantID(), profileID)
if err != nil {
return fmt.Errorf("cannot query documents: %w", err)
}
results, err = pgx.CollectRows(rows, pgx.RowToMap)
if err != nil {
return err
}
return nil
},
)
if err != nil {
return nil, err
}
return results, nil
}
func (s *DocumentService) SendSigningNotifications(
ctx context.Context,
organizationID gid.GID,
@@ -664,25 +602,11 @@ func (s *DocumentService) SendSigningNotifications(
}
for _, signatory := range signatories {
token, err := statelesstoken.NewToken(
s.svc.tokenSecret,
TokenTypeSigningRequest,
time.Hour*24*30,
SigningRequestData{
OrganizationID: organizationID,
PeopleID: signatory.ID,
},
)
if err != nil {
return fmt.Errorf("cannot create signing request token: %w", err)
}
emailPresenter := emails.NewPresenter(s.svc.fileManager, s.svc.bucket, s.svc.baseURL, signatory.FullName)
subject, textBody, htmlBody, err := emailPresenter.RenderDocumentSigning(
ctx,
"/documents/signing-requests",
token,
"/organizations/"+organizationID.String()+"/employee",
organization.Name,
)
if err != nil {
@@ -713,31 +637,6 @@ func (s *DocumentService) SendSigningNotifications(
return nil
}
func (s *DocumentService) SignDocumentVersion(
ctx context.Context,
documentVersionID gid.GID,
signatory gid.GID,
) error {
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
var err error
_, err = s.signDocumentVersionInTx(ctx, conn, documentVersionID, signatory)
if err != nil {
return fmt.Errorf("cannot sign document version: %w", err)
}
return nil
},
)
if err != nil {
return fmt.Errorf("cannot sign document version: %w", err)
}
return nil
}
func (s *DocumentService) SignDocumentVersionByIdentity(
ctx context.Context,
documentVersionID gid.GID,

View File

@@ -637,7 +637,7 @@ func (s *TrustCenterService) EmailPresenterConfig(ctx context.Context, complianc
baseURL := url.URL{
Scheme: parsedBaseURL.Scheme,
Host: parsedBaseURL.Host,
Path: "/trust/" + compliancePage.Slug,
Path: "/trust/" + compliancePage.ID.String(),
}
if customDomain != nil && customDomain.SSLStatus == coredata.CustomDomainSSLStatusActive {

View File

@@ -18,14 +18,11 @@ package console_v1
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/go-chi/chi/v5"
"go.gearno.de/crypto/uuid"
"go.gearno.de/kit/httpserver"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/baseurl"
@@ -40,7 +37,6 @@ import (
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/authz"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
"go.probo.inc/probo/pkg/statelesstoken"
)
type (
@@ -196,125 +192,6 @@ func NewMux(
})
})
r.Get(
"/documents/signing-requests",
func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "token is required", http.StatusUnauthorized)
return
}
token = strings.TrimPrefix(token, "Bearer ")
data, err := statelesstoken.ValidateToken[probo.SigningRequestData](tokenSecret, probo.TokenTypeSigningRequest, token)
if err != nil {
http.Error(w, "invalid token", http.StatusUnauthorized)
return
}
svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID())
requests, err := svc.Documents.ListSigningRequests(r.Context(), data.Data.OrganizationID, data.Data.PeopleID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(requests); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
},
)
r.Get(
"/documents/signing-requests/{document_version_id}/pdf",
func(w http.ResponseWriter, r *http.Request) {
token := r.URL.Query().Get("token")
if token == "" {
http.Error(w, "token is required", http.StatusUnauthorized)
return
}
data, err := statelesstoken.ValidateToken[probo.SigningRequestData](tokenSecret, probo.TokenTypeSigningRequest, token)
if err != nil {
http.Error(w, "invalid token", http.StatusUnauthorized)
return
}
documentVersionID, err := gid.ParseGID(chi.URLParam(r, "document_version_id"))
if err != nil {
http.Error(w, "invalid document version id", http.StatusBadRequest)
return
}
svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID())
// Get the people to get their email for watermark
profile, err := iamSvc.OrganizationService.GetProfile(r.Context(), data.Data.PeopleID)
if err != nil {
http.Error(w, "cannot get user", http.StatusInternalServerError)
return
}
// Generate PDF with watermark
pdfData, err := svc.Documents.ExportPDF(r.Context(), documentVersionID, probo.ExportPDFOptions{
WithWatermark: true,
WatermarkEmail: &profile.EmailAddress,
WithSignatures: false,
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
uuid, err := uuid.NewV7()
if err != nil {
http.Error(w, "cannot generate uuid", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", fmt.Sprintf("inline; filename=\"%s.pdf\"", uuid.String()))
w.WriteHeader(http.StatusOK)
_, _ = w.Write(pdfData)
},
)
r.Post(
"/documents/signing-requests/{document_version_id}/sign",
func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "token is required", http.StatusUnauthorized)
return
}
token = strings.TrimPrefix(token, "Bearer ")
data, err := statelesstoken.ValidateToken[probo.SigningRequestData](tokenSecret, probo.TokenTypeSigningRequest, token)
if err != nil {
http.Error(w, "invalid token", http.StatusUnauthorized)
return
}
documentVersionID, err := gid.ParseGID(chi.URLParam(r, "document_version_id"))
if err != nil {
http.Error(w, "invalid document version id", http.StatusBadRequest)
return
}
svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID())
if err := svc.Documents.SignDocumentVersion(r.Context(), documentVersionID, data.Data.PeopleID); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
},
)
return r
}