Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bbbeasy-backend/app/config/access.ini
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@ allow GET @get_reset_token = *
allow GET @roles_permissions_collect = *

; settings routes
allow POST @settings_save_logo = *
allow POST @settings_save_logo = *

allow POST @reset_password_attempts = *
10 changes: 6 additions & 4 deletions bbbeasy-backend/app/config/routes.ini
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ GET @roles_collect : /api/roles/collect = Actions\Roles\Collect->ex
GET @roles_permissions_collect : /api/roles-permissions = Actions\RolesPermissions\Collect->execute

; users routes
GET @users_index : /api/users = Actions\Users\Index->show
POST @users_add : /api/users = Actions\Users\Add->save
PUT @users_edit : /api/users/@id = Actions\Users\Edit->save
DELETE @user_delete : /api/users/@id = Actions\Users\Delete->execute
GET @users_index : /api/users = Actions\Users\Index->show
POST @users_add : /api/users = Actions\Users\Add->save
PUT @users_edit : /api/users/@id = Actions\Users\Edit->save
DELETE @user_delete : /api/users/@id = Actions\Users\Delete->execute
POST @reset_password_attempts : /api/users/reset-attempts/@id = Actions\Users\ResetPasswordAttempts->save


; presets routes
GET @presets_index : /api/presets/@user_id = Actions\Presets\Index->show
Expand Down
66 changes: 66 additions & 0 deletions bbbeasy-backend/app/src/Actions/Users/ResetPasswordAttempts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

/*
* BBBEasy open source platform - https://riadvice.tn/
*
* Copyright (c) 2022-2023 RIADVICE SUARL and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BBBEasy is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BBBEasy; if not, see <http://www.gnu.org/licenses/>.
*/


namespace Actions\Users;

use Actions\Base as BaseAction;
use Actions\RequirePrivilegeTrait;
use Models\User;
use Enum\ResponseCode;

/**
* Class ResetPasswordAttempts.
*/
class ResetPasswordAttempts extends BaseAction
{
use RequirePrivilegeTrait;

/**
* @param \Base $f3
* @param array $params
*/
public function save($f3, $params): void
{
$user = new User();
$userId = $params['id'];
$user->load(['id = ?', $userId]);
$errorMessage = 'Password attempts could not be reset';
if ($user->valid()) {

try {
$user->getPasswordAttemptsById($userId);
$this->logger->info('reset password attempts', ['user' => $userId]);

} catch (\Exception $e) {
$this->logger->error($errorMessage, ['user' => $userId, 'error' => $e->getMessage()]);
$this->renderJson(['errors' => $e->getMessage()], ResponseCode::HTTP_INTERNAL_SERVER_ERROR);

return;
}
$this->renderJson(['result' => 'success', 'message' => 'Password attempts have been reset']);
} else {
$this->logger->error($errorMessage);
$this->renderJson([], ResponseCode::HTTP_NOT_FOUND);
}
}
}
5 changes: 5 additions & 0 deletions bbbeasy-backend/app/src/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ public function countActiveUsers(array $ids = null): int
return (int) $result[0]['total'];
}

public function getPasswordAttemptsById($userId)
{
return $this->db->exec('UPDATE users SET password_attempts = 3 WHERE id = ?', $userId);
}

public function verifyPassword($password): bool
{
return password_verify(trim($password), $this->password);
Expand Down
31 changes: 29 additions & 2 deletions bbbeasy-frontend/src/components/Users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import EN_US from '../locale/en-US.json';
import { t } from 'i18next';

import { PageHeader } from '@ant-design/pro-layout';
import { Alert, Button, Form, Input, Modal, Popconfirm, Select, Space, Tag, Typography } from 'antd';
import { DeleteOutlined, EditOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Alert, Button, Form, Input, Modal, Popconfirm, Select, Space, Tag, Typography, Dropdown, Menu } from 'antd';
import { DeleteOutlined, EditOutlined, QuestionCircleOutlined, MoreOutlined } from '@ant-design/icons';

import { FormInstance } from 'antd/lib/form';
import { CompareRecords } from '../functions/compare.function';
Expand All @@ -36,6 +36,7 @@ import EditableTableColumnSearch from './EditableTableColumnSearch';
import AuthService from '../services/auth.service';
import UsersService from '../services/users.service';
import RolesService from '../services/roles.service';
import LocaleService from "../services/locale.service";

import { TableColumnType } from '../types/TableColumnType';
import { UserType } from '../types/UserType';
Expand Down Expand Up @@ -305,6 +306,17 @@ const Users = () => {
}
};

