Skip to content

Commit d8013c8

Browse files
committed
Fix duplicate user
1 parent 278a97b commit d8013c8

File tree

7 files changed

+76
-66
lines changed

7 files changed

+76
-66
lines changed

api/database.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export async function getUserById(id) {
8585
if (err) {
8686
reject(err);
8787
} else {
88-
delete row.password;
88+
if (row) delete row.password;
8989
resolve(row);
9090
}
9191
});
@@ -98,7 +98,7 @@ export async function getUserByUsername(username, { keepPassword } = {}) {
9898
if (err) {
9999
reject(err);
100100
} else {
101-
if (!keepPassword) delete row.password;
101+
if (!keepPassword && row) delete row.password;
102102
resolve(row);
103103
}
104104
});

api/index.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
getTranscriptionById,
1818
getTranscriptions,
1919
getUserById,
20+
getUserByUsername,
2021
getUsers,
2122
updateUser,
2223
} from './database.js';
@@ -107,6 +108,10 @@ app.post('/api/users', jwtMiddleware, async (req, res) => {
107108
}
108109
const { username, password, email } = req.body;
109110
try {
111+
if (await getUserByUsername(username)) {
112+
res.status(400).send('Username is already used');
113+
return;
114+
}
110115
const user = await createUser({ username, password, email, role: 'user' });
111116
res.json(user);
112117
}
@@ -122,14 +127,14 @@ app.put('/api/users/:id', jwtMiddleware, async (req, res) => {
122127
const { username, password, email, role } = req.body;
123128
try {
124129
const user = await getUserById(req.params.id);
125-
if (user.id === 1 && req.user.id !== 1) {
126-
res.status(403).send('Forbidden');
127-
return;
128-
}
129130
if (!user) {
130131
res.status(404).send('User not found');
131132
return;
132133
}
134+
if (user.id === 1 && req.user.id !== 1) {
135+
res.status(403).send('Forbidden');
136+
return;
137+
}
133138
await updateUser({ id: user.id, username, password, email, role });
134139
res.status(204).send('User updated');
135140
}

api/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "whisper-dashboard-api",
3-
"version": "1.0.1",
3+
"version": "1.1.2",
44
"description": "",
55
"main": "index.js",
66
"type": "module",
@@ -11,7 +11,7 @@
1111
},
1212
"keywords": [],
1313
"author": "",
14-
"license": "ISC",
14+
"license": "MIT",
1515
"dependencies": {
1616
"bcrypt": "^5.1.1",
1717
"cors": "^2.8.5",

app/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "whisper-dashboard-app",
33
"private": true,
4-
"version": "1.0.1",
4+
"version": "1.1.2",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

app/src/routes/admin.jsx

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { RiLoader4Fill } from "react-icons/ri"
55
import Modal from "../components/modal"
66
import Select from "../components/select"
77

8-
function Logout() {
8+
function Admin() {
99
const accessToken = useSelector((state) => state.accessToken)
1010
const loggedUser = useSelector((state) => state.user);
1111
const [users, setUsers] = useState(null)
@@ -37,7 +37,12 @@ function Logout() {
3737

3838
async function createUser() {
3939
try {
40+
if (!users) return
4041
if (!username || !email || !password) return
42+
if (users.find((user) => user.username === username)) {
43+
toast.error('An user with the same username already exists!')
44+
return
45+
}
4146
const response = await fetch(`${import.meta.env.VITE_API_URL || "/api"}/users`, {
4247
method: 'POST',
4348
headers: {
@@ -66,61 +71,61 @@ function Logout() {
6671
return (
6772
<div className="flex flex-col justify-center items-center gap-3">
6873
<h1 className="text-3xl">Admin panel</h1>
69-
<h2 className="text-xl mt-4">Create an user</h2>
70-
<div className="w-96 max-w-full">
71-
<label className="input-label" htmlFor="username">
72-
Username
73-
</label>
74-
<input
75-
className="input-field"
76-
id="username"
77-
type="username"
78-
placeholder="Username"
79-
value={username}
80-
onChange={(e) => setUsername(e.target.value)}
81-
onKeyDown={(e) => e.key === 'Enter' && emailInput.current.focus()}
82-
/>
83-
</div>
84-
<div className="w-96 max-w-full">
85-
<label className="input-label" htmlFor="email">
86-
Email
87-
</label>
88-
<input
89-
ref={emailInput}
90-
className="input-field"
91-
id="email"
92-
type="email"
93-
placeholder="Email"
94-
value={email}
95-
onChange={(e) => setEmail(e.target.value)}
96-
onKeyDown={(e) => e.key === 'Enter' && passwordInput.current.focus()}
97-
/>
98-
</div>
99-
<div className="w-96 max-w-full">
100-
<label className="input-label" htmlFor="password">
101-
Password
102-
</label>
103-
<input
104-
ref={passwordInput}
105-
className="input-field"
106-
id="password"
107-
type="password"
108-
placeholder="Password"
109-
value={password}
110-
onChange={(e) => setPassword(e.target.value)}
111-
onKeyDown={(e) => e.key === 'Enter' && createUser()}
112-
/>
113-
</div>
114-
<button className="button max-w-full" onClick={() => createUser()}>
115-
Create user
116-
</button>
11774
<h2 className="text-xl mt-6">Users list</h2>
11875
{!users && (
11976
<div className="flex justify-center items-center">
12077
<RiLoader4Fill className="text-3xl animate-spin" />
12178
</div>
12279
)}
123-
{users && (
80+
{users && <>
81+
<h2 className="text-xl mt-4">Create an user</h2>
82+
<div className="w-96 max-w-full">
83+
<label className="input-label" htmlFor="username">
84+
Username
85+
</label>
86+
<input
87+
className="input-field"
88+
id="username"
89+
type="username"
90+
placeholder="Username"
91+
value={username}
92+
onChange={(e) => setUsername(e.target.value)}
93+
onKeyDown={(e) => e.key === 'Enter' && emailInput.current.focus()}
94+
/>
95+
</div>
96+
<div className="w-96 max-w-full">
97+
<label className="input-label" htmlFor="email">
98+
Email
99+
</label>
100+
<input
101+
ref={emailInput}
102+
className="input-field"
103+
id="email"
104+
type="email"
105+
placeholder="Email"
106+
value={email}
107+
onChange={(e) => setEmail(e.target.value)}
108+
onKeyDown={(e) => e.key === 'Enter' && passwordInput.current.focus()}
109+
/>
110+
</div>
111+
<div className="w-96 max-w-full">
112+
<label className="input-label" htmlFor="password">
113+
Password
114+
</label>
115+
<input
116+
ref={passwordInput}
117+
className="input-field"
118+
id="password"
119+
type="password"
120+
placeholder="Password"
121+
value={password}
122+
onChange={(e) => setPassword(e.target.value)}
123+
onKeyDown={(e) => e.key === 'Enter' && createUser()}
124+
/>
125+
</div>
126+
<button className="button max-w-full" onClick={() => createUser()}>
127+
Create user
128+
</button>
124129
<div className="mt-2 rounded-lg border border-gray-600 p-4">
125130
<div className="flex flex-col gap-1">
126131
<div className="grid grid-cols-5 gap-4 mb-2 font-bold">
@@ -148,7 +153,7 @@ function Logout() {
148153
))}
149154
</div>
150155
</div>
151-
)}
156+
</>}
152157
</div>
153158
)
154159
}
@@ -308,4 +313,4 @@ function DeleteUserModal({ user, getUsers }) {
308313
</>
309314
}
310315

311-
export default Logout
316+
export default Admin

0 commit comments

Comments
 (0)