diff --git a/.env.local b/.env.local index 7c6dfc02..fea95e3b 100644 --- a/.env.local +++ b/.env.local @@ -74,4 +74,14 @@ NEXT_PUBLIC_GG_REDIRECT_URI = "http://localhost:3000" API_ROOT = "http://localhost:3000" -GOOGLE_MAP_API_KEY = AIzaSyCzeVrHt544bp_72YCFkw21eDsmI2JEsQo \ No newline at end of file +GOOGLE_MAP_API_KEY = AIzaSyCzeVrHt544bp_72YCFkw21eDsmI2JEsQo + + +EMAIL_SERVER_HOST=smtp.livemail.co.uk +EMAIL_SERVER_PORT=465 +EMAIL_SERVER_USER=rob@rdbsolutions.co.uk +EMAIL_SERVER_PASSWORD=R0b3rt72 +EMAIL_FROM=no-reply@example.com + +NEXT_PUBLIC_MAGIC_PK=pk_live_674E13244D1BB0A4 +MAGIC_SK=sk_live_F0E74A9557051A65 diff --git a/components/elements/index.js b/components/elements/index.js index 3c7aa921..5074f000 100644 --- a/components/elements/index.js +++ b/components/elements/index.js @@ -92,7 +92,9 @@ export function Textfield(props) { disabled /> -
{t(hint)}
+
+ {t("newappeal:new-appeal-introduction-paragraph")} +
); } else { @@ -350,8 +352,10 @@ const RenderDatePicker = ({ onChange={onChange} selected={value || null} className="govuk-input govuk-input--width-10" - minDate={minDate} - maxDate={maxDate} + {...(custom.dateStart !== false && { + minDate: minDate, + })} + {...(custom.dateEnd !== false && { maxDate: maxDate })} // value={!value ? null : new Date(value)} /> diff --git a/package.json b/package.json index fdce8e9f..4f8761f5 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@googlemaps/react-wrapper": "^1.1.24", + "@magic-sdk/admin": "^1.4.0", "@webdeb/next-styles": "^1.1.1", "applicationinsights": "^2.2.0", "axios": "^0.24.0", @@ -31,14 +32,17 @@ "leaflet": "^1.7.1", "leaflet-defaulticon-compatibility": "^0.1.1", "lodash": "^4.17.21", + "magic-sdk": "^8.1.0", "moment": "^2.29.1", "multer": "^1.4.4", "nanoid": "^3.2.0", "next": "^12.0.8", + "next-auth": "^4.3.1", "next-connect": "^0.12.2", "next-redux-wrapper": "^7.0.5", "next-translate": "^1.2.0", "nextjs-basic-auth-middleware": "^0.2.1", + "nodemailer": "^6.7.3", "nookies": "^2.5.2", "ospoint": "^0.2.1", "path": "^0.12.7", diff --git a/pages/_app.js b/pages/_app.js index 84cf6788..d5ed2ded 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -5,19 +5,25 @@ import { wrapper } from "../store/store"; import { useStore, Provider } from "react-redux"; import { persistStore } from "redux-persist"; import { PersistGate } from "redux-persist/integration/react"; +import { SessionProvider as AuthProvider } from "next-auth/react"; -const MyApp = ({ Component, pageProps }) => { +const MyApp = ({ Component, pageProps: { session, ...pageProps } }) => { const store = useStore((state) => state); const persistor = persistStore(store, {}, function () { persistor.persist(); }); return ( - - }> - - - + + + } + > + + + + ); }; diff --git a/pages/api/auth/[...nextauth].js b/pages/api/auth/[...nextauth].js new file mode 100644 index 00000000..23e1868d --- /dev/null +++ b/pages/api/auth/[...nextauth].js @@ -0,0 +1,33 @@ +import NextAuth from "next-auth"; +import Providers from "next-auth/providers"; +import { Magic } from "@magic-sdk/admin"; + +const magic = new Magic(process.env.MAGIC_SK); + +export default NextAuth({ + session: { + jwt: true, + }, + pages: { + // override signIn page so we can integrate with Magic + signIn: "/auth/signin", + }, + providers: [ + Providers.Credentials({ + name: "Magic Link", + credentials: { + didToken: { label: "DID Token", type: "text" }, + }, + async authorize({ didToken }, req) { + // validate magic DID token + magic.token.validate(didToken); + + // fetch user metadata + const metadata = await magic.users.getMetadataByToken(didToken); + + // return user info + return { ...metadata }; + }, + }), + ], +}); diff --git a/pages/auth/signin.js b/pages/auth/signin.js new file mode 100644 index 00000000..a2677342 --- /dev/null +++ b/pages/auth/signin.js @@ -0,0 +1,36 @@ +import { useRouter } from "next/router"; +import { signIn } from "next-auth/client"; + +// magic-sdk is only availabile in the browser +const magic = + typeof window !== "undefined" && + new Magic(process.env.NEXT_PUBLIC_MAGIC_PK || "a"); + +export default function SignIn() { + const router = useRouter(); + const { register, handleSubmit } = useForm(); + + const onSubmit = async ({ email }) => { + if (!magic) throw new Error(`magic not defined`); + + // login with Magic + const didToken = await magic.auth.loginWithMagicLink({ email }); + + // sign in with NextAuth + await signIn("credentials", { + didToken, + callbackUrl: router.query["callbackUrl"], + }); + }; + + return ( +
+ + + +
+ ); +} diff --git a/pages/myportal/index.js b/pages/myportal/index.js index b3f33595..fe2c014c 100644 --- a/pages/myportal/index.js +++ b/pages/myportal/index.js @@ -39,6 +39,8 @@ import { } from "../../store/watchedCases/action"; import { setCookie } from "nookies"; +import { useSession, signIn, signOut } from "next-auth/react"; + const Home = (props) => { const { footerLinks, @@ -56,6 +58,8 @@ const Home = (props) => { const { locale } = router; const { appealtypes } = router.query; + const { data: session } = useSession(); + return (