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 (