Skip to content

Commit

Permalink
Started work on detailed batch deletion tests
Browse files Browse the repository at this point in the history
  • Loading branch information
diamondap committed Jan 23, 2024
1 parent 047fabd commit e0c891d
Showing 1 changed file with 142 additions and 61 deletions.
203 changes: 142 additions & 61 deletions web/api/admin/intellectual_objects_batch_delete_test.go
Original file line number Diff line number Diff line change
@@ -1,92 +1,87 @@
package admin_api_test

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strconv"
"testing"

"github.com/APTrust/registry/common"
"github.com/APTrust/registry/constants"
"github.com/APTrust/registry/db"
"github.com/APTrust/registry/pgmodels"
admin_api "github.com/APTrust/registry/web/api/admin"
tu "github.com/APTrust/registry/web/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestObjectBatchDelete(t *testing.T) {

os.Setenv("APT_ENV", "test")
//os.Setenv("APT_ENV", "test")

err := db.ForceFixtureReload()
require.Nil(t, err)
tu.InitHTTPTests(t)

idsThatCanBeDeleted := []int64{5, 6, 12, 13}
idAlreadyDeleted := int64(14)
idWithPendingWorkItems := int64(4)
idBelongingToOtherInst := int64(1)

// validParams := url.Values{}
// validParams.Set("institutionID", strconv.FormatInt(tu.Inst2Admin.InstitutionID, 10))
// validParams.Set("requestorID", strconv.FormatInt(tu.Inst2Admin.ID, 10))
// for _, id := range idsThatCanBeDeleted {
// validParams.Add("objectID", strconv.FormatInt(id, 10))
// }
// idAlreadyDeleted := int64(14)
// idWithPendingWorkItems := int64(4)
// idBelongingToOtherInst := int64(1)

// These params are valid and will create a bulk deletion request
// if submitted by APTrust admin user.
validParams := admin_api.ObjectBatchDeleteParams{
InstitutionID: tu.Inst2Admin.InstitutionID,
RequestorID: tu.Inst2Admin.ID,
ObjectIDs: idsThatCanBeDeleted,
SecretKey: common.Context().Config.BatchDeletionKey,
}

// Inst admin can request batch deletion, but inst user cannot.
paramsBadRequestorRole := url.Values{}
paramsBadRequestorRole.Set("institutionID", strconv.FormatInt(tu.Inst2User.InstitutionID, 10))
paramsBadRequestorRole.Set("requestorID", strconv.FormatInt(tu.Inst2User.ID, 10))
for _, id := range idsThatCanBeDeleted {
paramsBadRequestorRole.Add("objectID", strconv.FormatInt(id, 10))
}
// // Inst admin can request batch deletion, but inst user cannot.
// paramsBadRequestorRole := admin_api.ObjectBatchDeleteParams{
// InstitutionID: tu.Inst2User.InstitutionID,
// RequestorID: tu.Inst2User.ID,
// ObjectIDs: idsThatCanBeDeleted,
// SecretKey: common.Context().Config.BatchDeletionKey,
// }

// This inst admin is at the wrong institution
paramsBadRequestorInst := url.Values{}
paramsBadRequestorInst.Set("institutionID", strconv.FormatInt(tu.Inst1Admin.InstitutionID, 10))
paramsBadRequestorInst.Set("requestorID", strconv.FormatInt(tu.Inst1Admin.ID, 10))
for _, id := range idsThatCanBeDeleted {
paramsBadRequestorInst.Add("objectID", strconv.FormatInt(id, 10))
}
// // This inst admin is at the wrong institution
// paramsBadRequestorInst := admin_api.ObjectBatchDeleteParams{
// InstitutionID: tu.Inst1Admin.InstitutionID,
// RequestorID: tu.Inst1Admin.ID,
// ObjectIDs: idsThatCanBeDeleted,
// SecretKey: common.Context().Config.BatchDeletionKey,
// }

