-
Notifications
You must be signed in to change notification settings - Fork 6
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 stage/pubtype restrictions to pub read api #988
base: main
Are you sure you want to change the base?
Conversation
…/platform into tfk/pub-read-restrictions
[ApiAccessType.read]: ({ value, onChange }) => { | ||
const context = useContext(CreateTokenFormContext); | ||
|
||
return ( | ||
<div className="flex flex-col gap-2"> | ||
<h3 className="font-semibold">Stages</h3> | ||
<span className="text-xs text-muted-foreground"> | ||
Select the stages this token can read Pubs from | ||
</span> | ||
<MultiSelect | ||
variant="inverted" | ||
options={context.stages.allOptions} | ||
defaultValue={ | ||
value === true || !value ? context.stages.allValues : value.stages | ||
} | ||
onValueChange={(val) => { | ||
const allStagesSelected = | ||
val.length === context.stages.allValues.length; | ||
|
||
const allPubTypesSelected = | ||
typeof value === "object" && | ||
value.pubTypes?.length === context.pubTypes.allValues.length; | ||
|
||
if ((allStagesSelected || val.length === 0) && allPubTypesSelected) { | ||
onChange(true); | ||
return; | ||
} | ||
|
||
onChange({ | ||
stages: | ||
val.length === 0 | ||
? context.stages.allValues | ||
: (val as StagesId[]), | ||
pubTypes: | ||
typeof value === "object" | ||
? value.pubTypes | ||
: context.pubTypes.allValues, | ||
}); | ||
}} | ||
animation={0} | ||
data-testid={`pub-${ApiAccessType.read}-stages-select`} | ||
/> | ||
|
||
<h3 className="font-semibold">Types</h3> | ||
<span className="text-xs text-muted-foreground"> | ||
Select the types of Pubs this token can read | ||
</span> | ||
<MultiSelect | ||
variant="inverted" | ||
options={context.pubTypes.allOptions} | ||
defaultValue={ | ||
value === true || !value ? context.pubTypes.allValues : value.pubTypes | ||
} | ||
onValueChange={(val) => { | ||
const allPubTypesSelected = | ||
val.length === context.pubTypes.allValues.length; | ||
|
||
const allStagesSelected = | ||
typeof value === "object" && | ||
value.stages?.length === context.stages.allValues.length; | ||
|
||
if ((allStagesSelected || val.length === 0) && allPubTypesSelected) { | ||
onChange(true); | ||
return; | ||
} | ||
|
||
onChange({ | ||
pubTypes: | ||
val.length === 0 | ||
? context.pubTypes.allValues | ||
: (val as PubTypesId[]), | ||
stages: | ||
typeof value == "object" | ||
? value.stages | ||
: context.stages.allValues, | ||
}); | ||
}} | ||
animation={0} | ||
data-testid={`pub-${ApiAccessType.read}-pubTypes-select`} | ||
/> | ||
</div> | ||
); | ||
}, |
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 we add another restriction at some point, we should make these components a bit DRYer
props: ExtraParams | ||
) => React.ReactNode; | ||
|
||
return CorrectlyTypedExtraContraints; |
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 really hate this typescript quirk.
here is a somewhat clearer demo of what happens
@@ -328,7 +414,7 @@ export const ConstraintFormFieldRender = ({ | |||
return ( | |||
<FormItemWrapper | |||
dataTestId={`${scope}-${type}-checkbox`} | |||
checked={Boolean(field.value)} | |||
checked={typeof field.value === "object" ? "indeterminate" : Boolean(field.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.
pubTypeId?: PubTypesId; | ||
stageId?: StagesId; | ||
/** | ||
* Multiple pubIds to filter by | ||
*/ | ||
pubIds?: PubsId[]; | ||
pubTypeId?: PubTypesId[]; | ||
stageId?: StageConstraint[]; |
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.
not reeeaally happy with having pubTypeId
and stageId
be singulars that accept arrays. mostly i did not want to introduce a bunch of noise to this PR, but i guess i already did
should i
a. change pubTypeId
->pubTypeIds
, same for stages
b. have both pubTypeId?: PubTypesId, pubTypeIds?: PubTypesIds[]
c. keep it like this
i think having pubIds
separate from pubId
makes sense, as they indicate a difference in the returned type (pubId
returns a singular pub, while pubTypeIds
returns an array)
Issue(s) Resolved
(not a ticket for this i believe)
Allow community admins to restrict Api access tokens to only read from an allowed list of stages/pub-types.
High-level Explanation of PR
Adds a new restriction for Pub.read api access tokens, allowing admins to specify "oh you can only read from these pub types/stages".
Some quirks:
Since we wanted to allow restricting both pub-types and stages, I was a bit stuck on how to do the selection UX.
Does only selecting one stage but no pub types allow you to read all pub types from that stage, or none, making the token effectively useless?
To solve this, I changed how the restriction selectors work: instead of having you select the things you want, you need to unselect the stages/pubtypes you do not want the token to have access to.
In addition, I added a "no stage" option to all the existing and new stage restrictions. While you could set a Pub create token to only allow creating pubs in certain stages, there was no option to allow pubs to be created without a stage. You can now explicitly allow this.
Test Plan
arcadia
./api/v0/c/arcadia-research/pubs
. Observe you only get back pubs from the pubtypes you specified./api/v0/c/arcadia-research/pubs?pubTypeId=...
. Observe you only get back pubs from the pubtype in the URL./api/v0/c/arcadia-research/pubs?pubTypeId=<some other pubtypeid>
. Observe you only get nothing.Screenshots (if applicable)
Notes