Skip to content

Commit

Permalink
Restructure ListItemAccessControl types (#8915)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens committed Nov 15, 2023
1 parent eca148b commit eead43e
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 125 deletions.
75 changes: 39 additions & 36 deletions packages/core/src/types/config/access-control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,43 +24,46 @@ export type ListFilterAccessControl<
args: BaseAccessArgs<ListTypeInfo> & { operation: Operation }
) => MaybePromise<boolean | ListTypeInfo['inputs']['where']>

export type CreateListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> = (
args: BaseAccessArgs<ListTypeInfo> & {
operation: 'create'

/**
* The input passed in from the GraphQL API
*/
inputData: ListTypeInfo['inputs']['create']
}
) => MaybePromise<boolean>

export type UpdateListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> = (
export type ListItemAccessControl<
Operation extends ItemOperation,
ListTypeInfo extends BaseListTypeInfo
> = (
args: BaseAccessArgs<ListTypeInfo> & {
operation: 'update'
create: {
operation: 'create'

/**
* The item being updated
*/
item: ListTypeInfo['item']
/**
* The input passed in from the GraphQL API
*/
inputData: ListTypeInfo['inputs']['create']
}
update: {
operation: 'update'

/**
* The input passed in from the GraphQL API
*/
inputData: ListTypeInfo['inputs']['update']

/**
* The item being updated
*/
item: ListTypeInfo['item']
}
delete: {
operation: 'delete'

/**
* The input passed in from the GraphQL API
*/
inputData: ListTypeInfo['inputs']['update']
}
/**
* The item being deleted
*/
item: ListTypeInfo['item']
}
}[Operation]
) => MaybePromise<boolean>

export type DeleteListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> = (
args: BaseAccessArgs<ListTypeInfo> & {
operation: 'delete'

/**
* The item being deleted
*/
item: ListTypeInfo['item']
}
) => MaybePromise<boolean>
export type CreateListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> = ListItemAccessControl<'create', ListTypeInfo>
export type UpdateListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> = ListItemAccessControl<'update', ListTypeInfo>
export type DeleteListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> = ListItemAccessControl<'delete', ListTypeInfo>

