-
Notifications
You must be signed in to change notification settings - Fork 72
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
feat: add error when using an owner field as a sort key field #517
feat: add error when using an owner field as a sort key field #517
Conversation
if (!validateNotOwnerAuth(sortKeyFieldName, config, ctx)) { | ||
throw new InvalidDirectiveError( | ||
`The primary key's sort key type '${sortKeyFieldName}' cannot be used as an owner @auth field too. Please user another field for the sort key.` | ||
); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could adding this validation now affect any existing customer schema?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sundersc no - the feature flag has to be enabled OR they have to be using the new feature (which is behind a feature flag) to see this (https://github.com/aws-amplify/amplify-category-api/pull/517/files#diff-5f8c05424d524274f208c275f81ac9d5b2f6fbf6a878f0bb1daa27f65f4f4289R101). Also, this will go out with a semver major, so anyone already using the feature and using the owner as a sort key will know this is a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just a few comments
|
||
if (!authDir) return true; | ||
|
||
const dirRules = (authDir.arguments?.find(arg => arg.name.value === 'rules')?.value as ListValueNode).values; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we ensure that dirRules is non-null before the ownerRules is initialized.
0eac49c
to
5728ec4
Compare
@sachscode @sundersc this is ready to be re-reviewed/approved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
ac1b8e8
to
a66a7ce
Compare
(Just rebased, so ready for rereview) |
8ea0dd5
to
8eb758b
Compare
"The primary key's sort key type 'myOwnerField' cannot be used as an owner @auth field too. Please use another field for the sort key.", | ||
); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally I had put these tests in the index transformer because the validation seemed to fit better in the sort key validations that run. There was a problem with circular dependencies though during the build, so I moved these tests to the auth transformer to prevent the circular dependency (I believe it was index transformer -> auth -> relational -> index). I can create a follow up task to organize these tests within their module, or move them to the velocity tests.
} | ||
}); | ||
|
||
const featureFlagEnabled = ctx.featureFlags.getBoolean('useSubUsernameForDefaultIdentityClaim'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want a default value here set to false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this value isn't set in the project, .getBoolean
will return the default value as configured between "existing" and "new" Amplify apps. (https://github.com/aws-amplify/amplify-cli/blob/master/packages/amplify-cli-core/src/feature-flags/featureFlags.ts#L218)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also, the feature flags module always errors out if the feature flag is missing from the instance because it acts as a singleton, so it always needs to be set in tests too.)
|
||
(rule as ObjectValueNode).fields?.forEach(field => { | ||
const name: string = field.name.value; | ||
const { value } = field?.value as StringValueNode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm wondering if this can throw an npe if value is not defined? As written it seems like you want this to kind of behave like field?.value?.value
, but I think that w/ the destructing and typecasting here it's more like field?.value!!.value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is really desireable we may need to do (field?.value as (StringValueNode | undefined))?.value;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change this to set value
as a string and have handle undefined.
if (!authDir) return true; | ||
|
||
const dirRules = (authDir.arguments?.find(arg => arg.name.value === 'rules')?.value as ListValueNode)?.values || []; | ||
const hasOwnerFieldAsSortKey = dirRules.some(rule => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might pull this rule validation out into it's own helper for readability, then it's clear that you're just reducing that state, i.e return dirRules.some(ruleHasOwnerFieldAsSortKey);
let isOwner = false; | ||
let identityClaimIsSet = false; | ||
let ownerFieldIsSet = false; | ||
let usesMultiClaim = false; | ||
let sortKeyFieldIsAuthField = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll OOS for this PR, since this isn't yet an established pattern, but I prefer to avoid let wherever possible, and rely instead on returning consistent shapes, and reducing state where necessary. In general for something like this I'd probably refactor to have your inner loop (i.e. rule.fields?.forEach
turn into a rule.fields.map(doesRuleHaveOwnerForSortKeyField)
, then just return a .some
for that mapped value. As written, I'm not sure if it's possible to have sortKeyFieldIsAuthField
be set to true
for a single rule, and usesImplicitOwnerField
for another unrelated rule, and result in a false positive here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As written, there's some chance for state interaction between rules, which I don't think is by design. If we need rules to 'see' each other, we should make that super explicit, and either preprocess the necessary cross-rule state, or otherwise allow the rule checker to look at it's neighbors rather than relying on global state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with that. This was the best way I could configure for my own readability since the GQL objects can be messy to parse (I always wanted to work on some GQL adapters to integrate the code into the transformers), but I can change the pattern. I'll refactor this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
fe018a2
if (value === 'useSubUsernameForDefaultIdentityClaim') { | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move the default values to a new hash map and use that here? In that way, if we have to check for any new flags in the future, we don't have to add multiple if statements in the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can potentially OOS for this change. I actually added a simple createFeatureFlagProviderWithOverrides util in another PR that can just become our standard to simplify behavior and keep us from reimplementing on a per-test basis. Your call if you think it's blocking or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this in theory and am happy to follow up, but since this isn't an established pattern (and there's a mix of using these mock objects in the current tests) is it okay if consolidating the tests is a follow up? If this is blocking I can fix it, but the reason I had to add this feature flag to each test is because this is how the other tests do it.
getBoolean: (value: string, defaultValue: boolean): boolean => { | ||
if (value === 'useSubUsernameForDefaultIdentityClaim') { | ||
return true; | ||
} | ||
return defaultValue; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as the previous. If possible, please move this to a hash map.
$parent: ID | ||
$child: ModelIDKeyConditionInput |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to remove this field from an existing test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, $child
is no longer part of the primary key's query.
* chore: upgrade api category dependencies * chore: reflect test updates from aws-amplify/amplify-category-api#517 in mock
Description of changes
As discussed, there's a breaking change when using owner
@auth
field as the@primaryKey
's sort key. Therefore, the transformer will raise an error and abort the transform process when using thesub::username
identity claim in which the owner attribute in the database is being used as the sort key.Docs PR to follow.
Issue #, if available
Description of how you validated changes
Checklist
yarn test
passesBy submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.