Skip to content

Commit

Permalink
[INTG-1869] Get lastModified timestamp based on org_id (#146)
Browse files Browse the repository at this point in the history
* [INTG-1869] Get lastModified timestamp based on org_id

* [INTG-1869] Fix tests

* [INTG-1869] Add org-index

* [INTG-1869] PR feedback
  • Loading branch information
phanikumarpatchigolla authored Jul 27, 2021
1 parent db3874a commit 6a3d5aa
Show file tree
Hide file tree
Showing 82 changed files with 919 additions and 345 deletions.
37 changes: 37 additions & 0 deletions internal/app/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,40 @@ func (a *Client) DownloadInspectionReportFile(ctx context.Context, url string) (

return res.Body, nil
}

// WhoAmIResponse represents the the response of WhoAmI
type WhoAmIResponse struct {
UserID string `json:"user_id"`
OrganisationID string `json:"organisation_id"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
}

// WhoAmI returns the details for the user who is making the request
func (a *Client) WhoAmI(ctx context.Context) (*WhoAmIResponse, error) {
var (
result *WhoAmIResponse
errMsg json.RawMessage
)

sl := a.sling.New().Get("accounts/user/v1/user:WhoAmI").
Set(string(Authorization), fmt.Sprintf("Bearer %s", a.accessToken)).
Set(string(IntegrationID), "iauditor-exporter").
Set(string(IntegrationVersion), version.GetVersion()).
Set(string(XRequestID), util.RequestIDFromContext(ctx))

req, _ := sl.Request()
req = req.WithContext(ctx)

_, err := a.do(&slingHTTPDoer{
sl: sl,
req: req,
successV: &result,
failureV: &errMsg,
})
if err != nil {
return nil, errors.Wrap(err, "Failed request to API")
}

return result, nil
}
14 changes: 12 additions & 2 deletions internal/app/feed/export_feeds.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,19 @@ func ExportFeeds(v *viper.Viper, apiClient *api.Client, exporter Exporter) error

// TODO. Should validate auth before doing anything

resp, err := apiClient.WhoAmI(ctx)
util.Check(err, "failed to get details of the current user")

logger.Infof("Exporting data by user: %s %s", resp.Firstname, resp.Lastname)

for _, feed := range GetFeeds(v) {
if tablesMap[feed.Name()] || len(tables) == 0 {
wg.Add(1)

go func(f Feed) {
defer wg.Done()

err := f.Export(ctx, apiClient, exporter)
err := f.Export(ctx, apiClient, exporter, resp.OrganisationID)
util.Check(err, "failed to export")
}(feed)
}
Expand All @@ -149,8 +154,13 @@ func ExportInspectionReports(v *viper.Viper, apiClient *api.Client, exporter *Re
logger := util.GetLogger()
ctx := context.Background()

resp, err := apiClient.WhoAmI(ctx)
util.Check(err, "failed to get details of the current user")

logger.Infof("Exporting inspection reports by user: %s %s", resp.Firstname, resp.Lastname)

feed := getInspectionFeed(v, config.GetInspectionConfig(v), getTemplateIDs(v))
err := feed.Export(ctx, apiClient, exporter)
err = feed.Export(ctx, apiClient, exporter, resp.OrganisationID)
util.Check(err, "failed to export inspection feed")

err = exporter.SaveReports(ctx, apiClient, feed)
Expand Down
27 changes: 27 additions & 0 deletions internal/app/feed/export_feeds_intg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/SafetyCulture/iauditor-exporter/internal/app/api"
"github.com/SafetyCulture/iauditor-exporter/internal/app/feed"
"gopkg.in/h2non/gock.v1"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
Expand All @@ -26,6 +27,19 @@ func TestIntegrationDbCreateSchema_should_create_all_schemas(t *testing.T) {

viperConfig := viper.New()

gock.New("http://localhost:9999").
Get("/accounts/user/v1/user:WhoAmI").
Times(2).
Reply(200).
BodyString(`
{
"user_id": "user_123",
"organisation_id": "role_123",
"firstname": "Test",
"lastname": "Test"
}
`)

err = feed.CreateSchemas(viperConfig, exporter)
assert.Nil(t, err)

Expand Down Expand Up @@ -56,6 +70,19 @@ func TestIntegrationDbExportFeeds_should_export_all_feeds_to_file(t *testing.T)
apiClient := api.GetTestClient()
initMockFeedsSet1(apiClient.HTTPClient())

gock.New("http://localhost:9999").
Get("/accounts/user/v1/user:WhoAmI").
Times(2).
Reply(200).
BodyString(`
{
"user_id": "user_123",
"organisation_id": "role_123",
"firstname": "Test",
"lastname": "Test"
}
`)

err = feed.ExportFeeds(viperConfig, apiClient, exporter)
assert.Nil(t, err)

Expand Down
44 changes: 44 additions & 0 deletions internal/app/feed/export_feeds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/SafetyCulture/iauditor-exporter/internal/app/api"
"github.com/SafetyCulture/iauditor-exporter/internal/app/feed"
"gopkg.in/h2non/gock.v1"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -38,6 +39,8 @@ func TestCreateSchemas_should_create_all_schemas_to_file(t *testing.T) {
}

func TestExportFeeds_should_export_all_feeds_to_file(t *testing.T) {
defer gock.Off()

exporter, err := getTemporaryCSVExporter()
assert.Nil(t, err)

Expand All @@ -47,6 +50,18 @@ func TestExportFeeds_should_export_all_feeds_to_file(t *testing.T) {
apiClient := api.GetTestClient()
initMockFeedsSet1(apiClient.HTTPClient())

gock.New("http://localhost:9999").
Get("/accounts/user/v1/user:WhoAmI").
Reply(200).
BodyString(`
{
"user_id": "user_123",
"organisation_id": "role_123",
"firstname": "Test",
"lastname": "Test"
}
`)

err = feed.ExportFeeds(viperConfig, apiClient, exporter)
assert.Nil(t, err)

Expand All @@ -72,6 +87,21 @@ func TestExportFeeds_should_export_all_feeds_to_file(t *testing.T) {
// Expectation of this test is that group_users and schedule_assignees are truncated and refreshed
// and that other tables are incrementally updated
func TestExportFeeds_should_perform_incremental_update_on_second_run(t *testing.T) {
defer gock.Off()

gock.New("http://localhost:9999").
Get("/accounts/user/v1/user:WhoAmI").
Times(2).
Reply(200).
BodyString(`
{
"user_id": "user_123",
"organisation_id": "role_123",
"firstname": "Test",
"lastname": "Test"
}
`)

exporter, err := getTemporaryCSVExporter()
assert.Nil(t, err)

Expand Down Expand Up @@ -110,6 +140,8 @@ func TestExportFeeds_should_perform_incremental_update_on_second_run(t *testing.
}

func TestExportFeeds_should_handle_lots_of_rows_ok(t *testing.T) {
defer gock.Off()

exporter, err := getTemporaryCSVExporter()
assert.Nil(t, err)

Expand All @@ -119,6 +151,18 @@ func TestExportFeeds_should_handle_lots_of_rows_ok(t *testing.T) {
apiClient := api.GetTestClient()
initMockFeedsSet3(apiClient.HTTPClient())

gock.New("http://localhost:9999").
Get("/accounts/user/v1/user:WhoAmI").
Reply(200).
BodyString(`
{
"user_id": "user_123",
"organisation_id": "role_123",
"firstname": "Test",
"lastname": "Test"
}
`)

err = feed.ExportFeeds(viperConfig, apiClient, exporter)
assert.Nil(t, err)

Expand Down
90 changes: 88 additions & 2 deletions internal/app/feed/exporter_csv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,53 @@ func TestCSVExporterLastModifiedAt_should_return_latest_modified_at(t *testing.T
err = exporter.WriteRows(inspectionFeed, inspections)
assert.Nil(t, err)

lastModifiedAt, err := exporter.LastModifiedAt(inspectionFeed, time.Now().Add(time.Hour*-30000))
// Check the timestamp for the audits that doesn't have organisation_id
lastModifiedAt, err := exporter.LastModifiedAt(inspectionFeed, time.Now().Add(time.Hour*-30000), "role_123")
assert.Nil(t, err)
// Times are slightly lossy, convery to ISO string
assert.Equal(t, now.Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))

lastModifiedAt, err = exporter.LastModifiedAt(inspectionFeed, time.Now().Add(time.Hour*-30000), "role_1234")
assert.Nil(t, err)
// Times are slightly lossy, convery to ISO string
assert.Equal(t, now.Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))

inspections = []feed.Inspection{
{
ID: "audit_5",
ModifiedAt: now,
OrganisationID: "role_123",
},
{
ID: "audit_6",
ModifiedAt: now.Add(time.Hour * -128),
OrganisationID: "role_123",
},
{
ID: "audit_7",
ModifiedAt: now.Add(time.Hour * -3000),
OrganisationID: "role_1234",
},
{
ID: "audit_8",
ModifiedAt: now.Add(time.Hour * -2),
OrganisationID: "role_1234",
},
}

err = exporter.WriteRows(inspectionFeed, inspections)
assert.Nil(t, err)

// Check the timestamp for the audits that contains organisation_id
lastModifiedAt, err = exporter.LastModifiedAt(inspectionFeed, time.Now().Add(time.Hour*-30000), "role_123")
assert.Nil(t, err)
// Times are slightly lossy, convery to ISO string
assert.Equal(t, now.Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))

lastModifiedAt, err = exporter.LastModifiedAt(inspectionFeed, time.Now().Add(time.Hour*-30000), "role_1234")
assert.Nil(t, err)
// Times are slightly lossy, convery to ISO string
assert.Equal(t, now.Add(time.Hour*-2).Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))
}

func TestCSVExporterLastModifiedAt_should_return_modified_after_if_latest(t *testing.T) {
Expand Down Expand Up @@ -260,7 +303,50 @@ func TestCSVExporterLastModifiedAt_should_return_modified_after_if_latest(t *tes
err = exporter.WriteRows(inspectionFeed, inspections)
assert.Nil(t, err)

lastModifiedAt, err := exporter.LastModifiedAt(inspectionFeed, now.Add(time.Hour))
// Check the timestamp for the audits that doesn't have organisation_id
lastModifiedAt, err := exporter.LastModifiedAt(inspectionFeed, now.Add(time.Hour), "role_123")
assert.Nil(t, err)
// Times are slightly lossy, converting to ISO string
assert.Equal(t, now.Add(time.Hour).Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))

lastModifiedAt, err = exporter.LastModifiedAt(inspectionFeed, now.Add(time.Hour), "role_124")
assert.Nil(t, err)
// Times are slightly lossy, converting to ISO string
assert.Equal(t, now.Add(time.Hour).Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))

inspections = []feed.Inspection{
{
ID: "audit_5",
ModifiedAt: now,
OrganisationID: "role_123",
},
{
ID: "audit_6",
ModifiedAt: now.Add(time.Hour * -128),
OrganisationID: "role_123",
},
{
ID: "audit_7",
ModifiedAt: now.Add(time.Hour * -3000),
OrganisationID: "role_1234",
},
{
ID: "audit_8",
ModifiedAt: now.Add(time.Hour * -2),
OrganisationID: "role_1234",
},
}

err = exporter.WriteRows(inspectionFeed, inspections)
assert.Nil(t, err)

// Check the timestamp for the audits that contains organisation_id
lastModifiedAt, err = exporter.LastModifiedAt(inspectionFeed, now.Add(time.Hour), "role_123")
assert.Nil(t, err)
// Times are slightly lossy, converting to ISO string
assert.Equal(t, now.Add(time.Hour).Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))

lastModifiedAt, err = exporter.LastModifiedAt(inspectionFeed, now.Add(time.Hour), "role_124")
assert.Nil(t, err)
// Times are slightly lossy, converting to ISO string
assert.Equal(t, now.Add(time.Hour).Format(time.RFC3339), lastModifiedAt.Format(time.RFC3339))
Expand Down
Loading

0 comments on commit 6a3d5aa

Please sign in to comment.