type ListAccessControlFunction<ListTypeInfo extends BaseListTypeInfo> = (
args: BaseAccessArgs<ListTypeInfo> & { operation: AccessOperation }
Expand Down Expand Up @@ -91,10 +94,10 @@ type ListAccessControlObject<ListTypeInfo extends BaseListTypeInfo> = {
// These rules are applied to each item being operated on individually. They return `true` or `false`,
// and if false, an access denied error will be returned for the individual operation.
item?: {
// read?: not supported
create?: CreateListItemAccessControl<ListTypeInfo>
update?: UpdateListItemAccessControl<ListTypeInfo>
delete?: DeleteListItemAccessControl<ListTypeInfo>
// read?: not supported // TODO: why not
create?: ListItemAccessControl<'create', ListTypeInfo>
update?: ListItemAccessControl<'update', ListTypeInfo>
delete?: ListItemAccessControl<'delete', ListTypeInfo>
}
}

Expand Down
179 changes: 90 additions & 89 deletions packages/core/src/types/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,62 +33,61 @@ export type KeystoneContext<TypeInfo extends BaseKeystoneTypeInfo = BaseKeystone

// List item API

// TODO: Work out whether we can generate useful return types based on the GraphQL Query
// passed to List API functions (see `readonly Record<string, any>` below)

type UniqueWhereInput<ListTypeInfo extends BaseListTypeInfo> =
false extends ListTypeInfo['isSingleton']
? { readonly where: ListTypeInfo['inputs']['uniqueWhere'] }
: { readonly where?: ListTypeInfo['inputs']['uniqueWhere'] }

type ListAPI <ListTypeInfo extends BaseListTypeInfo> = {
findMany(
args?: {
readonly where?: ListTypeInfo['inputs']['where']
readonly take?: number
readonly skip?: number
readonly orderBy?:
| ListTypeInfo['inputs']['orderBy']
| readonly ListTypeInfo['inputs']['orderBy'][]
readonly cursor?: ListTypeInfo['inputs']['uniqueWhere']
} & ResolveFields
): Promise<readonly Record<string, any>[]>
findOne(
args: UniqueWhereInput<ListTypeInfo> & ResolveFields
): Promise<Record<string, any>>
count(args?: {
readonly where?: ListTypeInfo['inputs']['where']
}): Promise<number>
updateOne(
args: UniqueWhereInput<ListTypeInfo> & {
readonly data: ListTypeInfo['inputs']['update']
} & ResolveFields
): Promise<Record<string, any>>
updateMany(
args: {
readonly data: readonly (UniqueWhereInput<ListTypeInfo> & {
readonly data: ListTypeInfo['inputs']['update']
})[]
} & ResolveFields
): Promise<Record<string, any>[]>
createOne(
args: { readonly data: ListTypeInfo['inputs']['create'] } & ResolveFields
): Promise<Record<string, any>>
createMany(
args: {
readonly data: readonly ListTypeInfo['inputs']['create'][]
} & ResolveFields
): Promise<Record<string, any>[]>
deleteOne(
args: UniqueWhereInput<ListTypeInfo> & ResolveFields
): Promise<Record<string, any> | null>
deleteMany(
args: {
readonly where: readonly ListTypeInfo['inputs']['uniqueWhere'][]
} & ResolveFields
): Promise<Record<string, any>[]>
}

export type KeystoneListsAPI<KeystoneListsTypeInfo extends Record<string, BaseListTypeInfo>> = {
[Key in keyof KeystoneListsTypeInfo]: {
findMany(
args?: {
readonly where?: KeystoneListsTypeInfo[Key]['inputs']['where']
readonly take?: number
readonly skip?: number
readonly orderBy?:
| KeystoneListsTypeInfo[Key]['inputs']['orderBy']
| readonly KeystoneListsTypeInfo[Key]['inputs']['orderBy'][]
readonly cursor?: KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere']
} & ResolveFields
): Promise<readonly Record<string, any>[]>
findOne(
args: UniqueWhereInput<KeystoneListsTypeInfo[Key]> & ResolveFields
): Promise<Record<string, any>>
count(args?: {
readonly where?: KeystoneListsTypeInfo[Key]['inputs']['where']
}): Promise<number>
updateOne(
args: UniqueWhereInput<KeystoneListsTypeInfo[Key]> & {
readonly data: KeystoneListsTypeInfo[Key]['inputs']['update']
} & ResolveFields
): Promise<Record<string, any>>
updateMany(
args: {
readonly data: readonly (UniqueWhereInput<KeystoneListsTypeInfo[Key]> & {
readonly data: KeystoneListsTypeInfo[Key]['inputs']['update']
})[]
} & ResolveFields
): Promise<Record<string, any>[]>
createOne(
args: { readonly data: KeystoneListsTypeInfo[Key]['inputs']['create'] } & ResolveFields
): Promise<Record<string, any>>
createMany(
args: {
readonly data: readonly KeystoneListsTypeInfo[Key]['inputs']['create'][]
} & ResolveFields
): Promise<Record<string, any>[]>
deleteOne(
args: UniqueWhereInput<KeystoneListsTypeInfo[Key]> & ResolveFields
): Promise<Record<string, any> | null>
deleteMany(
args: {
readonly where: readonly KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere'][]
} & ResolveFields
): Promise<Record<string, any>[]>
};
[Key in keyof KeystoneListsTypeInfo]: ListAPI<KeystoneListsTypeInfo[Key]>
}

type ResolveFields = {
Expand All @@ -98,46 +97,48 @@ type ResolveFields = {
readonly query?: string
}

type DbAPI <ListTypeInfo extends BaseListTypeInfo> = {
findMany(args?: {
readonly where?: ListTypeInfo['inputs']['where']
readonly take?: number
readonly skip?: number
readonly orderBy?:
| ListTypeInfo['inputs']['orderBy']
| readonly ListTypeInfo['inputs']['orderBy'][]
readonly cursor?: ListTypeInfo['inputs']['uniqueWhere']
}): Promise<readonly ListTypeInfo['item'][]>
findOne(
args: UniqueWhereInput<ListTypeInfo>
): Promise<ListTypeInfo['item'] | null>
count(args?: {
readonly where?: ListTypeInfo['inputs']['where']
}): Promise<number>
updateOne(
args: UniqueWhereInput<ListTypeInfo> & {
readonly data: ListTypeInfo['inputs']['update']
}
): Promise<ListTypeInfo['item']>
updateMany(args: {
readonly data: readonly (UniqueWhereInput<ListTypeInfo> & {
readonly data: ListTypeInfo['inputs']['update']
})[]
}): Promise<ListTypeInfo['item'][]>
createOne(args: {
readonly data: ListTypeInfo['inputs']['create']
}): Promise<ListTypeInfo['item']>
createMany(args: {
readonly data: readonly ListTypeInfo['inputs']['create'][]
}): Promise<ListTypeInfo['item'][]>
deleteOne(
args: UniqueWhereInput<ListTypeInfo>
): Promise<ListTypeInfo['item']>
deleteMany(args: {
readonly where: readonly ListTypeInfo['inputs']['uniqueWhere'][]
}): Promise<ListTypeInfo['item'][]>
}

export type KeystoneDbAPI<KeystoneListsTypeInfo extends Record<string, BaseListTypeInfo>> = {
[Key in keyof KeystoneListsTypeInfo]: {
findMany(args?: {
readonly where?: KeystoneListsTypeInfo[Key]['inputs']['where']
readonly take?: number
readonly skip?: number
readonly orderBy?:
| KeystoneListsTypeInfo[Key]['inputs']['orderBy']
| readonly KeystoneListsTypeInfo[Key]['inputs']['orderBy'][]
readonly cursor?: KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere']
}): Promise<readonly KeystoneListsTypeInfo[Key]['item'][]>
findOne(
args: UniqueWhereInput<KeystoneListsTypeInfo[Key]>
): Promise<KeystoneListsTypeInfo[Key]['item'] | null>
count(args?: {
readonly where?: KeystoneListsTypeInfo[Key]['inputs']['where']
}): Promise<number>
updateOne(
args: UniqueWhereInput<KeystoneListsTypeInfo[Key]> & {
readonly data: KeystoneListsTypeInfo[Key]['inputs']['update']
}
): Promise<KeystoneListsTypeInfo[Key]['item']>
updateMany(args: {
readonly data: readonly (UniqueWhereInput<KeystoneListsTypeInfo[Key]> & {
readonly data: KeystoneListsTypeInfo[Key]['inputs']['update']
})[]
}): Promise<KeystoneListsTypeInfo[Key]['item'][]>
createOne(args: {
readonly data: KeystoneListsTypeInfo[Key]['inputs']['create']
}): Promise<KeystoneListsTypeInfo[Key]['item']>
createMany(args: {
readonly data: readonly KeystoneListsTypeInfo[Key]['inputs']['create'][]
}): Promise<KeystoneListsTypeInfo[Key]['item'][]>
deleteOne(
args: UniqueWhereInput<KeystoneListsTypeInfo[Key]>
): Promise<KeystoneListsTypeInfo[Key]['item']>
deleteMany(args: {
readonly where: readonly KeystoneListsTypeInfo[Key]['inputs']['uniqueWhere'][]
}): Promise<KeystoneListsTypeInfo[Key]['item'][]>
};
[Key in keyof KeystoneListsTypeInfo]: DbAPI<KeystoneListsTypeInfo[Key]>
}

// GraphQL API
Expand Down

0 comments on commit eead43e

Please sign in to comment.