// This batch contains one id referring to an object that
// has already been deleted.
paramsBadIdAlreadyDeleted := url.Values{}
paramsBadIdAlreadyDeleted.Set("institutionID", strconv.FormatInt(tu.Inst2Admin.InstitutionID, 10))
paramsBadIdAlreadyDeleted.Set("requestorID", strconv.FormatInt(tu.Inst2Admin.ID, 10))
for _, id := range idsThatCanBeDeleted {
paramsBadIdAlreadyDeleted.Add("objectID", strconv.FormatInt(id, 10))
}
paramsBadIdAlreadyDeleted.Add("objectID", strconv.FormatInt(idAlreadyDeleted, 10))

// This batch contains one id that has pending work items.
paramsBadPendingWorkItem := url.Values{}
paramsBadPendingWorkItem.Set("institutionID", strconv.FormatInt(tu.Inst2Admin.InstitutionID, 10))
paramsBadPendingWorkItem.Set("requestorID", strconv.FormatInt(tu.Inst2Admin.ID, 10))
for _, id := range idsThatCanBeDeleted {
paramsBadPendingWorkItem.Add("objectID", strconv.FormatInt(id, 10))
}
paramsBadPendingWorkItem.Add("objectID", strconv.FormatInt(idWithPendingWorkItems, 10))

// This batch contains one object that belongs to another institution.
paramsBadOtherInstItem := url.Values{}
paramsBadOtherInstItem.Set("institutionID", strconv.FormatInt(tu.Inst2Admin.InstitutionID, 10))
paramsBadOtherInstItem.Set("requestorID", strconv.FormatInt(tu.Inst2Admin.ID, 10))
for _, id := range idsThatCanBeDeleted {
paramsBadOtherInstItem.Add("objectID", strconv.FormatInt(id, 10))
}
paramsBadOtherInstItem.Add("objectID", strconv.FormatInt(idBelongingToOtherInst, 10))
// // This batch contains one id referring to an object that
// // has already been deleted.
// paramsBadIdAlreadyDeleted := admin_api.ObjectBatchDeleteParams{
// InstitutionID: tu.Inst2Admin.InstitutionID,
// RequestorID: tu.Inst2Admin.ID,
// ObjectIDs: append(idsThatCanBeDeleted, idAlreadyDeleted),
// SecretKey: common.Context().Config.BatchDeletionKey,
// }

// // This batch contains one id that has pending work items.
// paramsBadPendingWorkItem := admin_api.ObjectBatchDeleteParams{
// InstitutionID: tu.Inst2Admin.InstitutionID,
// RequestorID: tu.Inst2Admin.ID,
// ObjectIDs: append(idsThatCanBeDeleted, idWithPendingWorkItems),
// SecretKey: common.Context().Config.BatchDeletionKey,
// }

// // This batch contains one object that belongs to another institution.
// paramsBadOtherInstItem := admin_api.ObjectBatchDeleteParams{
// InstitutionID: tu.Inst2Admin.InstitutionID,
// RequestorID: tu.Inst2Admin.ID,
// ObjectIDs: append(idsThatCanBeDeleted, idBelongingToOtherInst),
// SecretKey: common.Context().Config.BatchDeletionKey,
// }

testObjectBatchDeletePermissions(t, validParams)
testObjectBatchDeleteCreatesExpectedRecords(t, validParams)

// START HERE