// Reset password attempts
const handleResetPasswordAttemptsClick = (key: number) => {
UsersService.reset_password_attempts(key)
.then(() => {
Notifications.openNotificationWithIcon('success', t('password.resetAttempts'));
})
.catch((error) => {
console.log(error);
});
}

// delete
const handleDelete = (key: number) => {
UsersService.delete_user(key)
Expand Down Expand Up @@ -470,6 +482,21 @@ const Users = () => {
</Link>
</Popconfirm>
)}
<Dropdown
key="more"
overlay={
<Menu>
<Menu.Item key="1" onClick={() => handleResetPasswordAttemptsClick(record.key)}>
<Trans i18nKey={'reset_password_attempts'} />
</Menu.Item>
</Menu>
}
placement={LocaleService.direction == 'rtl' ? 'topRight' : 'topLeft'}
trigger={['click']}
arrow
>
<MoreOutlined />
</Dropdown>
</Space>
);
},
Expand Down
4 changes: 3 additions & 1 deletion bbbeasy-frontend/src/locale/ar-TN.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"label": "كلمة المرور",
"required": "كلمة المرور مطلوبة",
"size": "يجب أن تتكون كلمة المرور من 8 أحرف على الأقل",
"invalid": "كلمة المرور غير صحيحة"
"invalid": "كلمة المرور غير صحيحة",
"resetAttempts": "تمت إعادة تعيين محاولات كلمة المرور"
},
"join-us": "إنضم إلينا",
"register-now": "قم بالتسجيل الآن وانضم إلى مجتمعنا ",
Expand Down Expand Up @@ -185,6 +186,7 @@
"permissions": {
"label": "الصلاحيات"
},
"reset_password_attempts": "إعادة تعيين كلمة المرور",
"search": "البحث",
"reset": "إعادة التهيئة",
"filter": "التصفية",
Expand Down
4 changes: 3 additions & 1 deletion bbbeasy-frontend/src/locale/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"label": "Password",
"required": "Password is required",
"size": "Password must have at least 8 characters",
"invalid": "Invalid password"
"invalid": "Invalid password",
"resetAttempts": "Password attempts have been reset"
},
"join-us": "Join us",
"register-now": "Register now and join our community ",
Expand Down Expand Up @@ -186,6 +187,7 @@
"permissions": {
"label": "Permissions"
},
"reset_password_attempts": "Reset password attempts",
"search": "Search",
"reset": "Reset",
"filter": "Filter",
Expand Down
4 changes: 3 additions & 1 deletion bbbeasy-frontend/src/locale/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"label": "Mot de passe",
"required": "Le mot de passe est obligatoire",
"size": "Le mot de passe doit contenir au moins 8 caractères",
"invalid": "Mot de passe incorrect"
"invalid": "Mot de passe incorrect",
"resetAttempts": "Les tentatives de mot de passe ont été réinitialisées"
},
"join-us": "Rejoignez-nous",
"register-now": "Inscrivez-vous dès maintenant et rejoignez notre communauté ",
Expand Down Expand Up @@ -185,6 +186,7 @@
"permissions": {
"label": "Permissions"
},
"reset_password_attempts": "réinitialiser les tentatives de mot de passe",
"search": "Chercher",
"reset": "Réinitialiser",
"filter": "Filtrer",
Expand Down
1 change: 1 addition & 0 deletions bbbeasy-frontend/src/routing/backend-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const apiRoutes = {
ADD_USER_URL: API_URL + '/users',
EDIT_USER_URL: API_URL + '/users/',
DELETE_USER_URL: API_URL + '/users/',
RESET_PASSWORD_ATTEMPTS_URL: API_URL + '/users/reset-attempts/',

LIST_LABEL_URL: API_URL + '/labels',
ADD_LABEL_URL: API_URL + '/labels',
Expand Down
4 changes: 4 additions & 0 deletions bbbeasy-frontend/src/services/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class UsersService {
});
}

reset_password_attempts(id: number) {
return axiosInstance.post(apiRoutes.RESET_PASSWORD_ATTEMPTS_URL + id);
}

edit_user(data: object, id: number) {
return axiosInstance.put(apiRoutes.EDIT_USER_URL + id, {
data,
Expand Down