diff --git a/chart/templates/statefulset-clickhouse.yaml b/chart/templates/statefulset-clickhouse.yaml index 57b22a9..0db9a16 100644 --- a/chart/templates/statefulset-clickhouse.yaml +++ b/chart/templates/statefulset-clickhouse.yaml @@ -1,10 +1,15 @@ apiVersion: apps/v1 kind: StatefulSet metadata: - name: {{ include "poeticmetric.fullname" . }}-clickhouse labels: {{ include "poeticmetric.labels" . | nindent 4 }} + name: {{ include "poeticmetric.fullname" . }}-clickhouse spec: + {{ if .Values.clickhouse.persistence.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Retain + whenScaled: Retain + {{ end }} replicas: 1 selector: matchLabels: @@ -43,8 +48,8 @@ spec: name: clickhouse resources: {{ toYaml .Values.clickhouse.resources | nindent 10 }} volumeMounts: - - name: configmap-clickhouse - mountPath: /etc/clickhouse-server/config.d/custom_config.xml + - mountPath: /etc/clickhouse-server/config.d/custom_config.xml + name: configmap-clickhouse subPath: CONFIG {{ if .Values.clickhouse.persistence.enabled }} - mountPath: /var/lib/clickhouse/ @@ -56,12 +61,9 @@ spec: name: {{ include "poeticmetric.fullname" . }}-clickhouse name: configmap-clickhouse {{ if .Values.clickhouse.persistence.enabled }} - persistentVolumeClaimRetentionPolicy: - whenDeleted: Retain - whenScaled: Retain volumeClaimTemplates: - - kind: PersistentVolumeClaim - apiVersion: v1 + - apiVersion: v1 + kind: PersistentVolumeClaim metadata: name: data spec: diff --git a/chart/templates/statefulset-postgres.yaml b/chart/templates/statefulset-postgres.yaml index e4501a3..6f98358 100644 --- a/chart/templates/statefulset-postgres.yaml +++ b/chart/templates/statefulset-postgres.yaml @@ -5,6 +5,11 @@ metadata: {{ include "poeticmetric.labels" . | nindent 4 }} name: {{ include "poeticmetric.fullname" . }}-postgres spec: + {{ if .Values.postgres.persistence.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Retain + whenScaled: Retain + {{ end }} replicas: 1 selector: matchLabels: @@ -42,17 +47,16 @@ spec: imagePullPolicy: {{ .Values.postgres.image.pullPolicy }} name: postgres resources: {{ toYaml .Values.postgres.resources | nindent 10 }} - {{ if .Values.postgres.persistence.enabled }} + {{ if .Values.postgres.persistence.enabled }} volumeMounts: - mountPath: /var/lib/postgresql/data name: data subPath: postgres - persistentVolumeClaimRetentionPolicy: - whenDeleted: Retain - whenScaled: Retain + {{ end }} + {{ if .Values.postgres.persistence.enabled }} volumeClaimTemplates: - - kind: PersistentVolumeClaim - apiVersion: v1 + - apiVersion: v1 + kind: PersistentVolumeClaim metadata: name: data spec: diff --git a/chart/templates/statefulset-redis.yaml b/chart/templates/statefulset-redis.yaml index b0d8fcf..bee7b9b 100644 --- a/chart/templates/statefulset-redis.yaml +++ b/chart/templates/statefulset-redis.yaml @@ -5,6 +5,11 @@ metadata: {{ include "poeticmetric.labels" . | nindent 4 }} name: {{ include "poeticmetric.fullname" . }}-redis spec: + {{ if .Values.redis.persistence.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: Retain + whenScaled: Retain + {{ end }} replicas: 1 selector: matchLabels: @@ -36,9 +41,6 @@ spec: subPath: redis {{ end }} {{ if .Values.redis.persistence.enabled }} - persistentVolumeClaimRetentionPolicy: - whenDeleted: Retain - whenScaled: Retain volumeClaimTemplates: - kind: PersistentVolumeClaim apiVersion: v1 diff --git a/frontend/src/components/App/index.tsx b/frontend/src/components/App/index.tsx index 4c1f09a..1db66a7 100644 --- a/frontend/src/components/App/index.tsx +++ b/frontend/src/components/App/index.tsx @@ -6,6 +6,7 @@ import Error from "~/components/Error"; import Home from "~/components/Home"; import Manifesto from "~/components/Manifesto"; import PasswordRecovery from "~/components/PasswordRecovery"; +import PasswordReset from "~/components/PasswordReset"; import SignIn from "~/components/SignIn"; export default function App() { @@ -16,6 +17,7 @@ export default function App() { + diff --git a/frontend/src/components/Bootstrap/index.tsx b/frontend/src/components/Bootstrap/index.tsx index becdac4..88c84aa 100644 --- a/frontend/src/components/Bootstrap/index.tsx +++ b/frontend/src/components/Bootstrap/index.tsx @@ -1,3 +1,4 @@ +import { IconX } from "@tabler/icons-react"; import clsx from "clsx"; import { useEffect, useState } from "react"; import { useErrorBoundary } from "react-error-boundary"; @@ -155,11 +156,19 @@ export default function Bootstrap() {
+ {errors.root ? ( +
+ + + {errors.root.message} +
+ ) : null} +
E-mail address
- +
- +
- + @@ -223,7 +235,7 @@ export default function Bootstrap() {
:global(.container) { + align-self: center; + grid-row: 2 span / 3; + } + } +} diff --git a/frontend/src/components/PasswordReset/index.tsx b/frontend/src/components/PasswordReset/index.tsx new file mode 100644 index 0000000..242c1ca --- /dev/null +++ b/frontend/src/components/PasswordReset/index.tsx @@ -0,0 +1,198 @@ +import { IconX } from "@tabler/icons-react"; +import clsx from "clsx"; +import { useEffect, useState } from "react"; +import { useErrorBoundary } from "react-error-boundary"; +import { useForm } from "react-hook-form"; +import { Link, useSearch } from "wouter"; +import ActivityOverlay from "~/components/ActivityOverlay"; +import FormTitle from "~/components/FormTitle"; +import Layout from "~/components/Layout"; +import Title from "~/components/Title"; +import useUser from "~/hooks/useUser"; +import { api } from "~/lib/api"; +import { setErrors } from "~/lib/form"; +import styles from "./PasswordReset.module.css"; + +type State = { + isAlreadySignedIn: boolean; + isPasswordUpdated: boolean; + isTokenValid: boolean; +}; + +type Form = { + passwordResetToken: string; + userPassword: string; + userPassword2: string; +}; + +export default function PasswordReset() { + const { showBoundary } = useErrorBoundary(); + const search = useSearch(); + const user = useUser(); + const token = new URLSearchParams(search).get("t"); + const [state, setState] = useState({ isAlreadySignedIn: false, isPasswordUpdated: false, isTokenValid: false }); + const { clearErrors, formState: { errors, isSubmitting }, handleSubmit, register, reset, setError } = useForm(); + + useEffect(() => { + if (user) { + setState((prev) => ({ ...prev, isAlreadySignedIn: true })); + } + }, [user]); + + useEffect(() => { + setState((prev) => ({ ...prev, isTokenValid: !!token })); + }, [token]); + + useEffect(() => { + if (!!errors.passwordResetToken) { + setState((prev) => ({ ...prev, isTokenValid: false })); + + reset(); + } + }, [errors.passwordResetToken]); + + async function submit(data: Form) { + try { + const response = await api.post("/authentication/reset-user-password", { + ...data, + }); + + const responseJson = await response.json(); + + if (response.ok) { + setState((prev) => ({ ...prev, isPasswordUpdated: true })); + } else { + setErrors(setError, responseJson); + } + } catch (error) { + showBoundary(error); + } + } + + return ( + <> + Reset password + + + {state.isAlreadySignedIn ? ( +
+ + Go to settings + + )} + description="You can reset your password from user settings." + summary="Password reset" + title="You are already in!" + /> +
+ ) : state.isTokenValid ? + state.isPasswordUpdated ? ( +
+ + Sign in to your account + + )} + description="You succesfully reset your password." + showGoBack={false} + summary="Password reset" + title="You are all set!" + /> +
+ ) : ( +
+ + +
+ + +
+ {errors.root ? ( +
+ + + {errors.root.message} +
+ ) : null} + + clearErrors(), + value: token || "", + })} + /> + +
+ + + clearErrors() })} + /> + + {!!errors.userPassword ? ( +
{errors.userPassword.message}
+ ) : null} +
+ +
+ + + clearErrors() })} + /> + + {!!errors.userPassword2 ? ( +
{errors.userPassword2.message}
+ ) : null} +
+ + +
+ +
+
+
+ ) : ( +
+ + + Request new link + + + + Contact support + + + )} + description="Your link is invalid or expired. Request a new one or contact support for help." + maxWidth="28rem" + showGoBack={false} + summary="Password reset" + title="Ooops, invalid link!" + /> +
+ )} +
+ + ); +} diff --git a/frontend/src/components/SignIn/index.tsx b/frontend/src/components/SignIn/index.tsx index 57509d5..d8939cd 100644 --- a/frontend/src/components/SignIn/index.tsx +++ b/frontend/src/components/SignIn/index.tsx @@ -26,7 +26,7 @@ type State = { export default function SignIn() { const { showBoundary } = useErrorBoundary(); - const location = useLocation(); + const [, navigate] = useLocation(); const searchParams = useSearch(); const user = useUser(); const [state, setState] = useState({ isAlreadySignedIn: false }); @@ -54,7 +54,7 @@ export default function SignIn() { const next = new URLSearchParams(searchParams).get("next"); - location.push(next || "/sites"); + navigate(next || "/sites"); } else { setErrors(setError, responseJson); } @@ -121,7 +121,7 @@ export default function SignIn() {
- + Forgot password? @@ -129,7 +129,8 @@ export default function SignIn() {
clearErrors() })}