Expand Down Expand Up @@ -121,22 +116,108 @@ func TestObjectBatchDelete(t *testing.T) {

func testObjectBatchDeletePermissions(t *testing.T, params admin_api.ObjectBatchDeleteParams) {

tu.SysAdminClient.POST("/admin-api/v3/objects/init_batch_delete").
WithHeader(constants.APIUserHeader, tu.SysAdmin.Email).
WithHeader(constants.APIKeyHeader, "password").
WithJSON(params).
Expect().Status(http.StatusCreated)

// No institutional admin can create a bulk deletion request. Period.
tu.Inst1AdminClient.POST("/admin-api/v3/objects/init_batch_delete").
WithHeader(constants.APIUserHeader, tu.Inst2Admin.Email).
WithHeader(constants.APIKeyHeader, "password").
WithJSON(params).
Expect().Status(http.StatusForbidden)

// No institutional user can create a bulk deletion request. Period.
tu.Inst1UserClient.POST("/admin-api/v3/objects/init_batch_delete").
WithHeader(constants.APIUserHeader, tu.Inst2User.Email).
WithJSON(params).
WithHeader(constants.APIKeyHeader, "password").
Expect().Status(http.StatusForbidden)

// APTrust SysAdmin can create bulk deletion requests on behalf
// of a local institutional admin.
tu.SysAdminClient.POST("/admin-api/v3/objects/init_batch_delete").
WithHeader(constants.APIUserHeader, tu.SysAdmin.Email).
WithHeader(constants.APIKeyHeader, "password").
WithJSON(params).
Expect().Status(http.StatusCreated)

}

// Run this test with validaParams. All other param sets are invalid
// and will fail.
func testObjectBatchDeleteCreatesExpectedRecords(t *testing.T, params admin_api.ObjectBatchDeleteParams) {
resp := tu.SysAdminClient.POST("/admin-api/v3/objects/init_batch_delete").
WithHeader(constants.APIUserHeader, tu.SysAdmin.Email).
WithHeader(constants.APIKeyHeader, "password").
WithJSON(params).
Expect()

// Make sure we got the expected status.
resp.Status(http.StatusCreated)
respData, err := io.ReadAll(resp.Raw().Body)
resp.Raw().Body.Close()
require.NoError(t, err)

deletionRequest := &pgmodels.DeletionRequest{}
err = json.Unmarshal(respData, deletionRequest)
require.NoError(t, err)

// Make sure the deletion request has the right info.
// We're not testing RequestedByID here because we don't
// serialize that value to JSON. I can't remember why not,
// but I think it's to keep from exposing user IDs. We
// will test RequestedByID below, when we retrieve the
// database record.
assert.Equal(t, params.InstitutionID, deletionRequest.InstitutionID)
assert.Equal(t, len(params.ObjectIDs), len(deletionRequest.IntellectualObjects))
for _, objId := range params.ObjectIDs {
found := false
for _, obj := range deletionRequest.IntellectualObjects {
if obj.ID == objId {
found = true
break
}
}
assert.True(t, found, objId)
}

// Make sure this deletion request was saved to the DB as well.
savedDelRequest, err := pgmodels.DeletionRequestByID(deletionRequest.ID)
require.NoError(t, err)
require.NotNil(t, savedDelRequest)
assert.Equal(t, params.InstitutionID, savedDelRequest.InstitutionID)
assert.Equal(t, params.RequestorID, savedDelRequest.RequestedByID)
assert.Equal(t, len(params.ObjectIDs), len(savedDelRequest.IntellectualObjects))
for _, objId := range params.ObjectIDs {
found := false
for _, obj := range savedDelRequest.IntellectualObjects {
if obj.ID == objId {
found = true
break
}
}
assert.True(t, found, objId)
}

// Because this deletion request has not yet been approved,
// there should be no associated WorkItem. We create the WorkItem
// only after the deletion request has been approved by the
// local institutional admin.
assert.Empty(t, deletionRequest.WorkItemID)

// Make sure the deletion request alert was created in the DB.
query := pgmodels.NewQuery().Where("deletion_request_id", "=", deletionRequest.ID)
alerts, err := pgmodels.AlertSelect(query)
require.NoError(t, err)
assert.Equal(t, 1, len(alerts))
alert := alerts[0]
assert.Equal(t, params.InstitutionID, alert.InstitutionID)
assert.Equal(t, "Deletion Requested", alert.Subject)
assert.Equal(t, "Deletion Requested", alert.Type)

// The link to review the deletion request should also contain a token,
// but we don't know offhand what it is. Other tests dig into this.
// Here, we just want to be sure we're sending the right email message.
expectedReviewLink := fmt.Sprintf("http://localhost/deletions/review/%d?token=", deletionRequest.ID)
assert.Contains(t, alert.Content, expectedReviewLink)

// Should be no work items because request has not yet been approved.
assert.Empty(t, alert.WorkItems)
}

0 comments on commit e0c891d

Please sign in to comment.