validation
This commit is contained in:
parent
18c056ae52
commit
c803b2a62f
|
@ -13,6 +13,7 @@
|
|||
"autoprefixer": "^10.2.4",
|
||||
"dayjs": "^1.10.4",
|
||||
"express-jwt": "^6.0.0",
|
||||
"formik": "^2.2.6",
|
||||
"jwks-rsa": "^1.12.2",
|
||||
"next": "^10.0.6",
|
||||
"postcss": "^8.2.4",
|
||||
|
@ -21,6 +22,7 @@
|
|||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"swr": "^0.4.1",
|
||||
"tailwindcss": "^2.0.2"
|
||||
"tailwindcss": "^2.0.2",
|
||||
"yup": "^0.32.8"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
export default function Message({ title, items = [] }) {
|
||||
return (
|
||||
<div className="rounded-md bg-red-50 p-4">
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
{/* Heroicon name: solid/x-circle */}
|
||||
<svg
|
||||
className="h-5 w-5 text-red-400"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
{title && <h3 className="text-sm font-medium text-red-800">{title}</h3>}
|
||||
{items.length > 0 && (
|
||||
<div className={`${title ? "mt-2" : ""} text-sm text-red-700`}>
|
||||
<ul className={`${items.length > 1 ? "list-disc pl-5 space-y-1" : ""}`}>
|
||||
{items.map((item, index) => (
|
||||
<li key={index}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,12 +1,18 @@
|
|||
import Link from "next/link";
|
||||
import { Configuration, PublicApi } from "@ory/kratos-client";
|
||||
import { useFormik } from "formik";
|
||||
import config from "../../config";
|
||||
import Message from "../../components/Form/Message";
|
||||
|
||||
const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public }));
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const flow = context.query.flow;
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
return { props: { flow: require("../../../stubs/login.json") } };
|
||||
}
|
||||
|
||||
// The flow is used to identify the login and registration flow and
|
||||
// return data like the csrf_token and so on.
|
||||
if (!flow || typeof flow !== "string") {
|
||||
|
@ -59,8 +65,9 @@ export default function Login({ flow }) {
|
|||
...fieldProps[field.name],
|
||||
}))
|
||||
.sort((a, b) => (a.position < b.position ? -1 : 1));
|
||||
|
||||
console.log(flow);
|
||||
const formik = useFormik({
|
||||
initialValues: fields.reduce((acc, field) => ({ ...acc, [field.name]: field.value }), {}),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||
|
@ -87,6 +94,7 @@ export default function Login({ flow }) {
|
|||
if you don't have one yet
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
||||
<form
|
||||
|
@ -108,38 +116,37 @@ export default function Login({ flow }) {
|
|||
type={field.type}
|
||||
autoComplete={fieldProps[field.name]}
|
||||
required={field.required}
|
||||
value={field.value || undefined}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
value={formik.values[field.name]}
|
||||
className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-green-500 focus:border-green-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{field.errors && field.errors.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<Message items={field.errors.map(({ message }) => message)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
{/* <div className="flex items-center">
|
||||
<input
|
||||
id="remember_me"
|
||||
name="remember_me"
|
||||
type="checkbox"
|
||||
className="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-300 rounded"
|
||||
/>
|
||||
<label htmlFor="remember_me" className="ml-2 block text-sm text-gray-900">
|
||||
Remember me
|
||||
</label>
|
||||
</div> */}
|
||||
<div className="text-sm">
|
||||
<Link href="/recovery">
|
||||
<a className="font-medium text-green-600 hover:text-green-500">Forgot your password?</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
<Link href="/recovery">
|
||||
<a className="text-sm font-medium text-green-600 hover:text-green-500">Forgot your password?</a>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
|
||||
{flow.methods.password.config.errors.length > 0 && (
|
||||
<Message items={flow.methods.password.config.errors.map(({ message }) => message)} />
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import Link from "next/link";
|
||||
import { Configuration, PublicApi } from "@ory/kratos-client";
|
||||
import { useFormik } from "formik";
|
||||
import config from "../../config";
|
||||
import Message from "../../components/Form/Message";
|
||||
|
||||
const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public }));
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const flow = context.query.flow;
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
return { props: { flow: require("../../../stubs/registration.json") } };
|
||||
}
|
||||
|
||||
// The flow is used to identify the login and registration flow and
|
||||
// return data like the csrf_token and so on.
|
||||
if (!flow || typeof flow !== "string") {
|
||||
|
@ -69,8 +75,12 @@ export default function Registration({ flow }) {
|
|||
...fieldProps[field.name],
|
||||
}))
|
||||
.sort((a, b) => (a.position < b.position ? -1 : 1));
|
||||
const formik = useFormik({
|
||||
initialValues: fields.reduce((acc, field) => ({ ...acc, [field.name]: field.value }), {}),
|
||||
});
|
||||
|
||||
console.log(flow);
|
||||
console.log(fields);
|
||||
console.log("fieldProps", fieldProps);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||
|
@ -114,24 +124,34 @@ export default function Registration({ flow }) {
|
|||
<div>
|
||||
<input
|
||||
id={field.name}
|
||||
name={field.name}
|
||||
name={`['${field.name}']`}
|
||||
type={field.type}
|
||||
autoComplete={fieldProps[field.name]}
|
||||
autoComplete={field.autoComplete}
|
||||
required={field.required}
|
||||
value={field.value || undefined}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
value={formik.values[field.name]}
|
||||
className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-green-500 focus:border-green-500 sm:text-sm"
|
||||
/>
|
||||
{field.errors && field.errors.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<Message items={field.errors.map(({ message }) => message)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
||||
>
|
||||
Sign up
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
||||
>
|
||||
Sign up
|
||||
</button>
|
||||
|
||||
{flow.methods.password.config.errors.length > 0 && (
|
||||
<Message items={flow.methods.password.config.errors.map(({ message }) => message)} />
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"id": "bda73c77-1e21-4bfd-b85a-322fce2e4576",
|
||||
"expires_at": "2020-01-28T13:48:04.690715Z",
|
||||
"issued_at": "2020-01-28T13:38:04.690732Z",
|
||||
"request_url": "http://127.0.0.1:4455/auth/browser/login",
|
||||
"methods": {
|
||||
"oidc": {
|
||||
"method": "oidc",
|
||||
"config": {
|
||||
"action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/oidc/auth/bda73c77-1e21-4bfd-b85a-322fce2e4576",
|
||||
"method": "POST",
|
||||
"fields": [
|
||||
{
|
||||
"name": "csrf_token",
|
||||
"type": "hidden",
|
||||
"required": true,
|
||||
"value": "QJreyXtUD4oUSJfGNjA/+6ydsQyq0o/rfTL6QK86VadVFg6mwgX5x1QHVQ6uRqKxmwAcavQup3ILCSwl7ke97g=="
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"method": "password",
|
||||
"config": {
|
||||
"action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/password/login?request=bda73c77-1e21-4bfd-b85a-322fce2e4576",
|
||||
"method": "POST",
|
||||
"fields": [
|
||||
{
|
||||
"name": "csrf_token",
|
||||
"type": "hidden",
|
||||
"required": true,
|
||||
"value": "M1gAKA8fIhw4JOpQ/5m9mKARBAvKhzWkyhbxjtZNLG8m1NBHtk7UUXhrKJhn7yDSl4ypbZR7HT28LSfrlzDEJg=="
|
||||
},
|
||||
{ "name": "identifier", "type": "text", "required": true, "value": "asfdasdffads" },
|
||||
{ "name": "password", "type": "password", "required": true }
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"message": "The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"id": "dbff7b96-8116-42c5-8624-f9fb28f1db15",
|
||||
"expires_at": "2020-01-28T13:49:01.2274112Z",
|
||||
"issued_at": "2020-01-28T13:39:01.2274261Z",
|
||||
"request_url": "http://127.0.0.1:4455/auth/browser/registration",
|
||||
"methods": {
|
||||
"oidc": {
|
||||
"method": "oidc",
|
||||
"config": {
|
||||
"action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/oidc/auth/dbff7b96-8116-42c5-8624-f9fb28f1db15",
|
||||
"method": "POST",
|
||||
"fields": [
|
||||
{
|
||||
"name": "csrf_token",
|
||||
"type": "hidden",
|
||||
"required": true,
|
||||
"value": "xwb6A6iHdsguYwkAM6m3jj196E7TcmiWpAavIRxuAgXSiipsEdaAhW4sy8ir3yrECuBFKI2OQA/SPXlEXRPqTA=="
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"password": {
|
||||
"method": "password",
|
||||
"config": {
|
||||
"errors": [
|
||||
{
|
||||
"message": "The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number."
|
||||
}
|
||||
],
|
||||
"action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/password/registration?request=dbff7b96-8116-42c5-8624-f9fb28f1db15",
|
||||
"method": "POST",
|
||||
"fields": [
|
||||
{
|
||||
"name": "csrf_token",
|
||||
"type": "hidden",
|
||||
"required": true,
|
||||
"value": "xLg4B9WnuC0Ue+j9ay5EQvleaJpOl0H9xJJ7W3+Bwv7RNOhobPZOYFQ0KjXzWNkIzsPF/BBraWSyqa0+Pvwqtw=="
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"type": "password",
|
||||
"required": true,
|
||||
"errors": [{ "message": "password: Is required" }]
|
||||
},
|
||||
{
|
||||
"name": "traits.email",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"errors": [
|
||||
{ "message": "traits.email: String length must be greater than or equal to 3" },
|
||||
{ "message": "traits.email: Does not match format 'email'" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue