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

Restructure ListItemAccessControl types #8915

Merged
merged 2 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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