Add right requests
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
194
apps/console/src/hooks/graph/RightsRequestGraph.ts
Normal file
194
apps/console/src/hooks/graph/RightsRequestGraph.ts
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
import { graphql } from "relay-runtime";
|
||||||
|
import { useMutation } from "react-relay";
|
||||||
|
import { useConfirm } from "@probo/ui";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { promisifyMutation, sprintf } from "@probo/helpers";
|
||||||
|
import { useMutationWithToasts } from "../useMutationWithToasts";
|
||||||
|
|
||||||
|
export const RightsRequestsConnectionKey = "RightsRequestsPage_rightsRequests";
|
||||||
|
|
||||||
|
export const rightsRequestsQuery = graphql`
|
||||||
|
query RightsRequestGraphListQuery($organizationId: ID!) {
|
||||||
|
node(id: $organizationId) {
|
||||||
|
... on Organization {
|
||||||
|
...RightsRequestsPageFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const rightsRequestNodeQuery = graphql`
|
||||||
|
query RightsRequestGraphNodeQuery($rightsRequestId: ID!) {
|
||||||
|
node(id: $rightsRequestId) {
|
||||||
|
... on RightsRequest {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
contact
|
||||||
|
details
|
||||||
|
deadline
|
||||||
|
actionTaken
|
||||||
|
organization {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const createRightsRequestMutation = graphql`
|
||||||
|
mutation RightsRequestGraphCreateMutation(
|
||||||
|
$input: CreateRightsRequestInput!
|
||||||
|
$connections: [ID!]!
|
||||||
|
) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge @prependEdge(connections: $connections) {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
contact
|
||||||
|
details
|
||||||
|
deadline
|
||||||
|
actionTaken
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const updateRightsRequestMutation = graphql`
|
||||||
|
mutation RightsRequestGraphUpdateMutation($input: UpdateRightsRequestInput!) {
|
||||||
|
updateRightsRequest(input: $input) {
|
||||||
|
rightsRequest {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
contact
|
||||||
|
details
|
||||||
|
deadline
|
||||||
|
actionTaken
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const deleteRightsRequestMutation = graphql`
|
||||||
|
mutation RightsRequestGraphDeleteMutation(
|
||||||
|
$input: DeleteRightsRequestInput!
|
||||||
|
$connections: [ID!]!
|
||||||
|
) {
|
||||||
|
deleteRightsRequest(input: $input) {
|
||||||
|
deletedRightsRequestId @deleteEdge(connections: $connections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useDeleteRightsRequest = (
|
||||||
|
request: { id: string },
|
||||||
|
connectionId: string
|
||||||
|
) => {
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const [mutate] = useMutationWithToasts(deleteRightsRequestMutation, {
|
||||||
|
successMessage: __("Rights request deleted successfully"),
|
||||||
|
errorMessage: __("Failed to delete rights request"),
|
||||||
|
});
|
||||||
|
const confirm = useConfirm();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
confirm(
|
||||||
|
() =>
|
||||||
|
mutate({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
rightsRequestId: request.id,
|
||||||
|
},
|
||||||
|
connections: [connectionId],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
message: sprintf(
|
||||||
|
__(
|
||||||
|
"This will permanently delete the rights request. This action cannot be undone."
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCreateRightsRequest = (connectionId: string) => {
|
||||||
|
const [mutate] = useMutation(createRightsRequestMutation);
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
|
||||||
|
return (input: {
|
||||||
|
organizationId: string;
|
||||||
|
requestType: string;
|
||||||
|
requestState: string;
|
||||||
|
dataSubject?: string;
|
||||||
|
contact?: string;
|
||||||
|
details?: string;
|
||||||
|
deadline?: string;
|
||||||
|
actionTaken?: string;
|
||||||
|
}) => {
|
||||||
|
if (!input.organizationId) {
|
||||||
|
return alert(__("Failed to create rights request: organization is required"));
|
||||||
|
}
|
||||||
|
if (!input.requestType) {
|
||||||
|
return alert(__("Failed to create rights request: request type is required"));
|
||||||
|
}
|
||||||
|
if (!input.requestState) {
|
||||||
|
return alert(__("Failed to create rights request: request state is required"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return promisifyMutation(mutate)({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
organizationId: input.organizationId,
|
||||||
|
requestType: input.requestType,
|
||||||
|
requestState: input.requestState,
|
||||||
|
dataSubject: input.dataSubject,
|
||||||
|
contact: input.contact,
|
||||||
|
details: input.details,
|
||||||
|
deadline: input.deadline,
|
||||||
|
actionTaken: input.actionTaken,
|
||||||
|
},
|
||||||
|
connections: [connectionId],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateRightsRequest = () => {
|
||||||
|
const [mutate] = useMutation(updateRightsRequestMutation);
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
|
||||||
|
return (input: {
|
||||||
|
id: string;
|
||||||
|
requestType?: string;
|
||||||
|
requestState?: string;
|
||||||
|
dataSubject?: string;
|
||||||
|
contact?: string;
|
||||||
|
details?: string;
|
||||||
|
deadline?: string | null;
|
||||||
|
actionTaken?: string;
|
||||||
|
}) => {
|
||||||
|
if (!input.id) {
|
||||||
|
return alert(__("Failed to update rights request: ID is required"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return promisifyMutation(mutate)({
|
||||||
|
variables: {
|
||||||
|
input,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
231
apps/console/src/hooks/graph/__generated__/RightsRequestGraphCreateMutation.graphql.ts
generated
Normal file
231
apps/console/src/hooks/graph/__generated__/RightsRequestGraphCreateMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<630d2ddf409889a6c1632063d18a2545>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type RightsRequestState = "DONE" | "IN_PROGRESS" | "TODO";
|
||||||
|
export type RightsRequestType = "ACCESS" | "DELETION" | "PORTABILITY";
|
||||||
|
export type CreateRightsRequestInput = {
|
||||||
|
actionTaken?: string | null | undefined;
|
||||||
|
contact?: string | null | undefined;
|
||||||
|
dataSubject?: string | null | undefined;
|
||||||
|
deadline?: any | null | undefined;
|
||||||
|
details?: string | null | undefined;
|
||||||
|
organizationId: string;
|
||||||
|
requestState: RightsRequestState;
|
||||||
|
requestType: RightsRequestType;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphCreateMutation$variables = {
|
||||||
|
connections: ReadonlyArray<string>;
|
||||||
|
input: CreateRightsRequestInput;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphCreateMutation$data = {
|
||||||
|
readonly createRightsRequest: {
|
||||||
|
readonly rightsRequestEdge: {
|
||||||
|
readonly node: {
|
||||||
|
readonly actionTaken: string | null | undefined;
|
||||||
|
readonly contact: string | null | undefined;
|
||||||
|
readonly createdAt: any;
|
||||||
|
readonly dataSubject: string | null | undefined;
|
||||||
|
readonly deadline: any | null | undefined;
|
||||||
|
readonly details: string | null | undefined;
|
||||||
|
readonly id: string;
|
||||||
|
readonly requestState: RightsRequestState;
|
||||||
|
readonly requestType: RightsRequestType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphCreateMutation = {
|
||||||
|
response: RightsRequestGraphCreateMutation$data;
|
||||||
|
variables: RightsRequestGraphCreateMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "connections"
|
||||||
|
},
|
||||||
|
v1 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
},
|
||||||
|
v2 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequestEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "rightsRequestEdge",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequest",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestType",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestState",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "dataSubject",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "contact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "details",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deadline",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "actionTaken",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
(v1/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RightsRequestGraphCreateMutation",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "CreateRightsRequestPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "createRightsRequest",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RightsRequestGraphCreateMutation",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "CreateRightsRequestPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "createRightsRequest",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"filters": null,
|
||||||
|
"handle": "prependEdge",
|
||||||
|
"key": "",
|
||||||
|
"kind": "LinkedHandle",
|
||||||
|
"name": "rightsRequestEdge",
|
||||||
|
"handleArgs": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "connections",
|
||||||
|
"variableName": "connections"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "2642d9a5f58aa90190df6ccf73e6e06f",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RightsRequestGraphCreateMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation RightsRequestGraphCreateMutation(\n $input: CreateRightsRequestInput!\n) {\n createRightsRequest(input: $input) {\n rightsRequestEdge {\n node {\n id\n requestType\n requestState\n dataSubject\n contact\n details\n deadline\n actionTaken\n createdAt\n }\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "98fa74d3219cf56655e74441af4dc01d";
|
||||||
|
|
||||||
|
export default node;
|
||||||
132
apps/console/src/hooks/graph/__generated__/RightsRequestGraphDeleteMutation.graphql.ts
generated
Normal file
132
apps/console/src/hooks/graph/__generated__/RightsRequestGraphDeleteMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<274e16758d468bf7fb911965acca3264>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type DeleteRightsRequestInput = {
|
||||||
|
rightsRequestId: string;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphDeleteMutation$variables = {
|
||||||
|
connections: ReadonlyArray<string>;
|
||||||
|
input: DeleteRightsRequestInput;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphDeleteMutation$data = {
|
||||||
|
readonly deleteRightsRequest: {
|
||||||
|
readonly deletedRightsRequestId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphDeleteMutation = {
|
||||||
|
response: RightsRequestGraphDeleteMutation$data;
|
||||||
|
variables: RightsRequestGraphDeleteMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "connections"
|
||||||
|
},
|
||||||
|
v1 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
},
|
||||||
|
v2 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deletedRightsRequestId",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
(v1/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RightsRequestGraphDeleteMutation",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "DeleteRightsRequestPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "deleteRightsRequest",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RightsRequestGraphDeleteMutation",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "DeleteRightsRequestPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "deleteRightsRequest",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"filters": null,
|
||||||
|
"handle": "deleteEdge",
|
||||||
|
"key": "",
|
||||||
|
"kind": "ScalarHandle",
|
||||||
|
"name": "deletedRightsRequestId",
|
||||||
|
"handleArgs": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "connections",
|
||||||
|
"variableName": "connections"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "c81b44380a4647a241c72fe1ca359246",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RightsRequestGraphDeleteMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation RightsRequestGraphDeleteMutation(\n $input: DeleteRightsRequestInput!\n) {\n deleteRightsRequest(input: $input) {\n deletedRightsRequestId\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "e657b62ad808fa4fd5902cf4eea4ca3b";
|
||||||
|
|
||||||
|
export default node;
|
||||||
295
apps/console/src/hooks/graph/__generated__/RightsRequestGraphListQuery.graphql.ts
generated
Normal file
295
apps/console/src/hooks/graph/__generated__/RightsRequestGraphListQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<22e08aea59fb3427d7770d89a44d6e9e>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type RightsRequestGraphListQuery$variables = {
|
||||||
|
organizationId: string;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphListQuery$data = {
|
||||||
|
readonly node: {
|
||||||
|
readonly " $fragmentSpreads": FragmentRefs<"RightsRequestsPageFragment">;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphListQuery = {
|
||||||
|
response: RightsRequestGraphListQuery$data;
|
||||||
|
variables: RightsRequestGraphListQuery$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "organizationId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "id",
|
||||||
|
"variableName": "organizationId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v2 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v4 = [
|
||||||
|
{
|
||||||
|
"kind": "Literal",
|
||||||
|
"name": "first",
|
||||||
|
"value": 10
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RightsRequestGraphListQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"args": null,
|
||||||
|
"kind": "FragmentSpread",
|
||||||
|
"name": "RightsRequestsPageFragment"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Organization",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RightsRequestGraphListQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
(v3/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v4/*: any*/),
|
||||||
|
"concreteType": "RightsRequestConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "rightsRequests",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "totalCount",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequestEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequest",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestType",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestState",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "dataSubject",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "contact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "details",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deadline",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "actionTaken",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
(v2/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "PageInfo",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "pageInfo",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasNextPage",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "endCursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "ClientExtension",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": "rightsRequests(first:10)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v4/*: any*/),
|
||||||
|
"filters": null,
|
||||||
|
"handle": "connection",
|
||||||
|
"key": "RightsRequestsPage_rightsRequests",
|
||||||
|
"kind": "LinkedHandle",
|
||||||
|
"name": "rightsRequests"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Organization",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "77f124136a2da2eb84fb134e5d10396b",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RightsRequestGraphListQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query RightsRequestGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...RightsRequestsPageFragment\n }\n id\n }\n}\n\nfragment RightsRequestsPageFragment on Organization {\n id\n rightsRequests(first: 10) {\n totalCount\n edges {\n node {\n id\n requestType\n requestState\n dataSubject\n contact\n details\n deadline\n actionTaken\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "6ff83d9e0017a4fb245ad9f13106a439";
|
||||||
|
|
||||||
|
export default node;
|
||||||
241
apps/console/src/hooks/graph/__generated__/RightsRequestGraphNodeQuery.graphql.ts
generated
Normal file
241
apps/console/src/hooks/graph/__generated__/RightsRequestGraphNodeQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<7314c67aea13775f772b81880c524a60>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type RightsRequestState = "DONE" | "IN_PROGRESS" | "TODO";
|
||||||
|
export type RightsRequestType = "ACCESS" | "DELETION" | "PORTABILITY";
|
||||||
|
export type RightsRequestGraphNodeQuery$variables = {
|
||||||
|
rightsRequestId: string;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphNodeQuery$data = {
|
||||||
|
readonly node: {
|
||||||
|
readonly actionTaken?: string | null | undefined;
|
||||||
|
readonly contact?: string | null | undefined;
|
||||||
|
readonly createdAt?: any;
|
||||||
|
readonly dataSubject?: string | null | undefined;
|
||||||
|
readonly deadline?: any | null | undefined;
|
||||||
|
readonly details?: string | null | undefined;
|
||||||
|
readonly id?: string;
|
||||||
|
readonly organization?: {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
};
|
||||||
|
readonly requestState?: RightsRequestState;
|
||||||
|
readonly requestType?: RightsRequestType;
|
||||||
|
readonly updatedAt?: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphNodeQuery = {
|
||||||
|
response: RightsRequestGraphNodeQuery$data;
|
||||||
|
variables: RightsRequestGraphNodeQuery$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "rightsRequestId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "id",
|
||||||
|
"variableName": "rightsRequestId"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v2 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestType",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v4 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestState",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v5 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "dataSubject",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v6 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "contact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v7 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "details",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v8 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deadline",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v9 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "actionTaken",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v10 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "Organization",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "organization",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "name",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v11 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v12 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RightsRequestGraphNodeQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
(v2/*: any*/),
|
||||||
|
(v3/*: any*/),
|
||||||
|
(v4/*: any*/),
|
||||||
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/),
|
||||||
|
(v7/*: any*/),
|
||||||
|
(v8/*: any*/),
|
||||||
|
(v9/*: any*/),
|
||||||
|
(v10/*: any*/),
|
||||||
|
(v11/*: any*/),
|
||||||
|
(v12/*: any*/)
|
||||||
|
],
|
||||||
|
"type": "RightsRequest",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RightsRequestGraphNodeQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
(v2/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
(v4/*: any*/),
|
||||||
|
(v5/*: any*/),
|
||||||
|
(v6/*: any*/),
|
||||||
|
(v7/*: any*/),
|
||||||
|
(v8/*: any*/),
|
||||||
|
(v9/*: any*/),
|
||||||
|
(v10/*: any*/),
|
||||||
|
(v11/*: any*/),
|
||||||
|
(v12/*: any*/)
|
||||||
|
],
|
||||||
|
"type": "RightsRequest",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "93aa5fb44159c0ae2709c34f493bc69f",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RightsRequestGraphNodeQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query RightsRequestGraphNodeQuery(\n $rightsRequestId: ID!\n) {\n node(id: $rightsRequestId) {\n __typename\n ... on RightsRequest {\n id\n requestType\n requestState\n dataSubject\n contact\n details\n deadline\n actionTaken\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "9f7d09c59f937a8de6cfbc0354b42d1b";
|
||||||
|
|
||||||
|
export default node;
|
||||||
178
apps/console/src/hooks/graph/__generated__/RightsRequestGraphUpdateMutation.graphql.ts
generated
Normal file
178
apps/console/src/hooks/graph/__generated__/RightsRequestGraphUpdateMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<df8070312cba4b83a8f30231ac7b7fde>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type RightsRequestState = "DONE" | "IN_PROGRESS" | "TODO";
|
||||||
|
export type RightsRequestType = "ACCESS" | "DELETION" | "PORTABILITY";
|
||||||
|
export type UpdateRightsRequestInput = {
|
||||||
|
actionTaken?: string | null | undefined;
|
||||||
|
contact?: string | null | undefined;
|
||||||
|
dataSubject?: string | null | undefined;
|
||||||
|
deadline?: any | null | undefined;
|
||||||
|
details?: string | null | undefined;
|
||||||
|
id: string;
|
||||||
|
requestState?: RightsRequestState | null | undefined;
|
||||||
|
requestType?: RightsRequestType | null | undefined;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphUpdateMutation$variables = {
|
||||||
|
input: UpdateRightsRequestInput;
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphUpdateMutation$data = {
|
||||||
|
readonly updateRightsRequest: {
|
||||||
|
readonly rightsRequest: {
|
||||||
|
readonly actionTaken: string | null | undefined;
|
||||||
|
readonly contact: string | null | undefined;
|
||||||
|
readonly dataSubject: string | null | undefined;
|
||||||
|
readonly deadline: any | null | undefined;
|
||||||
|
readonly details: string | null | undefined;
|
||||||
|
readonly id: string;
|
||||||
|
readonly requestState: RightsRequestState;
|
||||||
|
readonly requestType: RightsRequestType;
|
||||||
|
readonly updatedAt: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RightsRequestGraphUpdateMutation = {
|
||||||
|
response: RightsRequestGraphUpdateMutation$data;
|
||||||
|
variables: RightsRequestGraphUpdateMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "UpdateRightsRequestPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "updateRightsRequest",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequest",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "rightsRequest",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestType",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestState",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "dataSubject",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "contact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "details",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deadline",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "actionTaken",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RightsRequestGraphUpdateMutation",
|
||||||
|
"selections": (v1/*: any*/),
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RightsRequestGraphUpdateMutation",
|
||||||
|
"selections": (v1/*: any*/)
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "4b06cb49236bb946cfa333e95b80f2a8",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RightsRequestGraphUpdateMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation RightsRequestGraphUpdateMutation(\n $input: UpdateRightsRequestInput!\n) {\n updateRightsRequest(input: $input) {\n rightsRequest {\n id\n requestType\n requestState\n dataSubject\n contact\n details\n deadline\n actionTaken\n updatedAt\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "f2f42ebc57de95ec4a760e7d701f90fa";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -224,6 +224,13 @@ function MainLayoutContent({
|
|||||||
to={`${prefix}/processing-activities`}
|
to={`${prefix}/processing-activities`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{isAuthorized("Organization", "listRightsRequests") && (
|
||||||
|
<SidebarItem
|
||||||
|
label={__("Rights Requests")}
|
||||||
|
icon={IconLock}
|
||||||
|
to={`${prefix}/rights-requests`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{isAuthorized("Organization", "listSnapshots") && (
|
{isAuthorized("Organization", "listSnapshots") && (
|
||||||
<SidebarItem
|
<SidebarItem
|
||||||
label={__("Snapshots")}
|
label={__("Snapshots")}
|
||||||
|
|||||||
@@ -0,0 +1,279 @@
|
|||||||
|
import {
|
||||||
|
ConnectionHandler,
|
||||||
|
usePreloadedQuery,
|
||||||
|
type PreloadedQuery,
|
||||||
|
} from "react-relay";
|
||||||
|
import {
|
||||||
|
rightsRequestNodeQuery,
|
||||||
|
useDeleteRightsRequest,
|
||||||
|
useUpdateRightsRequest,
|
||||||
|
RightsRequestsConnectionKey,
|
||||||
|
} from "../../../hooks/graph/RightsRequestGraph";
|
||||||
|
import {
|
||||||
|
ActionDropdown,
|
||||||
|
Badge,
|
||||||
|
Breadcrumb,
|
||||||
|
Button,
|
||||||
|
DropdownItem,
|
||||||
|
Field,
|
||||||
|
Option,
|
||||||
|
Input,
|
||||||
|
Card,
|
||||||
|
Textarea,
|
||||||
|
useToast,
|
||||||
|
Select,
|
||||||
|
Label,
|
||||||
|
} from "@probo/ui";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
|
import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
||||||
|
import { Controller } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
formatError,
|
||||||
|
type GraphQLError,
|
||||||
|
formatDatetime,
|
||||||
|
toDateInput,
|
||||||
|
getRightsRequestTypeLabel,
|
||||||
|
getRightsRequestTypeOptions,
|
||||||
|
getRightsRequestStateVariant,
|
||||||
|
getRightsRequestStateLabel,
|
||||||
|
getRightsRequestStateOptions,
|
||||||
|
} from "@probo/helpers";
|
||||||
|
import z from "zod";
|
||||||
|
import type { RightsRequestGraphNodeQuery } from "/hooks/graph/__generated__/RightsRequestGraphNodeQuery.graphql";
|
||||||
|
import { use } from "react";
|
||||||
|
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||||
|
|
||||||
|
const updateRequestSchema = z.object({
|
||||||
|
requestType: z.enum(["ACCESS", "DELETION", "PORTABILITY"]),
|
||||||
|
requestState: z.enum(["TODO", "IN_PROGRESS", "DONE"]),
|
||||||
|
dataSubject: z.string().optional(),
|
||||||
|
contact: z.string().optional(),
|
||||||
|
details: z.string().optional(),
|
||||||
|
deadline: z.string().optional(),
|
||||||
|
actionTaken: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
queryRef: PreloadedQuery<RightsRequestGraphNodeQuery>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RightsRequestDetailsPage(props: Props) {
|
||||||
|
const data = usePreloadedQuery<RightsRequestGraphNodeQuery>(rightsRequestNodeQuery, props.queryRef);
|
||||||
|
const request = data.node;
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const { toast } = useToast();
|
||||||
|
const organizationId = useOrganizationId();
|
||||||
|
const { isAuthorized } = use(PermissionsContext);
|
||||||
|
|
||||||
|
const updateRequest = useUpdateRightsRequest();
|
||||||
|
|
||||||
|
const connectionId = ConnectionHandler.getConnectionID(
|
||||||
|
organizationId,
|
||||||
|
RightsRequestsConnectionKey
|
||||||
|
);
|
||||||
|
|
||||||
|
const deleteRequest = useDeleteRightsRequest({ id: request.id! }, connectionId);
|
||||||
|
|
||||||
|
const { register, handleSubmit, formState, control } = useFormWithSchema(
|
||||||
|
updateRequestSchema,
|
||||||
|
{
|
||||||
|
defaultValues: {
|
||||||
|
requestType: request.requestType || "ACCESS",
|
||||||
|
requestState: request.requestState || "TODO",
|
||||||
|
dataSubject: request.dataSubject || "",
|
||||||
|
contact: request.contact || "",
|
||||||
|
details: request.details || "",
|
||||||
|
deadline: toDateInput(request.deadline),
|
||||||
|
actionTaken: request.actionTaken || "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(async (formData) => {
|
||||||
|
try {
|
||||||
|
await updateRequest({
|
||||||
|
id: request.id!,
|
||||||
|
requestType: formData.requestType,
|
||||||
|
requestState: formData.requestState,
|
||||||
|
dataSubject: formData.dataSubject || undefined,
|
||||||
|
contact: formData.contact || undefined,
|
||||||
|
details: formData.details || undefined,
|
||||||
|
deadline: formatDatetime(formData.deadline) ?? null,
|
||||||
|
actionTaken: formData.actionTaken || undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: __("Success"),
|
||||||
|
description: __("Rights request updated successfully"),
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: formatError(__("Failed to update rights request"), error as GraphQLError),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const typeOptions = getRightsRequestTypeOptions(__);
|
||||||
|
const stateOptions = getRightsRequestStateOptions(__);
|
||||||
|
|
||||||
|
const breadcrumbRequestsUrl = `/organizations/${organizationId}/rights-requests`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: __("Rights Requests"), to: breadcrumbRequestsUrl },
|
||||||
|
{ label: request.dataSubject || request.id! },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{isAuthorized("RightsRequest", "deleteRightsRequest") && (
|
||||||
|
<ActionDropdown>
|
||||||
|
<DropdownItem onClick={deleteRequest} variant="danger">
|
||||||
|
{__("Delete")}
|
||||||
|
</DropdownItem>
|
||||||
|
</ActionDropdown>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<div className="p-6">
|
||||||
|
<div className="mb-6">
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<h1 className="text-2xl font-bold">{getRightsRequestTypeLabel(__, request.requestType || "ACCESS")}</h1>
|
||||||
|
<Badge variant="neutral">{getRightsRequestTypeLabel(__, request.requestType || "ACCESS")}</Badge>
|
||||||
|
<Badge variant={getRightsRequestStateVariant(request.requestState || "TODO")}>
|
||||||
|
{getRightsRequestStateLabel(__, request.requestState || "TODO")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={onSubmit} className="space-y-4">
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="requestType"
|
||||||
|
render={({ field }) => (
|
||||||
|
<div>
|
||||||
|
<Label>{__("Request Type")} *</Label>
|
||||||
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
>
|
||||||
|
{typeOptions.map((option) => (
|
||||||
|
<Option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
{formState.errors.requestType?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.requestType.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="requestState"
|
||||||
|
render={({ field }) => (
|
||||||
|
<div>
|
||||||
|
<Label>{__("State")} *</Label>
|
||||||
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
>
|
||||||
|
{stateOptions.map((option) => (
|
||||||
|
<Option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
{formState.errors.requestState?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.requestState.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label={__("Data Subject")}
|
||||||
|
{...register("dataSubject")}
|
||||||
|
error={formState.errors.dataSubject?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label={__("Contact")}
|
||||||
|
{...register("contact")}
|
||||||
|
error={formState.errors.contact?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{__("Details")}</Label>
|
||||||
|
<Textarea
|
||||||
|
{...register("details")}
|
||||||
|
placeholder={__("Enter request details")}
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
{formState.errors.details?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.details.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<Label>{__("Deadline")}</Label>
|
||||||
|
<Input
|
||||||
|
type="date"
|
||||||
|
{...register("deadline")}
|
||||||
|
/>
|
||||||
|
{formState.errors.deadline?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.deadline.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{__("Action Taken")}</Label>
|
||||||
|
<Textarea
|
||||||
|
{...register("actionTaken")}
|
||||||
|
placeholder={__("Enter action taken")}
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
{formState.errors.actionTaken?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.actionTaken.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end pt-4">
|
||||||
|
{isAuthorized("RightsRequest", "updateRightsRequest") && (
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="primary"
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
|
>
|
||||||
|
{formState.isSubmitting ? __("Saving...") : __("Save Changes")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
IconPlusLarge,
|
||||||
|
PageHeader,
|
||||||
|
Card,
|
||||||
|
Thead,
|
||||||
|
Tbody,
|
||||||
|
Tr,
|
||||||
|
Th,
|
||||||
|
Td,
|
||||||
|
Badge,
|
||||||
|
ActionDropdown,
|
||||||
|
DropdownItem,
|
||||||
|
IconTrashCan,
|
||||||
|
Table,
|
||||||
|
useConfirm,
|
||||||
|
} from "@probo/ui";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { usePageTitle } from "@probo/hooks";
|
||||||
|
import {
|
||||||
|
ConnectionHandler,
|
||||||
|
graphql,
|
||||||
|
usePaginationFragment,
|
||||||
|
usePreloadedQuery,
|
||||||
|
useMutation,
|
||||||
|
type PreloadedQuery,
|
||||||
|
} from "react-relay";
|
||||||
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
|
import { CreateRightsRequestDialog } from "./dialogs/CreateRightsRequestDialog";
|
||||||
|
import { deleteRightsRequestMutation, RightsRequestsConnectionKey, rightsRequestsQuery } from "../../../hooks/graph/RightsRequestGraph";
|
||||||
|
import {
|
||||||
|
sprintf,
|
||||||
|
promisifyMutation,
|
||||||
|
formatDate,
|
||||||
|
getRightsRequestTypeLabel,
|
||||||
|
getRightsRequestStateVariant,
|
||||||
|
getRightsRequestStateLabel,
|
||||||
|
} from "@probo/helpers";
|
||||||
|
import type { NodeOf } from "/types";
|
||||||
|
import type {
|
||||||
|
RightsRequestsPageFragment$key,
|
||||||
|
RightsRequestsPageFragment$data,
|
||||||
|
} from "./__generated__/RightsRequestsPageFragment.graphql";
|
||||||
|
import { use } from "react";
|
||||||
|
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||||
|
import type { RightsRequestGraphListQuery } from "/hooks/graph/__generated__/RightsRequestGraphListQuery.graphql";
|
||||||
|
|
||||||
|
interface RightsRequestsPageProps {
|
||||||
|
queryRef: PreloadedQuery<RightsRequestGraphListQuery>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rightsRequestsPageFragment = graphql`
|
||||||
|
fragment RightsRequestsPageFragment on Organization
|
||||||
|
@refetchable(queryName: "RightsRequestsPageRefetchQuery")
|
||||||
|
@argumentDefinitions(
|
||||||
|
first: { type: "Int", defaultValue: 10 }
|
||||||
|
after: { type: "CursorKey" }
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
rightsRequests(
|
||||||
|
first: $first
|
||||||
|
after: $after
|
||||||
|
)
|
||||||
|
@connection(key: "RightsRequestsPage_rightsRequests") {
|
||||||
|
__id
|
||||||
|
totalCount
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
contact
|
||||||
|
details
|
||||||
|
deadline
|
||||||
|
actionTaken
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function RightsRequestsPage({ queryRef }: RightsRequestsPageProps) {
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const organizationId = useOrganizationId();
|
||||||
|
const { isAuthorized } = use(PermissionsContext);
|
||||||
|
|
||||||
|
usePageTitle(__("Rights Requests"));
|
||||||
|
|
||||||
|
const organization = usePreloadedQuery(
|
||||||
|
rightsRequestsQuery,
|
||||||
|
queryRef
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
loadNext,
|
||||||
|
hasNext,
|
||||||
|
isLoadingNext,
|
||||||
|
} = usePaginationFragment<
|
||||||
|
RightsRequestGraphListQuery,
|
||||||
|
RightsRequestsPageFragment$key
|
||||||
|
>(rightsRequestsPageFragment, organization.node);
|
||||||
|
|
||||||
|
const connectionId = ConnectionHandler.getConnectionID(
|
||||||
|
organizationId,
|
||||||
|
RightsRequestsConnectionKey
|
||||||
|
);
|
||||||
|
const requests = data?.rightsRequests?.edges?.map((edge) => edge.node) ?? [];
|
||||||
|
|
||||||
|
const hasAnyAction = (
|
||||||
|
isAuthorized("RightsRequest", "updateRightsRequest") ||
|
||||||
|
isAuthorized("RightsRequest", "deleteRightsRequest")
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<PageHeader title={__("Rights Requests")} description={__("Manage data subject rights requests.")}>
|
||||||
|
{isAuthorized("Organization", "createRightsRequest") && (
|
||||||
|
<CreateRightsRequestDialog
|
||||||
|
organizationId={organizationId}
|
||||||
|
connectionId={connectionId}
|
||||||
|
>
|
||||||
|
<Button icon={IconPlusLarge}>
|
||||||
|
{__("Add rights request")}
|
||||||
|
</Button>
|
||||||
|
</CreateRightsRequestDialog>
|
||||||
|
)}
|
||||||
|
</PageHeader>
|
||||||
|
|
||||||
|
{requests.length > 0 ? (
|
||||||
|
<Card>
|
||||||
|
<Table>
|
||||||
|
<Thead>
|
||||||
|
<Tr>
|
||||||
|
<Th>{__("Type")}</Th>
|
||||||
|
<Th>{__("State")}</Th>
|
||||||
|
<Th>{__("Data Subject")}</Th>
|
||||||
|
<Th>{__("Contact")}</Th>
|
||||||
|
<Th>{__("Deadline")}</Th>
|
||||||
|
{hasAnyAction && <Th>{__("Actions")}</Th>}
|
||||||
|
</Tr>
|
||||||
|
</Thead>
|
||||||
|
<Tbody>
|
||||||
|
{requests.map((request) => (
|
||||||
|
<RequestRow
|
||||||
|
key={request.id}
|
||||||
|
request={request}
|
||||||
|
connectionId={connectionId}
|
||||||
|
hasAnyAction={hasAnyAction}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
{hasNext && (
|
||||||
|
<div className="p-4 border-t">
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => loadNext(10)}
|
||||||
|
disabled={isLoadingNext}
|
||||||
|
>
|
||||||
|
{isLoadingNext ? __("Loading...") : __("Load more")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
) : (
|
||||||
|
<Card padded>
|
||||||
|
<div className="text-center py-12">
|
||||||
|
<h3 className="text-lg font-semibold mb-2">
|
||||||
|
{__("No rights requests yet")}
|
||||||
|
</h3>
|
||||||
|
<p className="text-txt-tertiary mb-4">
|
||||||
|
{__("Create your first rights request to get started.")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RequestRow({
|
||||||
|
request,
|
||||||
|
connectionId,
|
||||||
|
hasAnyAction,
|
||||||
|
}: {
|
||||||
|
request: NodeOf<NonNullable<RightsRequestsPageFragment$data['rightsRequests']>>;
|
||||||
|
connectionId: string;
|
||||||
|
hasAnyAction: boolean;
|
||||||
|
}) {
|
||||||
|
const organizationId = useOrganizationId();
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const [deleteRequest] = useMutation(deleteRightsRequestMutation);
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const { isAuthorized } = use(PermissionsContext);
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
confirm(
|
||||||
|
() =>
|
||||||
|
promisifyMutation(deleteRequest)({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
rightsRequestId: request.id,
|
||||||
|
},
|
||||||
|
connections: [connectionId],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
message: sprintf(
|
||||||
|
__(
|
||||||
|
"This will permanently delete the rights request. This action cannot be undone."
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const detailsUrl = `/organizations/${organizationId}/rights-requests/${request.id}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tr to={detailsUrl}>
|
||||||
|
<Td>
|
||||||
|
<Badge variant="neutral">{getRightsRequestTypeLabel(__, request.requestType)}</Badge>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Badge variant={getRightsRequestStateVariant(request.requestState)}>
|
||||||
|
{getRightsRequestStateLabel(__, request.requestState)}
|
||||||
|
</Badge>
|
||||||
|
</Td>
|
||||||
|
<Td>{request.dataSubject || "-"}</Td>
|
||||||
|
<Td>{request.contact || "-"}</Td>
|
||||||
|
<Td>
|
||||||
|
{request.deadline ? (
|
||||||
|
<time dateTime={request.deadline}>
|
||||||
|
{formatDate(request.deadline)}
|
||||||
|
</time>
|
||||||
|
) : (
|
||||||
|
<span className="text-txt-tertiary">{__("No deadline")}</span>
|
||||||
|
)}
|
||||||
|
</Td>
|
||||||
|
{hasAnyAction && (
|
||||||
|
<Td noLink width={50} className="text-end">
|
||||||
|
<ActionDropdown>
|
||||||
|
{isAuthorized("RightsRequest", "deleteRightsRequest") && (
|
||||||
|
<DropdownItem
|
||||||
|
icon={IconTrashCan}
|
||||||
|
variant="danger"
|
||||||
|
onSelect={handleDelete}
|
||||||
|
>
|
||||||
|
{__("Delete")}
|
||||||
|
</DropdownItem>
|
||||||
|
)}
|
||||||
|
</ActionDropdown>
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
|
</Tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
267
apps/console/src/pages/organizations/rightsRequests/__generated__/RightsRequestsPageFragment.graphql.ts
generated
Normal file
267
apps/console/src/pages/organizations/rightsRequests/__generated__/RightsRequestsPageFragment.graphql.ts
generated
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<4b94130573ce20c5879e717c00128fbb>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ReaderFragment } from 'relay-runtime';
|
||||||
|
export type RightsRequestState = "DONE" | "IN_PROGRESS" | "TODO";
|
||||||
|
export type RightsRequestType = "ACCESS" | "DELETION" | "PORTABILITY";
|
||||||
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type RightsRequestsPageFragment$data = {
|
||||||
|
readonly id: string;
|
||||||
|
readonly rightsRequests: {
|
||||||
|
readonly __id: string;
|
||||||
|
readonly edges: ReadonlyArray<{
|
||||||
|
readonly node: {
|
||||||
|
readonly actionTaken: string | null | undefined;
|
||||||
|
readonly contact: string | null | undefined;
|
||||||
|
readonly createdAt: any;
|
||||||
|
readonly dataSubject: string | null | undefined;
|
||||||
|
readonly deadline: any | null | undefined;
|
||||||
|
readonly details: string | null | undefined;
|
||||||
|
readonly id: string;
|
||||||
|
readonly requestState: RightsRequestState;
|
||||||
|
readonly requestType: RightsRequestType;
|
||||||
|
readonly updatedAt: any;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
readonly pageInfo: {
|
||||||
|
readonly endCursor: any | null | undefined;
|
||||||
|
readonly hasNextPage: boolean;
|
||||||
|
};
|
||||||
|
readonly totalCount: number;
|
||||||
|
};
|
||||||
|
readonly " $fragmentType": "RightsRequestsPageFragment";
|
||||||
|
};
|
||||||
|
export type RightsRequestsPageFragment$key = {
|
||||||
|
readonly " $data"?: RightsRequestsPageFragment$data;
|
||||||
|
readonly " $fragmentSpreads": FragmentRefs<"RightsRequestsPageFragment">;
|
||||||
|
};
|
||||||
|
|
||||||
|
import RightsRequestsPageRefetchQuery_graphql from './RightsRequestsPageRefetchQuery.graphql';
|
||||||
|
|
||||||
|
const node: ReaderFragment = (function(){
|
||||||
|
var v0 = [
|
||||||
|
"rightsRequests"
|
||||||
|
],
|
||||||
|
v1 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "after"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": 10,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "first"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": {
|
||||||
|
"connection": [
|
||||||
|
{
|
||||||
|
"count": "first",
|
||||||
|
"cursor": "after",
|
||||||
|
"direction": "forward",
|
||||||
|
"path": (v0/*: any*/)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refetch": {
|
||||||
|
"connection": {
|
||||||
|
"forward": {
|
||||||
|
"count": "first",
|
||||||
|
"cursor": "after"
|
||||||
|
},
|
||||||
|
"backward": null,
|
||||||
|
"path": (v0/*: any*/)
|
||||||
|
},
|
||||||
|
"fragmentPathInResult": [
|
||||||
|
"node"
|
||||||
|
],
|
||||||
|
"operation": RightsRequestsPageRefetchQuery_graphql,
|
||||||
|
"identifierInfo": {
|
||||||
|
"identifierField": "id",
|
||||||
|
"identifierQueryVariableName": "id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "RightsRequestsPageFragment",
|
||||||
|
"selections": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": "rightsRequests",
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequestConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "__RightsRequestsPage_rightsRequests_connection",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "totalCount",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequestEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequest",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestType",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestState",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "dataSubject",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "contact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "details",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deadline",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "actionTaken",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "PageInfo",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "pageInfo",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasNextPage",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "endCursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "ClientExtension",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Organization",
|
||||||
|
"abstractKey": null
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "3476c393dc97ae3d730ed5715922e987";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<dddf70832ae8eecef831e8832a782f20>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
import { FragmentRefs } from "relay-runtime";
|
||||||
|
export type RightsRequestsPageRefetchQuery$variables = {
|
||||||
|
after?: any | null | undefined;
|
||||||
|
first?: number | null | undefined;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
export type RightsRequestsPageRefetchQuery$data = {
|
||||||
|
readonly node: {
|
||||||
|
readonly " $fragmentSpreads": FragmentRefs<"RightsRequestsPageFragment">;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RightsRequestsPageRefetchQuery = {
|
||||||
|
response: RightsRequestsPageRefetchQuery$data;
|
||||||
|
variables: RightsRequestsPageRefetchQuery$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "after"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": 10,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "first"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "id",
|
||||||
|
"variableName": "id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v2 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "after",
|
||||||
|
"variableName": "after"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "first",
|
||||||
|
"variableName": "first"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__typename",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v4 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RightsRequestsPageRefetchQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"kind": "FragmentSpread",
|
||||||
|
"name": "RightsRequestsPageFragment"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Query",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RightsRequestsPageRefetchQuery",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v1/*: any*/),
|
||||||
|
"concreteType": null,
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
(v4/*: any*/),
|
||||||
|
{
|
||||||
|
"kind": "InlineFragment",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "RightsRequestConnection",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "rightsRequests",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "totalCount",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequestEdge",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "edges",
|
||||||
|
"plural": true,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "RightsRequest",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "node",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v4/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestType",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "requestState",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "dataSubject",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "contact",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "details",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deadline",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "actionTaken",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "createdAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "updatedAt",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
(v3/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "cursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "PageInfo",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "pageInfo",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasNextPage",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "endCursor",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "ClientExtension",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "__id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"filters": null,
|
||||||
|
"handle": "connection",
|
||||||
|
"key": "RightsRequestsPage_rightsRequests",
|
||||||
|
"kind": "LinkedHandle",
|
||||||
|
"name": "rightsRequests"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Organization",
|
||||||
|
"abstractKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "10c7e9a6f7813d150e34282befd799ff",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RightsRequestsPageRefetchQuery",
|
||||||
|
"operationKind": "query",
|
||||||
|
"text": "query RightsRequestsPageRefetchQuery(\n $after: CursorKey\n $first: Int = 10\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RightsRequestsPageFragment_2HEEH6\n id\n }\n}\n\nfragment RightsRequestsPageFragment_2HEEH6 on Organization {\n id\n rightsRequests(first: $first, after: $after) {\n totalCount\n edges {\n node {\n id\n requestType\n requestState\n dataSubject\n contact\n details\n deadline\n actionTaken\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "3476c393dc97ae3d730ed5715922e987";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
import { type ReactNode } from "react";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Field,
|
||||||
|
useToast,
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
useDialogRef,
|
||||||
|
Textarea,
|
||||||
|
Breadcrumb,
|
||||||
|
Label,
|
||||||
|
Select,
|
||||||
|
Option,
|
||||||
|
Input,
|
||||||
|
} from "@probo/ui";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
||||||
|
import { useCreateRightsRequest } from "../../../../hooks/graph/RightsRequestGraph";
|
||||||
|
import { Controller } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
formatError,
|
||||||
|
type GraphQLError,
|
||||||
|
formatDatetime,
|
||||||
|
getRightsRequestTypeOptions,
|
||||||
|
getRightsRequestStateOptions,
|
||||||
|
} from "@probo/helpers";
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
requestType: z.enum(["ACCESS", "DELETION", "PORTABILITY"]),
|
||||||
|
requestState: z.enum(["TODO", "IN_PROGRESS", "DONE"]),
|
||||||
|
dataSubject: z.string().optional(),
|
||||||
|
contact: z.string().optional(),
|
||||||
|
details: z.string().optional(),
|
||||||
|
deadline: z.string().optional(),
|
||||||
|
actionTaken: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormData = z.infer<typeof schema>;
|
||||||
|
|
||||||
|
interface CreateRightsRequestDialogProps {
|
||||||
|
children: ReactNode;
|
||||||
|
organizationId: string;
|
||||||
|
connectionId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CreateRightsRequestDialog({
|
||||||
|
children,
|
||||||
|
organizationId,
|
||||||
|
connectionId,
|
||||||
|
}: CreateRightsRequestDialogProps) {
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const { toast } = useToast();
|
||||||
|
const dialogRef = useDialogRef();
|
||||||
|
|
||||||
|
const createRequest = useCreateRightsRequest(connectionId || "");
|
||||||
|
|
||||||
|
const { register, handleSubmit, formState, reset, control } = useFormWithSchema(schema, {
|
||||||
|
defaultValues: {
|
||||||
|
requestType: "ACCESS" as const,
|
||||||
|
requestState: "TODO" as const,
|
||||||
|
dataSubject: "",
|
||||||
|
contact: "",
|
||||||
|
details: "",
|
||||||
|
deadline: "",
|
||||||
|
actionTaken: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(async (formData: FormData) => {
|
||||||
|
try {
|
||||||
|
await createRequest({
|
||||||
|
organizationId,
|
||||||
|
requestType: formData.requestType,
|
||||||
|
requestState: formData.requestState,
|
||||||
|
dataSubject: formData.dataSubject || undefined,
|
||||||
|
contact: formData.contact || undefined,
|
||||||
|
details: formData.details || undefined,
|
||||||
|
deadline: formatDatetime(formData.deadline),
|
||||||
|
actionTaken: formData.actionTaken || undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: __("Success"),
|
||||||
|
description: __("Rights request created successfully"),
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
|
||||||
|
reset();
|
||||||
|
dialogRef.current?.close();
|
||||||
|
} catch (error) {
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: formatError(__("Failed to create rights request"), error as GraphQLError),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const typeOptions = getRightsRequestTypeOptions(__);
|
||||||
|
const stateOptions = getRightsRequestStateOptions(__);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
ref={dialogRef}
|
||||||
|
trigger={children}
|
||||||
|
title={<Breadcrumb items={[__("Rights Requests"), __("Create Request")]} />}
|
||||||
|
className="max-w-2xl"
|
||||||
|
>
|
||||||
|
<form onSubmit={onSubmit}>
|
||||||
|
<DialogContent padded className="space-y-4">
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="requestType"
|
||||||
|
render={({ field }) => (
|
||||||
|
<div>
|
||||||
|
<Label>{__("Request Type")} *</Label>
|
||||||
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
>
|
||||||
|
{typeOptions.map((option) => (
|
||||||
|
<Option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
{formState.errors.requestType?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.requestType.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="requestState"
|
||||||
|
render={({ field }) => (
|
||||||
|
<div>
|
||||||
|
<Label>{__("State")} *</Label>
|
||||||
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
>
|
||||||
|
{stateOptions.map((option) => (
|
||||||
|
<Option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
{formState.errors.requestState?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.requestState.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label={__("Data Subject")}
|
||||||
|
{...register("dataSubject")}
|
||||||
|
placeholder={__("Enter data subject name")}
|
||||||
|
error={formState.errors.dataSubject?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
label={__("Contact")}
|
||||||
|
{...register("contact")}
|
||||||
|
placeholder={__("Enter contact information")}
|
||||||
|
error={formState.errors.contact?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{__("Details")}</Label>
|
||||||
|
<Textarea
|
||||||
|
{...register("details")}
|
||||||
|
placeholder={__("Enter request details")}
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
{formState.errors.details?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.details.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<Label>{__("Deadline")}</Label>
|
||||||
|
<Input
|
||||||
|
type="date"
|
||||||
|
{...register("deadline")}
|
||||||
|
/>
|
||||||
|
{formState.errors.deadline?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.deadline.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{__("Action Taken")}</Label>
|
||||||
|
<Textarea
|
||||||
|
{...register("actionTaken")}
|
||||||
|
placeholder={__("Enter action taken")}
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
{formState.errors.actionTaken?.message && (
|
||||||
|
<div className="text-red-500 text-sm mt-1">
|
||||||
|
{formState.errors.actionTaken.message}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="primary"
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
|
>
|
||||||
|
{formState.isSubmitting ? __("Creating...") : __("Create Request")}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import { nonconformityRoutes } from "./routes/nonconformityRoutes.ts";
|
|||||||
import { obligationRoutes } from "./routes/obligationRoutes.ts";
|
import { obligationRoutes } from "./routes/obligationRoutes.ts";
|
||||||
import { snapshotsRoutes } from "./routes/snapshotsRoutes.ts";
|
import { snapshotsRoutes } from "./routes/snapshotsRoutes.ts";
|
||||||
import { continualImprovementRoutes } from "./routes/continualImprovementRoutes.ts";
|
import { continualImprovementRoutes } from "./routes/continualImprovementRoutes.ts";
|
||||||
|
import { rightsRequestRoutes } from "./routes/rightsRequestRoutes.ts";
|
||||||
import { processingActivityRoutes } from "./routes/processingActivityRoutes.ts";
|
import { processingActivityRoutes } from "./routes/processingActivityRoutes.ts";
|
||||||
import { lazy } from "@probo/react-lazy";
|
import { lazy } from "@probo/react-lazy";
|
||||||
import { loaderFromQueryLoader, routeFromAppRoute, withQueryRef, type AppRoute } from "@probo/routes";
|
import { loaderFromQueryLoader, routeFromAppRoute, withQueryRef, type AppRoute } from "@probo/routes";
|
||||||
@@ -224,6 +225,7 @@ const routes = [
|
|||||||
...nonconformityRoutes,
|
...nonconformityRoutes,
|
||||||
...obligationRoutes,
|
...obligationRoutes,
|
||||||
...continualImprovementRoutes,
|
...continualImprovementRoutes,
|
||||||
|
...rightsRequestRoutes,
|
||||||
...processingActivityRoutes,
|
...processingActivityRoutes,
|
||||||
...snapshotsRoutes,
|
...snapshotsRoutes,
|
||||||
...trustCenterRoutes,
|
...trustCenterRoutes,
|
||||||
|
|||||||
35
apps/console/src/routes/rightsRequestRoutes.ts
Normal file
35
apps/console/src/routes/rightsRequestRoutes.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { loadQuery } from "react-relay";
|
||||||
|
import { relayEnvironment } from "/providers/RelayProviders";
|
||||||
|
import { PageSkeleton } from "/components/skeletons/PageSkeleton";
|
||||||
|
import { lazy } from "@probo/react-lazy";
|
||||||
|
import { rightsRequestsQuery, rightsRequestNodeQuery } from "/hooks/graph/RightsRequestGraph";
|
||||||
|
import type { RightsRequestGraphListQuery } from "/hooks/graph/__generated__/RightsRequestGraphListQuery.graphql";
|
||||||
|
import type { RightsRequestGraphNodeQuery } from "/hooks/graph/__generated__/RightsRequestGraphNodeQuery.graphql";
|
||||||
|
import { loaderFromQueryLoader, withQueryRef, type AppRoute } from "@probo/routes";
|
||||||
|
|
||||||
|
export const rightsRequestRoutes = [
|
||||||
|
{
|
||||||
|
path: "rights-requests",
|
||||||
|
Fallback: PageSkeleton,
|
||||||
|
loader: loaderFromQueryLoader(({ organizationId }) =>
|
||||||
|
loadQuery<RightsRequestGraphListQuery>(relayEnvironment, rightsRequestsQuery, {
|
||||||
|
organizationId,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Component: withQueryRef(lazy(
|
||||||
|
() => import("/pages/organizations/rightsRequests/RightsRequestsPage")
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "rights-requests/:requestId",
|
||||||
|
Fallback: PageSkeleton,
|
||||||
|
loader: loaderFromQueryLoader(({ requestId }) =>
|
||||||
|
loadQuery<RightsRequestGraphNodeQuery>(relayEnvironment, rightsRequestNodeQuery, {
|
||||||
|
rightsRequestId: requestId!,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Component: withQueryRef(lazy(
|
||||||
|
() => import("/pages/organizations/rightsRequests/RightsRequestDetailsPage")
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
] satisfies AppRoute[];
|
||||||
394
e2e/console/rights_request_test.go
Normal file
394
e2e/console/rights_request_test.go
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package console_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.probo.inc/probo/e2e/internal/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRightsRequest_Create(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||||
|
|
||||||
|
query := `
|
||||||
|
mutation CreateRightsRequest($input: CreateRightsRequestInput!) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
contact
|
||||||
|
details
|
||||||
|
actionTaken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
CreateRightsRequest struct {
|
||||||
|
RightsRequestEdge struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
RequestType string `json:"requestType"`
|
||||||
|
RequestState string `json:"requestState"`
|
||||||
|
DataSubject string `json:"dataSubject"`
|
||||||
|
Contact string `json:"contact"`
|
||||||
|
Details string `json:"details"`
|
||||||
|
ActionTaken string `json:"actionTaken"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"rightsRequestEdge"`
|
||||||
|
} `json:"createRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := owner.Execute(query, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"organizationId": owner.GetOrganizationID().String(),
|
||||||
|
"requestType": "ACCESS",
|
||||||
|
"requestState": "TODO",
|
||||||
|
"dataSubject": "John Doe",
|
||||||
|
"contact": "john.doe@example.com",
|
||||||
|
"details": "Request access to personal data",
|
||||||
|
"actionTaken": "Initial review completed",
|
||||||
|
},
|
||||||
|
}, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
rr := result.CreateRightsRequest.RightsRequestEdge.Node
|
||||||
|
assert.NotEmpty(t, rr.ID)
|
||||||
|
assert.Equal(t, "ACCESS", rr.RequestType)
|
||||||
|
assert.Equal(t, "TODO", rr.RequestState)
|
||||||
|
assert.Equal(t, "John Doe", rr.DataSubject)
|
||||||
|
assert.Equal(t, "john.doe@example.com", rr.Contact)
|
||||||
|
assert.Equal(t, "Request access to personal data", rr.Details)
|
||||||
|
assert.Equal(t, "Initial review completed", rr.ActionTaken)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRightsRequest_Update(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||||
|
|
||||||
|
createQuery := `
|
||||||
|
mutation CreateRightsRequest($input: CreateRightsRequestInput!) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var createResult struct {
|
||||||
|
CreateRightsRequest struct {
|
||||||
|
RightsRequestEdge struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"rightsRequestEdge"`
|
||||||
|
} `json:"createRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := owner.Execute(createQuery, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"organizationId": owner.GetOrganizationID().String(),
|
||||||
|
"requestType": "ACCESS",
|
||||||
|
"requestState": "TODO",
|
||||||
|
"dataSubject": "Original Subject",
|
||||||
|
"contact": "original@example.com",
|
||||||
|
},
|
||||||
|
}, &createResult)
|
||||||
|
require.NoError(t, err)
|
||||||
|
rrID := createResult.CreateRightsRequest.RightsRequestEdge.Node.ID
|
||||||
|
|
||||||
|
query := `
|
||||||
|
mutation UpdateRightsRequest($input: UpdateRightsRequestInput!) {
|
||||||
|
updateRightsRequest(input: $input) {
|
||||||
|
rightsRequest {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
contact
|
||||||
|
details
|
||||||
|
actionTaken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
UpdateRightsRequest struct {
|
||||||
|
RightsRequest struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
RequestType string `json:"requestType"`
|
||||||
|
RequestState string `json:"requestState"`
|
||||||
|
DataSubject string `json:"dataSubject"`
|
||||||
|
Contact string `json:"contact"`
|
||||||
|
Details string `json:"details"`
|
||||||
|
ActionTaken string `json:"actionTaken"`
|
||||||
|
} `json:"rightsRequest"`
|
||||||
|
} `json:"updateRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err = owner.Execute(query, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"id": rrID,
|
||||||
|
"requestType": "DELETION",
|
||||||
|
"requestState": "IN_PROGRESS",
|
||||||
|
"dataSubject": "Updated Subject",
|
||||||
|
"contact": "updated@example.com",
|
||||||
|
"details": "Updated details",
|
||||||
|
"actionTaken": "Processing deletion request",
|
||||||
|
},
|
||||||
|
}, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, rrID, result.UpdateRightsRequest.RightsRequest.ID)
|
||||||
|
assert.Equal(t, "DELETION", result.UpdateRightsRequest.RightsRequest.RequestType)
|
||||||
|
assert.Equal(t, "IN_PROGRESS", result.UpdateRightsRequest.RightsRequest.RequestState)
|
||||||
|
assert.Equal(t, "Updated Subject", result.UpdateRightsRequest.RightsRequest.DataSubject)
|
||||||
|
assert.Equal(t, "updated@example.com", result.UpdateRightsRequest.RightsRequest.Contact)
|
||||||
|
assert.Equal(t, "Updated details", result.UpdateRightsRequest.RightsRequest.Details)
|
||||||
|
assert.Equal(t, "Processing deletion request", result.UpdateRightsRequest.RightsRequest.ActionTaken)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRightsRequest_Delete(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||||
|
|
||||||
|
createQuery := `
|
||||||
|
mutation CreateRightsRequest($input: CreateRightsRequestInput!) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var createResult struct {
|
||||||
|
CreateRightsRequest struct {
|
||||||
|
RightsRequestEdge struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"rightsRequestEdge"`
|
||||||
|
} `json:"createRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := owner.Execute(createQuery, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"organizationId": owner.GetOrganizationID().String(),
|
||||||
|
"requestType": "ACCESS",
|
||||||
|
"requestState": "TODO",
|
||||||
|
},
|
||||||
|
}, &createResult)
|
||||||
|
require.NoError(t, err)
|
||||||
|
rrID := createResult.CreateRightsRequest.RightsRequestEdge.Node.ID
|
||||||
|
|
||||||
|
query := `
|
||||||
|
mutation DeleteRightsRequest($input: DeleteRightsRequestInput!) {
|
||||||
|
deleteRightsRequest(input: $input) {
|
||||||
|
deletedRightsRequestId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
DeleteRightsRequest struct {
|
||||||
|
DeletedRightsRequestID string `json:"deletedRightsRequestId"`
|
||||||
|
} `json:"deleteRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err = owner.Execute(query, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"rightsRequestId": rrID,
|
||||||
|
},
|
||||||
|
}, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, rrID, result.DeleteRightsRequest.DeletedRightsRequestID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRightsRequest_List(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||||
|
|
||||||
|
createQuery := `
|
||||||
|
mutation CreateRightsRequest($input: CreateRightsRequestInput!) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
_, err := owner.Do(createQuery, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"organizationId": owner.GetOrganizationID().String(),
|
||||||
|
"requestType": "ACCESS",
|
||||||
|
"requestState": "TODO",
|
||||||
|
"dataSubject": fmt.Sprintf("Subject %d", i),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := `
|
||||||
|
query GetRightsRequests($id: ID!) {
|
||||||
|
node(id: $id) {
|
||||||
|
... on Organization {
|
||||||
|
rightsRequests(first: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
requestState
|
||||||
|
dataSubject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
Node struct {
|
||||||
|
RightsRequests struct {
|
||||||
|
Edges []struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
RequestType string `json:"requestType"`
|
||||||
|
RequestState string `json:"requestState"`
|
||||||
|
DataSubject string `json:"dataSubject"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"edges"`
|
||||||
|
TotalCount int `json:"totalCount"`
|
||||||
|
} `json:"rightsRequests"`
|
||||||
|
} `json:"node"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := owner.Execute(query, map[string]any{
|
||||||
|
"id": owner.GetOrganizationID().String(),
|
||||||
|
}, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.GreaterOrEqual(t, result.Node.RightsRequests.TotalCount, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRightsRequest_TypeAndStateValues(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||||
|
|
||||||
|
t.Run("request type values", func(t *testing.T) {
|
||||||
|
types := []string{"ACCESS", "DELETION", "PORTABILITY"}
|
||||||
|
|
||||||
|
for _, requestType := range types {
|
||||||
|
t.Run(requestType, func(t *testing.T) {
|
||||||
|
query := `
|
||||||
|
mutation CreateRightsRequest($input: CreateRightsRequestInput!) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
requestType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
CreateRightsRequest struct {
|
||||||
|
RightsRequestEdge struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
RequestType string `json:"requestType"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"rightsRequestEdge"`
|
||||||
|
} `json:"createRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := owner.Execute(query, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"organizationId": owner.GetOrganizationID().String(),
|
||||||
|
"requestType": requestType,
|
||||||
|
"requestState": "TODO",
|
||||||
|
},
|
||||||
|
}, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, requestType, result.CreateRightsRequest.RightsRequestEdge.Node.RequestType)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("request state values", func(t *testing.T) {
|
||||||
|
states := []string{"TODO", "IN_PROGRESS", "DONE"}
|
||||||
|
|
||||||
|
for _, requestState := range states {
|
||||||
|
t.Run(requestState, func(t *testing.T) {
|
||||||
|
query := `
|
||||||
|
mutation CreateRightsRequest($input: CreateRightsRequestInput!) {
|
||||||
|
createRightsRequest(input: $input) {
|
||||||
|
rightsRequestEdge {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
requestState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
CreateRightsRequest struct {
|
||||||
|
RightsRequestEdge struct {
|
||||||
|
Node struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
RequestState string `json:"requestState"`
|
||||||
|
} `json:"node"`
|
||||||
|
} `json:"rightsRequestEdge"`
|
||||||
|
} `json:"createRightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := owner.Execute(query, map[string]any{
|
||||||
|
"input": map[string]any{
|
||||||
|
"organizationId": owner.GetOrganizationID().String(),
|
||||||
|
"requestType": "ACCESS",
|
||||||
|
"requestState": requestState,
|
||||||
|
},
|
||||||
|
}, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, requestState, result.CreateRightsRequest.RightsRequestEdge.Node.RequestState)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -71,3 +71,14 @@ export {
|
|||||||
getTrustCenterDocumentAccessStatusLabel,
|
getTrustCenterDocumentAccessStatusLabel,
|
||||||
type TrustCenterDocumentAccessInfo,
|
type TrustCenterDocumentAccessInfo,
|
||||||
} from "./trustCenterDocumentAccess";
|
} from "./trustCenterDocumentAccess";
|
||||||
|
export {
|
||||||
|
getRightsRequestTypeLabel,
|
||||||
|
getRightsRequestTypeOptions,
|
||||||
|
getRightsRequestStateVariant,
|
||||||
|
getRightsRequestStateLabel,
|
||||||
|
getRightsRequestStateOptions,
|
||||||
|
rightsRequestTypes,
|
||||||
|
rightsRequestStates,
|
||||||
|
type RightsRequestType,
|
||||||
|
type RightsRequestState,
|
||||||
|
} from "./rightsRequest";
|
||||||
|
|||||||
80
packages/helpers/src/rightsRequest.ts
Normal file
80
packages/helpers/src/rightsRequest.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
type Translator = (s: string) => string;
|
||||||
|
|
||||||
|
export type RightsRequestType = "ACCESS" | "DELETION" | "PORTABILITY";
|
||||||
|
|
||||||
|
export const rightsRequestTypes = [
|
||||||
|
"ACCESS",
|
||||||
|
"DELETION",
|
||||||
|
"PORTABILITY",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type RightsRequestState = "TODO" | "IN_PROGRESS" | "DONE";
|
||||||
|
|
||||||
|
export const rightsRequestStates = [
|
||||||
|
"TODO",
|
||||||
|
"IN_PROGRESS",
|
||||||
|
"DONE",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function getRightsRequestTypeLabel(__: Translator, type: RightsRequestType) {
|
||||||
|
switch (type) {
|
||||||
|
case "ACCESS":
|
||||||
|
return __("Access");
|
||||||
|
case "DELETION":
|
||||||
|
return __("Deletion");
|
||||||
|
case "PORTABILITY":
|
||||||
|
return __("Portability");
|
||||||
|
default:
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRightsRequestTypeOptions(__: Translator) {
|
||||||
|
return rightsRequestTypes.map((type) => ({
|
||||||
|
value: type,
|
||||||
|
label: __({
|
||||||
|
"ACCESS": "Access",
|
||||||
|
"DELETION": "Deletion",
|
||||||
|
"PORTABILITY": "Portability",
|
||||||
|
}[type]),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getRightsRequestStateVariant = (
|
||||||
|
state: RightsRequestState
|
||||||
|
): "danger" | "warning" | "success" | "neutral" | "info" | "outline" | "highlight" => {
|
||||||
|
switch (state) {
|
||||||
|
case "TODO":
|
||||||
|
return "warning" as const;
|
||||||
|
case "IN_PROGRESS":
|
||||||
|
return "info" as const;
|
||||||
|
case "DONE":
|
||||||
|
return "success" as const;
|
||||||
|
default:
|
||||||
|
return "neutral" as const;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getRightsRequestStateLabel(__: Translator, state: RightsRequestState) {
|
||||||
|
switch (state) {
|
||||||
|
case "TODO":
|
||||||
|
return __("To Do");
|
||||||
|
case "IN_PROGRESS":
|
||||||
|
return __("In Progress");
|
||||||
|
case "DONE":
|
||||||
|
return __("Done");
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRightsRequestStateOptions(__: Translator) {
|
||||||
|
return rightsRequestStates.map((state) => ({
|
||||||
|
value: state,
|
||||||
|
label: __({
|
||||||
|
"TODO": "To Do",
|
||||||
|
"IN_PROGRESS": "In Progress",
|
||||||
|
"DONE": "Done",
|
||||||
|
}[state]),
|
||||||
|
}));
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@ const (
|
|||||||
ActionListComplianceReports Action = "listComplianceReports"
|
ActionListComplianceReports Action = "listComplianceReports"
|
||||||
ActionListContacts Action = "listContacts"
|
ActionListContacts Action = "listContacts"
|
||||||
ActionListContinualImprovements Action = "listContinualImprovements"
|
ActionListContinualImprovements Action = "listContinualImprovements"
|
||||||
|
ActionListRightsRequests Action = "listRightsRequests"
|
||||||
ActionListControls Action = "listControls"
|
ActionListControls Action = "listControls"
|
||||||
ActionListData Action = "listData"
|
ActionListData Action = "listData"
|
||||||
ActionListDocuments Action = "listDocuments"
|
ActionListDocuments Action = "listDocuments"
|
||||||
@@ -122,6 +123,7 @@ const (
|
|||||||
ActionCreateAsset Action = "createAsset"
|
ActionCreateAsset Action = "createAsset"
|
||||||
ActionCreateAudit Action = "createAudit"
|
ActionCreateAudit Action = "createAudit"
|
||||||
ActionCreateContinualImprovement Action = "createContinualImprovement"
|
ActionCreateContinualImprovement Action = "createContinualImprovement"
|
||||||
|
ActionCreateRightsRequest Action = "createRightsRequest"
|
||||||
ActionCreateControl Action = "createControl"
|
ActionCreateControl Action = "createControl"
|
||||||
ActionCreateControlAuditMapping Action = "createControlAuditMapping"
|
ActionCreateControlAuditMapping Action = "createControlAuditMapping"
|
||||||
ActionCreateControlDocumentMapping Action = "createControlDocumentMapping"
|
ActionCreateControlDocumentMapping Action = "createControlDocumentMapping"
|
||||||
@@ -159,6 +161,7 @@ const (
|
|||||||
ActionUpdateAsset Action = "updateAsset"
|
ActionUpdateAsset Action = "updateAsset"
|
||||||
ActionUpdateAudit Action = "updateAudit"
|
ActionUpdateAudit Action = "updateAudit"
|
||||||
ActionUpdateContinualImprovement Action = "updateContinualImprovement"
|
ActionUpdateContinualImprovement Action = "updateContinualImprovement"
|
||||||
|
ActionUpdateRightsRequest Action = "updateRightsRequest"
|
||||||
ActionUpdateControl Action = "updateControl"
|
ActionUpdateControl Action = "updateControl"
|
||||||
ActionUpdateDatum Action = "updateDatum"
|
ActionUpdateDatum Action = "updateDatum"
|
||||||
ActionUpdateDocument Action = "updateDocument"
|
ActionUpdateDocument Action = "updateDocument"
|
||||||
@@ -191,6 +194,7 @@ const (
|
|||||||
ActionDeleteAudit Action = "deleteAudit"
|
ActionDeleteAudit Action = "deleteAudit"
|
||||||
ActionDeleteAuditReport Action = "deleteAuditReport"
|
ActionDeleteAuditReport Action = "deleteAuditReport"
|
||||||
ActionDeleteContinualImprovement Action = "deleteContinualImprovement"
|
ActionDeleteContinualImprovement Action = "deleteContinualImprovement"
|
||||||
|
ActionDeleteRightsRequest Action = "deleteRightsRequest"
|
||||||
ActionDeleteControl Action = "deleteControl"
|
ActionDeleteControl Action = "deleteControl"
|
||||||
ActionDeleteControlAuditMapping Action = "deleteControlAuditMapping"
|
ActionDeleteControlAuditMapping Action = "deleteControlAuditMapping"
|
||||||
ActionDeleteControlDocumentMapping Action = "deleteControlDocumentMapping"
|
ActionDeleteControlDocumentMapping Action = "deleteControlDocumentMapping"
|
||||||
@@ -299,6 +303,7 @@ var Permissions = map[uint16]map[Action][]Role{
|
|||||||
ActionListNonconformities: NonEmployeeRoles,
|
ActionListNonconformities: NonEmployeeRoles,
|
||||||
ActionListObligations: NonEmployeeRoles,
|
ActionListObligations: NonEmployeeRoles,
|
||||||
ActionListContinualImprovements: NonEmployeeRoles,
|
ActionListContinualImprovements: NonEmployeeRoles,
|
||||||
|
ActionListRightsRequests: NonEmployeeRoles,
|
||||||
ActionListProcessingActivities: NonEmployeeRoles,
|
ActionListProcessingActivities: NonEmployeeRoles,
|
||||||
ActionListSnapshots: NonEmployeeRoles,
|
ActionListSnapshots: NonEmployeeRoles,
|
||||||
ActionConfirmEmail: NonEmployeeRoles,
|
ActionConfirmEmail: NonEmployeeRoles,
|
||||||
@@ -337,6 +342,7 @@ var Permissions = map[uint16]map[Action][]Role{
|
|||||||
ActionCreateNonconformity: EditRoles,
|
ActionCreateNonconformity: EditRoles,
|
||||||
ActionCreateObligation: EditRoles,
|
ActionCreateObligation: EditRoles,
|
||||||
ActionCreateContinualImprovement: EditRoles,
|
ActionCreateContinualImprovement: EditRoles,
|
||||||
|
ActionCreateRightsRequest: EditRoles,
|
||||||
ActionCreateProcessingActivity: EditRoles,
|
ActionCreateProcessingActivity: EditRoles,
|
||||||
ActionCreateSnapshot: EditRoles,
|
ActionCreateSnapshot: EditRoles,
|
||||||
ActionCreateTrustCenterFile: EditRoles,
|
ActionCreateTrustCenterFile: EditRoles,
|
||||||
@@ -674,6 +680,13 @@ var Permissions = map[uint16]map[Action][]Role{
|
|||||||
ActionUpdateContinualImprovement: EditRoles,
|
ActionUpdateContinualImprovement: EditRoles,
|
||||||
ActionDeleteContinualImprovement: EditRoles,
|
ActionDeleteContinualImprovement: EditRoles,
|
||||||
},
|
},
|
||||||
|
coredata.RightsRequestEntityType: {
|
||||||
|
ActionGet: NonEmployeeRoles,
|
||||||
|
ActionGetOrganization: NonEmployeeRoles,
|
||||||
|
|
||||||
|
ActionUpdateRightsRequest: EditRoles,
|
||||||
|
ActionDeleteRightsRequest: EditRoles,
|
||||||
|
},
|
||||||
coredata.ProcessingActivityEntityType: {
|
coredata.ProcessingActivityEntityType: {
|
||||||
ActionGet: NonEmployeeRoles,
|
ActionGet: NonEmployeeRoles,
|
||||||
ActionGetOrganization: NonEmployeeRoles,
|
ActionGetOrganization: NonEmployeeRoles,
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ const (
|
|||||||
MeetingEntityType uint16 = 45
|
MeetingEntityType uint16 = 45
|
||||||
DataProtectionImpactAssessmentEntityType uint16 = 46
|
DataProtectionImpactAssessmentEntityType uint16 = 46
|
||||||
TransferImpactAssessmentEntityType uint16 = 47
|
TransferImpactAssessmentEntityType uint16 = 47
|
||||||
|
RightsRequestEntityType uint16 = 48
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntityInfo struct {
|
type EntityInfo struct {
|
||||||
@@ -269,6 +270,10 @@ var entityRegistry = map[uint16]EntityInfo{
|
|||||||
Model: "TransferImpactAssessment",
|
Model: "TransferImpactAssessment",
|
||||||
Table: "processing_activity_transfer_impact_assessments",
|
Table: "processing_activity_transfer_impact_assessments",
|
||||||
},
|
},
|
||||||
|
RightsRequestEntityType: {
|
||||||
|
Model: "RightsRequest",
|
||||||
|
Table: "rights_requests",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func EntityTable(entityType uint16) (string, bool) {
|
func EntityTable(entityType uint16) (string, bool) {
|
||||||
|
|||||||
37
pkg/coredata/migrations/20251226T130238Z.sql
Normal file
37
pkg/coredata/migrations/20251226T130238Z.sql
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
CREATE TYPE rights_request_type AS ENUM (
|
||||||
|
'ACCESS',
|
||||||
|
'DELETION',
|
||||||
|
'PORTABILITY'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE rights_request_state AS ENUM (
|
||||||
|
'TODO',
|
||||||
|
'IN_PROGRESS',
|
||||||
|
'DONE'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE rights_requests (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
tenant_id TEXT NOT NULL,
|
||||||
|
organization_id TEXT NOT NULL,
|
||||||
|
|
||||||
|
request_type rights_request_type NOT NULL,
|
||||||
|
request_state rights_request_state NOT NULL,
|
||||||
|
|
||||||
|
data_subject TEXT,
|
||||||
|
contact TEXT,
|
||||||
|
details TEXT,
|
||||||
|
|
||||||
|
deadline DATE,
|
||||||
|
|
||||||
|
action_taken TEXT,
|
||||||
|
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT rights_requests_organization_id_fkey
|
||||||
|
FOREIGN KEY (organization_id)
|
||||||
|
REFERENCES organizations(id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE CASCADE
|
||||||
|
);
|
||||||
41
pkg/coredata/rights_request_order_field.go
Normal file
41
pkg/coredata/rights_request_order_field.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package coredata
|
||||||
|
|
||||||
|
type RightsRequestOrderField string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RightsRequestOrderFieldCreatedAt RightsRequestOrderField = "CREATED_AT"
|
||||||
|
RightsRequestOrderFieldDeadline RightsRequestOrderField = "DEADLINE"
|
||||||
|
RightsRequestOrderFieldState RightsRequestOrderField = "STATE"
|
||||||
|
RightsRequestOrderFieldType RightsRequestOrderField = "TYPE"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p RightsRequestOrderField) Column() string {
|
||||||
|
return string(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p RightsRequestOrderField) String() string {
|
||||||
|
return string(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p RightsRequestOrderField) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(p.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RightsRequestOrderField) UnmarshalText(text []byte) error {
|
||||||
|
*p = RightsRequestOrderField(text)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
68
pkg/coredata/rights_request_state.go
Normal file
68
pkg/coredata/rights_request_state.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package coredata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RightsRequestState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RightsRequestStateTodo RightsRequestState = "TODO"
|
||||||
|
RightsRequestStateInProgress RightsRequestState = "IN_PROGRESS"
|
||||||
|
RightsRequestStateDone RightsRequestState = "DONE"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RightsRequestStates() []RightsRequestState {
|
||||||
|
return []RightsRequestState{
|
||||||
|
RightsRequestStateTodo,
|
||||||
|
RightsRequestStateInProgress,
|
||||||
|
RightsRequestStateDone,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrs RightsRequestState) String() string {
|
||||||
|
return string(rrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrs *RightsRequestState) Scan(value any) error {
|
||||||
|
var s string
|
||||||
|
switch v := value.(type) {
|
||||||
|
case string:
|
||||||
|
s = v
|
||||||
|
case []byte:
|
||||||
|
s = string(v)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type for RightsRequestState: %T", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s {
|
||||||
|
case "TODO":
|
||||||
|
*rrs = RightsRequestStateTodo
|
||||||
|
case "IN_PROGRESS":
|
||||||
|
*rrs = RightsRequestStateInProgress
|
||||||
|
case "DONE":
|
||||||
|
*rrs = RightsRequestStateDone
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid RightsRequestState value: %q", s)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrs RightsRequestState) Value() (driver.Value, error) {
|
||||||
|
return string(rrs), nil
|
||||||
|
}
|
||||||
68
pkg/coredata/rights_request_type.go
Normal file
68
pkg/coredata/rights_request_type.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package coredata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RightsRequestType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RightsRequestTypeAccess RightsRequestType = "ACCESS"
|
||||||
|
RightsRequestTypeDeletion RightsRequestType = "DELETION"
|
||||||
|
RightsRequestTypePortability RightsRequestType = "PORTABILITY"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RightsRequestTypes() []RightsRequestType {
|
||||||
|
return []RightsRequestType{
|
||||||
|
RightsRequestTypeAccess,
|
||||||
|
RightsRequestTypeDeletion,
|
||||||
|
RightsRequestTypePortability,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrt RightsRequestType) String() string {
|
||||||
|
return string(rrt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrt *RightsRequestType) Scan(value any) error {
|
||||||
|
var s string
|
||||||
|
switch v := value.(type) {
|
||||||
|
case string:
|
||||||
|
s = v
|
||||||
|
case []byte:
|
||||||
|
s = string(v)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported type for RightsRequestType: %T", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s {
|
||||||
|
case "ACCESS":
|
||||||
|
*rrt = RightsRequestTypeAccess
|
||||||
|
case "DELETION":
|
||||||
|
*rrt = RightsRequestTypeDeletion
|
||||||
|
case "PORTABILITY":
|
||||||
|
*rrt = RightsRequestTypePortability
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid RightsRequestType value: %q", s)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrt RightsRequestType) Value() (driver.Value, error) {
|
||||||
|
return string(rrt), nil
|
||||||
|
}
|
||||||
327
pkg/coredata/rights_requests.go
Normal file
327
pkg/coredata/rights_requests.go
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package coredata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"maps"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
"go.gearno.de/kit/pg"
|
||||||
|
"go.probo.inc/probo/pkg/gid"
|
||||||
|
"go.probo.inc/probo/pkg/page"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
ErrRightsRequestNotFound struct {
|
||||||
|
Identifier string
|
||||||
|
}
|
||||||
|
|
||||||
|
RightsRequest struct {
|
||||||
|
ID gid.GID `db:"id"`
|
||||||
|
OrganizationID gid.GID `db:"organization_id"`
|
||||||
|
RequestType RightsRequestType `db:"request_type"`
|
||||||
|
RequestState RightsRequestState `db:"request_state"`
|
||||||
|
DataSubject *string `db:"data_subject"`
|
||||||
|
Contact *string `db:"contact"`
|
||||||
|
Details *string `db:"details"`
|
||||||
|
Deadline *time.Time `db:"deadline"`
|
||||||
|
ActionTaken *string `db:"action_taken"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
RightsRequests []*RightsRequest
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e ErrRightsRequestNotFound) Error() string {
|
||||||
|
return fmt.Sprintf("rights request not found: %q", e.Identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RightsRequest) CursorKey(field RightsRequestOrderField) page.CursorKey {
|
||||||
|
switch field {
|
||||||
|
case RightsRequestOrderFieldCreatedAt:
|
||||||
|
return page.NewCursorKey(rr.ID, rr.CreatedAt)
|
||||||
|
case RightsRequestOrderFieldDeadline:
|
||||||
|
return page.NewCursorKey(rr.ID, rr.Deadline)
|
||||||
|
case RightsRequestOrderFieldState:
|
||||||
|
return page.NewCursorKey(rr.ID, rr.RequestState)
|
||||||
|
case RightsRequestOrderFieldType:
|
||||||
|
return page.NewCursorKey(rr.ID, rr.RequestType)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RightsRequest) LoadByID(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
rightsRequestID gid.GID,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
organization_id,
|
||||||
|
request_type,
|
||||||
|
request_state,
|
||||||
|
data_subject,
|
||||||
|
contact,
|
||||||
|
details,
|
||||||
|
deadline,
|
||||||
|
action_taken,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
FROM
|
||||||
|
rights_requests
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND id = @rights_request_id
|
||||||
|
LIMIT 1;
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"rights_request_id": rightsRequestID}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
rows, err := conn.Query(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot query rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
request, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[RightsRequest])
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return &ErrRightsRequestNotFound{Identifier: rightsRequestID.String()}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("cannot collect rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
*rr = request
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrs *RightsRequests) CountByOrganizationID(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
) (int, error) {
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
COUNT(id)
|
||||||
|
FROM
|
||||||
|
rights_requests
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND organization_id = @organization_id
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
row := conn.QueryRow(ctx, q, args)
|
||||||
|
|
||||||
|
var count int
|
||||||
|
err := row.Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("cannot count rights requests: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rrs *RightsRequests) LoadByOrganizationID(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
organizationID gid.GID,
|
||||||
|
cursor *page.Cursor[RightsRequestOrderField],
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
organization_id,
|
||||||
|
request_type,
|
||||||
|
request_state,
|
||||||
|
data_subject,
|
||||||
|
contact,
|
||||||
|
details,
|
||||||
|
deadline,
|
||||||
|
action_taken,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
FROM
|
||||||
|
rights_requests
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND organization_id = @organization_id
|
||||||
|
AND %s
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
maps.Copy(args, cursor.SQLArguments())
|
||||||
|
|
||||||
|
rows, err := conn.Query(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot query rights requests: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
requests, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[RightsRequest])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot collect rights requests: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
*rrs = requests
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RightsRequest) Insert(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
INSERT INTO rights_requests (
|
||||||
|
id,
|
||||||
|
tenant_id,
|
||||||
|
organization_id,
|
||||||
|
request_type,
|
||||||
|
request_state,
|
||||||
|
data_subject,
|
||||||
|
contact,
|
||||||
|
details,
|
||||||
|
deadline,
|
||||||
|
action_taken,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
) VALUES (
|
||||||
|
@id,
|
||||||
|
@tenant_id,
|
||||||
|
@organization_id,
|
||||||
|
@request_type,
|
||||||
|
@request_state,
|
||||||
|
@data_subject,
|
||||||
|
@contact,
|
||||||
|
@details,
|
||||||
|
@deadline,
|
||||||
|
@action_taken,
|
||||||
|
@created_at,
|
||||||
|
@updated_at
|
||||||
|
)
|
||||||
|
`
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"id": rr.ID,
|
||||||
|
"tenant_id": scope.GetTenantID(),
|
||||||
|
"organization_id": rr.OrganizationID,
|
||||||
|
"request_type": rr.RequestType,
|
||||||
|
"request_state": rr.RequestState,
|
||||||
|
"data_subject": rr.DataSubject,
|
||||||
|
"contact": rr.Contact,
|
||||||
|
"details": rr.Details,
|
||||||
|
"deadline": rr.Deadline,
|
||||||
|
"action_taken": rr.ActionTaken,
|
||||||
|
"created_at": rr.CreatedAt,
|
||||||
|
"updated_at": rr.UpdatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot insert rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RightsRequest) Update(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
UPDATE rights_requests SET
|
||||||
|
request_type = @request_type,
|
||||||
|
request_state = @request_state,
|
||||||
|
data_subject = @data_subject,
|
||||||
|
contact = @contact,
|
||||||
|
details = @details,
|
||||||
|
deadline = @deadline,
|
||||||
|
action_taken = @action_taken,
|
||||||
|
updated_at = @updated_at
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND id = @id
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"id": rr.ID,
|
||||||
|
"request_type": rr.RequestType,
|
||||||
|
"request_state": rr.RequestState,
|
||||||
|
"data_subject": rr.DataSubject,
|
||||||
|
"contact": rr.Contact,
|
||||||
|
"details": rr.Details,
|
||||||
|
"deadline": rr.Deadline,
|
||||||
|
"action_taken": rr.ActionTaken,
|
||||||
|
"updated_at": rr.UpdatedAt,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot update rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *RightsRequest) Delete(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope Scoper,
|
||||||
|
) error {
|
||||||
|
q := `
|
||||||
|
DELETE FROM rights_requests
|
||||||
|
WHERE
|
||||||
|
%s
|
||||||
|
AND id = @id
|
||||||
|
`
|
||||||
|
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"id": rr.ID}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
_, err := conn.Exec(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot delete rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
291
pkg/probo/rights_request_service.go
Normal file
291
pkg/probo/rights_request_service.go
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package probo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.gearno.de/kit/pg"
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
|
"go.probo.inc/probo/pkg/gid"
|
||||||
|
"go.probo.inc/probo/pkg/page"
|
||||||
|
"go.probo.inc/probo/pkg/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RightsRequestService struct {
|
||||||
|
svc *TenantService
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
CreateRightsRequestRequest struct {
|
||||||
|
OrganizationID gid.GID
|
||||||
|
RequestType *coredata.RightsRequestType
|
||||||
|
RequestState *coredata.RightsRequestState
|
||||||
|
DataSubject *string
|
||||||
|
Contact *string
|
||||||
|
Details *string
|
||||||
|
Deadline *time.Time
|
||||||
|
ActionTaken *string
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateRightsRequestRequest struct {
|
||||||
|
ID gid.GID
|
||||||
|
RequestType *coredata.RightsRequestType
|
||||||
|
RequestState *coredata.RightsRequestState
|
||||||
|
DataSubject **string
|
||||||
|
Contact **string
|
||||||
|
Details **string
|
||||||
|
Deadline **time.Time
|
||||||
|
ActionTaken **string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (crrr *CreateRightsRequestRequest) Validate() error {
|
||||||
|
v := validator.New()
|
||||||
|
|
||||||
|
v.Check(crrr.OrganizationID, "organization_id", validator.Required(), validator.GID(coredata.OrganizationEntityType))
|
||||||
|
v.Check(crrr.RequestType, "request_type", validator.Required(), validator.OneOfSlice(coredata.RightsRequestTypes()))
|
||||||
|
v.Check(crrr.RequestState, "request_state", validator.Required(), validator.OneOfSlice(coredata.RightsRequestStates()))
|
||||||
|
v.Check(crrr.DataSubject, "data_subject", validator.SafeText(ContentMaxLength))
|
||||||
|
v.Check(crrr.Contact, "contact", validator.SafeText(ContentMaxLength))
|
||||||
|
v.Check(crrr.Details, "details", validator.SafeText(ContentMaxLength))
|
||||||
|
v.Check(crrr.ActionTaken, "action_taken", validator.SafeText(ContentMaxLength))
|
||||||
|
|
||||||
|
return v.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (urrr *UpdateRightsRequestRequest) Validate() error {
|
||||||
|
v := validator.New()
|
||||||
|
|
||||||
|
v.Check(urrr.ID, "id", validator.Required(), validator.GID(coredata.RightsRequestEntityType))
|
||||||
|
v.Check(urrr.RequestType, "request_type", validator.OneOfSlice(coredata.RightsRequestTypes()))
|
||||||
|
v.Check(urrr.RequestState, "request_state", validator.OneOfSlice(coredata.RightsRequestStates()))
|
||||||
|
v.Check(urrr.DataSubject, "data_subject", validator.SafeText(ContentMaxLength))
|
||||||
|
v.Check(urrr.Contact, "contact", validator.SafeText(ContentMaxLength))
|
||||||
|
v.Check(urrr.Details, "details", validator.SafeText(ContentMaxLength))
|
||||||
|
v.Check(urrr.ActionTaken, "action_taken", validator.SafeText(ContentMaxLength))
|
||||||
|
|
||||||
|
return v.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s RightsRequestService) Get(
|
||||||
|
ctx context.Context,
|
||||||
|
rightsRequestID gid.GID,
|
||||||
|
) (*coredata.RightsRequest, error) {
|
||||||
|
request := &coredata.RightsRequest{}
|
||||||
|
|
||||||
|
err := s.svc.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
if err := request.LoadByID(ctx, conn, s.svc.scope, rightsRequestID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return request, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RightsRequestService) Create(
|
||||||
|
ctx context.Context,
|
||||||
|
req *CreateRightsRequestRequest,
|
||||||
|
) (*coredata.RightsRequest, error) {
|
||||||
|
if err := req.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
request := &coredata.RightsRequest{
|
||||||
|
ID: gid.New(s.svc.scope.GetTenantID(), coredata.RightsRequestEntityType),
|
||||||
|
OrganizationID: req.OrganizationID,
|
||||||
|
RequestType: *req.RequestType,
|
||||||
|
RequestState: *req.RequestState,
|
||||||
|
DataSubject: req.DataSubject,
|
||||||
|
Contact: req.Contact,
|
||||||
|
Details: req.Details,
|
||||||
|
Deadline: req.Deadline,
|
||||||
|
ActionTaken: req.ActionTaken,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.svc.pg.WithTx(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
organization := &coredata.Organization{}
|
||||||
|
if err := organization.LoadByID(ctx, conn, s.svc.scope, req.OrganizationID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load organization: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := request.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot insert rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return request, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RightsRequestService) Update(
|
||||||
|
ctx context.Context,
|
||||||
|
req *UpdateRightsRequestRequest,
|
||||||
|
) (*coredata.RightsRequest, error) {
|
||||||
|
if err := req.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &coredata.RightsRequest{}
|
||||||
|
|
||||||
|
err := s.svc.pg.WithTx(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
if err := request.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.RequestType != nil {
|
||||||
|
request.RequestType = *req.RequestType
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.RequestState != nil {
|
||||||
|
request.RequestState = *req.RequestState
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.DataSubject != nil {
|
||||||
|
request.DataSubject = *req.DataSubject
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Contact != nil {
|
||||||
|
request.Contact = *req.Contact
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Details != nil {
|
||||||
|
request.Details = *req.Details
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Deadline != nil {
|
||||||
|
request.Deadline = *req.Deadline
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.ActionTaken != nil {
|
||||||
|
request.ActionTaken = *req.ActionTaken
|
||||||
|
}
|
||||||
|
|
||||||
|
request.UpdatedAt = time.Now()
|
||||||
|
|
||||||
|
if err := request.Update(ctx, conn, s.svc.scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot update rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return request, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RightsRequestService) Delete(
|
||||||
|
ctx context.Context,
|
||||||
|
rightsRequestID gid.GID,
|
||||||
|
) error {
|
||||||
|
err := s.svc.pg.WithTx(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
request := &coredata.RightsRequest{}
|
||||||
|
if err := request.LoadByID(ctx, conn, s.svc.scope, rightsRequestID); err != nil {
|
||||||
|
return fmt.Errorf("cannot load rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := request.Delete(ctx, conn, s.svc.scope); err != nil {
|
||||||
|
return fmt.Errorf("cannot delete rights request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s RightsRequestService) CountByOrganizationID(
|
||||||
|
ctx context.Context,
|
||||||
|
organizationID gid.GID,
|
||||||
|
) (int, error) {
|
||||||
|
var count int
|
||||||
|
|
||||||
|
err := s.svc.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) (err error) {
|
||||||
|
requests := coredata.RightsRequests{}
|
||||||
|
count, err = requests.CountByOrganizationID(ctx, conn, s.svc.scope, organizationID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot count rights requests: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s RightsRequestService) ListForOrganizationID(
|
||||||
|
ctx context.Context,
|
||||||
|
organizationID gid.GID,
|
||||||
|
cursor *page.Cursor[coredata.RightsRequestOrderField],
|
||||||
|
) (*page.Page[*coredata.RightsRequest, coredata.RightsRequestOrderField], error) {
|
||||||
|
var requests coredata.RightsRequests
|
||||||
|
|
||||||
|
err := s.svc.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
err := requests.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot load rights requests: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return page.NewPage(requests, cursor), nil
|
||||||
|
}
|
||||||
@@ -113,6 +113,7 @@ type (
|
|||||||
Obligations *ObligationService
|
Obligations *ObligationService
|
||||||
Snapshots *SnapshotService
|
Snapshots *SnapshotService
|
||||||
ContinualImprovements *ContinualImprovementService
|
ContinualImprovements *ContinualImprovementService
|
||||||
|
RightsRequests *RightsRequestService
|
||||||
ProcessingActivities *ProcessingActivityService
|
ProcessingActivities *ProcessingActivityService
|
||||||
DataProtectionImpactAssessments *DataProtectionImpactAssessmentService
|
DataProtectionImpactAssessments *DataProtectionImpactAssessmentService
|
||||||
TransferImpactAssessments *TransferImpactAssessmentService
|
TransferImpactAssessments *TransferImpactAssessmentService
|
||||||
@@ -250,6 +251,7 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
|
|||||||
tenantService.Obligations = &ObligationService{svc: tenantService}
|
tenantService.Obligations = &ObligationService{svc: tenantService}
|
||||||
tenantService.Snapshots = &SnapshotService{svc: tenantService}
|
tenantService.Snapshots = &SnapshotService{svc: tenantService}
|
||||||
tenantService.ContinualImprovements = &ContinualImprovementService{svc: tenantService}
|
tenantService.ContinualImprovements = &ContinualImprovementService{svc: tenantService}
|
||||||
|
tenantService.RightsRequests = &RightsRequestService{svc: tenantService}
|
||||||
tenantService.ProcessingActivities = &ProcessingActivityService{svc: tenantService}
|
tenantService.ProcessingActivities = &ProcessingActivityService{svc: tenantService}
|
||||||
tenantService.DataProtectionImpactAssessments = &DataProtectionImpactAssessmentService{svc: tenantService}
|
tenantService.DataProtectionImpactAssessments = &DataProtectionImpactAssessmentService{svc: tenantService}
|
||||||
tenantService.TransferImpactAssessments = &TransferImpactAssessmentService{svc: tenantService}
|
tenantService.TransferImpactAssessments = &TransferImpactAssessmentService{svc: tenantService}
|
||||||
|
|||||||
@@ -260,6 +260,42 @@ enum ContinualImprovementPriority
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum RightsRequestType
|
||||||
|
@goModel(
|
||||||
|
model: "go.probo.inc/probo/pkg/coredata.RightsRequestType"
|
||||||
|
) {
|
||||||
|
ACCESS
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestTypeAccess"
|
||||||
|
)
|
||||||
|
DELETION
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestTypeDeletion"
|
||||||
|
)
|
||||||
|
PORTABILITY
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestTypePortability"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RightsRequestState
|
||||||
|
@goModel(
|
||||||
|
model: "go.probo.inc/probo/pkg/coredata.RightsRequestState"
|
||||||
|
) {
|
||||||
|
TODO
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestStateTodo"
|
||||||
|
)
|
||||||
|
IN_PROGRESS
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestStateInProgress"
|
||||||
|
)
|
||||||
|
DONE
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestStateDone"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
enum ProcessingActivitySpecialOrCriminalDatum
|
enum ProcessingActivitySpecialOrCriminalDatum
|
||||||
@goModel(
|
@goModel(
|
||||||
model: "go.probo.inc/probo/pkg/coredata.ProcessingActivitySpecialOrCriminalDatum"
|
model: "go.probo.inc/probo/pkg/coredata.ProcessingActivitySpecialOrCriminalDatum"
|
||||||
@@ -1065,6 +1101,28 @@ enum ContinualImprovementOrderField
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum RightsRequestOrderField
|
||||||
|
@goModel(
|
||||||
|
model: "go.probo.inc/probo/pkg/coredata.RightsRequestOrderField"
|
||||||
|
) {
|
||||||
|
CREATED_AT
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestOrderFieldCreatedAt"
|
||||||
|
)
|
||||||
|
DEADLINE
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestOrderFieldDeadline"
|
||||||
|
)
|
||||||
|
STATE
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestOrderFieldState"
|
||||||
|
)
|
||||||
|
TYPE
|
||||||
|
@goEnum(
|
||||||
|
value: "go.probo.inc/probo/pkg/coredata.RightsRequestOrderFieldType"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
enum ProcessingActivityOrderField
|
enum ProcessingActivityOrderField
|
||||||
@goModel(
|
@goModel(
|
||||||
model: "go.probo.inc/probo/pkg/coredata.ProcessingActivityOrderField"
|
model: "go.probo.inc/probo/pkg/coredata.ProcessingActivityOrderField"
|
||||||
@@ -1344,6 +1402,14 @@ input ContinualImprovementOrder
|
|||||||
field: ContinualImprovementOrderField!
|
field: ContinualImprovementOrderField!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input RightsRequestOrder
|
||||||
|
@goModel(
|
||||||
|
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.RightsRequestOrderBy"
|
||||||
|
) {
|
||||||
|
direction: OrderDirection!
|
||||||
|
field: RightsRequestOrderField!
|
||||||
|
}
|
||||||
|
|
||||||
input ProcessingActivityOrder
|
input ProcessingActivityOrder
|
||||||
@goModel(
|
@goModel(
|
||||||
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.ProcessingActivityOrderBy"
|
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.ProcessingActivityOrderBy"
|
||||||
@@ -1513,6 +1579,7 @@ input ContinualImprovementFilter {
|
|||||||
snapshotId: ID
|
snapshotId: ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
input ProcessingActivityFilter {
|
input ProcessingActivityFilter {
|
||||||
snapshotId: ID
|
snapshotId: ID
|
||||||
}
|
}
|
||||||
@@ -1727,6 +1794,14 @@ type Organization implements Node {
|
|||||||
filter: ContinualImprovementFilter = { snapshotId: null }
|
filter: ContinualImprovementFilter = { snapshotId: null }
|
||||||
): ContinualImprovementConnection! @goField(forceResolver: true)
|
): ContinualImprovementConnection! @goField(forceResolver: true)
|
||||||
|
|
||||||
|
rightsRequests(
|
||||||
|
first: Int
|
||||||
|
after: CursorKey
|
||||||
|
last: Int
|
||||||
|
before: CursorKey
|
||||||
|
orderBy: RightsRequestOrder
|
||||||
|
): RightsRequestConnection! @goField(forceResolver: true)
|
||||||
|
|
||||||
processingActivities(
|
processingActivities(
|
||||||
first: Int
|
first: Int
|
||||||
after: CursorKey
|
after: CursorKey
|
||||||
@@ -2326,6 +2401,20 @@ type ContinualImprovement implements Node {
|
|||||||
updatedAt: Datetime!
|
updatedAt: Datetime!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RightsRequest implements Node {
|
||||||
|
id: ID!
|
||||||
|
organization: Organization! @goField(forceResolver: true)
|
||||||
|
requestType: RightsRequestType!
|
||||||
|
requestState: RightsRequestState!
|
||||||
|
dataSubject: String
|
||||||
|
contact: String
|
||||||
|
details: String
|
||||||
|
deadline: Datetime
|
||||||
|
actionTaken: String
|
||||||
|
createdAt: Datetime!
|
||||||
|
updatedAt: Datetime!
|
||||||
|
}
|
||||||
|
|
||||||
type ProcessingActivity implements Node {
|
type ProcessingActivity implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
snapshotId: ID
|
snapshotId: ID
|
||||||
@@ -2879,6 +2968,20 @@ type ContinualImprovementEdge {
|
|||||||
node: ContinualImprovement!
|
node: ContinualImprovement!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RightsRequestConnection
|
||||||
|
@goModel(
|
||||||
|
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.RightsRequestConnection"
|
||||||
|
) {
|
||||||
|
totalCount: Int! @goField(forceResolver: true)
|
||||||
|
edges: [RightsRequestEdge!]!
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
}
|
||||||
|
|
||||||
|
type RightsRequestEdge {
|
||||||
|
cursor: CursorKey!
|
||||||
|
node: RightsRequest!
|
||||||
|
}
|
||||||
|
|
||||||
type ProcessingActivityConnection
|
type ProcessingActivityConnection
|
||||||
@goModel(
|
@goModel(
|
||||||
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.ProcessingActivityConnection"
|
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.ProcessingActivityConnection"
|
||||||
@@ -3246,6 +3349,20 @@ type Mutation {
|
|||||||
deleteContinualImprovement(
|
deleteContinualImprovement(
|
||||||
input: DeleteContinualImprovementInput!
|
input: DeleteContinualImprovementInput!
|
||||||
): DeleteContinualImprovementPayload!
|
): DeleteContinualImprovementPayload!
|
||||||
|
|
||||||
|
# Rights Request mutations
|
||||||
|
createRightsRequest(
|
||||||
|
input: CreateRightsRequestInput!
|
||||||
|
): CreateRightsRequestPayload!
|
||||||
|
|
||||||
|
updateRightsRequest(
|
||||||
|
input: UpdateRightsRequestInput!
|
||||||
|
): UpdateRightsRequestPayload!
|
||||||
|
|
||||||
|
deleteRightsRequest(
|
||||||
|
input: DeleteRightsRequestInput!
|
||||||
|
): DeleteRightsRequestPayload!
|
||||||
|
|
||||||
# Processing Activity mutations
|
# Processing Activity mutations
|
||||||
createProcessingActivity(
|
createProcessingActivity(
|
||||||
input: CreateProcessingActivityInput!
|
input: CreateProcessingActivityInput!
|
||||||
@@ -4022,6 +4139,32 @@ input DeleteContinualImprovementInput {
|
|||||||
continualImprovementId: ID!
|
continualImprovementId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input CreateRightsRequestInput {
|
||||||
|
organizationId: ID!
|
||||||
|
requestType: RightsRequestType!
|
||||||
|
requestState: RightsRequestState!
|
||||||
|
dataSubject: String
|
||||||
|
contact: String
|
||||||
|
details: String
|
||||||
|
deadline: Datetime
|
||||||
|
actionTaken: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input UpdateRightsRequestInput {
|
||||||
|
id: ID!
|
||||||
|
requestType: RightsRequestType
|
||||||
|
requestState: RightsRequestState
|
||||||
|
dataSubject: String @goField(omittable: true)
|
||||||
|
contact: String @goField(omittable: true)
|
||||||
|
details: String @goField(omittable: true)
|
||||||
|
deadline: Datetime @goField(omittable: true)
|
||||||
|
actionTaken: String @goField(omittable: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
input DeleteRightsRequestInput {
|
||||||
|
rightsRequestId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
input CreateProcessingActivityInput {
|
input CreateProcessingActivityInput {
|
||||||
organizationId: ID!
|
organizationId: ID!
|
||||||
name: String!
|
name: String!
|
||||||
@@ -4964,6 +5107,18 @@ type DeleteContinualImprovementPayload {
|
|||||||
deletedContinualImprovementId: ID!
|
deletedContinualImprovementId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreateRightsRequestPayload {
|
||||||
|
rightsRequestEdge: RightsRequestEdge!
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateRightsRequestPayload {
|
||||||
|
rightsRequest: RightsRequest!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteRightsRequestPayload {
|
||||||
|
deletedRightsRequestId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type CreateProcessingActivityPayload {
|
type CreateProcessingActivityPayload {
|
||||||
processingActivityEdge: ProcessingActivityEdge!
|
processingActivityEdge: ProcessingActivityEdge!
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
75
pkg/server/api/console/v1/types/rights_request.go
Normal file
75
pkg/server/api/console/v1/types/rights_request.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
|
"go.probo.inc/probo/pkg/gid"
|
||||||
|
"go.probo.inc/probo/pkg/page"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
RightsRequestOrderBy OrderBy[coredata.RightsRequestOrderField]
|
||||||
|
|
||||||
|
RightsRequestConnection struct {
|
||||||
|
TotalCount int
|
||||||
|
Edges []*RightsRequestEdge
|
||||||
|
PageInfo PageInfo
|
||||||
|
|
||||||
|
Resolver any
|
||||||
|
ParentID gid.GID
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRightsRequestConnection(
|
||||||
|
p *page.Page[*coredata.RightsRequest, coredata.RightsRequestOrderField],
|
||||||
|
parentType any,
|
||||||
|
parentID gid.GID,
|
||||||
|
) *RightsRequestConnection {
|
||||||
|
edges := make([]*RightsRequestEdge, len(p.Data))
|
||||||
|
for i, request := range p.Data {
|
||||||
|
edges[i] = NewRightsRequestEdge(request, p.Cursor.OrderBy.Field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &RightsRequestConnection{
|
||||||
|
Edges: edges,
|
||||||
|
PageInfo: *NewPageInfo(p),
|
||||||
|
|
||||||
|
Resolver: parentType,
|
||||||
|
ParentID: parentID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRightsRequest(rr *coredata.RightsRequest) *RightsRequest {
|
||||||
|
return &RightsRequest{
|
||||||
|
ID: rr.ID,
|
||||||
|
RequestType: rr.RequestType,
|
||||||
|
RequestState: rr.RequestState,
|
||||||
|
DataSubject: rr.DataSubject,
|
||||||
|
Contact: rr.Contact,
|
||||||
|
Details: rr.Details,
|
||||||
|
Deadline: rr.Deadline,
|
||||||
|
ActionTaken: rr.ActionTaken,
|
||||||
|
CreatedAt: rr.CreatedAt,
|
||||||
|
UpdatedAt: rr.UpdatedAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRightsRequestEdge(rr *coredata.RightsRequest, orderField coredata.RightsRequestOrderField) *RightsRequestEdge {
|
||||||
|
return &RightsRequestEdge{
|
||||||
|
Node: NewRightsRequest(rr),
|
||||||
|
Cursor: rr.CursorKey(orderField),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -464,6 +464,21 @@ type CreateProcessingActivityPayload struct {
|
|||||||
ProcessingActivityEdge *ProcessingActivityEdge `json:"processingActivityEdge"`
|
ProcessingActivityEdge *ProcessingActivityEdge `json:"processingActivityEdge"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreateRightsRequestInput struct {
|
||||||
|
OrganizationID gid.GID `json:"organizationId"`
|
||||||
|
RequestType coredata.RightsRequestType `json:"requestType"`
|
||||||
|
RequestState coredata.RightsRequestState `json:"requestState"`
|
||||||
|
DataSubject *string `json:"dataSubject,omitempty"`
|
||||||
|
Contact *string `json:"contact,omitempty"`
|
||||||
|
Details *string `json:"details,omitempty"`
|
||||||
|
Deadline *time.Time `json:"deadline,omitempty"`
|
||||||
|
ActionTaken *string `json:"actionTaken,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateRightsRequestPayload struct {
|
||||||
|
RightsRequestEdge *RightsRequestEdge `json:"rightsRequestEdge"`
|
||||||
|
}
|
||||||
|
|
||||||
type CreateRiskDocumentMappingInput struct {
|
type CreateRiskDocumentMappingInput struct {
|
||||||
RiskID gid.GID `json:"riskId"`
|
RiskID gid.GID `json:"riskId"`
|
||||||
DocumentID gid.GID `json:"documentId"`
|
DocumentID gid.GID `json:"documentId"`
|
||||||
@@ -934,6 +949,14 @@ type DeleteProcessingActivityPayload struct {
|
|||||||
DeletedProcessingActivityID gid.GID `json:"deletedProcessingActivityId"`
|
DeletedProcessingActivityID gid.GID `json:"deletedProcessingActivityId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeleteRightsRequestInput struct {
|
||||||
|
RightsRequestID gid.GID `json:"rightsRequestId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteRightsRequestPayload struct {
|
||||||
|
DeletedRightsRequestID gid.GID `json:"deletedRightsRequestId"`
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteRiskDocumentMappingInput struct {
|
type DeleteRiskDocumentMappingInput struct {
|
||||||
RiskID gid.GID `json:"riskId"`
|
RiskID gid.GID `json:"riskId"`
|
||||||
DocumentID gid.GID `json:"documentId"`
|
DocumentID gid.GID `json:"documentId"`
|
||||||
@@ -1515,6 +1538,7 @@ type Organization struct {
|
|||||||
Nonconformities *NonconformityConnection `json:"nonconformities"`
|
Nonconformities *NonconformityConnection `json:"nonconformities"`
|
||||||
Obligations *ObligationConnection `json:"obligations"`
|
Obligations *ObligationConnection `json:"obligations"`
|
||||||
ContinualImprovements *ContinualImprovementConnection `json:"continualImprovements"`
|
ContinualImprovements *ContinualImprovementConnection `json:"continualImprovements"`
|
||||||
|
RightsRequests *RightsRequestConnection `json:"rightsRequests"`
|
||||||
ProcessingActivities *ProcessingActivityConnection `json:"processingActivities"`
|
ProcessingActivities *ProcessingActivityConnection `json:"processingActivities"`
|
||||||
DataProtectionImpactAssessments *DataProtectionImpactAssessmentConnection `json:"dataProtectionImpactAssessments"`
|
DataProtectionImpactAssessments *DataProtectionImpactAssessmentConnection `json:"dataProtectionImpactAssessments"`
|
||||||
TransferImpactAssessments *TransferImpactAssessmentConnection `json:"transferImpactAssessments"`
|
TransferImpactAssessments *TransferImpactAssessmentConnection `json:"transferImpactAssessments"`
|
||||||
@@ -1682,6 +1706,28 @@ type RequestSignaturePayload struct {
|
|||||||
DocumentVersionSignatureEdge *DocumentVersionSignatureEdge `json:"documentVersionSignatureEdge"`
|
DocumentVersionSignatureEdge *DocumentVersionSignatureEdge `json:"documentVersionSignatureEdge"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RightsRequest struct {
|
||||||
|
ID gid.GID `json:"id"`
|
||||||
|
Organization *Organization `json:"organization"`
|
||||||
|
RequestType coredata.RightsRequestType `json:"requestType"`
|
||||||
|
RequestState coredata.RightsRequestState `json:"requestState"`
|
||||||
|
DataSubject *string `json:"dataSubject,omitempty"`
|
||||||
|
Contact *string `json:"contact,omitempty"`
|
||||||
|
Details *string `json:"details,omitempty"`
|
||||||
|
Deadline *time.Time `json:"deadline,omitempty"`
|
||||||
|
ActionTaken *string `json:"actionTaken,omitempty"`
|
||||||
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (RightsRequest) IsNode() {}
|
||||||
|
func (this RightsRequest) GetID() gid.GID { return this.ID }
|
||||||
|
|
||||||
|
type RightsRequestEdge struct {
|
||||||
|
Cursor page.CursorKey `json:"cursor"`
|
||||||
|
Node *RightsRequest `json:"node"`
|
||||||
|
}
|
||||||
|
|
||||||
type Risk struct {
|
type Risk struct {
|
||||||
ID gid.GID `json:"id"`
|
ID gid.GID `json:"id"`
|
||||||
SnapshotID *gid.GID `json:"snapshotId,omitempty"`
|
SnapshotID *gid.GID `json:"snapshotId,omitempty"`
|
||||||
@@ -2199,6 +2245,21 @@ type UpdateProcessingActivityPayload struct {
|
|||||||
ProcessingActivity *ProcessingActivity `json:"processingActivity"`
|
ProcessingActivity *ProcessingActivity `json:"processingActivity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateRightsRequestInput struct {
|
||||||
|
ID gid.GID `json:"id"`
|
||||||
|
RequestType *coredata.RightsRequestType `json:"requestType,omitempty"`
|
||||||
|
RequestState *coredata.RightsRequestState `json:"requestState,omitempty"`
|
||||||
|
DataSubject graphql.Omittable[*string] `json:"dataSubject,omitempty"`
|
||||||
|
Contact graphql.Omittable[*string] `json:"contact,omitempty"`
|
||||||
|
Details graphql.Omittable[*string] `json:"details,omitempty"`
|
||||||
|
Deadline graphql.Omittable[*time.Time] `json:"deadline,omitempty"`
|
||||||
|
ActionTaken graphql.Omittable[*string] `json:"actionTaken,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateRightsRequestPayload struct {
|
||||||
|
RightsRequest *RightsRequest `json:"rightsRequest"`
|
||||||
|
}
|
||||||
|
|
||||||
type UpdateRiskInput struct {
|
type UpdateRiskInput struct {
|
||||||
ID gid.GID `json:"id"`
|
ID gid.GID `json:"id"`
|
||||||
Name *string `json:"name,omitempty"`
|
Name *string `json:"name,omitempty"`
|
||||||
|
|||||||
@@ -4243,6 +4243,76 @@ func (r *mutationResolver) DeleteContinualImprovement(ctx context.Context, input
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateRightsRequest is the resolver for the createRightsRequest field.
|
||||||
|
func (r *mutationResolver) CreateRightsRequest(ctx context.Context, input types.CreateRightsRequestInput) (*types.CreateRightsRequestPayload, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateRightsRequest)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, input.OrganizationID.TenantID())
|
||||||
|
|
||||||
|
req := probo.CreateRightsRequestRequest{
|
||||||
|
OrganizationID: input.OrganizationID,
|
||||||
|
RequestType: &input.RequestType,
|
||||||
|
RequestState: &input.RequestState,
|
||||||
|
DataSubject: input.DataSubject,
|
||||||
|
Contact: input.Contact,
|
||||||
|
Details: input.Details,
|
||||||
|
Deadline: input.Deadline,
|
||||||
|
ActionTaken: input.ActionTaken,
|
||||||
|
}
|
||||||
|
|
||||||
|
rightsRequest, err := prb.RightsRequests.Create(ctx, &req)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot create rights request: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.CreateRightsRequestPayload{
|
||||||
|
RightsRequestEdge: types.NewRightsRequestEdge(rightsRequest, coredata.RightsRequestOrderFieldCreatedAt),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateRightsRequest is the resolver for the updateRightsRequest field.
|
||||||
|
func (r *mutationResolver) UpdateRightsRequest(ctx context.Context, input types.UpdateRightsRequestInput) (*types.UpdateRightsRequestPayload, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateRightsRequest)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, input.ID.TenantID())
|
||||||
|
|
||||||
|
req := probo.UpdateRightsRequestRequest{
|
||||||
|
ID: input.ID,
|
||||||
|
RequestType: input.RequestType,
|
||||||
|
RequestState: input.RequestState,
|
||||||
|
DataSubject: UnwrapOmittable(input.DataSubject),
|
||||||
|
Contact: UnwrapOmittable(input.Contact),
|
||||||
|
Details: UnwrapOmittable(input.Details),
|
||||||
|
Deadline: UnwrapOmittable(input.Deadline),
|
||||||
|
ActionTaken: UnwrapOmittable(input.ActionTaken),
|
||||||
|
}
|
||||||
|
|
||||||
|
rightsRequest, err := prb.RightsRequests.Update(ctx, &req)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot update rights request: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.UpdateRightsRequestPayload{
|
||||||
|
RightsRequest: types.NewRightsRequest(rightsRequest),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRightsRequest is the resolver for the deleteRightsRequest field.
|
||||||
|
func (r *mutationResolver) DeleteRightsRequest(ctx context.Context, input types.DeleteRightsRequestInput) (*types.DeleteRightsRequestPayload, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.RightsRequestID, authz.ActionDeleteRightsRequest)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, input.RightsRequestID.TenantID())
|
||||||
|
|
||||||
|
err := prb.RightsRequests.Delete(ctx, input.RightsRequestID)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot delete rights request: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.DeleteRightsRequestPayload{
|
||||||
|
DeletedRightsRequestID: input.RightsRequestID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateProcessingActivity is the resolver for the createProcessingActivity field.
|
// CreateProcessingActivity is the resolver for the createProcessingActivity field.
|
||||||
func (r *mutationResolver) CreateProcessingActivity(ctx context.Context, input types.CreateProcessingActivityInput) (*types.CreateProcessingActivityPayload, error) {
|
func (r *mutationResolver) CreateProcessingActivity(ctx context.Context, input types.CreateProcessingActivityInput) (*types.CreateProcessingActivityPayload, error) {
|
||||||
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateProcessingActivity)
|
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateProcessingActivity)
|
||||||
@@ -5535,6 +5605,34 @@ func (r *organizationResolver) ContinualImprovements(ctx context.Context, obj *t
|
|||||||
return types.NewContinualImprovementConnection(page, r, obj.ID, filter), nil
|
return types.NewContinualImprovementConnection(page, r, obj.ID, filter), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RightsRequests is the resolver for the rightsRequests field.
|
||||||
|
func (r *organizationResolver) RightsRequests(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RightsRequestOrderBy) (*types.RightsRequestConnection, error) {
|
||||||
|
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListRightsRequests)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.RightsRequestOrderField]{
|
||||||
|
Field: coredata.RightsRequestOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
if orderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.RightsRequestOrderField]{
|
||||||
|
Field: orderBy.Field,
|
||||||
|
Direction: orderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||||
|
|
||||||
|
page, err := prb.RightsRequests.ListForOrganizationID(ctx, obj.ID, cursor)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot list organization rights requests: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewRightsRequestConnection(page, r, obj.ID), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ProcessingActivities is the resolver for the processingActivities field.
|
// ProcessingActivities is the resolver for the processingActivities field.
|
||||||
func (r *organizationResolver) ProcessingActivities(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProcessingActivityOrderBy, filter *types.ProcessingActivityFilter) (*types.ProcessingActivityConnection, error) {
|
func (r *organizationResolver) ProcessingActivities(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProcessingActivityOrderBy, filter *types.ProcessingActivityFilter) (*types.ProcessingActivityConnection, error) {
|
||||||
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListProcessingActivities)
|
r.MustBeAuthorized(ctx, obj.ID, authz.ActionListProcessingActivities)
|
||||||
@@ -6146,6 +6244,17 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
return types.NewMeeting(meeting), nil
|
return types.NewMeeting(meeting), nil
|
||||||
|
case coredata.RightsRequestEntityType:
|
||||||
|
rightsRequest, err := prb.RightsRequests.Get(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
var errNotFound *coredata.ErrRightsRequestNotFound
|
||||||
|
if errors.As(err, &errNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(errNotFound)
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("cannot get rights request: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewRightsRequest(rightsRequest), nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6201,6 +6310,48 @@ func (r *reportResolver) Audit(ctx context.Context, obj *types.Report) (*types.A
|
|||||||
return types.NewAudit(audit), nil
|
return types.NewAudit(audit), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Organization is the resolver for the organization field.
|
||||||
|
func (r *rightsRequestResolver) Organization(ctx context.Context, obj *types.RightsRequest) (*types.Organization, error) {
|
||||||
|
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOrganization)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
|
rightsRequest, err := prb.RightsRequests.Get(ctx, obj.ID)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot get rights request: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
organization, err := prb.Organizations.Get(ctx, rightsRequest.OrganizationID)
|
||||||
|
if err != nil {
|
||||||
|
var errNotFound *coredata.ErrOrganizationNotFound
|
||||||
|
if errors.As(err, &errNotFound) {
|
||||||
|
return nil, gqlutils.NotFound(errNotFound)
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("cannot get organization: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewOrganization(organization), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalCount is the resolver for the totalCount field.
|
||||||
|
func (r *rightsRequestConnectionResolver) TotalCount(ctx context.Context, obj *types.RightsRequestConnection) (int, error) {
|
||||||
|
r.MustBeAuthorized(ctx, obj.ParentID, authz.ActionTotalCount)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, obj.ParentID.TenantID())
|
||||||
|
|
||||||
|
switch obj.Resolver.(type) {
|
||||||
|
case *organizationResolver:
|
||||||
|
count, err := prb.RightsRequests.CountByOrganizationID(ctx, obj.ParentID)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot count rights requests: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unsupported resolver type for RightsRequestConnection: %T", obj.Resolver))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Owner is the resolver for the owner field.
|
// Owner is the resolver for the owner field.
|
||||||
func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.People, error) {
|
func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.People, error) {
|
||||||
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
|
r.MustBeAuthorized(ctx, obj.ID, authz.ActionGetOwner)
|
||||||
@@ -7789,6 +7940,14 @@ func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
|
|||||||
// Report returns schema.ReportResolver implementation.
|
// Report returns schema.ReportResolver implementation.
|
||||||
func (r *Resolver) Report() schema.ReportResolver { return &reportResolver{r} }
|
func (r *Resolver) Report() schema.ReportResolver { return &reportResolver{r} }
|
||||||
|
|
||||||
|
// RightsRequest returns schema.RightsRequestResolver implementation.
|
||||||
|
func (r *Resolver) RightsRequest() schema.RightsRequestResolver { return &rightsRequestResolver{r} }
|
||||||
|
|
||||||
|
// RightsRequestConnection returns schema.RightsRequestConnectionResolver implementation.
|
||||||
|
func (r *Resolver) RightsRequestConnection() schema.RightsRequestConnectionResolver {
|
||||||
|
return &rightsRequestConnectionResolver{r}
|
||||||
|
}
|
||||||
|
|
||||||
// Risk returns schema.RiskResolver implementation.
|
// Risk returns schema.RiskResolver implementation.
|
||||||
func (r *Resolver) Risk() schema.RiskResolver { return &riskResolver{r} }
|
func (r *Resolver) Risk() schema.RiskResolver { return &riskResolver{r} }
|
||||||
|
|
||||||
@@ -7947,6 +8106,8 @@ type processingActivityResolver struct{ *Resolver }
|
|||||||
type processingActivityConnectionResolver struct{ *Resolver }
|
type processingActivityConnectionResolver struct{ *Resolver }
|
||||||
type queryResolver struct{ *Resolver }
|
type queryResolver struct{ *Resolver }
|
||||||
type reportResolver struct{ *Resolver }
|
type reportResolver struct{ *Resolver }
|
||||||
|
type rightsRequestResolver struct{ *Resolver }
|
||||||
|
type rightsRequestConnectionResolver struct{ *Resolver }
|
||||||
type riskResolver struct{ *Resolver }
|
type riskResolver struct{ *Resolver }
|
||||||
type riskConnectionResolver struct{ *Resolver }
|
type riskConnectionResolver struct{ *Resolver }
|
||||||
type sAMLConfigurationResolver struct{ *Resolver }
|
type sAMLConfigurationResolver struct{ *Resolver }
|
||||||
|
|||||||
Reference in New Issue
Block a user