From 37f99b9aa68cff4265d9c99a0203f80da456276f Mon Sep 17 00:00:00 2001 From: Nell Hardcastle Date: Thu, 7 Nov 2024 12:35:58 -0800 Subject: [PATCH 1/8] chore(app): Remove unused duplicate permission mutations --- .../datalad/mutations/remove-permissions.jsx | 42 --------- .../datalad/mutations/update-permissions.jsx | 86 ------------------- 2 files changed, 128 deletions(-) delete mode 100644 packages/openneuro-app/src/scripts/datalad/mutations/remove-permissions.jsx delete mode 100644 packages/openneuro-app/src/scripts/datalad/mutations/update-permissions.jsx diff --git a/packages/openneuro-app/src/scripts/datalad/mutations/remove-permissions.jsx b/packages/openneuro-app/src/scripts/datalad/mutations/remove-permissions.jsx deleted file mode 100644 index 705eb4c19..000000000 --- a/packages/openneuro-app/src/scripts/datalad/mutations/remove-permissions.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from "react" -import PropTypes from "prop-types" -import { gql } from "@apollo/client" -import { Mutation } from "@apollo/client/react/components" -import WarnButton from "../../common/forms/warn-button.jsx" - -const REMOVE_PERMISSION = gql` - mutation removePermissions($datasetId: ID!, $userId: String!) { - removePermissions(datasetId: $datasetId, userId: $userId) - } -` - -/** - * Remove any permissions matching the user - * @param {object} userPermissions - * @param {string} userId - */ -export const userPermissionsFilter = (userPermissions, userId) => - userPermissions.filter((permission) => permission.user.id !== userId) - -const RemovePermissions = ({ datasetId, userId }) => ( - - {(removePermissions) => ( - { - await removePermissions({ variables: { datasetId, userId } }) - cb() - }} - /> - )} - -) - -RemovePermissions.propTypes = { - datasetId: PropTypes.string, - userId: PropTypes.string, -} - -export default RemovePermissions diff --git a/packages/openneuro-app/src/scripts/datalad/mutations/update-permissions.jsx b/packages/openneuro-app/src/scripts/datalad/mutations/update-permissions.jsx deleted file mode 100644 index 5e660e86d..000000000 --- a/packages/openneuro-app/src/scripts/datalad/mutations/update-permissions.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import React from "react" -import PropTypes from "prop-types" -import { gql } from "@apollo/client" -import { Mutation } from "@apollo/client/react/components" -import { toast } from "react-toastify" -import ToastContent from "../../common/partials/toast-content.jsx" -import { validate as isValidEmail } from "email-validator" - -const UPDATE_PERMISSIONS = gql` - mutation updatePermissions( - $datasetId: ID! - $userEmail: String! - $level: String! - ) { - updatePermissions( - datasetId: $datasetId - userEmail: $userEmail - level: $level - ) { - id - email - } - } -` - -export const mergeNewPermission = ( - datasetId, - oldPermissions, - userInfo, - metadata, -) => { - return { - __typename: "Dataset", - id: datasetId, - permissions: { - ...oldPermissions, - userPermissions: [ - ...oldPermissions.userPermissions, - { - __typename: "Permission", - user: { __typename: "User", ...userInfo }, - level: metadata, - }, - ], - }, - } -} - -const UpdateDatasetPermissions = ({ datasetId, userEmail, metadata, done }) => ( - - {(UpdateDatasetPermissions) => ( - - )} - -) - -UpdateDatasetPermissions.propTypes = { - datasetId: PropTypes.string, - userEmail: PropTypes.string, - metadata: PropTypes.oneOf(["ro", "rw", "admin"]), - done: PropTypes.func, -} - -export default UpdateDatasetPermissions From 2ef50b4c666d754ff640c401fa1ddb8919d4b438 Mon Sep 17 00:00:00 2001 From: Nell Hardcastle Date: Thu, 7 Nov 2024 12:56:16 -0800 Subject: [PATCH 2/8] feat(app): Allow sharing of permissions by ORCID --- .../__tests__/update-permissions.spec.jsx | 14 +++- .../dataset/mutations/update-permissions.tsx | 74 ++++++++++++++++-- .../src/graphql/resolvers/mutation.ts | 7 +- .../src/graphql/resolvers/permissions.ts | 78 +++++++++++-------- .../openneuro-server/src/graphql/schema.ts | 4 +- 5 files changed, 138 insertions(+), 39 deletions(-) diff --git a/packages/openneuro-app/src/scripts/dataset/mutations/__tests__/update-permissions.spec.jsx b/packages/openneuro-app/src/scripts/dataset/mutations/__tests__/update-permissions.spec.jsx index ae9c10e94..fdeac5ff5 100644 --- a/packages/openneuro-app/src/scripts/dataset/mutations/__tests__/update-permissions.spec.jsx +++ b/packages/openneuro-app/src/scripts/dataset/mutations/__tests__/update-permissions.spec.jsx @@ -1,7 +1,7 @@ import React from "react" import { render } from "@testing-library/react" import { MockedProvider } from "@apollo/client/testing" -import { UpdateDatasetPermissions } from "../update-permissions" +import { isValidOrcid, UpdateDatasetPermissions } from "../update-permissions" describe("UpdateDatasetPermissions mutation", () => { it("renders with default props", () => { @@ -25,4 +25,16 @@ describe("UpdateDatasetPermissions mutation", () => { ) expect(asFragment()).toMatchSnapshot() }) + describe("isValidOrcid", () => { + it("matches typical ORCID strings", () => { + expect(isValidOrcid("0000-0001-2345-678")).toBe(false) + expect(isValidOrcid("0000-0001-2345-678f")).toBe(false) + expect(isValidOrcid("19818c4d-1e60-4480-a317-6fcc1c1a88c6")).toBe(false) + expect(isValidOrcid("0000000123456789")).toBe(false) + // Check for a correct value + expect(isValidOrcid("0000-0001-2345-6789")).toBe(true) + // Test with the X checksum value + expect(isValidOrcid("0000-0002-1694-233X")).toBe(true) + }) + }) }) diff --git a/packages/openneuro-app/src/scripts/dataset/mutations/update-permissions.tsx b/packages/openneuro-app/src/scripts/dataset/mutations/update-permissions.tsx index 3430425cd..0cd5eca19 100644 --- a/packages/openneuro-app/src/scripts/dataset/mutations/update-permissions.tsx +++ b/packages/openneuro-app/src/scripts/dataset/mutations/update-permissions.tsx @@ -1,11 +1,22 @@ import React from "react" import type { FC } from "react" import { gql, useMutation } from "@apollo/client" +import type { ApolloError } from "@apollo/client" import { toast } from "react-toastify" import ToastContent from "../../common/partials/toast-content" import { validate as isValidEmail } from "email-validator" import { Button } from "@openneuro/components/button" +export function isValidOrcid(orcid: string) { + if (orcid) { + return /^[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{3}[0-9X]$/.test(orcid) + ? true + : false + } else { + return false + } +} + const UPDATE_PERMISSIONS = gql` mutation updatePermissions( $datasetId: ID! @@ -18,7 +29,42 @@ const UPDATE_PERMISSIONS = gql` level: $level ) { id - email + userPermissions { + datasetId + userId + level + user { + id + email + oricd + } + } + } + } +` + +const UPDATE_ORCID_PERMISSIONS = gql` + mutation updateOrcidPermissions( + $datasetId: ID! + $userOrcid: String! + $level: String! + ) { + updateOrcidPermissions( + datasetId: $datasetId + userOrcid: $userOrcid + level: $level + ) { + id + userPermissions { + datasetId + userId + level + user { + id + email + orcid + } + } } } ` @@ -53,13 +99,26 @@ interface UpdateDatasetPermissionsProps { done: () => void } +function onError(err: ApolloError) { + toast.error( + , + ) +} + export const UpdateDatasetPermissions: FC = ({ datasetId, userEmail, metadata, done, }) => { - const [UpdateDatasetPermissions] = useMutation(UPDATE_PERMISSIONS) + const [updateDatasetPermissions] = useMutation( + UPDATE_PERMISSIONS, + { onError }, + ) + const [updateDatasetPermissionsOrcid] = useMutation( + UPDATE_ORCID_PERMISSIONS, + { onError }, + ) return ( <> + +`; + +exports[`UpdateDatasetPermissions mutation > calls UPDATE_PERMISSIONS when clicked with an email address 1`] = `