Skip to content

Instantly share code, notes, and snippets.

@ianaz
Created April 25, 2023 10:46
Show Gist options
  • Save ianaz/3b58b93982e76bb12f9e594a10488c43 to your computer and use it in GitHub Desktop.
Save ianaz/3b58b93982e76bb12f9e594a10488c43 to your computer and use it in GitHub Desktop.
diff --git a/main.go b/main.go
index 5eeaadeb..012c19dd 100644
--- a/main.go
+++ b/main.go
@@ -339,9 +339,7 @@ func initFactory(ctx context.Context) (deps endpoints.AppDependencies, err error
}
settingService := setting.NewSettingService(config, db, repository.NewSqlSettingRepository(db), organizationService, fileObjectStorageService, featureService)
settingService.AddObserver(observers.NewOrganization2faSettingObserver(organizationService, roleRepository, auth0Client))
- if config.FF_ConfigurableDeletionEnabled {
- settingService.AddObserver(observers.NewOrganizationDeletionTimelineObserver(dbTransactionManager, signatureRepository))
- }
+ settingService.AddObserver(observers.NewOrganizationDeletionTimelineObserver(dbTransactionManager, signatureRepository, config.FF_ConfigurableDeletionEnabled))
fileService := file.NewFileService(config, fileRepository, organizationService, settingService, shortenerRepository)
diff --git a/service/observers/organization_deletion_timeline_observer.go b/service/observers/organization_deletion_timeline_observer.go
index 21e06957..02b09f2b 100644
--- a/service/observers/organization_deletion_timeline_observer.go
+++ b/service/observers/organization_deletion_timeline_observer.go
@@ -17,187 +17,98 @@ import (
type organizationDeletionTimelineObserver struct {
transactionManager dbRepository.DBTransactionManager
signatureRepo signaturesRepository.Repository
- getNowTime func() time.Time
+ active bool
}
-func NewOrganizationDeletionTimelineObserver(transactionManager dbRepository.DBTransactionManager, signatureRepo signaturesRepository.Repository) *organizationDeletionTimelineObserver {
+func NewOrganizationDeletionTimelineObserver(
+ transactionManager dbRepository.DBTransactionManager,
+ signatureRepo signaturesRepository.Repository,
+ active bool,
+) *organizationDeletionTimelineObserver {
return &organizationDeletionTimelineObserver{
transactionManager: transactionManager,
signatureRepo: signatureRepo,
- getNowTime: func() time.Time {
- return time.Now()
- },
+ active: active,
}
}
var neverExpireTime = time.Date(9999, 12, 31, 0, 0, 0, 0, time.UTC)
-func (me *organizationDeletionTimelineObserver) Notify(ctx context.Context, event observable.Event) error {
+func (me *organizationDeletionTimelineObserver) Notify(ctx context.Context, Event observable.Event) error {
- newSetting, ok := event.GetContent().(model.EntitySetting)
+ if !me.active {
+ return nil
+ }
+
+ event, ok := Event.GetContent().(model.EntitySetting)
if !ok {
log.ErrorCtx(ctx, "Deletion Timeline Observer Unable to convert event content")
return errors.New("invalid event content passed")
}
- if newSetting.Setting.ID != model.SettingDeletionTimeline {
- log.DebugfCtx(ctx, "Skipping Deletion Timeline update for the setting: %s", newSetting.Setting.ID)
+ if event.Setting.ID != model.SettingDeletionTimeline {
+ log.DebugfCtx(ctx, "Skipping Deletion Timeline update for the setting: %s", event.Setting.ID)
return nil
}
- newDurationDays, err := strconv.Atoi(newSetting.GetValue())
+ deletionTimeline, err := strconv.Atoi(event.GetValue())
if err != nil {
log.ErrorCtx(ctx, "Unable to convert file expiry into integer")
return err
}
- if newDurationDays == timelineNeverDelete {
+ if deletionTimeline < 0 {
log.DebugfCtx(ctx, "Skipping deleting previous files. Timeline is set to never delete")
return nil
}
- previousSetting, ok := event.GetBeforeContent().(model.EntitySetting)
- if !ok {
- log.ErrorCtx(ctx, "Encountered a different type than EntitySetting: %+v", event.GetBeforeContent())
- return err
- }
-
- previousDurationDays, err := strconv.Atoi(previousSetting.GetValue())
- if err != nil {
- log.ErrorfCtx(ctx, "Unable to convert previous setting file expiry into integer: %s", err, previousSetting.GetValue())
- return err
- }
+ fileExpiryDate := time.Now().AddDate(0, 0, deletionTimeline)
ctx, err = me.transactionManager.BeginTransaction(ctx, sql.LevelReadCommitted)
if err != nil {
return err
}
- err = me.updateAsNeeded(ctx, durationChange{previousDurationDays, newDurationDays}, newSetting.EntityID)
+ activeOrganizationSignatures, err := me.signatureRepo.FindActiveOrganizationSignatures(ctx, event.EntityID)
if err != nil {
me.transactionManager.Rollback(ctx)
return err
}
- ctx, err = me.transactionManager.Commit(ctx)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (me *organizationDeletionTimelineObserver) updateAsNeeded(ctx context.Context, change durationChange, entityID string) error {
- if change.IsTimelineIncreased() || change.IsFromDeleteInstantlyToTimeline() || change.IsFromDeleteInstantlyToNeverDelete() {
- // Do nothing, only takes effect going forward
- return nil
- }
-
- newExpiryDate := me.getNowTime().AddDate(0, 0, change.newDurationDays)
- if change.IsToNeverDelete() {
- newExpiryDate = neverExpireTime
- }
- if change.IsToDeleteInstantly() {
- newExpiryDate = me.getNowTime()
- }
-
- var signatureRequestsToUpdate []model.SignatureRequest
- var err error
-
- signatureRequestsToUpdate, err = me.signatureRepo.FindCompletedForOrganization(ctx, entityID)
- if err != nil {
- return err
- }
-
- return me.clearThemUp(ctx, signatureRequestsToUpdate, newExpiryDate)
-}
-
-func (me *organizationDeletionTimelineObserver) clearThemUp(ctx context.Context, signatureRequests []model.SignatureRequest, newExpiryDate time.Time) error {
- for _, originalSignatureRequest := range signatureRequests {
-
- signatureRequest := originalSignatureRequest
-
- signatureRequest.FileURLExpiry = newExpiryDate
- if me.getNowTime().After(newExpiryDate) || me.getNowTime().Equal(newExpiryDate) {
- signatureRequest.FileURL = ""
- }
+ for _, activeOrganizationSignature := range activeOrganizationSignatures {
- for i, envelopeItem := range originalSignatureRequest.EnvelopeItems {
- envelopeItem.FileURLExpiry = newExpiryDate
- if me.getNowTime().After(newExpiryDate) || me.getNowTime().Equal(newExpiryDate) {
- envelopeItem.FileURL = ""
+ for i, envelopItem := range activeOrganizationSignature.EnvelopeItems {
+ // If the file expiry comes after the new file Expiry Date delete the name and URl
+ if envelopItem.FileURLExpiry.Equal(neverExpireTime) {
+ envelopItem.FileURLExpiry = fileExpiryDate
+ } else if envelopItem.FileURLExpiry.After(fileExpiryDate) {
+ // If the expiry is before the new fileExpiry set the new expiry date
+ envelopItem.FileURL = ""
}
- signatureRequest.EnvelopeItems[i] = envelopeItem
+ activeOrganizationSignature.EnvelopeItems[i] = envelopItem
}
- sr := signatureRequest
- err := me.signatureRepo.Update(ctx, &sr)
+ // If the file expiry comes after the new file Expiry Date delete the name and URl
+ if activeOrganizationSignature.FileURLExpiry.Equal(neverExpireTime) {
+ activeOrganizationSignature.FileURLExpiry = fileExpiryDate
+ } else if activeOrganizationSignature.FileURLExpiry.After(fileExpiryDate) {
+ // If the expiry is before the new fileExpiry set the new expiry date
+ activeOrganizationSignature.Filename = ""
+ activeOrganizationSignature.FileURL = ""
+ }
+ err = me.signatureRepo.Update(ctx, &activeOrganizationSignature)
if err != nil {
log.ErrorfCtx(ctx, "Update signature request file url: %s", err)
+ me.transactionManager.Rollback(ctx)
return err
}
}
- return nil
-}
-
-func (me *organizationDeletionTimelineObserver) setNowTime(getNowTime func() time.Time) {
- me.getNowTime = getNowTime
-}
-
-const (
- timelineNeverDelete = -1
- timelineDeleteInstantly = 0
-)
-
-type durationChange struct {
- previousDurationDays, newDurationDays int
-}
-
-func (me durationChange) NewDurationChange(previous, new int) durationChange {
- return durationChange{
- previousDurationDays: previous,
- newDurationDays: new,
+ ctx, err = me.transactionManager.Commit(ctx)
+ if err != nil {
+ return err
}
-}
-
-func (me durationChange) IsTimelineIncreased() bool {
- return me.previousDurationDays > 0 && me.newDurationDays > me.previousDurationDays
-}
-func (me durationChange) IsFromDeleteInstantlyToTimeline() bool {
- return me.previousDurationDays == timelineDeleteInstantly && me.newDurationDays > 0
-}
-
-func (me durationChange) IsFromDeleteInstantlyToNeverDelete() bool {
- return me.previousDurationDays == timelineDeleteInstantly && me.newDurationDays == timelineNeverDelete
-}
-
-func (me durationChange) IsToNeverDelete() bool {
- return me.newDurationDays == timelineNeverDelete
-}
-
-func (me durationChange) IsToDeleteInstantly() bool {
- return me.newDurationDays == timelineDeleteInstantly
-}
-
-func (me durationChange) IsFromNeverDeleteToDeleteInstantly() bool {
- return me.previousDurationDays == timelineNeverDelete && me.newDurationDays == timelineDeleteInstantly
-}
-
-func (me durationChange) IsFromTimelineToDeleteInstantly() bool {
- return me.previousDurationDays > 0 && me.newDurationDays == timelineDeleteInstantly
-}
-
-func (me durationChange) IsFromNeverDeleteToTimeline() bool {
- return me.previousDurationDays == timelineNeverDelete && me.newDurationDays > 0
-}
-
-func (me durationChange) IsFromTimelineToNeverDelete() bool {
- return me.previousDurationDays > 0 && me.newDurationDays == timelineNeverDelete
-}
-
-func (me durationChange) IsTimelineDecreased() bool {
- return me.previousDurationDays > 0 && me.newDurationDays > 0 && me.newDurationDays < me.previousDurationDays
+ return nil
}
diff --git a/service/observers/organization_deletion_timeline_observer_integration_test.go b/service/observers/organization_deletion_timeline_observer_integration_test.go
deleted file mode 100644
index f488ed70..00000000
--- a/service/observers/organization_deletion_timeline_observer_integration_test.go
+++ /dev/null
@@ -1,327 +0,0 @@
-//go:build integration
-
-package observers
-
-import (
- "context"
- "database/sql"
- "math"
- "strconv"
- "testing"
- "time"
-
- "github.com/certifaction/api/observable"
-
- identitydb "github.com/certifaction/api/identity/repository/db"
- "github.com/certifaction/api/model"
- "github.com/certifaction/api/repository/user"
- "github.com/certifaction/api/service/configuration"
- signatureRepository "github.com/certifaction/api/signature_requests/repository"
- "github.com/certifaction/base-service/connection"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-var (
- observer *organizationDeletionTimelineObserver
- signaturesRepo signatureRepository.Repository
- txContext context.Context
- user1 = model.User{UID: "uid-2000"}
- user2 = model.User{UID: "uid-2001"}
-)
-
-func setupTestSuite(t *testing.T) func(t *testing.T) {
- config, err := configuration.NewConfiguration(nil)
- assert.NoError(t, err)
-
- db, err := connection.NewMySQLDBConnection(config.DbUsername, config.DbPassword, config.DbUrl, config.DbName)
- assert.NoError(t, err)
-
- txContext, err = db.BeginTransaction(context.Background(), sql.LevelSerializable) // Start a new transaction
- assert.NoError(t, err)
-
- identityStore := identitydb.NewDbIdentityStore(db)
- userRepository := user.NewSQLUserRepository(db, identityStore)
- signaturesRepo = signatureRepository.NewDefaultRepository(db, userRepository, nil)
-
- insertTestDataQuery := `
-INSERT INTO users (id, uid, email, name, verified, address, hash, randomhash, secret_auth_token)
-VALUES
- (1005, 'uid-2000', 'integration-test-cleanup@certifaction.com', 'Integration Test', '1', '', '', '', ''),
- (1006, 'uid-2001', 'integration-test-cleanup@certifaction.com', 'Integration Test', '1', '', '', '', '');
-
-INSERT INTO organizations (id, name) VALUES ('org-001', 'Test Org');
-
-INSERT INTO organizations_users (user_uid, organization_id, role, status, invite_email, verification_hash, role_id_after_invite)
-VALUES ('uid-2000', 'org-001', 'user', 'joined', null, null, DEFAULT);
-
-INSERT INTO roles (id, organization_id, name, admin, default_role)
-VALUES ('entity-001', 'org-001', 'Admin', 1, 0);
-
-INSERT INTO users_roles (user_uid,role_id) VALUES ('uid-2000', 'entity-001');
-`
- _, err = db.Exec(txContext, insertTestDataQuery)
- assert.NoError(t, err)
-
- err = signaturesRepo.Create(txContext, &model.SignatureRequest{
- EnvelopeItems: []model.EnvelopeItem{{
- FileID: "111",
- FileURLExpiry: time.Now().Add(5 * time.Second),
- FileURL: "https://...",
- Filename: "fileName111",
- LegalWeight: model.StandardLevel,
- }},
- FileID: "111",
- FileURLExpiry: time.Now().Add(5 * time.Second),
- FileURL: "https://...",
- Filename: "fileName111",
- Signer: &user1,
- Requester: &user1,
- Signed: true,
- })
- assert.NoError(t, err)
-
- err = signaturesRepo.Create(txContext, &model.SignatureRequest{
- EnvelopeItems: []model.EnvelopeItem{{
- FileID: "112",
- FileURLExpiry: time.Now().Add((24 * 15) * time.Hour),
- FileURL: "https://...",
- Filename: "fileName112",
- LegalWeight: model.StandardLevel,
- }},
- FileID: "112",
- FileURLExpiry: time.Now().Add((24 * 15) * time.Hour),
- FileURL: "https://...",
- Filename: "fileName112",
- Signer: &user1,
- Requester: &user1,
- Signed: true,
- })
- assert.NoError(t, err)
-
- observer = NewOrganizationDeletionTimelineObserver(db, signaturesRepo)
-
- return func(t *testing.T) {
- txContext = db.Rollback(txContext)
- }
-}
-func TestOrganizationDeletionTimelineObserver_Notify(t *testing.T) {
- teardown := setupTestSuite(t)
- t.Cleanup(func() {
- teardown(t)
- })
-
- tests := []struct {
- name string
- timelineDaysFrom int
- timelineDaysTo int
- beforeTest func()
- expected func()
- }{
- {
- name: "Timeline → Never delete",
- timelineDaysFrom: 5,
- timelineDaysTo: timelineNeverDelete,
- expected: func() {
- signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"111", "112", "113"}, true)
- require.NoError(t, err)
- assert.Len(t, signatureRequests, 2)
-
- var cleared []model.SignatureRequest
- for _, signatureRequest := range signatureRequests {
- if signatureRequest.FileURL == "" {
- cleared = append(cleared, signatureRequest)
- }
- }
-
- assert.Len(t, cleared, 0)
- },
- },
- {
- name: "Never delete → Timeline",
- timelineDaysFrom: timelineNeverDelete,
- timelineDaysTo: 13,
- expected: func() {
- signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"111", "112", "113"}, true)
- require.NoError(t, err)
- assert.Len(t, signatureRequests, 2)
- require.Equal(t, "https://...", signatureRequests[0].FileURL, "should not delete any file URLs as the date have been set to the future")
-
- diffDates := signatureRequests[0].FileURLExpiry.Sub(time.Now().AddDate(0, 0, 13))
- dateTolerance := 500 * time.Millisecond
- assert.InDelta(t, float64(diffDates.Milliseconds()), 0, float64(dateTolerance))
- },
- },
- {
- name: "Timeline increased",
- timelineDaysFrom: 3,
- timelineDaysTo: 6,
- expected: func() {
- signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"111"}, true)
- require.NoError(t, err)
-
- request := signatureRequests[0]
- assert.Equal(t, "111", request.FileID)
- assert.Equal(t, "https://...", request.FileURL)
- },
- },
- {
- name: "Never delete → Delete instantly",
- timelineDaysFrom: timelineNeverDelete,
- timelineDaysTo: timelineDeleteInstantly,
- beforeTest: func() {
- err := signaturesRepo.Create(txContext, &model.SignatureRequest{
- EnvelopeItems: []model.EnvelopeItem{{
- FileID: "113",
- FileURLExpiry: neverExpireTime,
- Filename: "fileName113",
- FileURL: "https://...",
- LegalWeight: model.StandardLevel,
- }},
- FileID: "113",
- FileURLExpiry: neverExpireTime,
- Filename: "fileName113",
- FileURL: "https://...",
- Signer: &user1,
- Requester: &user1,
- Signed: true,
- })
- assert.NoError(t, err)
-
- err = signaturesRepo.Create(txContext, &model.SignatureRequest{
- EnvelopeItems: []model.EnvelopeItem{{
- FileID: "113",
- FileURLExpiry: neverExpireTime,
- FileURL: "https://...",
- Filename: "fileName113",
- LegalWeight: model.StandardLevel,
- }},
- FileID: "113",
- FileURLExpiry: neverExpireTime,
- FileURL: "https://...",
- Filename: "fileName113",
- Signer: &user2,
- Requester: &user1,
- Signed: true,
- })
-
- assert.NoError(t, err)
- },
- expected: func() {
- signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"113"}, true)
- require.NoError(t, err)
-
- signatureRequest := signatureRequests[0]
- changeTimeline := signatureRequest.FileURLExpiry.Sub(time.Now()).Hours()
- changeTimelineDays := int(math.Round(changeTimeline / 24))
- assert.Equal(t, 0, changeTimelineDays)
-
- envelopeItem := signatureRequest.EnvelopeItems[0]
- envelopeItemTimeChange := envelopeItem.FileURLExpiry.Sub(time.Now()).Hours()
- envelopeItemChangeInDays := int(math.Round(envelopeItemTimeChange / 24))
- assert.Equal(t, 0, envelopeItemChangeInDays)
-
- assert.Empty(t, signatureRequest.FileURL)
- assert.Empty(t, signatureRequest.EnvelopeItems[0].FileURL)
- },
- },
- {
- name: "Timeline decreased",
- timelineDaysFrom: 9,
- timelineDaysTo: 3,
- beforeTest: func() {
- manyDaysFromNow := time.Now().AddDate(0, 0, 300)
- err := signaturesRepo.Create(txContext, &model.SignatureRequest{
- EnvelopeItems: []model.EnvelopeItem{{
- FileID: "114",
- FileURLExpiry: manyDaysFromNow,
- FileURL: "https://...",
- Filename: "fileName113",
- LegalWeight: model.StandardLevel,
- }},
- FileID: "114",
- FileURLExpiry: manyDaysFromNow,
- FileURL: "https://...",
- Filename: "fileName114",
- Signer: &user2,
- Requester: &user1,
- Signed: true,
- })
- assert.NoError(t, err)
- },
- expected: func() {
- signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"114"}, true)
- require.NoError(t, err)
- request := signatureRequests[0]
- assert.Equal(t, "114", request.FileID)
- assert.Equal(t, "https://...", request.FileURL)
- assert.Equal(t, "https://...", request.EnvelopeItems[0].FileURL)
-
- assert.WithinDuration(t, request.FileURLExpiry, time.Now().AddDate(0, 0, 3), 500*time.Millisecond)
- },
- },
- {
- name: "Timeline → Delete instantly",
- timelineDaysFrom: 5,
- timelineDaysTo: timelineDeleteInstantly,
- beforeTest: func() {
- manyDaysFromNow := time.Now().AddDate(0, 0, 300)
- err := signaturesRepo.Create(txContext, &model.SignatureRequest{
- EnvelopeItems: []model.EnvelopeItem{{
- FileID: "115",
- FileURLExpiry: manyDaysFromNow,
- FileURL: "https://...",
- Filename: "fileName113",
- LegalWeight: model.StandardLevel,
- }},
- FileID: "115",
- FileURLExpiry: manyDaysFromNow,
- FileURL: "https://...",
- Filename: "fileName114",
- Signer: &user2,
- Requester: &user1,
- Signed: true,
- })
- assert.NoError(t, err)
- },
- expected: func() {
- signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"115"}, true)
- require.NoError(t, err)
- request := signatureRequests[0]
- assert.Equal(t, "115", request.FileID)
- assert.Equal(t, "", request.FileURL, "should remove file URL")
- assert.Equal(t, "", request.EnvelopeItems[0].FileURL, "should remove file URL")
-
- assert.WithinDuration(t, request.FileURLExpiry, time.Now(), 500*time.Millisecond)
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if tt.beforeTest != nil {
- tt.beforeTest()
- }
-
- err := observer.Notify(txContext, observable.ObserverEvent{
- Type: model.NotificationEventTypeDeletionTimelineChange,
- BeforeContent: model.EntitySetting{
- EntityID: "entity-001",
- Setting: model.Setting{
- ID: model.SettingDeletionTimeline,
- },
- Value: strconv.Itoa(tt.timelineDaysFrom),
- },
- Content: model.EntitySetting{
- EntityID: "entity-001",
- Setting: model.Setting{
- ID: model.SettingDeletionTimeline,
- },
- Value: strconv.Itoa(tt.timelineDaysTo),
- },
- })
- assert.NoError(t, err)
- tt.expected()
- })
- }
-}
diff --git a/service/observers/organization_deletion_timeline_observer_test.go b/service/observers/organization_deletion_timeline_observer_test.go
index 252095b9..8519b168 100644
--- a/service/observers/organization_deletion_timeline_observer_test.go
+++ b/service/observers/organization_deletion_timeline_observer_test.go
@@ -1,251 +1,265 @@
+//go:build integration
+
package observers
import (
"context"
+ "database/sql"
+ "fmt"
+ "math"
"testing"
"time"
+ identitydb "github.com/certifaction/api/identity/repository/db"
"github.com/certifaction/api/model"
- repositoryfakes2 "github.com/certifaction/api/repository/repositoryfakes"
- "github.com/certifaction/api/signature_requests/repository/repositoryfakes"
- "github.com/google/go-cmp/cmp"
- "github.com/google/go-cmp/cmp/cmpopts"
+ "github.com/certifaction/api/observable"
+ "github.com/certifaction/api/repository/user"
+ "github.com/certifaction/api/service/configuration"
+ signatureRepository "github.com/certifaction/api/signature_requests/repository"
+ "github.com/certifaction/base-service/connection"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
-func TestUpdateAsNeeded(t *testing.T) {
- testStartTime := time.Now()
-
- testCases := []struct {
- name string
- previousDurationDays int
- newDurationDays int
- signatureRequests []model.SignatureRequest
- expectedSignatureRequests []model.SignatureRequest
- expectedFindCompleted bool
- }{
- {
- name: "From timelineNeverDelete to timelineDeleteInstantly",
- previousDurationDays: timelineNeverDelete,
- newDurationDays: timelineDeleteInstantly,
- expectedFindCompleted: true,
- signatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "https://da.certifaction.com/abc.pdf",
- FileURLExpiry: neverExpireTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/abc.pdf", Filename: "abc.pdf", FileURLExpiry: neverExpireTime},
- },
- },
- {
- ID: "def",
- FileURL: "",
- FileURLExpiry: neverExpireTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/def.pdf", Filename: "def.pdf", FileURLExpiry: neverExpireTime},
- },
- },
- },
- expectedSignatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "",
- FileURLExpiry: testStartTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "", Filename: "abc.pdf", FileURLExpiry: testStartTime},
- },
- },
- {
- ID: "def",
- FileURL: "",
- FileURLExpiry: testStartTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "", Filename: "def.pdf", FileURLExpiry: testStartTime},
- },
- },
- },
- },
- {
- name: "From timelineNeverDelete to timeline value",
- previousDurationDays: timelineNeverDelete,
- newDurationDays: 10,
- expectedFindCompleted: false,
- signatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "https://da.certifaction.com/abc.pdf",
- FileURLExpiry: neverExpireTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/abc.pdf", Filename: "abc.pdf", FileURLExpiry: neverExpireTime},
- },
- },
- {
- ID: "def",
- FileURL: "https://da.certifaction.com/def.pdf",
- FileURLExpiry: neverExpireTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/def.pdf", Filename: "def.pdf", FileURLExpiry: neverExpireTime},
- },
- },
- },
- expectedSignatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "https://da.certifaction.com/abc.pdf",
- FileURLExpiry: testStartTime.AddDate(0, 0, 10),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/abc.pdf", Filename: "abc.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, 10)},
- },
- },
- {
- ID: "def",
- FileURL: "https://da.certifaction.com/def.pdf",
- FileURLExpiry: testStartTime.AddDate(0, 0, 10),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/def.pdf", Filename: "def.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, 10)},
- },
- },
- },
- },
- {
- name: "From timelineDeleteInstantly to timelineNeverDelete",
- previousDurationDays: timelineDeleteInstantly,
- newDurationDays: timelineNeverDelete,
- expectedFindCompleted: false,
- signatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "",
- FileURLExpiry: testStartTime.AddDate(0, 0, -5),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "", Filename: "abc.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, -5)},
- },
- },
- },
- },
- {
- name: "From timelineDeleteInstantly to timeline value",
- previousDurationDays: timelineDeleteInstantly,
- newDurationDays: 5,
- expectedFindCompleted: false,
- },
- {
- name: "From timeline value to another timeline value",
- previousDurationDays: 5,
- newDurationDays: 10,
- expectedFindCompleted: false,
- },
- {
- name: "From a higher timeline value to a lower timeline value",
- previousDurationDays: 10,
- newDurationDays: 5,
- expectedFindCompleted: true,
- signatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "https://da.certifaction.com/abc.pdf",
- FileURLExpiry: testStartTime.AddDate(0, 0, 7),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/abc.pdf", Filename: "abc.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, 7)},
- },
- },
- },
- expectedSignatureRequests: []model.SignatureRequest{
- {
- ID: "abc",
- FileURL: "https://da.certifaction.com/abc.pdf",
- FileURLExpiry: testStartTime.AddDate(0, 0, 5),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/abc.pdf", Filename: "abc.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, 5)},
- },
- },
- },
- },
- {
- name: "From a timeline value to timelineNeverDelete",
- previousDurationDays: 5,
- newDurationDays: timelineNeverDelete,
- expectedFindCompleted: true,
- signatureRequests: []model.SignatureRequest{
- {
- ID: "def",
- FileURL: "https://da.certifaction.com/def.pdf",
- FileURLExpiry: testStartTime.AddDate(0, 0, 6),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/def.pdf", Filename: "def.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, 6)},
- },
- },
- },
- expectedSignatureRequests: []model.SignatureRequest{
- {
- ID: "def",
- FileURL: "https://da.certifaction.com/def.pdf",
- FileURLExpiry: neverExpireTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/def.pdf", Filename: "def.pdf", FileURLExpiry: neverExpireTime},
- },
- },
- },
- },
- {
- name: "From a timeline value to timelineDeleteInstantly",
- previousDurationDays: 5,
- newDurationDays: timelineDeleteInstantly,
- expectedFindCompleted: true,
- signatureRequests: []model.SignatureRequest{
- {
- ID: "def",
- FileURL: "https://da.certifaction.com/def.pdf",
- FileURLExpiry: testStartTime.AddDate(0, 0, 6),
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "https://da.certifaction.com/def.pdf", Filename: "def.pdf", FileURLExpiry: testStartTime.AddDate(0, 0, 6)},
- },
- },
- },
- expectedSignatureRequests: []model.SignatureRequest{
- {
- ID: "def",
- FileURL: "",
- FileURLExpiry: testStartTime,
- EnvelopeItems: []model.EnvelopeItem{
- {FileURL: "", Filename: "def.pdf", FileURLExpiry: testStartTime},
- },
- },
- },
- },
+var (
+ observer *organizationDeletionTimelineObserver
+ signaturesRepo signatureRepository.Repository
+ txContext context.Context
+ user1 = model.User{UID: "uid-2000"}
+ user2 = model.User{UID: "uid-2001"}
+)
+
+func setupTestSuite(t *testing.T) func(t *testing.T) {
+ config, err := configuration.NewConfiguration(nil)
+ assert.NoError(t, err)
+
+ db, err := connection.NewMySQLDBConnection(config.DbUsername, config.DbPassword, config.DbUrl, config.DbName)
+ assert.NoError(t, err)
+
+ txContext, err = db.BeginTransaction(context.Background(), sql.LevelSerializable) // Start a new transaction
+ assert.NoError(t, err)
+
+ identityStore := identitydb.NewDbIdentityStore(db)
+ userRepository := user.NewSQLUserRepository(db, identityStore)
+ signaturesRepo = signatureRepository.NewDefaultRepository(db, userRepository, nil)
+
+ insertTestDataQuery := `
+INSERT INTO users (id, uid, email, name, verified, address, hash, randomhash, secret_auth_token)
+VALUES
+ (1005, 'uid-2000', 'integration-test-cleanup@certifaction.com', 'Integration Test', '1', '', '', '', ''),
+ (1006, 'uid-2001', 'integration-test-cleanup@certifaction.com', 'Integration Test', '1', '', '', '', '');
+
+INSERT INTO organizations (id, name) VALUES ('org-001', 'Test Org');
+
+INSERT INTO organizations_users (user_uid, organization_id, role, status, invite_email, verification_hash, role_id_after_invite)
+VALUES ('uid-2000', 'org-001', 'user', 'joined', null, null, DEFAULT);
+
+INSERT INTO roles (id, organization_id, name, admin, default_role)
+VALUES ('entity-001', 'org-001', 'Admin', 1, 0);
+
+INSERT INTO users_roles (user_uid,role_id) VALUES ('uid-2000', 'entity-001');
+`
+ _, err = db.Exec(txContext, insertTestDataQuery)
+ assert.NoError(t, err)
+
+ err = signaturesRepo.Create(txContext, &model.SignatureRequest{
+ EnvelopeItems: []model.EnvelopeItem{{
+ FileID: "111",
+ FileURLExpiry: time.Now().Add(5 * time.Second),
+ FileURL: "https://...",
+ Filename: "fileName111",
+ LegalWeight: model.StandardLevel,
+ }},
+ FileID: "111",
+ FileURLExpiry: time.Now().Add(5 * time.Second),
+ FileURL: "https://...",
+ Filename: "fileName111",
+ Signer: &user1,
+ Requester: &user1,
+ Signed: true,
+ })
+ assert.NoError(t, err)
+
+ err = signaturesRepo.Create(txContext, &model.SignatureRequest{
+ EnvelopeItems: []model.EnvelopeItem{{
+ FileID: "112",
+ FileURLExpiry: time.Now().Add((24 * 15) * time.Hour),
+ FileURL: "https://...",
+ Filename: "fileName112",
+ LegalWeight: model.StandardLevel,
+ }},
+ FileID: "112",
+ FileURLExpiry: time.Now().Add((24 * 15) * time.Hour),
+ FileURL: "https://...",
+ Filename: "fileName112",
+ Signer: &user1,
+ Requester: &user1,
+ Signed: true,
+ })
+ assert.NoError(t, err)
+
+ observer = NewOrganizationDeletionTimelineObserver(db, signaturesRepo, true)
+
+ return func(t *testing.T) {
+ txContext = db.Rollback(txContext)
}
+}
+
+func TestOrganizationDeletionTimelineObserver_Notify(t *testing.T) {
+ teardown := setupTestSuite(t)
+ t.Cleanup(func() {
+ teardown(t)
+ })
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- fakeTransactionManager := new(repositoryfakes2.FakeDBTransactionManager)
- fakeSignatureRepository := new(repositoryfakes.FakeRepository)
- fakeSignatureRepository.FindCompletedForOrganizationStub = func(ctx context.Context, entityID string) ([]model.SignatureRequest, error) {
- return tc.signatureRequests, nil
+ t.Run("No changes are made if deletion timeline is set to never delete", func(t *testing.T) {
+ setting := model.EntitySetting{
+ EntityID: "entity-001",
+ Setting: model.Setting{
+ ID: model.SettingDeletionTimeline,
+ },
+ Value: "-1",
+ }
+
+ err := observer.Notify(txContext, observable.ObserverEvent{Type: model.NotificationEventTypeDeletionTimelineChange, Content: setting})
+
+ assert.NoError(t, err)
+
+ signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"111", "112", "113"}, true)
+ require.NoError(t, err)
+ assert.Len(t, signatureRequests, 2)
+
+ var cleared []model.SignatureRequest
+ for _, signatureRequest := range signatureRequests {
+ if signatureRequest.FileURL == "" {
+ cleared = append(cleared, signatureRequest)
}
+ }
+
+ assert.Len(t, cleared, 0)
+
+ })
- obs := NewOrganizationDeletionTimelineObserver(fakeTransactionManager, fakeSignatureRepository)
- obs.setNowTime(func() time.Time {
- return testStartTime
- })
+ t.Run("Files with expiry after the new deletion timeline are delete", func(t *testing.T) {
- err := obs.updateAsNeeded(context.Background(), durationChange{
- tc.previousDurationDays,
- tc.newDurationDays},
- "someEntityID")
+ setting := model.EntitySetting{
+ EntityID: "entity-001",
+ Setting: model.Setting{
+ ID: model.SettingDeletionTimeline,
+ },
+ Value: "13",
+ }
+
+ err := observer.Notify(txContext, observable.ObserverEvent{Type: model.NotificationEventTypeDeletionTimelineChange, Content: setting})
- assert.Nil(t, err)
+ assert.NoError(t, err)
- require.Equal(t, len(tc.expectedSignatureRequests), fakeSignatureRepository.UpdateCallCount())
- var updatedSignatureRequests []model.SignatureRequest
- for i := 0; i < len(tc.expectedSignatureRequests); i++ {
- _, sr := fakeSignatureRepository.UpdateArgsForCall(i)
- updatedSignatureRequests = append(updatedSignatureRequests, *sr)
+ signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"111", "112", "113"}, true)
+ require.NoError(t, err)
+ assert.Len(t, signatureRequests, 2)
+
+ var cleared []model.SignatureRequest
+ for _, signatureRequest := range signatureRequests {
+ if signatureRequest.FileURL == "" {
+ cleared = append(cleared, signatureRequest)
}
+ }
+
+ assert.Len(t, cleared, 1)
+ clearedRequest := cleared[0]
+ assert.Equal(t, "112", clearedRequest.FileID)
+ assert.Equal(t, "", clearedRequest.FileURL)
+
+ envelopItem := clearedRequest.EnvelopeItems[0]
+ assert.NotEmpty(t, envelopItem.Filename)
+ assert.Equal(t, "", envelopItem.FileURL)
+ })
+
+ t.Run("Files with expiry before the new deletion timeline don't change", func(t *testing.T) {
+
+ setting := model.EntitySetting{
+ EntityID: "entity-001",
+ Setting: model.Setting{
+ ID: model.SettingDeletionTimeline,
+ },
+ Value: "9",
+ }
+
+ err := observer.Notify(txContext, observable.ObserverEvent{Type: model.NotificationEventTypeDeletionTimelineChange, Content: setting})
+
+ assert.NoError(t, err)
+
+ signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"111"}, true)
+ require.NoError(t, err)
+ request := signatureRequests[0]
+ assert.Equal(t, "111", request.FileID)
+ assert.Equal(t, "https://...", request.FileURL)
+ assert.Equal(t, "fileName111", request.Filename)
- require.Empty(t, cmp.Diff(tc.expectedSignatureRequests, updatedSignatureRequests),
- cmpopts.EquateApproxTime(100*time.Millisecond))
+ envelopItem := request.EnvelopeItems[0]
+ assert.Equal(t, "fileName111", envelopItem.Filename)
+ assert.Equal(t, "https://...", envelopItem.FileURL)
+ })
+
+ t.Run("Files set to an newer expiry date are updated to the new deletion date", func(t *testing.T) {
+ err := signaturesRepo.Create(txContext, &model.SignatureRequest{
+ EnvelopeItems: []model.EnvelopeItem{{
+ FileID: "113",
+ FileURLExpiry: neverExpireTime,
+ Filename: "fileName113",
+ FileURL: "https://...",
+ LegalWeight: model.StandardLevel,
+ }},
+ FileID: "113",
+ FileURLExpiry: neverExpireTime,
+ Filename: "fileName113",
+ FileURL: "https://...",
+ Signer: &user1,
+ Requester: &user1,
+ Signed: true,
})
- }
+ assert.NoError(t, err)
+
+ err = signaturesRepo.Create(txContext, &model.SignatureRequest{
+ EnvelopeItems: []model.EnvelopeItem{{
+ FileID: "113",
+ FileURLExpiry: neverExpireTime,
+ FileURL: "https://...",
+ Filename: "fileName113",
+ LegalWeight: model.StandardLevel,
+ }},
+ FileID: "113",
+ FileURLExpiry: neverExpireTime,
+ FileURL: "https://...",
+ Filename: "fileName113",
+ Signer: &user2,
+ Requester: &user1,
+ Signed: true,
+ })
+
+ assert.NoError(t, err)
+ expiryTimeline := 5
+ setting := model.EntitySetting{
+ EntityID: "entity-001",
+ Setting: model.Setting{
+ ID: model.SettingDeletionTimeline,
+ },
+ Value: fmt.Sprintf("%d", expiryTimeline),
+ }
+
+ err = observer.Notify(txContext, observable.ObserverEvent{Type: model.NotificationEventTypeDeletionTimelineChange, Content: setting})
+
+ assert.NoError(t, err)
+ signatureRequests, err := signaturesRepo.FindByFileID(txContext, []string{"113"}, true)
+ require.NoError(t, err)
+
+ signatureRequest := signatureRequests[0]
+ changeTimeline := signatureRequest.FileURLExpiry.Sub(time.Now()).Hours()
+ changeTimelineDays := int(math.Round(changeTimeline / 24))
+ assert.Equal(t, changeTimelineDays, expiryTimeline)
+
+ envelopItem := signatureRequest.EnvelopeItems[0]
+ envelopItemTimeChange := envelopItem.FileURLExpiry.Sub(time.Now()).Hours()
+ envelopItemChangeInDays := int(math.Round(envelopItemTimeChange / 24))
+ assert.Equal(t, envelopItemChangeInDays, expiryTimeline)
+ })
}
diff --git a/signature_requests/repository/repository.go b/signature_requests/repository/repository.go
index 3aa8dd5c..65f28d52 100644
--- a/signature_requests/repository/repository.go
+++ b/signature_requests/repository/repository.go
@@ -35,6 +35,35 @@ type defaultRepository struct {
userRepoFindByUIDCache cache.Cache
}
+func (me *defaultRepository) FindByDocumentIDAndSignerUID(ctx context.Context, documentID string, signerUID string) (*model.SignatureRequest, error) {
+ log.DebugCtx(ctx, "Attempt to retrieve signature request found for documentID %s and signerUID %s", documentID, signerUID)
+ sqlQuery := fmt.Sprintf(
+ `%s JOIN files f on s.file_id = f.id WHERE f.document_id = ? and s.signer_uid = ?`,
+ me.selectSQLAsString(),
+ )
+
+ rows, err := me.db.Query(ctx, sqlQuery, documentID, signerUID)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return nil, nil
+ }
+
+ return nil, err
+ }
+
+ signature, err := me.singleRowToSignatureRequest(ctx, rows)
+ if err == sql.ErrNoRows {
+ log.DebugfCtx(ctx, "No signature request found for documentID %s and signerUID %s", documentID, signerUID)
+
+ } else if err != nil {
+ log.ErrorCtx(ctx, "Scanning row to SignatureRequest", err)
+ return nil, err
+ }
+
+ log.DebugCtx(ctx, "Successfully retrieved signature request found for documentID %s and signerUID %s", documentID, signerUID)
+ return signature, nil
+}
+
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Repository
type Repository interface {
Create(ctx context.Context, signature *model.SignatureRequest) error
@@ -59,7 +88,7 @@ type Repository interface {
DeleteTokens(ctx context.Context, id string) error
FindByRequestorCreatedBeforeNotAnonymizedForUpdate(ctx context.Context, orgID string, createdBefore time.Time, limit int) ([]model.SignatureRequest, error)
FindByDocumentIDAndSignerUID(ctx context.Context, documentID string, signerUID string) (*model.SignatureRequest, error)
- FindCompletedForOrganization(ctx context.Context, entityID string) ([]model.SignatureRequest, error)
+ FindActiveOrganizationSignatures(ctx context.Context, entityID string) ([]model.SignatureRequest, error)
}
var _ Repository = &defaultRepository{}
@@ -752,7 +781,7 @@ func (me *defaultRepository) FindByHashedSignerToken(ctx context.Context, hashed
return &signatureRequests[0], err
}
-func (me *defaultRepository) UpdateEnvelopeItems(ctx context.Context, envelopeItems []model.EnvelopeItem) error {
+func (me *defaultRepository) UpdateEnvelopItems(ctx context.Context, envelopeItems []model.EnvelopeItem) error {
log.InfoCtx(ctx, "Updating Envelop Items")
for _, item := range envelopeItems {
@@ -804,7 +833,7 @@ func (me *defaultRepository) Update(ctx context.Context, signature *model.Signat
return err
}
- err = me.UpdateEnvelopeItems(ctx, signature.EnvelopeItems)
+ err = me.UpdateEnvelopItems(ctx, signature.EnvelopeItems)
if err != nil {
log.ErrorCtx(ctx, "Failed to update envelop Items")
me.db.Rollback(ctx)
@@ -957,36 +986,7 @@ func (me *defaultRepository) FindExpiredBefore(ctx context.Context, t time.Time)
return signatureRequests, err
}
-func (me *defaultRepository) FindByDocumentIDAndSignerUID(ctx context.Context, documentID string, signerUID string) (*model.SignatureRequest, error) {
- log.DebugCtx(ctx, "Attempt to retrieve signature request found for documentID %s and signerUID %s", documentID, signerUID)
- sqlQuery := fmt.Sprintf(
- `%s JOIN files f on s.file_id = f.id WHERE f.document_id = ? and s.signer_uid = ?`,
- me.selectSQLAsString(),
- )
-
- rows, err := me.db.Query(ctx, sqlQuery, documentID, signerUID)
- if err != nil {
- if err == sql.ErrNoRows {
- return nil, nil
- }
-
- return nil, err
- }
-
- signature, err := me.singleRowToSignatureRequest(ctx, rows)
- if err == sql.ErrNoRows {
- log.DebugfCtx(ctx, "No signature request found for documentID %s and signerUID %s", documentID, signerUID)
-
- } else if err != nil {
- log.ErrorCtx(ctx, "Scanning row to SignatureRequest", err)
- return nil, err
- }
-
- log.DebugCtx(ctx, "Successfully retrieved signature request found for documentID %s and signerUID %s", documentID, signerUID)
- return signature, nil
-}
-
-func (me *defaultRepository) FindCompletedForOrganization(ctx context.Context, entityID string) ([]model.SignatureRequest, error) {
+func (me *defaultRepository) FindActiveOrganizationSignatures(ctx context.Context, entityID string) ([]model.SignatureRequest, error) {
sqlQuery := me.selectSQLAsString() + `
WHERE file_id IN(
SELECT file_id FROM signature_requests WHERE file_url <> '' AND cancelled = 0 AND
diff --git a/signature_requests/repository/repositoryfakes/fake_repository.go b/signature_requests/repository/repositoryfakes/fake_repository.go
index a4ec569c..5cb82a14 100644
--- a/signature_requests/repository/repositoryfakes/fake_repository.go
+++ b/signature_requests/repository/repositoryfakes/fake_repository.go
@@ -86,6 +86,20 @@ type FakeRepository struct {
deleteTokensReturnsOnCall map[int]struct {
result1 error
}
+ FindActiveOrganizationSignaturesStub func(context.Context, string) ([]model.SignatureRequest, error)
+ findActiveOrganizationSignaturesMutex sync.RWMutex
+ findActiveOrganizationSignaturesArgsForCall []struct {
+ arg1 context.Context
+ arg2 string
+ }
+ findActiveOrganizationSignaturesReturns struct {
+ result1 []model.SignatureRequest
+ result2 error
+ }
+ findActiveOrganizationSignaturesReturnsOnCall map[int]struct {
+ result1 []model.SignatureRequest
+ result2 error
+ }
FindAllForSignerStub func(context.Context, string) ([]model.SignatureRequest, error)
findAllForSignerMutex sync.RWMutex
findAllForSignerArgsForCall []struct {
@@ -264,20 +278,6 @@ type FakeRepository struct {
result1 []model.SignatureRequest
result2 error
}
- FindCompletedForOrganizationStub func(context.Context, string) ([]model.SignatureRequest, error)
- findCompletedForOrganizationMutex sync.RWMutex
- findCompletedForOrganizationArgsForCall []struct {
- arg1 context.Context
- arg2 string
- }
- findCompletedForOrganizationReturns struct {
- result1 []model.SignatureRequest
- result2 error
- }
- findCompletedForOrganizationReturnsOnCall map[int]struct {
- result1 []model.SignatureRequest
- result2 error
- }
FindExpiredBeforeStub func(context.Context, time.Time) ([]model.SignatureRequest, error)
findExpiredBeforeMutex sync.RWMutex
findExpiredBeforeArgsForCall []struct {
@@ -712,6 +712,71 @@ func (fake *FakeRepository) DeleteTokensReturnsOnCall(i int, result1 error) {
}{result1}
}
+func (fake *FakeRepository) FindActiveOrganizationSignatures(arg1 context.Context, arg2 string) ([]model.SignatureRequest, error) {
+ fake.findActiveOrganizationSignaturesMutex.Lock()
+ ret, specificReturn := fake.findActiveOrganizationSignaturesReturnsOnCall[len(fake.findActiveOrganizationSignaturesArgsForCall)]
+ fake.findActiveOrganizationSignaturesArgsForCall = append(fake.findActiveOrganizationSignaturesArgsForCall, struct {
+ arg1 context.Context
+ arg2 string
+ }{arg1, arg2})
+ stub := fake.FindActiveOrganizationSignaturesStub
+ fakeReturns := fake.findActiveOrganizationSignaturesReturns
+ fake.recordInvocation("FindActiveOrganizationSignatures", []interface{}{arg1, arg2})
+ fake.findActiveOrganizationSignaturesMutex.Unlock()
+ if stub != nil {
+ return stub(arg1, arg2)
+ }
+ if specificReturn {
+ return ret.result1, ret.result2
+ }
+ return fakeReturns.result1, fakeReturns.result2
+}
+
+func (fake *FakeRepository) FindActiveOrganizationSignaturesCallCount() int {
+ fake.findActiveOrganizationSignaturesMutex.RLock()
+ defer fake.findActiveOrganizationSignaturesMutex.RUnlock()
+ return len(fake.findActiveOrganizationSignaturesArgsForCall)
+}
+
+func (fake *FakeRepository) FindActiveOrganizationSignaturesCalls(stub func(context.Context, string) ([]model.SignatureRequest, error)) {
+ fake.findActiveOrganizationSignaturesMutex.Lock()
+ defer fake.findActiveOrganizationSignaturesMutex.Unlock()
+ fake.FindActiveOrganizationSignaturesStub = stub
+}
+
+func (fake *FakeRepository) FindActiveOrganizationSignaturesArgsForCall(i int) (context.Context, string) {
+ fake.findActiveOrganizationSignaturesMutex.RLock()
+ defer fake.findActiveOrganizationSignaturesMutex.RUnlock()
+ argsForCall := fake.findActiveOrganizationSignaturesArgsForCall[i]
+ return argsForCall.arg1, argsForCall.arg2
+}
+
+func (fake *FakeRepository) FindActiveOrganizationSignaturesReturns(result1 []model.SignatureRequest, result2 error) {
+ fake.findActiveOrganizationSignaturesMutex.Lock()
+ defer fake.findActiveOrganizationSignaturesMutex.Unlock()
+ fake.FindActiveOrganizationSignaturesStub = nil
+ fake.findActiveOrganizationSignaturesReturns = struct {
+ result1 []model.SignatureRequest
+ result2 error
+ }{result1, result2}
+}
+
+func (fake *FakeRepository) FindActiveOrganizationSignaturesReturnsOnCall(i int, result1 []model.SignatureRequest, result2 error) {
+ fake.findActiveOrganizationSignaturesMutex.Lock()
+ defer fake.findActiveOrganizationSignaturesMutex.Unlock()
+ fake.FindActiveOrganizationSignaturesStub = nil
+ if fake.findActiveOrganizationSignaturesReturnsOnCall == nil {
+ fake.findActiveOrganizationSignaturesReturnsOnCall = make(map[int]struct {
+ result1 []model.SignatureRequest
+ result2 error
+ })
+ }
+ fake.findActiveOrganizationSignaturesReturnsOnCall[i] = struct {
+ result1 []model.SignatureRequest
+ result2 error
+ }{result1, result2}
+}
+
func (fake *FakeRepository) FindAllForSigner(arg1 context.Context, arg2 string) ([]model.SignatureRequest, error) {
fake.findAllForSignerMutex.Lock()
ret, specificReturn := fake.findAllForSignerReturnsOnCall[len(fake.findAllForSignerArgsForCall)]
@@ -1512,71 +1577,6 @@ func (fake *FakeRepository) FindBySignerWithNameOrEmailLikeReturnsOnCall(i int,
}{result1, result2}
}
-func (fake *FakeRepository) FindCompletedForOrganization(arg1 context.Context, arg2 string) ([]model.SignatureRequest, error) {
- fake.findCompletedForOrganizationMutex.Lock()
- ret, specificReturn := fake.findCompletedForOrganizationReturnsOnCall[len(fake.findCompletedForOrganizationArgsForCall)]
- fake.findCompletedForOrganizationArgsForCall = append(fake.findCompletedForOrganizationArgsForCall, struct {
- arg1 context.Context
- arg2 string
- }{arg1, arg2})
- stub := fake.FindCompletedForOrganizationStub
- fakeReturns := fake.findCompletedForOrganizationReturns
- fake.recordInvocation("FindCompletedForOrganization", []interface{}{arg1, arg2})
- fake.findCompletedForOrganizationMutex.Unlock()
- if stub != nil {
- return stub(arg1, arg2)
- }
- if specificReturn {
- return ret.result1, ret.result2
- }
- return fakeReturns.result1, fakeReturns.result2
-}
-
-func (fake *FakeRepository) FindCompletedForOrganizationCallCount() int {
- fake.findCompletedForOrganizationMutex.RLock()
- defer fake.findCompletedForOrganizationMutex.RUnlock()
- return len(fake.findCompletedForOrganizationArgsForCall)
-}
-
-func (fake *FakeRepository) FindCompletedForOrganizationCalls(stub func(context.Context, string) ([]model.SignatureRequest, error)) {
- fake.findCompletedForOrganizationMutex.Lock()
- defer fake.findCompletedForOrganizationMutex.Unlock()
- fake.FindCompletedForOrganizationStub = stub
-}
-
-func (fake *FakeRepository) FindCompletedForOrganizationArgsForCall(i int) (context.Context, string) {
- fake.findCompletedForOrganizationMutex.RLock()
- defer fake.findCompletedForOrganizationMutex.RUnlock()
- argsForCall := fake.findCompletedForOrganizationArgsForCall[i]
- return argsForCall.arg1, argsForCall.arg2
-}
-
-func (fake *FakeRepository) FindCompletedForOrganizationReturns(result1 []model.SignatureRequest, result2 error) {
- fake.findCompletedForOrganizationMutex.Lock()
- defer fake.findCompletedForOrganizationMutex.Unlock()
- fake.FindCompletedForOrganizationStub = nil
- fake.findCompletedForOrganizationReturns = struct {
- result1 []model.SignatureRequest
- result2 error
- }{result1, result2}
-}
-
-func (fake *FakeRepository) FindCompletedForOrganizationReturnsOnCall(i int, result1 []model.SignatureRequest, result2 error) {
- fake.findCompletedForOrganizationMutex.Lock()
- defer fake.findCompletedForOrganizationMutex.Unlock()
- fake.FindCompletedForOrganizationStub = nil
- if fake.findCompletedForOrganizationReturnsOnCall == nil {
- fake.findCompletedForOrganizationReturnsOnCall = make(map[int]struct {
- result1 []model.SignatureRequest
- result2 error
- })
- }
- fake.findCompletedForOrganizationReturnsOnCall[i] = struct {
- result1 []model.SignatureRequest
- result2 error
- }{result1, result2}
-}
-
func (fake *FakeRepository) FindExpiredBefore(arg1 context.Context, arg2 time.Time) ([]model.SignatureRequest, error) {
fake.findExpiredBeforeMutex.Lock()
ret, specificReturn := fake.findExpiredBeforeReturnsOnCall[len(fake.findExpiredBeforeArgsForCall)]
@@ -1850,6 +1850,8 @@ func (fake *FakeRepository) Invocations() map[string][][]interface{} {
defer fake.deleteByIDMutex.RUnlock()
fake.deleteTokensMutex.RLock()
defer fake.deleteTokensMutex.RUnlock()
+ fake.findActiveOrganizationSignaturesMutex.RLock()
+ defer fake.findActiveOrganizationSignaturesMutex.RUnlock()
fake.findAllForSignerMutex.RLock()
defer fake.findAllForSignerMutex.RUnlock()
fake.findByDocumentIDAndSignerUIDMutex.RLock()
@@ -1874,8 +1876,6 @@ func (fake *FakeRepository) Invocations() map[string][][]interface{} {
defer fake.findBySignerUIDMutex.RUnlock()
fake.findBySignerWithNameOrEmailLikeMutex.RLock()
defer fake.findBySignerWithNameOrEmailLikeMutex.RUnlock()
- fake.findCompletedForOrganizationMutex.RLock()
- defer fake.findCompletedForOrganizationMutex.RUnlock()
fake.findExpiredBeforeMutex.RLock()
defer fake.findExpiredBeforeMutex.RUnlock()
fake.findExpiredByFileIdMutex.RLock()
diff --git a/signature_requests/service.go b/signature_requests/service.go
index cb12885c..954ccaa5 100644
--- a/signature_requests/service.go
+++ b/signature_requests/service.go
@@ -74,66 +74,6 @@ type defaultService struct {
var _ Service = &defaultService{}
-var EventTypeDeleteSignature model.EventType = "delete_signature_request"
-var EventTypeSignatureRequestCreated model.EventType = "signature_request_created"
-
-type SignatureRequestCreated = struct {
- Request model.SignatureRequest
- Token string
-}
-
-func NewDefaultService(
- config *configuration.Configuration,
- repository repository.Repository,
- signingProcessWriteRepo signingprocess.Repository,
- transactionManager dbrepository.DBTransactionManager,
- mailService mail.MailService,
- identityService identity.IdentityService,
- userService user.UserService,
- featureService feature.FeatureService,
- fileService file.FileService,
- organizationService organization.Service,
- balanceService balance.BalanceService,
- templateService template.TemplateService,
- claimMetadataService claim.ClaimMetadataService,
- signatureService signatures.Service,
- notificationService notification.NotificationService,
- storageService storage.Service,
- settingService setting.SettingService) *defaultService {
-
- return &defaultService{
- config: config,
- repository: repository,
- signingProcessRepo: signingProcessWriteRepo,
- transactionManager: transactionManager,
- mailService: mailService,
- userService: userService,
- identityService: identityService,
- featureService: featureService,
- fileService: fileService,
- organizationService: organizationService,
- balanceService: balanceService,
- templateService: templateService,
- claimMetadataService: claimMetadataService,
- fileExpiryInDays: config.FileURLExpiryInDays,
- anonymizeOlderThanInDays: config.SRAnonymizationOlderThanInDays,
- anonymizationBatchCountLimit: config.SRAnonymizationBatchCountLimit,
- anonymizationBatchSize: config.SRAnonymizationBatchSize,
- signatureService: signatureService,
- notificationService: notificationService,
- storageService: storageService,
- settingService: settingService,
- }
-}
-
-type SignaturesRequestResult struct {
- Err error
- SignerToken string
- CreditTransactionId string //contains the signatureRequest.ID
- Prepaid bool
- SendEmail bool // is true if sendEmail is true and if this user is next to sign (depending on signOrder)
-}
-
func (me *defaultService) DocumentUploaded(ctx context.Context, event callback.Event) error {
signatureRequest, err := me.repository.FindByDocumentIDAndSignerUID(ctx, event.DocumentID, event.Author)
if err != nil {
@@ -261,6 +201,68 @@ func (me *defaultService) anonymizeSignatureRequest(ctx context.Context, request
return nil
}
+var _ Service = &defaultService{}
+
+var EventTypeDeleteSignature model.EventType = "delete_signature_request"
+var EventTypeSignatureRequestCreated model.EventType = "signature_request_created"
+
+type SignatureRequestCreated = struct {
+ Request model.SignatureRequest
+ Token string
+}
+
+func NewDefaultService(
+ config *configuration.Configuration,
+ repository repository.Repository,
+ signingProcessWriteRepo signingprocess.Repository,
+ transactionManager dbrepository.DBTransactionManager,
+ mailService mail.MailService,
+ identityService identity.IdentityService,
+ userService user.UserService,
+ featureService feature.FeatureService,
+ fileService file.FileService,
+ organizationService organization.Service,
+ balanceService balance.BalanceService,
+ templateService template.TemplateService,
+ claimMetadataService claim.ClaimMetadataService,
+ signatureService signatures.Service,
+ notificationService notification.NotificationService,
+ storageService storage.Service,
+ settingService setting.SettingService) *defaultService {
+
+ return &defaultService{
+ config: config,
+ repository: repository,
+ signingProcessRepo: signingProcessWriteRepo,
+ transactionManager: transactionManager,
+ mailService: mailService,
+ userService: userService,
+ identityService: identityService,
+ featureService: featureService,
+ fileService: fileService,
+ organizationService: organizationService,
+ balanceService: balanceService,
+ templateService: templateService,
+ claimMetadataService: claimMetadataService,
+ fileExpiryInDays: config.FileURLExpiryInDays,
+ anonymizeOlderThanInDays: config.SRAnonymizationOlderThanInDays,
+ anonymizationBatchCountLimit: config.SRAnonymizationBatchCountLimit,
+ anonymizationBatchSize: config.SRAnonymizationBatchSize,
+ signatureService: signatureService,
+ notificationService: notificationService,
+ storageService: storageService,
+ settingService: settingService,
+ }
+}
+
+type SignaturesRequestResult struct {
+ Err error
+ SignerToken string
+ CreditTransactionId string //contains the signatureRequest.ID
+ Prepaid bool
+ SendEmail bool // is true if sendEmail is true and if this user is next to sign (depending on signOrder)
+}
+
func (me *defaultService) GetByID(ctx context.Context, id string) (*model.SignatureRequest, error) {
return me.repository.FindByID(ctx, id)
}
@@ -1702,9 +1704,6 @@ func (me *defaultService) ClearExpired(ctx context.Context) error {
for _, expiredSignatureRequest := range expiredSignatureRequests {
expiredSignatureRequest.FileURL = ""
- for i := range expiredSignatureRequest.GetEnvelopeItems() {
- expiredSignatureRequest.EnvelopeItems[i].FileURL = ""
- }
err = me.repository.Update(ctx, &expiredSignatureRequest)
if err != nil {
log.ErrorfCtx(ctx, "Update signature request file url: %s", err)
@@ -2114,7 +2113,7 @@ func (me *defaultService) sendNextEmailsIfNeeded(ctx context.Context, signatureR
return nil
}
-func (me *defaultService) minSignOrder(signaturesRequest model.SignaturesRequest) int {
+func (me defaultService) minSignOrder(signaturesRequest model.SignaturesRequest) int {
minSignOrder := math.MaxInt
for _, signer := range signaturesRequest.Signers {
if signer.SignOrder < minSignOrder {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment