added chaging of password
This commit is contained in:
@@ -24,11 +24,6 @@ func hashPassword(password string) ([]byte, error) {
|
|||||||
return bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
return bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validates a password against the password-rules
|
|
||||||
func ValidatePassword(password string) bool {
|
|
||||||
return len(password) >= 12 && len(password) <= 64
|
|
||||||
}
|
|
||||||
|
|
||||||
func Get() (map[string]User, error) {
|
func Get() (map[string]User, error) {
|
||||||
if users, hit := c.Get("users"); !hit {
|
if users, hit := c.Get("users"); !hit {
|
||||||
refresh()
|
refresh()
|
||||||
@@ -41,7 +36,7 @@ func Get() (map[string]User, error) {
|
|||||||
|
|
||||||
type UserAdd struct {
|
type UserAdd struct {
|
||||||
UserName string `json:"userName" validate:"required" db:"userName"`
|
UserName string `json:"userName" validate:"required" db:"userName"`
|
||||||
Password string `json:"password" validate:"required,min=8"`
|
Password string `json:"password" validate:"required,min=12"`
|
||||||
Admin bool `json:"admin" db:"admin"`
|
Admin bool `json:"admin" db:"admin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +65,36 @@ func Add(user UserAdd) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserChangePassword struct {
|
||||||
|
UserName string `json:"userName" validate:"required" db:"userName"`
|
||||||
|
Password string `json:"password" validate:"required,min=12"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangePassword(user UserChangePassword) error {
|
||||||
|
// try to hash teh password
|
||||||
|
if hash, err := hashPassword(user.Password); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
execStruct := struct {
|
||||||
|
UserName string `db:"userName"`
|
||||||
|
Password []byte `db:"password"`
|
||||||
|
TokenID string `db:"tokenID"`
|
||||||
|
}{
|
||||||
|
UserName: user.UserName,
|
||||||
|
Password: hash,
|
||||||
|
TokenID: uuid.NewString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := db.DB.NamedExec("UPDATE USERS SET tokenID = :tokenID, password = :password WHERE name = :userName", execStruct); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
refresh()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func refresh() {
|
func refresh() {
|
||||||
// get the usersRaw from the database
|
// get the usersRaw from the database
|
||||||
var usersRaw []User
|
var usersRaw []User
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ func init() {
|
|||||||
"events": postEvent,
|
"events": postEvent,
|
||||||
"users": postUser,
|
"users": postUser,
|
||||||
},
|
},
|
||||||
"PATCH": {},
|
"PATCH": {
|
||||||
|
"users/password": patchPassword,
|
||||||
|
},
|
||||||
"DELETE": {
|
"DELETE": {
|
||||||
"event": deleteEvent,
|
"event": deleteEvent,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,3 +34,29 @@ func postUser(args HandlerArgs) responseMessage {
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func patchPassword(args HandlerArgs) responseMessage {
|
||||||
|
response := responseMessage{}
|
||||||
|
// parse the body
|
||||||
|
var body users.UserChangePassword
|
||||||
|
|
||||||
|
if err := args.C.BodyParser(&body); err != nil {
|
||||||
|
response.Status = fiber.StatusBadRequest
|
||||||
|
|
||||||
|
logger.Log().Msgf("can't parse body: %v", err)
|
||||||
|
} else {
|
||||||
|
body.UserName = args.User.UserName
|
||||||
|
|
||||||
|
if err := validate.Struct(body); err != nil {
|
||||||
|
response.Status = fiber.StatusBadRequest
|
||||||
|
|
||||||
|
logger.Info().Msgf("invalid body: %v", err)
|
||||||
|
} else if err := users.ChangePassword(body); err != nil {
|
||||||
|
response.Status = fiber.StatusInternalServerError
|
||||||
|
|
||||||
|
logger.Error().Msgf("can't update password: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|||||||
77
client/src/app/account/page.tsx
Normal file
77
client/src/app/account/page.tsx
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { apiCall, vaidatePassword as validatePassword } from "@/lib";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CardBody,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
} from "@nextui-org/react";
|
||||||
|
import { FormEvent, useState } from "react";
|
||||||
|
|
||||||
|
export default function Account() {
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const errors = validatePassword(password);
|
||||||
|
|
||||||
|
async function changePassword(e: FormEvent<HTMLFormElement>) {
|
||||||
|
const data = Object.fromEntries(new FormData(e.currentTarget));
|
||||||
|
|
||||||
|
const result = await apiCall("PATCH", "users/password", undefined, data);
|
||||||
|
|
||||||
|
if (result.ok) {
|
||||||
|
setPassword("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2 className="text-center text-4xl">Account</h2>
|
||||||
|
<div>
|
||||||
|
<Card className="max-w-md">
|
||||||
|
<CardHeader>
|
||||||
|
<h3 className="text-2xl">Change Password</h3>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<Form
|
||||||
|
validationBehavior="native"
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
changePassword(e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardBody>
|
||||||
|
<Input
|
||||||
|
isRequired
|
||||||
|
label="Password"
|
||||||
|
name="password"
|
||||||
|
variant="bordered"
|
||||||
|
value={password}
|
||||||
|
onValueChange={setPassword}
|
||||||
|
isInvalid={password.length > 0 && errors.length > 0}
|
||||||
|
errorMessage={
|
||||||
|
<ul>
|
||||||
|
{errors.map((e, ii) => (
|
||||||
|
<li key={ii}>{e}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</CardBody>
|
||||||
|
<CardFooter>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
isDisabled={errors.length > 0}
|
||||||
|
>
|
||||||
|
Change password
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -80,3 +80,13 @@ export class DateFormatter {
|
|||||||
return this.formatter.format(dt);
|
return this.formatter.format(dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function vaidatePassword(password: string): string[] {
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
if (password.length < 1) {
|
||||||
|
errors.push("Password must be 16 characters or more");
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user