when that server action hits
This commit is contained in:
parent
56e11c4d76
commit
d05961ad15
17 changed files with 325 additions and 579 deletions
299
package-lock.json
generated
299
package-lock.json
generated
|
@ -21,14 +21,15 @@
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"graphql": "^16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"ldapts": "^4.2.5",
|
"ldapts": "^4.2.5",
|
||||||
"next": "13.3.1",
|
"next": "^13.4.2-canary.3",
|
||||||
"pino": "^8.11.0",
|
"pino": "^8.11.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"sharp": "^0.32.0",
|
"sharp": "^0.32.0",
|
||||||
"typescript": "5.0.4",
|
"typescript": "5.0.4",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"yup": "^1.1.1"
|
"zod": "^3.21.4",
|
||||||
|
"zod-formik-adapter": "^1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/cli": "^3.3.1",
|
"@graphql-codegen/cli": "^3.3.1",
|
||||||
|
@ -1991,9 +1992,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@next/env": {
|
"node_modules/@next/env": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-EDtCoedIZC7JlUQ3uaQpSc4aVmyhbLHmQVALg7pFfQgOTjgSnn7mKtA0DiCMkYvvsx6aFb5octGMtWrOtGXW9A=="
|
"integrity": "sha512-xPzFvIhHqh2V1pbcgtL/MD1QbJanKieiACs4U3ctVAvbd3WWXi0duZ321hPGrLHaVg3V4QmWPUJi0/68u+8hMQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@next/eslint-plugin-next": {
|
"node_modules/@next/eslint-plugin-next": {
|
||||||
"version": "13.3.1",
|
"version": "13.3.1",
|
||||||
|
@ -2004,9 +2005,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-darwin-arm64": {
|
"node_modules/@next/swc-darwin-arm64": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-UXPtriEc/pBP8luSLSCZBcbzPeVv+SSjs9cH/KygTbhmACye8/OOXRZO13Z2Wq1G0gLmEAIHQAOuF+vafPd2lw==",
|
"integrity": "sha512-soq2iMZNi9A4CXxhzYytNGhDkvyngB7WFhPk+UpfR6xb6DcWajqdrL1D+LE2c0UgXdejyN6CmMKgVMZdKJ6EZg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2019,9 +2020,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-darwin-x64": {
|
"node_modules/@next/swc-darwin-x64": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-lT36yYxosCfLtplFzJWgo0hrPu6/do8+msgM7oQkPeohDNdhjtjFUgOOwdSnPublLR6Mo2Ym4P/wl5OANuD2bw==",
|
"integrity": "sha512-z45IfyF0YM+TZ3jWpAV6sbqHPZOdx4XD8ClwZ0rA8SxmH4rvSPDcMxSp5Yz9nuTMTWp1Xz7ewXeaQV4kwY1qmw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2034,9 +2035,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-wRb76nLWJhonH8s3kxC/1tFguEkeOPayIwe9mkaz1G/yeS3OrjeyKMJsb4+Kdg0zbTo53bNCOl59NNtDM7yyyw==",
|
"integrity": "sha512-Rk+VMv/PBjcvmSQY4lR87gCIAhPQIR/DV7PaCAWmtu5zbGsPjERQ7IwMj69QH2lcEtNLu0n3IkC9SuWLqpxFtg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2049,9 +2050,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-linux-arm64-musl": {
|
"node_modules/@next/swc-linux-arm64-musl": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-qz3BzjJRZ16Iq/jrp+pjiYOc0jTjHlfmxQmZk9x/+5uhRP6/eWQSTAPVJ33BMo6oK5O5N4644OgTAbzXzorecg==",
|
"integrity": "sha512-JQNxpHomFtQUny1os63AXdAr5ADc7UugA1Yo5bR0KvqviYHew50nehBuPdSWhWB80HePQRa7O5C5+x8afcBsGg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2064,9 +2065,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-linux-x64-gnu": {
|
"node_modules/@next/swc-linux-x64-gnu": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-6mgkLmwlyWlomQmpl21I3hxgqE5INoW4owTlcLpNsd1V4wP+J46BlI/5zV5KWWbzjfncIqzXoeGs5Eg+1GHODA==",
|
"integrity": "sha512-Te7h7ynuVkQ1bXOJouLQ01DQ+d94v+AZ2E7Z56+faR/cC7n1sJ+fLbBD49gCT/1Fd+cZ7KMrZ9h8SjQUxB7nyw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2079,9 +2080,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-linux-x64-musl": {
|
"node_modules/@next/swc-linux-x64-musl": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-uqm5sielhQmKJM+qayIhgZv1KlS5pqTdQ99b+Z7hMWryXS96qE0DftTmMZowBcUL6x7s2vSXyH5wPtO1ON7LBg==",
|
"integrity": "sha512-SD2PWkZPeSXEmzTM8OfDkVAIYy5d/Q1slZ4kLL3ab581pEcorhUa59IXt4ocx4T8Wl+EDGUHb7lgRzcfHm4c8w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2094,9 +2095,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-WomIiTj/v3LevltlibNQKmvrOymNRYL+a0dp5R73IwPWN5FvXWwSELN/kiNALig/+T3luc4qHNTyvMCp9L6U5Q==",
|
"integrity": "sha512-dG2VhnamPCiqCjqu/QM8rt8j6qTxthKN8QxbwhIHybSyKYELWHrKHouxSRyOK5Ai0FojcsdWmsMcu+MMiqnwmg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2109,9 +2110,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-win32-ia32-msvc": {
|
"node_modules/@next/swc-win32-ia32-msvc": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-M+PoH+0+q658wRUbs285RIaSTYnGBSTdweH/0CdzDgA6Q4rBM0sQs4DHmO3BPP0ltCO/vViIoyG7ks66XmCA5g==",
|
"integrity": "sha512-tnrhuv1MIXjOiHzDt6HnQSa3urbtAoanbd70SvlXMK9jTFajSgzeJ6o+ZO28RfYSUr/mXajS3HlF+4MBO8oVnw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
@ -2124,9 +2125,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@next/swc-win32-x64-msvc": {
|
"node_modules/@next/swc-win32-x64-msvc": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-Sl1F4Vp5Z1rNXWZYqJwMuWRRol4bqOB6+/d7KqkgQ4AcafKPN1PZmpkCoxv4UFHtFNIB7EotnuIhtXu3zScicQ==",
|
"integrity": "sha512-L3RSWOY27A6W2aNa05RX4tFwpLzNEyKQbr7bGn/MMMctuoRQfPZiogsdSFqYe/s8d5GsMAIhfB1yJ1oGrRiYTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2292,9 +2293,9 @@
|
||||||
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
||||||
},
|
},
|
||||||
"node_modules/@swc/helpers": {
|
"node_modules/@swc/helpers": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz",
|
||||||
"integrity": "sha512-SjY/p4MmECVVEWspzSRpQEM3sjR17sP8PbGxELWrT+YZMBfiUyt1MRUNjMV23zohwlG2HYtCQOsCwsTHguXkyg==",
|
"integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
|
@ -6027,33 +6028,34 @@
|
||||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
||||||
},
|
},
|
||||||
"node_modules/next": {
|
"node_modules/next": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/next/-/next-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/next/-/next-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-eByWRxPzKHs2oQz1yE41LX35umhz86ZSZ+mYyXBqn2IBi2hyUqxBA88avywdr4uyH+hCJczegGsDGWbzQA5Rqw==",
|
"integrity": "sha512-23JMGWN3fs3Tq8x1dVslWsOAlxQh5jhPXXQrKszmps1UVzvv/hA+hhAUZYeKrltfjWUEk6tZ9JEM49IO4jFnTg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@next/env": "13.3.1",
|
"@next/env": "13.4.2-canary.3",
|
||||||
"@swc/helpers": "0.5.0",
|
"@swc/helpers": "0.5.1",
|
||||||
"busboy": "1.6.0",
|
"busboy": "1.6.0",
|
||||||
"caniuse-lite": "^1.0.30001406",
|
"caniuse-lite": "^1.0.30001406",
|
||||||
"postcss": "8.4.14",
|
"postcss": "8.4.14",
|
||||||
"styled-jsx": "5.1.1"
|
"styled-jsx": "5.1.1",
|
||||||
|
"zod": "3.21.4"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"next": "dist/bin/next"
|
"next": "dist/bin/next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.18.0"
|
"node": ">=16.8.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@next/swc-darwin-arm64": "13.3.1",
|
"@next/swc-darwin-arm64": "13.4.2-canary.3",
|
||||||
"@next/swc-darwin-x64": "13.3.1",
|
"@next/swc-darwin-x64": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-arm64-gnu": "13.3.1",
|
"@next/swc-linux-arm64-gnu": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-arm64-musl": "13.3.1",
|
"@next/swc-linux-arm64-musl": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-x64-gnu": "13.3.1",
|
"@next/swc-linux-x64-gnu": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-x64-musl": "13.3.1",
|
"@next/swc-linux-x64-musl": "13.4.2-canary.3",
|
||||||
"@next/swc-win32-arm64-msvc": "13.3.1",
|
"@next/swc-win32-arm64-msvc": "13.4.2-canary.3",
|
||||||
"@next/swc-win32-ia32-msvc": "13.3.1",
|
"@next/swc-win32-ia32-msvc": "13.4.2-canary.3",
|
||||||
"@next/swc-win32-x64-msvc": "13.3.1"
|
"@next/swc-win32-x64-msvc": "13.4.2-canary.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@opentelemetry/api": "^1.1.0",
|
"@opentelemetry/api": "^1.1.0",
|
||||||
|
@ -6820,11 +6822,6 @@
|
||||||
"react-is": "^16.13.1"
|
"react-is": "^16.13.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/property-expr": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
|
||||||
},
|
|
||||||
"node_modules/pump": {
|
"node_modules/pump": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||||
|
@ -7722,11 +7719,6 @@
|
||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/tiny-case": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="
|
|
||||||
},
|
|
||||||
"node_modules/tiny-glob": {
|
"node_modules/tiny-glob": {
|
||||||
"version": "0.2.9",
|
"version": "0.2.9",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
||||||
|
@ -7782,11 +7774,6 @@
|
||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/toposort": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
|
|
||||||
},
|
|
||||||
"node_modules/tr46": {
|
"node_modules/tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
@ -8274,28 +8261,6 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yup": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/yup/-/yup-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-KfCGHdAErqFZWA5tZf7upSUnGKuTOnsI3hUsLr7fgVtx+DK04NPV01A68/FslI4t3s/ZWpvXJmgXhd7q6ICnag==",
|
|
||||||
"dependencies": {
|
|
||||||
"property-expr": "^2.0.5",
|
|
||||||
"tiny-case": "^1.0.3",
|
|
||||||
"toposort": "^2.0.2",
|
|
||||||
"type-fest": "^2.19.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yup/node_modules/type-fest": {
|
|
||||||
"version": "2.19.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
|
||||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.20"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/zen-observable": {
|
"node_modules/zen-observable": {
|
||||||
"version": "0.8.15",
|
"version": "0.8.15",
|
||||||
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
|
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
|
||||||
|
@ -8308,6 +8273,23 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"zen-observable": "0.8.15"
|
"zen-observable": "0.8.15"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod": {
|
||||||
|
"version": "3.21.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
||||||
|
"integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod-formik-adapter": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod-formik-adapter/-/zod-formik-adapter-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-62U+Mf8U05pvLsIMUTC1H6d4K5SmsrXM+YgiZhCpPin5GNhnVuXCGySmJCs0FHuTJCBy7Et5Z1i8KF5ffuLttg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"formik": "^2.2.9",
|
||||||
|
"zod": "^3.14.4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9777,9 +9759,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@next/env": {
|
"@next/env": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-EDtCoedIZC7JlUQ3uaQpSc4aVmyhbLHmQVALg7pFfQgOTjgSnn7mKtA0DiCMkYvvsx6aFb5octGMtWrOtGXW9A=="
|
"integrity": "sha512-xPzFvIhHqh2V1pbcgtL/MD1QbJanKieiACs4U3ctVAvbd3WWXi0duZ321hPGrLHaVg3V4QmWPUJi0/68u+8hMQ=="
|
||||||
},
|
},
|
||||||
"@next/eslint-plugin-next": {
|
"@next/eslint-plugin-next": {
|
||||||
"version": "13.3.1",
|
"version": "13.3.1",
|
||||||
|
@ -9790,57 +9772,57 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@next/swc-darwin-arm64": {
|
"@next/swc-darwin-arm64": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-UXPtriEc/pBP8luSLSCZBcbzPeVv+SSjs9cH/KygTbhmACye8/OOXRZO13Z2Wq1G0gLmEAIHQAOuF+vafPd2lw==",
|
"integrity": "sha512-soq2iMZNi9A4CXxhzYytNGhDkvyngB7WFhPk+UpfR6xb6DcWajqdrL1D+LE2c0UgXdejyN6CmMKgVMZdKJ6EZg==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-darwin-x64": {
|
"@next/swc-darwin-x64": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-lT36yYxosCfLtplFzJWgo0hrPu6/do8+msgM7oQkPeohDNdhjtjFUgOOwdSnPublLR6Mo2Ym4P/wl5OANuD2bw==",
|
"integrity": "sha512-z45IfyF0YM+TZ3jWpAV6sbqHPZOdx4XD8ClwZ0rA8SxmH4rvSPDcMxSp5Yz9nuTMTWp1Xz7ewXeaQV4kwY1qmw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-linux-arm64-gnu": {
|
"@next/swc-linux-arm64-gnu": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-wRb76nLWJhonH8s3kxC/1tFguEkeOPayIwe9mkaz1G/yeS3OrjeyKMJsb4+Kdg0zbTo53bNCOl59NNtDM7yyyw==",
|
"integrity": "sha512-Rk+VMv/PBjcvmSQY4lR87gCIAhPQIR/DV7PaCAWmtu5zbGsPjERQ7IwMj69QH2lcEtNLu0n3IkC9SuWLqpxFtg==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-linux-arm64-musl": {
|
"@next/swc-linux-arm64-musl": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-qz3BzjJRZ16Iq/jrp+pjiYOc0jTjHlfmxQmZk9x/+5uhRP6/eWQSTAPVJ33BMo6oK5O5N4644OgTAbzXzorecg==",
|
"integrity": "sha512-JQNxpHomFtQUny1os63AXdAr5ADc7UugA1Yo5bR0KvqviYHew50nehBuPdSWhWB80HePQRa7O5C5+x8afcBsGg==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-linux-x64-gnu": {
|
"@next/swc-linux-x64-gnu": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-6mgkLmwlyWlomQmpl21I3hxgqE5INoW4owTlcLpNsd1V4wP+J46BlI/5zV5KWWbzjfncIqzXoeGs5Eg+1GHODA==",
|
"integrity": "sha512-Te7h7ynuVkQ1bXOJouLQ01DQ+d94v+AZ2E7Z56+faR/cC7n1sJ+fLbBD49gCT/1Fd+cZ7KMrZ9h8SjQUxB7nyw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-linux-x64-musl": {
|
"@next/swc-linux-x64-musl": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-uqm5sielhQmKJM+qayIhgZv1KlS5pqTdQ99b+Z7hMWryXS96qE0DftTmMZowBcUL6x7s2vSXyH5wPtO1ON7LBg==",
|
"integrity": "sha512-SD2PWkZPeSXEmzTM8OfDkVAIYy5d/Q1slZ4kLL3ab581pEcorhUa59IXt4ocx4T8Wl+EDGUHb7lgRzcfHm4c8w==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-win32-arm64-msvc": {
|
"@next/swc-win32-arm64-msvc": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-WomIiTj/v3LevltlibNQKmvrOymNRYL+a0dp5R73IwPWN5FvXWwSELN/kiNALig/+T3luc4qHNTyvMCp9L6U5Q==",
|
"integrity": "sha512-dG2VhnamPCiqCjqu/QM8rt8j6qTxthKN8QxbwhIHybSyKYELWHrKHouxSRyOK5Ai0FojcsdWmsMcu+MMiqnwmg==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-win32-ia32-msvc": {
|
"@next/swc-win32-ia32-msvc": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-M+PoH+0+q658wRUbs285RIaSTYnGBSTdweH/0CdzDgA6Q4rBM0sQs4DHmO3BPP0ltCO/vViIoyG7ks66XmCA5g==",
|
"integrity": "sha512-tnrhuv1MIXjOiHzDt6HnQSa3urbtAoanbd70SvlXMK9jTFajSgzeJ6o+ZO28RfYSUr/mXajS3HlF+4MBO8oVnw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@next/swc-win32-x64-msvc": {
|
"@next/swc-win32-x64-msvc": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-Sl1F4Vp5Z1rNXWZYqJwMuWRRol4bqOB6+/d7KqkgQ4AcafKPN1PZmpkCoxv4UFHtFNIB7EotnuIhtXu3zScicQ==",
|
"integrity": "sha512-L3RSWOY27A6W2aNa05RX4tFwpLzNEyKQbr7bGn/MMMctuoRQfPZiogsdSFqYe/s8d5GsMAIhfB1yJ1oGrRiYTA==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
|
@ -9955,9 +9937,9 @@
|
||||||
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
|
||||||
},
|
},
|
||||||
"@swc/helpers": {
|
"@swc/helpers": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz",
|
||||||
"integrity": "sha512-SjY/p4MmECVVEWspzSRpQEM3sjR17sP8PbGxELWrT+YZMBfiUyt1MRUNjMV23zohwlG2HYtCQOsCwsTHguXkyg==",
|
"integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
|
@ -12704,25 +12686,26 @@
|
||||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
||||||
},
|
},
|
||||||
"next": {
|
"next": {
|
||||||
"version": "13.3.1",
|
"version": "13.4.2-canary.3",
|
||||||
"resolved": "https://registry.npmjs.org/next/-/next-13.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/next/-/next-13.4.2-canary.3.tgz",
|
||||||
"integrity": "sha512-eByWRxPzKHs2oQz1yE41LX35umhz86ZSZ+mYyXBqn2IBi2hyUqxBA88avywdr4uyH+hCJczegGsDGWbzQA5Rqw==",
|
"integrity": "sha512-23JMGWN3fs3Tq8x1dVslWsOAlxQh5jhPXXQrKszmps1UVzvv/hA+hhAUZYeKrltfjWUEk6tZ9JEM49IO4jFnTg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@next/env": "13.3.1",
|
"@next/env": "13.4.2-canary.3",
|
||||||
"@next/swc-darwin-arm64": "13.3.1",
|
"@next/swc-darwin-arm64": "13.4.2-canary.3",
|
||||||
"@next/swc-darwin-x64": "13.3.1",
|
"@next/swc-darwin-x64": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-arm64-gnu": "13.3.1",
|
"@next/swc-linux-arm64-gnu": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-arm64-musl": "13.3.1",
|
"@next/swc-linux-arm64-musl": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-x64-gnu": "13.3.1",
|
"@next/swc-linux-x64-gnu": "13.4.2-canary.3",
|
||||||
"@next/swc-linux-x64-musl": "13.3.1",
|
"@next/swc-linux-x64-musl": "13.4.2-canary.3",
|
||||||
"@next/swc-win32-arm64-msvc": "13.3.1",
|
"@next/swc-win32-arm64-msvc": "13.4.2-canary.3",
|
||||||
"@next/swc-win32-ia32-msvc": "13.3.1",
|
"@next/swc-win32-ia32-msvc": "13.4.2-canary.3",
|
||||||
"@next/swc-win32-x64-msvc": "13.3.1",
|
"@next/swc-win32-x64-msvc": "13.4.2-canary.3",
|
||||||
"@swc/helpers": "0.5.0",
|
"@swc/helpers": "0.5.1",
|
||||||
"busboy": "1.6.0",
|
"busboy": "1.6.0",
|
||||||
"caniuse-lite": "^1.0.30001406",
|
"caniuse-lite": "^1.0.30001406",
|
||||||
"postcss": "8.4.14",
|
"postcss": "8.4.14",
|
||||||
"styled-jsx": "5.1.1"
|
"styled-jsx": "5.1.1",
|
||||||
|
"zod": "3.21.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"no-case": {
|
"no-case": {
|
||||||
|
@ -13256,11 +13239,6 @@
|
||||||
"react-is": "^16.13.1"
|
"react-is": "^16.13.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"property-expr": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
|
||||||
},
|
|
||||||
"pump": {
|
"pump": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||||
|
@ -13915,11 +13893,6 @@
|
||||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"tiny-case": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="
|
|
||||||
},
|
|
||||||
"tiny-glob": {
|
"tiny-glob": {
|
||||||
"version": "0.2.9",
|
"version": "0.2.9",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
||||||
|
@ -13966,11 +13939,6 @@
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"toposort": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
|
|
||||||
},
|
|
||||||
"tr46": {
|
"tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
@ -14319,24 +14287,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||||
},
|
},
|
||||||
"yup": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/yup/-/yup-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-KfCGHdAErqFZWA5tZf7upSUnGKuTOnsI3hUsLr7fgVtx+DK04NPV01A68/FslI4t3s/ZWpvXJmgXhd7q6ICnag==",
|
|
||||||
"requires": {
|
|
||||||
"property-expr": "^2.0.5",
|
|
||||||
"tiny-case": "^1.0.3",
|
|
||||||
"toposort": "^2.0.2",
|
|
||||||
"type-fest": "^2.19.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"type-fest": {
|
|
||||||
"version": "2.19.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
|
||||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zen-observable": {
|
"zen-observable": {
|
||||||
"version": "0.8.15",
|
"version": "0.8.15",
|
||||||
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
|
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
|
||||||
|
@ -14349,6 +14299,17 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"zen-observable": "0.8.15"
|
"zen-observable": "0.8.15"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"zod": {
|
||||||
|
"version": "3.21.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
||||||
|
"integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw=="
|
||||||
|
},
|
||||||
|
"zod-formik-adapter": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod-formik-adapter/-/zod-formik-adapter-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-62U+Mf8U05pvLsIMUTC1H6d4K5SmsrXM+YgiZhCpPin5GNhnVuXCGySmJCs0FHuTJCBy7Et5Z1i8KF5ffuLttg==",
|
||||||
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,15 @@
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"graphql": "^16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"ldapts": "^4.2.5",
|
"ldapts": "^4.2.5",
|
||||||
"next": "13.3.1",
|
"next": "^13.4.2-canary.3",
|
||||||
"pino": "^8.11.0",
|
"pino": "^8.11.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"sharp": "^0.32.0",
|
"sharp": "^0.32.0",
|
||||||
"typescript": "5.0.4",
|
"typescript": "5.0.4",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"yup": "^1.1.1"
|
"zod": "^3.21.4",
|
||||||
|
"zod-formik-adapter": "^1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/cli": "^3.3.1",
|
"@graphql-codegen/cli": "^3.3.1",
|
||||||
|
|
4
src/actions/index.ts
Normal file
4
src/actions/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export type ActionResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
error?: string;
|
||||||
|
};
|
26
src/actions/login.ts
Normal file
26
src/actions/login.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
import * as ldap from "@/ldap";
|
||||||
|
import { LoginSchema, loginSchema } from "@/schemas";
|
||||||
|
import { ActionResponse } from ".";
|
||||||
|
import { getLogger } from "@/logger";
|
||||||
|
import { authTicketLogin } from "@/auth/auth";
|
||||||
|
|
||||||
|
type Response = ActionResponse & {
|
||||||
|
ticket?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function login(data: LoginSchema): Promise<Response> {
|
||||||
|
const { username, password } = await loginSchema.parse(data);
|
||||||
|
|
||||||
|
const valid = await ldap.validateUser(username, password);
|
||||||
|
if (!valid) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
error: "invalidCredentials"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const [_, ticket] = await authTicketLogin(username);
|
||||||
|
return { ok: true, ticket: ticket.ticket };
|
||||||
|
}
|
|
@ -1,38 +1,47 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
import * as ldap from "@/ldap";
|
import * as ldap from "@/ldap";
|
||||||
import prisma from "@/prisma";
|
import prisma from "@/prisma";
|
||||||
import { getUser } from "@/auth/auth";
|
import { getUser } from "@/auth/auth";
|
||||||
import { getLogger } from "@/logger";
|
import { getLogger } from "@/logger";
|
||||||
import { registerServerSchema } from "@/schemas";
|
import { RegisterSchema, registerSchema } from "@/schemas";
|
||||||
|
import { ActionResponse } from ".";
|
||||||
|
|
||||||
const logger = getLogger("/api/register");
|
const logger = getLogger("/actions/register");
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export default async function register(
|
||||||
|
data: RegisterSchema
|
||||||
|
): Promise<ActionResponse> {
|
||||||
const user = await getUser();
|
const user = await getUser();
|
||||||
if (user == null) return new Response(null, { status: 401 });
|
|
||||||
|
|
||||||
// user already has an account, don't re-register
|
if (user == null) {
|
||||||
|
return { ok: false, error: "invalidAuth" };
|
||||||
|
}
|
||||||
|
|
||||||
if (user.username != null) {
|
if (user.username != null) {
|
||||||
logger.info(
|
logger.info(
|
||||||
{ username: user.username, id: user.id },
|
{ username: user.username, id: user.id },
|
||||||
`user tried to register twice`
|
`user tried to register twice`
|
||||||
);
|
);
|
||||||
return new Response(null, { status: 403 });
|
return { ok: false, error: "invalidAuth" };
|
||||||
}
|
}
|
||||||
|
|
||||||
const { username, displayName, email, password, avatar } =
|
const { username, displayName, email, password, avatar } =
|
||||||
await registerServerSchema.validate(await request.json());
|
await registerSchema.parse(data);
|
||||||
let avatarBuf = avatar != null ? Buffer.from(avatar, "base64") : null;
|
let avatarBuf = null;
|
||||||
|
if (avatar != null) {
|
||||||
|
const parts = avatar.split(",");
|
||||||
|
const data = parts.length === 2 ? parts[1] : parts[0];
|
||||||
|
avatarBuf = Buffer.from(data, "base64");
|
||||||
|
}
|
||||||
|
|
||||||
const users = await ldap.getUsers();
|
const users = await ldap.getUsers();
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
if (user.id.toLowerCase() === username.toLowerCase()) {
|
if (user.id.toLowerCase() === username.toLowerCase()) {
|
||||||
return new Response(
|
return {
|
||||||
JSON.stringify({
|
|
||||||
ok: false,
|
ok: false,
|
||||||
error: "usernameTaken"
|
error: "usernameTaken"
|
||||||
}),
|
};
|
||||||
{ status: 400 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,10 +58,5 @@ export async function POST(request: Request) {
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(outputUser, "registered user");
|
logger.info(outputUser, "registered user");
|
||||||
return new Response(
|
return { ok: true };
|
||||||
JSON.stringify({
|
|
||||||
ok: true
|
|
||||||
}),
|
|
||||||
{ status: 201 }
|
|
||||||
);
|
|
||||||
}
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
import { ValidAuthProvider } from "@/auth/AuthProvider";
|
||||||
import {
|
import {
|
||||||
AuthState,
|
AuthState,
|
||||||
getAuthState,
|
getAuthState,
|
||||||
|
@ -35,8 +38,7 @@ async function deleteUser(id: number) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export default async function unlink(provider?: ValidAuthProvider) {
|
||||||
export async function POST(request: Request) {
|
|
||||||
const authState = await getAuthState();
|
const authState = await getAuthState();
|
||||||
|
|
||||||
if (authState == AuthState.Registering) {
|
if (authState == AuthState.Registering) {
|
||||||
|
@ -49,30 +51,22 @@ export async function POST(request: Request) {
|
||||||
|
|
||||||
await deleteUser(registeringUser.id);
|
await deleteUser(registeringUser.id);
|
||||||
|
|
||||||
return new Response(null, { status: 200 });
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await getUser();
|
const user = await getUser();
|
||||||
if (user == null) return new Response(null, { status: 401 });
|
if (user == null) return;
|
||||||
|
|
||||||
const { searchParams } = new URL(request.url);
|
|
||||||
const provider = searchParams.get("provider");
|
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case "discord":
|
case "Discord":
|
||||||
const discord = await user.getDiscord();
|
const discord = await user.getDiscord();
|
||||||
if (discord == null) return new Response(null, { status: 400 });
|
if (discord == null) return;
|
||||||
await unlinkDiscord(await discord.getId());
|
await unlinkDiscord(await discord.getId());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "github":
|
case "GitHub":
|
||||||
const github = await user.getGitHub();
|
const github = await user.getGitHub();
|
||||||
if (github == null) return new Response(null, { status: 400 });
|
if (github == null) return;
|
||||||
await unlinkGitHub(await github.getId());
|
await unlinkGitHub(await github.getId());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
return new Response(null, { status: 400 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(null, { status: 200 });
|
|
||||||
}
|
}
|
|
@ -1,30 +1,28 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
import { AboutMeSchema, aboutMeSchema } from "@/schemas";
|
||||||
|
import { ActionResponse } from ".";
|
||||||
|
import { getLogger } from "@/logger";
|
||||||
import { getUser } from "@/auth/auth";
|
import { getUser } from "@/auth/auth";
|
||||||
import { getUserInfo, updateUser } from "@/ldap";
|
import { getUserInfo, updateUser } from "@/ldap";
|
||||||
import { getLogger } from "@/logger";
|
|
||||||
|
|
||||||
type RequestBody = {
|
const logger = getLogger("/actions/update");
|
||||||
displayName?: string;
|
|
||||||
email?: string;
|
|
||||||
avatar?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
|
||||||
const logger = getLogger("/api/update");
|
|
||||||
|
|
||||||
|
export default async function update(
|
||||||
|
data: AboutMeSchema
|
||||||
|
): Promise<ActionResponse> {
|
||||||
const user = await getUser();
|
const user = await getUser();
|
||||||
if (user == null) return new Response(null, { status: 401 });
|
if (user == null) {
|
||||||
|
return { ok: false, error: "invalidAuth" };
|
||||||
|
}
|
||||||
|
|
||||||
const userInfo = await getUserInfo(user);
|
const userInfo = await getUserInfo(user);
|
||||||
if (userInfo == null) {
|
if (userInfo == null) {
|
||||||
// no user info = hasn't registered yet
|
// no user info = hasn't registered yet
|
||||||
return new Response(null, { status: 409 });
|
return { ok: false, error: "invalidAuth" };
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const { displayName, email, avatar } = await aboutMeSchema.parse(data);
|
||||||
displayName,
|
|
||||||
email,
|
|
||||||
avatar: avatarBase64
|
|
||||||
} = (await request.json()) as RequestBody;
|
|
||||||
|
|
||||||
let changeDisplayName = false;
|
let changeDisplayName = false;
|
||||||
if (
|
if (
|
||||||
|
@ -47,25 +45,24 @@ export async function POST(request: Request) {
|
||||||
|
|
||||||
let avatarBuf = undefined;
|
let avatarBuf = undefined;
|
||||||
if (
|
if (
|
||||||
avatarBase64 !== undefined &&
|
avatar !== undefined &&
|
||||||
typeof avatarBase64 === "string" &&
|
typeof avatar === "string" &&
|
||||||
avatarBase64 !== userInfo.avatar
|
avatar !== userInfo.avatar
|
||||||
) {
|
) {
|
||||||
avatarBuf = Buffer.from(avatarBase64, "base64");
|
const parts = avatar.split(",");
|
||||||
|
const data = parts.length === 2 ? parts[1] : parts[0];
|
||||||
|
avatarBuf = Buffer.from(data, "base64");
|
||||||
|
|
||||||
if (avatarBuf.length > 2_000_000) {
|
if (avatarBuf.length > 2_000_000) {
|
||||||
return new Response(
|
return {
|
||||||
JSON.stringify({
|
|
||||||
ok: false,
|
ok: false,
|
||||||
error: "avatarBig"
|
error: "avatarBig"
|
||||||
}),
|
};
|
||||||
{ status: 400 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changeDisplayName && !changeEmail && !avatarBuf) {
|
if (!changeDisplayName && !changeEmail && !avatarBuf) {
|
||||||
return new Response(null, { status: 200 });
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateUser(
|
await updateUser(
|
||||||
|
@ -85,12 +82,5 @@ export async function POST(request: Request) {
|
||||||
"updated user"
|
"updated user"
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Response(
|
return { ok: true };
|
||||||
JSON.stringify({
|
|
||||||
ok: true
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
status: 200
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
import { authTicketLogin } from "@/auth/auth";
|
|
||||||
import * as ldap from "@/ldap";
|
|
||||||
import { loginSchema } from "@/schemas";
|
|
||||||
|
|
||||||
type RequestBody = {
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
|
||||||
const { username, password } = await loginSchema.validate(
|
|
||||||
await request.json()
|
|
||||||
);
|
|
||||||
|
|
||||||
const valid = await ldap.validateUser(username, password);
|
|
||||||
if (!valid) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
ok: false,
|
|
||||||
error: "invalidCredentials"
|
|
||||||
}),
|
|
||||||
{ status: 401 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [_, ticket] = await authTicketLogin(username);
|
|
||||||
// not confident if we can set-cookie and I cba to try
|
|
||||||
return new Response(JSON.stringify({ ok: true, ticket: ticket.ticket }));
|
|
||||||
}
|
|
|
@ -1,43 +1,28 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import login from "@/actions/login";
|
||||||
import Input from "@/components/Input";
|
import Input from "@/components/Input";
|
||||||
import PrettyForm from "@/components/PrettyForm";
|
import PrettyForm from "@/components/PrettyForm";
|
||||||
import { LoginFormValues, loginSchema } from "@/schemas";
|
import { LoginSchema, loginSchema } from "@/schemas";
|
||||||
import { Form, Formik, FormikHelpers, FormikValues } from "formik";
|
import { Form, Formik, FormikHelpers, FormikValues } from "formik";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { toFormikValidationSchema } from "zod-formik-adapter";
|
||||||
|
|
||||||
export default function LoginForm() {
|
export default function LoginForm() {
|
||||||
const [globalError, setGlobalError] = React.useState<string | null>(null);
|
const [globalError, setGlobalError] = React.useState<string | null>(null);
|
||||||
|
|
||||||
async function handleFormSubmit(
|
async function handleFormSubmit(
|
||||||
{ username, password }: LoginFormValues,
|
data: LoginSchema,
|
||||||
{ setSubmitting }: FormikHelpers<LoginFormValues>
|
{ setSubmitting }: FormikHelpers<LoginSchema>
|
||||||
) {
|
) {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
|
||||||
if (username === "greets") {
|
if (data.username === "greets") {
|
||||||
window.location.href = "/sekrit";
|
window.location.href = "/sekrit";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const req = await fetch("/api/login", {
|
const res = await login(data);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
password
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res: {
|
|
||||||
ok: boolean;
|
|
||||||
error?: string;
|
|
||||||
ticket: string;
|
|
||||||
} = await req.json();
|
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
document.cookie = `ticket=${res.ticket}; path=/;`;
|
document.cookie = `ticket=${res.ticket}; path=/;`;
|
||||||
window.location.href = "/me";
|
window.location.href = "/me";
|
||||||
|
@ -45,11 +30,6 @@ export default function LoginForm() {
|
||||||
// only error is invalidCredentials, I am lazy
|
// only error is invalidCredentials, I am lazy
|
||||||
setGlobalError("Invalid credentials.");
|
setGlobalError("Invalid credentials.");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
setGlobalError("shits fucked up yo");
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -57,7 +37,7 @@ export default function LoginForm() {
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{ username: "", password: "" }}
|
initialValues={{ username: "", password: "" }}
|
||||||
onSubmit={handleFormSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
validationSchema={loginSchema}
|
validationSchema={toFormikValidationSchema(loginSchema)}
|
||||||
>
|
>
|
||||||
{({ isSubmitting }) => (
|
{({ isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.content {
|
.content {
|
||||||
width: min(100vw, min-content);
|
width: min-content;
|
||||||
margin: 2rem auto;
|
margin: 2rem auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,6 @@ import styles from "./AboutMe.module.css";
|
||||||
import AvatarChanger from "@/components/AvatarChanger";
|
import AvatarChanger from "@/components/AvatarChanger";
|
||||||
import Input, { Hint, Label } from "@/components/Input";
|
import Input, { Hint, Label } from "@/components/Input";
|
||||||
import { Form, Formik, FormikHelpers } from "formik";
|
import { Form, Formik, FormikHelpers } from "formik";
|
||||||
import {
|
|
||||||
AboutMeFormValues,
|
|
||||||
PasswordUpdateFormValues,
|
|
||||||
aboutMeSchema,
|
|
||||||
passwordUpdateSchema
|
|
||||||
} from "@/schemas";
|
|
||||||
import PrettyForm from "@/components/PrettyForm";
|
import PrettyForm from "@/components/PrettyForm";
|
||||||
import Toast from "@/components/Toast";
|
import Toast from "@/components/Toast";
|
||||||
import { AuthProviderState } from "@/auth/AuthProvider";
|
import { AuthProviderState } from "@/auth/AuthProvider";
|
||||||
|
@ -21,11 +15,9 @@ import DiscordIcon from "@/components/icons/DiscordIcon";
|
||||||
import GitHubIcon from "@/components/icons/GitHubIcon";
|
import GitHubIcon from "@/components/icons/GitHubIcon";
|
||||||
import TailscaleIcon from "@/components/icons/TailscaleIcon";
|
import TailscaleIcon from "@/components/icons/TailscaleIcon";
|
||||||
import MigaduIcon from "@/components/icons/MigaduIcon";
|
import MigaduIcon from "@/components/icons/MigaduIcon";
|
||||||
|
import { AboutMeSchema, aboutMeSchema } from "@/schemas";
|
||||||
type UpdateResponse = {
|
import update from "@/actions/update";
|
||||||
ok: boolean;
|
import { toFormikValidationSchema } from "zod-formik-adapter";
|
||||||
error?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function AboutMe({
|
export default function AboutMe({
|
||||||
info,
|
info,
|
||||||
|
@ -39,7 +31,7 @@ export default function AboutMe({
|
||||||
const [madeProfileChanges, setMadeChanges] = React.useState(false);
|
const [madeProfileChanges, setMadeChanges] = React.useState(false);
|
||||||
const [madePasswordChanges, setMadePasswordChanges] = React.useState(false);
|
const [madePasswordChanges, setMadePasswordChanges] = React.useState(false);
|
||||||
|
|
||||||
const initialValues: AboutMeFormValues = {
|
const initialValues: AboutMeSchema = {
|
||||||
username: info.username,
|
username: info.username,
|
||||||
displayName: info.displayName,
|
displayName: info.displayName,
|
||||||
email: info.email,
|
email: info.email,
|
||||||
|
@ -47,78 +39,21 @@ export default function AboutMe({
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handleFormSubmit(
|
async function handleFormSubmit(
|
||||||
{ displayName, email, avatar }: AboutMeFormValues,
|
data: AboutMeSchema,
|
||||||
{ setSubmitting }: FormikHelpers<AboutMeFormValues>
|
{ setSubmitting }: FormikHelpers<AboutMeSchema>
|
||||||
) {
|
) {
|
||||||
setMadeChanges(false);
|
setMadeChanges(false);
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
const req = await fetch("/api/update", {
|
const res = await update(data);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
displayName,
|
|
||||||
email,
|
|
||||||
avatar: avatar != null ? avatar.split(",")[1] : null
|
|
||||||
})
|
|
||||||
});
|
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
|
|
||||||
try {
|
if (res.ok) {
|
||||||
const res: UpdateResponse = await req.json();
|
|
||||||
|
|
||||||
if (!res.ok && res.error !== null) {
|
|
||||||
switch (res.error) {
|
|
||||||
case "avatarBig":
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setMadeChanges(true);
|
setMadeChanges(true);
|
||||||
} catch {
|
} else {
|
||||||
console.error(req);
|
if (res.error != undefined) {
|
||||||
|
setGlobalError("Unknown error: " + res.error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [passwordError, setPasswordError] = React.useState<string | null>(null);
|
|
||||||
const initialPasswordValues: PasswordUpdateFormValues = {
|
|
||||||
password: "",
|
|
||||||
newPassword: "",
|
|
||||||
confirmPassword: ""
|
|
||||||
};
|
|
||||||
|
|
||||||
async function handlePasswordSubmit(
|
|
||||||
{ password, newPassword }: PasswordUpdateFormValues,
|
|
||||||
{ setFieldError, setSubmitting }: FormikHelpers<PasswordUpdateFormValues>
|
|
||||||
) {
|
|
||||||
setMadePasswordChanges(false);
|
|
||||||
setSubmitting(true);
|
|
||||||
const req = await fetch("/api/changePassword", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
currentPassword: password,
|
|
||||||
newPassword: newPassword
|
|
||||||
})
|
|
||||||
});
|
|
||||||
setSubmitting(false);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res: UpdateResponse = await req.json();
|
|
||||||
|
|
||||||
if (!res.ok && res.error !== null) {
|
|
||||||
switch (res.error) {
|
|
||||||
case "incorrectPassword":
|
|
||||||
setFieldError("password", "Incorrect password.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setMadePasswordChanges(true);
|
|
||||||
} catch {
|
|
||||||
console.error(req);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -127,7 +62,7 @@ export default function AboutMe({
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleFormSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
validationSchema={aboutMeSchema}
|
validationSchema={toFormikValidationSchema(aboutMeSchema)}
|
||||||
>
|
>
|
||||||
{({ isSubmitting }) => (
|
{({ isSubmitting }) => (
|
||||||
<Form className={styles.profileGrid}>
|
<Form className={styles.profileGrid}>
|
||||||
|
@ -150,7 +85,7 @@ export default function AboutMe({
|
||||||
<div>
|
<div>
|
||||||
<h2 className={styles.userName}>{info.username}</h2>
|
<h2 className={styles.userName}>{info.username}</h2>
|
||||||
<div className={styles.rightGrid}>
|
<div className={styles.rightGrid}>
|
||||||
<div>
|
<div className={styles.profile}>
|
||||||
{madeProfileChanges ? (
|
{madeProfileChanges ? (
|
||||||
<Toast>Saved your changes.</Toast>
|
<Toast>Saved your changes.</Toast>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -233,69 +168,6 @@ export default function AboutMe({
|
||||||
)}
|
)}
|
||||||
</Formik>
|
</Formik>
|
||||||
</PrettyForm>
|
</PrettyForm>
|
||||||
{/*<PrettyForm globalError={passwordError}>
|
|
||||||
<Formik
|
|
||||||
initialValues={initialPasswordValues}
|
|
||||||
onSubmit={handlePasswordSubmit}
|
|
||||||
validationSchema={passwordUpdateSchema}
|
|
||||||
>
|
|
||||||
{({ isSubmitting }) => (
|
|
||||||
<Form>
|
|
||||||
{madePasswordChanges ? (
|
|
||||||
<Toast>Changed your password.</Toast>
|
|
||||||
) : null}
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
name="password"
|
|
||||||
label="Current"
|
|
||||||
minLength={12}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
name="newPassword"
|
|
||||||
label="New"
|
|
||||||
minLength={12}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
name="confirmPassword"
|
|
||||||
label="Confirm"
|
|
||||||
minLength={12}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="submit"
|
|
||||||
value="Save"
|
|
||||||
className={styles.fancyInput}
|
|
||||||
disabled={isSubmitting}
|
|
||||||
/>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</PrettyForm>
|
|
||||||
|
|
||||||
<h2 className={styles.header}>Connections</h2>
|
|
||||||
<div className={styles.authProviderList}>
|
|
||||||
{providers.map((provider) => (
|
|
||||||
<AuthProviderEntry provider={provider} key={provider.name} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
value="Log out"
|
|
||||||
className={styles.logout}
|
|
||||||
onClick={async () => {
|
|
||||||
document.cookie =
|
|
||||||
"ticket=; expires=" + new Date().toUTCString() + "; path=/";
|
|
||||||
window.location.href = "/";
|
|
||||||
}}
|
|
||||||
/>*/}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,17 @@
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styles from "./RegisterForm.module.css";
|
import styles from "./RegisterForm.module.css";
|
||||||
import { Form, Formik, FormikHelpers, yupToFormErrors } from "formik";
|
import { Form, Formik, FormikHelpers } from "formik";
|
||||||
import { RegisterFormValues, registerSchema } from "@/schemas";
|
import { registerSchema, RegisterSchema } from "@/schemas";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { fileAsBase64 } from "@/forms";
|
|
||||||
import Input from "@/components/Input";
|
import Input from "@/components/Input";
|
||||||
import PrettyForm from "@/components/PrettyForm";
|
import PrettyForm from "@/components/PrettyForm";
|
||||||
import HugeSubmit from "@/components/HugeSubmit";
|
import HugeSubmit from "@/components/HugeSubmit";
|
||||||
import AvatarChanger from "@/components/AvatarChanger";
|
import AvatarChanger from "@/components/AvatarChanger";
|
||||||
import { ValidAuthProvider } from "@/auth/AuthProvider";
|
import { ValidAuthProvider } from "@/auth/AuthProvider";
|
||||||
|
import { toFormikValidationSchema } from "zod-formik-adapter";
|
||||||
type RegisterResponse = {
|
import register from "@/actions/register";
|
||||||
ok: boolean;
|
import unlink from "@/actions/unlink";
|
||||||
error?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RegisterForm({
|
export default function RegisterForm({
|
||||||
initialDisplayName,
|
initialDisplayName,
|
||||||
|
@ -31,7 +28,7 @@ export default function RegisterForm({
|
||||||
const [globalError, setGlobalError] = React.useState<string | null>(null);
|
const [globalError, setGlobalError] = React.useState<string | null>(null);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const initialValues: RegisterFormValues = {
|
const initialValues: RegisterSchema = {
|
||||||
username: "",
|
username: "",
|
||||||
displayName: initialDisplayName ?? "",
|
displayName: initialDisplayName ?? "",
|
||||||
email: initialEmail ?? "",
|
email: initialEmail ?? "",
|
||||||
|
@ -41,28 +38,12 @@ export default function RegisterForm({
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handleFormSubmit(
|
async function handleFormSubmit(
|
||||||
{ avatar, username, displayName, email, password }: RegisterFormValues,
|
data: RegisterSchema,
|
||||||
{ setFieldError, setSubmitting }: FormikHelpers<RegisterFormValues>
|
{ setFieldError, setSubmitting }: FormikHelpers<RegisterSchema>
|
||||||
) {
|
) {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
|
||||||
const resp = await fetch(`/api/register`, {
|
const res = await register(data);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
displayName,
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
avatar: avatar != null ? avatar.split(",")[1] : undefined
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res: RegisterResponse = await resp.json();
|
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
router.replace("/me");
|
router.replace("/me");
|
||||||
} else {
|
} else {
|
||||||
|
@ -78,13 +59,13 @@ export default function RegisterForm({
|
||||||
case "usernameTaken":
|
case "usernameTaken":
|
||||||
setFieldError("username", "Username is already taken.");
|
setFieldError("username", "Username is already taken.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
setGlobalError("Unknown error: " + res.error);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
setGlobalError("you done fucked up kiddo");
|
|
||||||
}
|
|
||||||
|
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +75,7 @@ export default function RegisterForm({
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={handleFormSubmit}
|
onSubmit={handleFormSubmit}
|
||||||
validationSchema={registerSchema}
|
validationSchema={toFormikValidationSchema(registerSchema)}
|
||||||
enableReinitialize
|
enableReinitialize
|
||||||
>
|
>
|
||||||
{({ isSubmitting }) => (
|
{({ isSubmitting }) => (
|
||||||
|
@ -163,7 +144,7 @@ export default function RegisterForm({
|
||||||
<a
|
<a
|
||||||
className={styles.bail}
|
className={styles.bail}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await fetch("/api/unlink", { method: "POST" });
|
await unlink();
|
||||||
document.cookie =
|
document.cookie =
|
||||||
"ticket=; expires=" + new Date().toUTCString() + "; path=/";
|
"ticket=; expires=" + new Date().toUTCString() + "; path=/";
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
|
|
|
@ -2,7 +2,7 @@ export type ValidAuthProvider = "Discord" | "GitHub";
|
||||||
|
|
||||||
// Can't send the providers across the wire, do this instead
|
// Can't send the providers across the wire, do this instead
|
||||||
export type AuthProviderState = {
|
export type AuthProviderState = {
|
||||||
name: string;
|
name: ValidAuthProvider;
|
||||||
} & ({ connected: false } | { connected: true; id: string; username: string });
|
} & ({ connected: false } | { connected: true; id: string; username: string });
|
||||||
|
|
||||||
export abstract class AuthProvider {
|
export abstract class AuthProvider {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import classnames from "classnames";
|
||||||
import CheckIcon from "./icons/CheckIcon";
|
import CheckIcon from "./icons/CheckIcon";
|
||||||
import { type AuthProviderState } from "@/auth/AuthProvider";
|
import { type AuthProviderState } from "@/auth/AuthProvider";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import unlink from "@/actions/unlink";
|
||||||
|
|
||||||
export default function Connection({
|
export default function Connection({
|
||||||
service,
|
service,
|
||||||
|
@ -23,11 +24,11 @@ export default function Connection({
|
||||||
const interval = React.useRef<NodeJS.Timeout | null>();
|
const interval = React.useRef<NodeJS.Timeout | null>();
|
||||||
|
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
const name = authState?.name.toLowerCase();
|
const name = authState?.name;
|
||||||
if (!authState?.connected) {
|
if (!authState?.connected) {
|
||||||
router.push(`/oauth/${name}/login`);
|
router.push(`/oauth/${name?.toLowerCase()}/login`);
|
||||||
} else {
|
} else {
|
||||||
await fetch(`/api/unlink?provider=${name}`, { method: "POST" });
|
await unlink(name);
|
||||||
router.refresh();
|
router.refresh();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -74,7 +74,6 @@ export default function Input<T>(
|
||||||
title={props.title}
|
title={props.title}
|
||||||
{...inputFields}
|
{...inputFields}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
console.log(event);
|
|
||||||
if (props.customOnChange) {
|
if (props.customOnChange) {
|
||||||
console.log("using custom on change");
|
console.log("using custom on change");
|
||||||
props.customOnChange(event, form);
|
props.customOnChange(event, form);
|
||||||
|
|
|
@ -5,7 +5,7 @@ export default function PrettyForm({
|
||||||
globalError,
|
globalError,
|
||||||
children
|
children
|
||||||
}: {
|
}: {
|
||||||
globalError: string | null;
|
globalError?: string | null;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
|
|
116
src/schemas.ts
116
src/schemas.ts
|
@ -1,109 +1,71 @@
|
||||||
import * as Yup from "yup";
|
import { z } from "zod";
|
||||||
|
|
||||||
const REQUIRED = "Required.";
|
const USERNAME = z
|
||||||
const USERNAME = Yup.string()
|
.string()
|
||||||
.required(REQUIRED)
|
|
||||||
.min(1, "Username is too short.")
|
.min(1, "Username is too short.")
|
||||||
.matches(/^[a-z0-9]+$/, "Username must be lowercase letters and numbers.");
|
.regex(/^[a-z0-9]+$/, "Username must be lowercase alphanumeric.");
|
||||||
|
const DISPLAY_NAME = z.string().min(1, "Display name is too short.");
|
||||||
const DISPLAY_NAME = Yup.string()
|
const EMAIL = z.string().email("Not an email.");
|
||||||
.required(REQUIRED)
|
const PASSWORD = z
|
||||||
.min(1, "Display name is too short.");
|
.string()
|
||||||
const EMAIL = Yup.string().required(REQUIRED).email("Not an email.");
|
|
||||||
|
|
||||||
const PASSWORD = Yup.string()
|
|
||||||
.required(REQUIRED)
|
|
||||||
.min(12, "Password must be at least 12 characters long.");
|
.min(12, "Password must be at least 12 characters long.");
|
||||||
const CONFIRM_PASSWORD = (name: string) =>
|
const AVATAR = z.string().refine(
|
||||||
Yup.string()
|
(val) => {
|
||||||
.required(REQUIRED)
|
const parts = val.split(",");
|
||||||
.oneOf([Yup.ref(name, {})], "Passwords must match.");
|
const data = parts.length === 2 ? parts[1] : parts[0];
|
||||||
|
|
||||||
const AVATAR = Yup.string().test(
|
|
||||||
"file-size",
|
|
||||||
"File is bigger than 2 MB.",
|
|
||||||
(value) => {
|
|
||||||
if (value == null) return true;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const buf = Buffer.from(value, "base64");
|
const buf = Buffer.from(data, "base64");
|
||||||
return buf.length <= 2_000_000;
|
return buf.length <= 2_000_000;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "File is bigger than 2 MB.",
|
||||||
|
path: ["avatar"]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const loginSchema = Yup.object().shape({
|
export const loginSchema = z.object({
|
||||||
username: USERNAME,
|
username: USERNAME,
|
||||||
password: PASSWORD
|
password: PASSWORD
|
||||||
});
|
});
|
||||||
|
export type LoginSchema = z.infer<typeof loginSchema>;
|
||||||
|
|
||||||
export type LoginFormValues = {
|
export const registerSchema = z
|
||||||
username: string;
|
.object({
|
||||||
password: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const registerSchema: Yup.Schema<RegisterFormValues> =
|
|
||||||
Yup.object().shape({
|
|
||||||
username: USERNAME,
|
username: USERNAME,
|
||||||
displayName: DISPLAY_NAME,
|
displayName: DISPLAY_NAME,
|
||||||
email: EMAIL,
|
email: EMAIL,
|
||||||
password: PASSWORD,
|
password: PASSWORD,
|
||||||
confirmPassword: CONFIRM_PASSWORD("password"),
|
confirmPassword: PASSWORD,
|
||||||
avatar: AVATAR
|
avatar: AVATAR.optional()
|
||||||
|
})
|
||||||
|
.refine((data) => data.password === data.confirmPassword, {
|
||||||
|
message: "Passwords do not match.",
|
||||||
|
path: ["confirmPassword"]
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface RegisterFormValues {
|
export type RegisterSchema = z.infer<typeof registerSchema>;
|
||||||
username: string;
|
|
||||||
displayName: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
confirmPassword: string;
|
|
||||||
avatar?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const aboutMeSchema: Yup.Schema<AboutMeFormValues> = Yup.object().shape({
|
export const aboutMeSchema = z.object({
|
||||||
username: USERNAME,
|
username: USERNAME,
|
||||||
displayName: DISPLAY_NAME,
|
displayName: DISPLAY_NAME,
|
||||||
email: EMAIL,
|
email: EMAIL,
|
||||||
avatar: AVATAR
|
avatar: AVATAR.optional()
|
||||||
});
|
});
|
||||||
|
export type AboutMeSchema = z.infer<typeof aboutMeSchema>;
|
||||||
|
|
||||||
export interface AboutMeFormValues {
|
export const passwordUpdateSchema = z
|
||||||
username: string;
|
.object({
|
||||||
displayName: string;
|
|
||||||
email: string;
|
|
||||||
avatar?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const passwordUpdateSchema: Yup.Schema<PasswordUpdateFormValues> =
|
|
||||||
Yup.object().shape({
|
|
||||||
password: PASSWORD,
|
password: PASSWORD,
|
||||||
newPassword: PASSWORD,
|
newPassword: PASSWORD,
|
||||||
confirmPassword: CONFIRM_PASSWORD("newPassword")
|
confirmPassword: PASSWORD
|
||||||
|
})
|
||||||
|
.refine((data) => data.newPassword === data.confirmPassword, {
|
||||||
|
message: "Passwords do not match.",
|
||||||
|
path: ["confirmPassword"]
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface PasswordUpdateFormValues {
|
export type PasswordUpdateSchema = z.infer<typeof passwordUpdateSchema>;
|
||||||
password: string;
|
|
||||||
newPassword: string;
|
|
||||||
confirmPassword: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Types specific to the server, because sometimes we omit fields (like confirmPassword)
|
|
||||||
export const registerServerSchema: Yup.Schema<RegisterServerFormValues> =
|
|
||||||
Yup.object().shape({
|
|
||||||
username: USERNAME,
|
|
||||||
displayName: DISPLAY_NAME,
|
|
||||||
email: EMAIL,
|
|
||||||
password: PASSWORD,
|
|
||||||
avatar: AVATAR
|
|
||||||
});
|
|
||||||
|
|
||||||
export interface RegisterServerFormValues {
|
|
||||||
username: string;
|
|
||||||
displayName: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
avatar?: string;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue