Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Css 10530/filterning resources #1353

Merged

Conversation

SimoneDutto
Copy link
Contributor

Description

Follow-up to 1347 to enable filtering based of resource name, resource type.

  • refactor the big raw query into multiple gorm query to be able to select them based of filtering mechanism.
  • Add unit test file, thanks @ale8k because I caught a nasty bug thanks to them.

fly by entitlements parametrization because it was useful to validate entityType filter.

Fixes JIRA/GitHub issue number

Engineering checklist

Check only items that apply

  • Documentation updated
  • Covered by unit tests
  • Covered by integration tests

Test instructions

Notes for code reviewers

@SimoneDutto SimoneDutto requested a review from a team as a code owner September 5, 2024 12:55
internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Show resolved Hide resolved
Copy link
Contributor

@kian99 kian99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good with some minor comments

internal/db/resource.go Outdated Show resolved Hide resolved
internal/db/resource.go Outdated Show resolved Hide resolved
@@ -66,7 +66,7 @@ type JIMM interface {
InitiateMigration(ctx context.Context, user *openfga.User, spec jujuparams.MigrationSpec) (jujuparams.InitiateMigrationResult, error)
ListApplicationOffers(ctx context.Context, user *openfga.User, filters ...jujuparams.OfferFilter) ([]jujuparams.ApplicationOfferAdminDetailsV5, error)
ListIdentities(ctx context.Context, user *openfga.User, filter pagination.LimitOffsetPagination) ([]openfga.User, error)
ListResources(ctx context.Context, user *openfga.User, filter pagination.LimitOffsetPagination) ([]db.Resource, error)
ListResources(ctx context.Context, user *openfga.User, filter pagination.LimitOffsetPagination, nameFilter, typeFilter string) ([]db.Resource, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about using stronger types for nameFilter and typeFilter that provide validation?
Like

type NameFilter struct{
   name string
}

Then we can have

func (n NameFilter) Validate() bool{}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the thing is that validation is only for entity and it should be done at API layer before entering Jimm world.
I'll be constructing a strong just for one of the two, so i don't see many benefits.
But I am open to be convinced

@SimoneDutto SimoneDutto force-pushed the CSS-10530/filterning-resources branch from 7e380fa to 08afc6e Compare September 6, 2024 07:25
@kian99 kian99 requested review from kian99 and babakks September 6, 2024 10:50

applicationOffersQuery := db.Select(selectApplicationOffers).
Model(&dbmodel.ApplicationOffer{}).
Where("? IS TRUE OR application_offers.name LIKE ?", namePrefixEmpty, namePrefixFilter).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for applying this suggestion, but I felt a bit suspicious about PostgreSQL expression evaluation (and short-circuiting of condition), and found out there is no such guaranty in PostgreSQL (See here). The gist is we have to use the CASE statement. With that we don't need the extra boolean argument:

WHERE (CASE WHEN ? = '' THEN TRUE ELSE application_offers.name LIKE ? END)

I tried this with PostgreSQL and it seems working.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was not aware of that.
Updated

func buildQuery(db *gorm.DB, offset, limit int, namePrefixFilter, typeFilter string) (*gorm.DB, error) {
applicationOffersQuery := db.Select(selectApplicationOffers).
Model(&dbmodel.ApplicationOffer{}).
Where("(CASE WHEN ? = '' THEN TRUE ELSE application_offers.name LIKE ? END)", namePrefixFilter, namePrefixFilter+"%").
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Where("(CASE WHEN ? = '' THEN TRUE ELSE application_offers.name LIKE ? END)", namePrefixFilter, namePrefixFilter+"%").
Where("(CASE WHEN ? = '' THEN TRUE ELSE application_offers.name LIKE ?% END)", namePrefixFilter, namePrefixFilter).

? and elsewhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't work with the SQL replacements

Comment on lines +35 to +41
namePrefixFilter, typeFilter := utils.GetNameAndTypeResourceFilter(params.EntityName, params.EntityType)
if typeFilter != "" {
typeFilter, err = validateAndConvertResourceFilter(typeFilter)
if err != nil {
return nil, v1.NewInvalidRequestError(err.Error())
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a follow-up, but I think this should be calling an application layer function to create custom types. Like the idea I was suggesting earlier, the API layer can pass the strings it has received from the client into application layer validators that return app layer types that can be used in ListResources().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because a string doesn't tell me much, but a type resource struct{ resource string } tells me a lot more.

@SimoneDutto SimoneDutto merged commit 4d88a29 into canonical:v3 Sep 6, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants