diff --git a/README.md b/README.md index 1211720..ddf8dc3 100644 --- a/README.md +++ b/README.md @@ -253,9 +253,9 @@ Create a new migration using the following command: npx supabase db diff | npx supabase migration new ``` -### Password Reset +### Password Reset And Invitations -If users forget their password, they can request for a reset. Atomic CRM handles it for you, using Supabase. +An user can be invited to the CRM by an administrator. The user will receive an email with a link to set their password. The password reset feature is also available. You don't have to worry about these processes, Atomic CRM handles them for you, using Supabase. Please make sure to read and apply the [Login Callback](./doc/supabase-configuration.md#login-callback) and [Customizing Mail Template](./doc/supabase-configuration.md#customizing-mail-template) sections to properly configure the password reset feature. diff --git a/package-lock.json b/package-lock.json index 2d882c6..3eb1fa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "papaparse": "^5.4.1", "prop-types": "^15.8.1", "ra-data-fakerest": "^5.1.1", - "ra-supabase": "^3.0.0", + "ra-supabase": "^3.0.1", "react": "^18.2.0", "react-admin": "^5.1.0", "react-cropper": "^2.3.3", @@ -10570,19 +10570,19 @@ } }, "node_modules/ra-supabase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ra-supabase/-/ra-supabase-3.0.0.tgz", - "integrity": "sha512-vBVPyPkPhlfuAJp5CnQseNioBcpqGjfz9MOuOekXsRRXA+5dv8nJfp9XnX7wytGU4oax+gRNqlXJMZJEtZDJXQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ra-supabase/-/ra-supabase-3.1.0.tgz", + "integrity": "sha512-T+OtQ4FTYcJqWUdgZ5rcLamHbU2Ae0BqMEuBLry9sXPUFOtsh26+zShFRe6mtkbJA2ydjfiYW01/n5SQrWP2eg==", "dependencies": { - "ra-supabase-core": "^3.0.0", - "ra-supabase-language-english": "^3.0.0", - "ra-supabase-ui-materialui": "^3.0.0" + "ra-supabase-core": "^3.1.0", + "ra-supabase-language-english": "^3.1.0", + "ra-supabase-ui-materialui": "^3.1.0" } }, "node_modules/ra-supabase-core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ra-supabase-core/-/ra-supabase-core-3.0.0.tgz", - "integrity": "sha512-V6OHsgOE7icqH6ZstwOjny55mxPeSh2mmAdsUnuiYORk6mWAq8g7d5ba8pZHhowXKiUK3G0Pw9VEqMVIZ55y2g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ra-supabase-core/-/ra-supabase-core-3.1.0.tgz", + "integrity": "sha512-KagSKm+fJLkQTtNc7OtejktXMIysv80ZgOzJAM5nz+xyHNVhFb2GEbW+AvYI3uXejay/cQL8WvfQkczl/NeZ7Q==", "peerDependencies": { "@raphiniert/ra-data-postgrest": "^2.3.0", "@supabase/supabase-js": "^2.0.0", @@ -10590,16 +10590,16 @@ } }, "node_modules/ra-supabase-language-english": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ra-supabase-language-english/-/ra-supabase-language-english-3.0.0.tgz", - "integrity": "sha512-V1VJrUnAZWTys1s7Qv7xJx55mxDrgui7E22NtNPe+ET+TROsLs7xtDZmsWcmMDTOpqnzuqyPS5x/zmJDJ7/uxw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ra-supabase-language-english/-/ra-supabase-language-english-3.1.0.tgz", + "integrity": "sha512-9/S8n6quJeJiOcFVLDZQNqXOMcGnlwmdZ+Xy4UFGcfdsGCuPr68CYxdG68WnP1jxyo7Hy7b/zvfr+Zu5rW8f+g==" }, "node_modules/ra-supabase-ui-materialui": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ra-supabase-ui-materialui/-/ra-supabase-ui-materialui-3.0.0.tgz", - "integrity": "sha512-BcZr4AeqCfSLpc+fUWaaKzw+F5xI3bp9nBmSuk+eoUW7c67uDqY0eSi7kO5HmiM6WoCnerfhrDrljAs4JKMavg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ra-supabase-ui-materialui/-/ra-supabase-ui-materialui-3.1.0.tgz", + "integrity": "sha512-F/6JfoBEwW4wAZ/0b8ccJ/EqjGR460+ermU1HuGxXXj5YCd9Gg6Oc+YDcKlSZ7F0bH16DI9Q8z08EXns6cvyQw==", "dependencies": { - "ra-supabase-core": "^3.0.0" + "ra-supabase-core": "^3.1.0" }, "peerDependencies": { "@mui/icons-material": "^5.0.0", diff --git a/package.json b/package.json index 0661a8c..c304b0d 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "papaparse": "^5.4.1", "prop-types": "^15.8.1", "ra-data-fakerest": "^5.1.1", - "ra-supabase": "^3.0.0", + "ra-supabase": "^3.1.0", "react": "^18.2.0", "react-admin": "^5.1.0", "react-cropper": "^2.3.3", diff --git a/public/auth-callback/index.html b/public/auth-callback.html similarity index 97% rename from public/auth-callback/index.html rename to public/auth-callback.html index ef7d292..ab2d5f0 100644 --- a/public/auth-callback/index.html +++ b/public/auth-callback.html @@ -131,7 +131,7 @@ function interceptAuthCallback() { const hash = window.location.hash; const {access_token, refresh_token, type} = getUrlParams(); - window.location.href = `../?access_token=${access_token}&refresh_token=${refresh_token}&type=${type}#/auth-callback`; + window.location.href = `../#/auth-callback?access_token=${access_token}&refresh_token=${refresh_token}&type=${type}`; } // Call the function to intercept the auth callback diff --git a/src/providers/fakerest/dataProvider.ts b/src/providers/fakerest/dataProvider.ts index e78b252..e1ab574 100644 --- a/src/providers/fakerest/dataProvider.ts +++ b/src/providers/fakerest/dataProvider.ts @@ -157,12 +157,12 @@ const dataProviderWithCustomMethod: CrmDataProvider = { password, }; }, - async salesCreate({ - password: _password, - ...data - }: SalesFormData): Promise { + async salesCreate({ ...data }: SalesFormData): Promise { const user = await dataProvider.create('sales', { - data, + data: { + ...data, + password: 'new_password', + }, }); return { diff --git a/src/providers/supabase/authProvider.ts b/src/providers/supabase/authProvider.ts index 0ed2597..fb7752c 100644 --- a/src/providers/supabase/authProvider.ts +++ b/src/providers/supabase/authProvider.ts @@ -68,35 +68,8 @@ export const authProvider: AuthProvider = { return baseAuthProvider.checkAuth(params); }, - // We need to ovveride the getPermissions here to avoid the `ra-supabase` retries async getPermissions(params) { const isInitialized = await getIsInitialized(); return isInitialized ? baseAuthProvider.getPermissions(params) : null; }, - handleCallback: async () => { - const { access_token, refresh_token, type } = getUrlParams(); - // Users have reset their password or have just been invited and must set a new password - if (type === 'recovery' || type === 'invite') { - if (access_token && refresh_token) { - return { - redirectTo: `/set-password?access_token=${access_token}&refresh_token=${refresh_token}&type=${type}`, - }; - } - - if (process.env.NODE_ENV === 'development') { - console.error( - 'Missing access_token or refresh_token for an invite or recovery' - ); - } - } - }, -}; - -const getUrlParams = () => { - const urlSearchParams = new URLSearchParams(window.location.search); - const access_token = urlSearchParams.get('access_token'); - const refresh_token = urlSearchParams.get('refresh_token'); - const type = urlSearchParams.get('type'); - - return { access_token, refresh_token, type }; }; diff --git a/src/sales/SalesCreate.tsx b/src/sales/SalesCreate.tsx index 3dd2df0..6452609 100644 --- a/src/sales/SalesCreate.tsx +++ b/src/sales/SalesCreate.tsx @@ -1,8 +1,6 @@ import { Card, Container, Typography } from '@mui/material'; import { useMutation } from '@tanstack/react-query'; import { - PasswordInput, - required, SimpleForm, useDataProvider, useNotify, @@ -50,13 +48,7 @@ export function SalesCreate() { }> Create sale person - - - + diff --git a/src/sales/SalesInputs.tsx b/src/sales/SalesInputs.tsx index 0f6b70b..c0440bf 100644 --- a/src/sales/SalesInputs.tsx +++ b/src/sales/SalesInputs.tsx @@ -6,10 +6,9 @@ import { useRecordContext, } from 'react-admin'; import { Sale } from '../types'; -import { ReactNode } from 'react'; import { Stack } from '@mui/material'; -export function SalesInputs({ children }: { children?: ReactNode }) { +export function SalesInputs() { const { identity } = useGetIdentity(); const record = useRecordContext(); return ( @@ -29,7 +28,6 @@ export function SalesInputs({ children }: { children?: ReactNode }) { validate={required()} helperText={false} /> - {children} + + + + + +
+
+

Confirm your account

+
+
+

Welcome to Atomic CRM.

+

+ You've been invited to join the (Name) organization. Confirm + your address below: +

+ Confirm my account +

+ Warning: If the password reset request did + not originate from you, please contact us immediately as + this may be a fraudulent attempt. +

+

See you soon!

+

The Atomic CRM team

+
+ +
+ + diff --git a/supabase/templates/recovery.html b/supabase/templates/recovery.html index e021e56..e0ec103 100644 --- a/supabase/templates/recovery.html +++ b/supabase/templates/recovery.html @@ -61,7 +61,7 @@

Reset Password

Hello,

To reset your password, follow the link below:

Reset my password