Can replace user password from profile
This commit is contained in:
		@@ -11,6 +11,14 @@ export interface User {
 | 
				
			|||||||
  has_password: boolean;
 | 
					  has_password: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export enum ReplacePasswordResponse {
 | 
				
			||||||
 | 
					  Error,
 | 
				
			||||||
 | 
					  Success,
 | 
				
			||||||
 | 
					  InvalidOldPassword,
 | 
				
			||||||
 | 
					  InvalidNewPassword,
 | 
				
			||||||
 | 
					  TooManyRequests,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class UserApi {
 | 
					export class UserApi {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Get current user information
 | 
					   * Get current user information
 | 
				
			||||||
@@ -36,4 +44,39 @@ export class UserApi {
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Replace user password
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  static async ReplacePassword(
 | 
				
			||||||
 | 
					    oldPwd: string,
 | 
				
			||||||
 | 
					    newPwd: string
 | 
				
			||||||
 | 
					  ): Promise<ReplacePasswordResponse> {
 | 
				
			||||||
 | 
					    const res = await APIClient.exec({
 | 
				
			||||||
 | 
					      uri: "/user/replace_password",
 | 
				
			||||||
 | 
					      method: "POST",
 | 
				
			||||||
 | 
					      jsonData: {
 | 
				
			||||||
 | 
					        old_password: oldPwd,
 | 
				
			||||||
 | 
					        new_password: newPwd,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      allowFail: true,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (res.status >= 200 && res.status < 300)
 | 
				
			||||||
 | 
					      return ReplacePasswordResponse.Success;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (res.status) {
 | 
				
			||||||
 | 
					      case 400:
 | 
				
			||||||
 | 
					        return ReplacePasswordResponse.InvalidNewPassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case 401:
 | 
				
			||||||
 | 
					        return ReplacePasswordResponse.InvalidOldPassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case 429:
 | 
				
			||||||
 | 
					        return ReplacePasswordResponse.TooManyRequests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        return ReplacePasswordResponse.Error;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import React, { useRef } from "react";
 | 
					import React, { useRef } from "react";
 | 
				
			||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
					import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
				
			||||||
import { User, UserApi } from "../api/UserApi";
 | 
					import { ReplacePasswordResponse, User, UserApi } from "../api/UserApi";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Alert,
 | 
					  Alert,
 | 
				
			||||||
  Box,
 | 
					  Box,
 | 
				
			||||||
@@ -9,43 +9,26 @@ import {
 | 
				
			|||||||
  CardActions,
 | 
					  CardActions,
 | 
				
			||||||
  CardContent,
 | 
					  CardContent,
 | 
				
			||||||
  Checkbox,
 | 
					  Checkbox,
 | 
				
			||||||
 | 
					  CircularProgress,
 | 
				
			||||||
  FormControlLabel,
 | 
					  FormControlLabel,
 | 
				
			||||||
  TextField,
 | 
					  TextField,
 | 
				
			||||||
  Typography,
 | 
					  Typography,
 | 
				
			||||||
} from "@mui/material";
 | 
					} from "@mui/material";
 | 
				
			||||||
import { TimeWidget, formatDate } from "../widgets/TimeWidget";
 | 
					import { TimeWidget, formatDate } from "../widgets/TimeWidget";
 | 
				
			||||||
import { ServerApi } from "../api/ServerApi";
 | 
					import { ServerApi } from "../api/ServerApi";
 | 
				
			||||||
 | 
					import { PasswordInput } from "../widgets/PasswordInput";
 | 
				
			||||||
 | 
					import { normalize } from "path/win32";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function ProfileRoute(): React.ReactElement {
 | 
					export function ProfileRoute(): React.ReactElement {
 | 
				
			||||||
  const [user, setUser] = React.useState<null | User>(null);
 | 
					  const [user, setUser] = React.useState<null | User>(null);
 | 
				
			||||||
  const [newName, setNewName] = React.useState("");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const [error, setError] = React.useState<string | null>(null);
 | 
					 | 
				
			||||||
  const [success, setSuccess] = React.useState<string | null>(null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const load = async () => {
 | 
					  const load = async () => {
 | 
				
			||||||
    const u = await UserApi.GetUserInfo();
 | 
					    const u = await UserApi.GetUserInfo();
 | 
				
			||||||
    setUser(u);
 | 
					    setUser(u);
 | 
				
			||||||
    setNewName(u.name);
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const counter = useRef(0);
 | 
					  const counter = useRef(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const updateProfile = async () => {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      setSuccess(null);
 | 
					 | 
				
			||||||
      setError(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      await UserApi.UpdateProfile(newName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      counter.current += 1;
 | 
					 | 
				
			||||||
      setSuccess("Informations du profil mises à jour avec succès !");
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					 | 
				
			||||||
      console.error(e);
 | 
					 | 
				
			||||||
      setError("Echec de la mise à jour du profil !");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <AsyncWidget
 | 
					    <AsyncWidget
 | 
				
			||||||
      loadKey={counter.current}
 | 
					      loadKey={counter.current}
 | 
				
			||||||
@@ -55,76 +38,225 @@ export function ProfileRoute(): React.ReactElement {
 | 
				
			|||||||
        <div style={{ maxWidth: "500px", margin: "auto" }}>
 | 
					        <div style={{ maxWidth: "500px", margin: "auto" }}>
 | 
				
			||||||
          <Typography variant="h3">Profil</Typography>
 | 
					          <Typography variant="h3">Profil</Typography>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          {error && <Alert severity="error">{error}</Alert>}
 | 
					          <ProfileSettingsCard
 | 
				
			||||||
          {success && <Alert severity="success">{success}</Alert>}
 | 
					            user={user!}
 | 
				
			||||||
 | 
					            onUpdate={() => (counter.current += 1)}
 | 
				
			||||||
          <Card style={{ marginTop: "10px" }}>
 | 
					          />
 | 
				
			||||||
            <CardContent>
 | 
					          {user?.has_password && <ChangePasswordCard />}
 | 
				
			||||||
              <Typography gutterBottom variant="h5" component="div">
 | 
					 | 
				
			||||||
                Paramètres du compte
 | 
					 | 
				
			||||||
              </Typography>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <Box
 | 
					 | 
				
			||||||
                component="form"
 | 
					 | 
				
			||||||
                sx={{
 | 
					 | 
				
			||||||
                  "& .MuiTextField-root": { m: 1 },
 | 
					 | 
				
			||||||
                }}
 | 
					 | 
				
			||||||
                noValidate
 | 
					 | 
				
			||||||
                autoComplete="off"
 | 
					 | 
				
			||||||
              >
 | 
					 | 
				
			||||||
                <TextField
 | 
					 | 
				
			||||||
                  disabled
 | 
					 | 
				
			||||||
                  fullWidth
 | 
					 | 
				
			||||||
                  label="Identifiant"
 | 
					 | 
				
			||||||
                  value={user?.id}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <TextField
 | 
					 | 
				
			||||||
                  disabled
 | 
					 | 
				
			||||||
                  fullWidth
 | 
					 | 
				
			||||||
                  label="Création du compte"
 | 
					 | 
				
			||||||
                  value={formatDate(user!.time_create)}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <TextField
 | 
					 | 
				
			||||||
                  disabled
 | 
					 | 
				
			||||||
                  fullWidth
 | 
					 | 
				
			||||||
                  label="Activation du compte"
 | 
					 | 
				
			||||||
                  value={formatDate(user!.time_activate)}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <TextField
 | 
					 | 
				
			||||||
                  disabled
 | 
					 | 
				
			||||||
                  fullWidth
 | 
					 | 
				
			||||||
                  label="Adresse mail"
 | 
					 | 
				
			||||||
                  value={user?.email}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <TextField
 | 
					 | 
				
			||||||
                  fullWidth
 | 
					 | 
				
			||||||
                  label="Nom d'utilisateur"
 | 
					 | 
				
			||||||
                  value={newName}
 | 
					 | 
				
			||||||
                  onChange={(e) => setNewName(e.target.value)}
 | 
					 | 
				
			||||||
                  inputProps={{
 | 
					 | 
				
			||||||
                    maxLength: ServerApi.Config.constraints.user_name_len.max,
 | 
					 | 
				
			||||||
                  }}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <FormControlLabel
 | 
					 | 
				
			||||||
                  disabled
 | 
					 | 
				
			||||||
                  control={<Checkbox checked={user!.admin} />}
 | 
					 | 
				
			||||||
                  label="Compte administrateur"
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
              </Box>
 | 
					 | 
				
			||||||
            </CardContent>
 | 
					 | 
				
			||||||
            <CardActions>
 | 
					 | 
				
			||||||
              <Button onClick={updateProfile} style={{ marginLeft: "auto" }}>
 | 
					 | 
				
			||||||
                Enregistrer
 | 
					 | 
				
			||||||
              </Button>
 | 
					 | 
				
			||||||
            </CardActions>
 | 
					 | 
				
			||||||
          </Card>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function ProfileSettingsCard(p: { user: User; onUpdate: () => {} }) {
 | 
				
			||||||
 | 
					  const [newName, setNewName] = React.useState(p.user.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [error, setError] = React.useState<string | null>(null);
 | 
				
			||||||
 | 
					  const [success, setSuccess] = React.useState<string | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const updateProfile = async () => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      setSuccess(null);
 | 
				
			||||||
 | 
					      setError(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      await UserApi.UpdateProfile(newName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      p.onUpdate();
 | 
				
			||||||
 | 
					      setSuccess("Informations du profil enregistrées avec succès !");
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      console.error(e);
 | 
				
			||||||
 | 
					      setError("Echec de la mise à jour du profil !");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <Card style={{ marginTop: "10px" }}>
 | 
				
			||||||
 | 
					        {error && <Alert severity="error">{error}</Alert>}
 | 
				
			||||||
 | 
					        {success && <Alert severity="success">{success}</Alert>}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <CardContent>
 | 
				
			||||||
 | 
					          <Typography gutterBottom variant="h5" component="div">
 | 
				
			||||||
 | 
					            Paramètres du compte
 | 
				
			||||||
 | 
					          </Typography>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <Box
 | 
				
			||||||
 | 
					            component="form"
 | 
				
			||||||
 | 
					            sx={{
 | 
				
			||||||
 | 
					              "& .MuiTextField-root": { my: 1 },
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            noValidate
 | 
				
			||||||
 | 
					            autoComplete="off"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              disabled
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              label="Identifiant"
 | 
				
			||||||
 | 
					              value={p.user.id}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              disabled
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              label="Création du compte"
 | 
				
			||||||
 | 
					              value={formatDate(p.user.time_create)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              disabled
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              label="Activation du compte"
 | 
				
			||||||
 | 
					              value={formatDate(p.user.time_activate)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              disabled
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              label="Adresse mail"
 | 
				
			||||||
 | 
					              value={p.user.email}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              label="Nom d'utilisateur"
 | 
				
			||||||
 | 
					              value={newName}
 | 
				
			||||||
 | 
					              onChange={(e) => setNewName(e.target.value)}
 | 
				
			||||||
 | 
					              inputProps={{
 | 
				
			||||||
 | 
					                maxLength: ServerApi.Config.constraints.user_name_len.max,
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <FormControlLabel
 | 
				
			||||||
 | 
					              disabled
 | 
				
			||||||
 | 
					              control={<Checkbox checked={p.user.admin} />}
 | 
				
			||||||
 | 
					              label="Compte administrateur"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </Box>
 | 
				
			||||||
 | 
					        </CardContent>
 | 
				
			||||||
 | 
					        <CardActions>
 | 
				
			||||||
 | 
					          <Button onClick={updateProfile} style={{ marginLeft: "auto" }}>
 | 
				
			||||||
 | 
					            Enregistrer
 | 
				
			||||||
 | 
					          </Button>
 | 
				
			||||||
 | 
					        </CardActions>
 | 
				
			||||||
 | 
					      </Card>
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function ChangePasswordCard(): React.ReactElement {
 | 
				
			||||||
 | 
					  const [loading, setLoading] = React.useState(false);
 | 
				
			||||||
 | 
					  const [error, setError] = React.useState<string | null>(null);
 | 
				
			||||||
 | 
					  const [success, setSuccess] = React.useState<string | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [oldPassword, setOldpassword] = React.useState("");
 | 
				
			||||||
 | 
					  const [newPassword, setNewpassword] = React.useState("");
 | 
				
			||||||
 | 
					  const [confirmNewPassword, setConfirmNewpassword] = React.useState("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const isValid =
 | 
				
			||||||
 | 
					    ServerApi.CheckPassword(newPassword) === null &&
 | 
				
			||||||
 | 
					    oldPassword.length > 0 &&
 | 
				
			||||||
 | 
					    confirmNewPassword === newPassword;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const updatePassword = async (e: React.FormEvent<HTMLFormElement>) => {
 | 
				
			||||||
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!isValid || loading) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setLoading(true);
 | 
				
			||||||
 | 
					    setSuccess(null);
 | 
				
			||||||
 | 
					    setError(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const result = await UserApi.ReplacePassword(oldPassword, newPassword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      switch (result) {
 | 
				
			||||||
 | 
					        case ReplacePasswordResponse.Error:
 | 
				
			||||||
 | 
					          setError("Echec du changement de mot de passe !");
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case ReplacePasswordResponse.Success:
 | 
				
			||||||
 | 
					          setSuccess("Mot de passe changé avec succès !");
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case ReplacePasswordResponse.InvalidOldPassword:
 | 
				
			||||||
 | 
					          setError("Ancien mot de passe saisi invalide !");
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case ReplacePasswordResponse.InvalidNewPassword:
 | 
				
			||||||
 | 
					          setError("Nouveau mot de passe saisi invalide !");
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case ReplacePasswordResponse.TooManyRequests:
 | 
				
			||||||
 | 
					          setError(
 | 
				
			||||||
 | 
					            "Trop de tentatives de changement de mot de passe, veuillez réessayer ultérieurement !"
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      console.error(e);
 | 
				
			||||||
 | 
					      setError("Echec de la mise à jour du mot de passe !");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setLoading(false);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <Card style={{ marginTop: "10px" }}>
 | 
				
			||||||
 | 
					        {error && <Alert severity="error">{error}</Alert>}
 | 
				
			||||||
 | 
					        {success && <Alert severity="success">{success}</Alert>}
 | 
				
			||||||
 | 
					        <Box
 | 
				
			||||||
 | 
					          component="form"
 | 
				
			||||||
 | 
					          sx={{
 | 
				
			||||||
 | 
					            "& .MuiTextField-root": { my: 1 },
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					          noValidate
 | 
				
			||||||
 | 
					          autoComplete="off"
 | 
				
			||||||
 | 
					          onSubmit={updatePassword}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <CardContent>
 | 
				
			||||||
 | 
					            <Typography gutterBottom variant="h5" component="div">
 | 
				
			||||||
 | 
					              Changement du mot de passe
 | 
				
			||||||
 | 
					            </Typography>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              label="Mot de passe actuel"
 | 
				
			||||||
 | 
					              value={oldPassword}
 | 
				
			||||||
 | 
					              type="password"
 | 
				
			||||||
 | 
					              onChange={(e) => setOldpassword(e.target.value)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <PasswordInput
 | 
				
			||||||
 | 
					              value={newPassword}
 | 
				
			||||||
 | 
					              onChange={(n) => setNewpassword(n)}
 | 
				
			||||||
 | 
					              label={"Nouveau mot de passe"}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <TextField
 | 
				
			||||||
 | 
					              fullWidth
 | 
				
			||||||
 | 
					              error={
 | 
				
			||||||
 | 
					                confirmNewPassword !== "" && confirmNewPassword !== newPassword
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              helperText={
 | 
				
			||||||
 | 
					                confirmNewPassword !== newPassword
 | 
				
			||||||
 | 
					                  ? "Le nouveau mot de passe et sa confirmation doivent être identiques !"
 | 
				
			||||||
 | 
					                  : ""
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              label="Confirmation du nouveau mot de passe"
 | 
				
			||||||
 | 
					              value={confirmNewPassword}
 | 
				
			||||||
 | 
					              type="password"
 | 
				
			||||||
 | 
					              onChange={(e) => setConfirmNewpassword(e.target.value)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          </CardContent>
 | 
				
			||||||
 | 
					          <CardActions>
 | 
				
			||||||
 | 
					            <Button
 | 
				
			||||||
 | 
					              disabled={!isValid && !loading}
 | 
				
			||||||
 | 
					              type="submit"
 | 
				
			||||||
 | 
					              style={{ marginLeft: "auto" }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              Enregistrer
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
					          </CardActions>{" "}
 | 
				
			||||||
 | 
					        </Box>
 | 
				
			||||||
 | 
					      </Card>
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,7 +80,7 @@ pub async fn replace_password(
 | 
				
			|||||||
        .password_len
 | 
					        .password_len
 | 
				
			||||||
        .validate(&q.new_password)
 | 
					        .validate(&q.new_password)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return Ok(HttpResponse::BadRequest().json("Nouveau mot de passe invalide!"));
 | 
					        return Ok(HttpResponse::BadRequest().json("Invalid new password!"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut user = users_service::get_by_id(token.user_id).await?;
 | 
					    let mut user = users_service::get_by_id(token.user_id).await?;
 | 
				
			||||||
@@ -90,7 +90,7 @@ pub async fn replace_password(
 | 
				
			|||||||
            RatedAction::RequestReplacePasswordSignedIn,
 | 
					            RatedAction::RequestReplacePasswordSignedIn,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
        return Ok(HttpResponse::BadRequest().json("Ancien mot de passe invalide !"));
 | 
					        return Ok(HttpResponse::Unauthorized().json("Invalid old password!"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    users_service::change_password(&mut user, &q.new_password).await?;
 | 
					    users_service::change_password(&mut user, &q.new_password).await?;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user