assign trainers to user; add email to jwt token

This commit is contained in:
Roland Schneider 2021-10-04 18:13:32 +02:00
parent 439fb12b6e
commit 7a55ca9ff3
21 changed files with 671 additions and 350 deletions

View File

@ -172,19 +172,68 @@ class AdminMenuStructure
///////////////////////////// /////////////////////////////
// Group Training // Group Training
///////////////////////////// /////////////////////////////
if (RoleDefinition::isLoggedUser()) { $items = [];
$items = []; // $items[] = ['label' => 'Felszerelés', 'url' => ['/event-equipment-type'], 'role' => [RoleDefinition::$ROLE_ADMIN]];
$items[] = ['label' => 'Felszerelés', 'url' => ['/event-equipment-type']]; $items[] = [
$items[] = ['label' => 'Edzők', 'url' => ['/trainer']]; 'label' => 'Edzők',
$items[] = ['label' => 'Termek', 'url' => ['/room']]; 'url' => ['/trainer'],
$items[] = ['label' => 'Esemény típusok', 'url' => ['/event-type']]; 'role' => [
$items[] = ['label' => 'Események', 'url' => ['/event/event/index']]; RoleDefinition::$ROLE_ADMIN,
$items[] = ['label' => 'Órarend', 'url' => ['/event/event/timetable']]; RoleDefinition::$ROLE_EMPLOYEE,
$items[] = ['label' => 'Hét másolása', 'url' => ['/event/event/copy-week']]; ]
$this->menuItems[] = ['label' => 'Csoportos edzés', 'url' => $this->emptyUrl, ];
'items' => $items $items[] = ['label' => 'Termek',
]; 'url' => ['/room'],
} 'role' => [
RoleDefinition::$ROLE_ADMIN,
RoleDefinition::$ROLE_EMPLOYEE,
]
];
$items[] = ['label' => 'Esemény típusok',
'url' => ['/event-type'],
'role' => [
RoleDefinition::$ROLE_ADMIN,
RoleDefinition::$ROLE_EMPLOYEE,
]
];
$items[] = [
'label' => 'Események',
'url' => ['/event/event/index'],
'role' => [
RoleDefinition::$ROLE_ADMIN,
RoleDefinition::$ROLE_EMPLOYEE,
RoleDefinition::$ROLE_TRAINER
]
];
$items[] = [
'label' => 'Órarend',
'url' => ['/event/event/timetable'],
'role' => [
RoleDefinition::$ROLE_ADMIN,
RoleDefinition::$ROLE_EMPLOYEE,
RoleDefinition::$ROLE_TRAINER
]
];
$items[] = [
'label' => 'Hét másolása',
'url' => ['/event/event/copy-week'],
'role' => [
RoleDefinition::$ROLE_ADMIN,
RoleDefinition::$ROLE_EMPLOYEE,
RoleDefinition::$ROLE_TRAINER
]
];
$this->menuItems[] = [
'label' => 'Csoportos edzés',
'url' => $this->emptyUrl,
'items' => $items,
'role' => [
RoleDefinition::$ROLE_ADMIN,
RoleDefinition::$ROLE_EMPLOYEE,
RoleDefinition::$ROLE_TRAINER
]
];
///////////////////////////// /////////////////////////////
// Development // Development
@ -198,10 +247,50 @@ class AdminMenuStructure
]; ];
} }
$this->menuItems = $this->filterMenu($this->menuItems);
} }
} }
protected function filterMenu($menuItems)
{
$result = [];
foreach ($menuItems as $item) {
$filteredItem = $this->filterMenuItem($item);
if (isset($filteredItem)) {
$result[] = $filteredItem;
}
}
return $result;
}
protected function filterMenuItem($menuItem)
{
$result = $menuItem;
if (isset($menuItem)) {
if (isset($menuItem['role'])) {
$roles = $menuItem['role'];
$canAny = RoleDefinition::canAny($roles);
if ($canAny === false) {
$result = null;
} else {
if (isset($menuItem['items'])) {
$result['items'] = [];
$items = $menuItem['items'];
foreach ($items as $subItem) {
$filteredItem = $this->filterMenuItem($subItem);
if (isset($filteredItem)) {
$result['items'][] = $filteredItem;
}
}
}
}
}
}
return $result;
}
protected function addLoginMainMenu() protected function addLoginMainMenu()
{ {
if (Yii::$app->user->isGuest) { if (Yii::$app->user->isGuest) {

View File

@ -2,10 +2,13 @@
namespace backend\controllers; namespace backend\controllers;
use common\models\Trainer;
use common\models\UserTrainerAssignment;
use Yii; use Yii;
use common\models\User; use common\models\User;
use backend\models\UserSearch; use backend\models\UserSearch;
use backend\models\UserCreate; use backend\models\UserCreate;
use yii\web\BadRequestHttpException;
use yii\web\Controller; use yii\web\Controller;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter; use yii\filters\VerbFilter;
@ -20,7 +23,7 @@ use common\components\RoleDefinition;
*/ */
class UserController extends \backend\controllers\BackendController class UserController extends \backend\controllers\BackendController
{ {
public function behaviors() public function behaviors()
{ {
@ -45,8 +48,8 @@ class UserController extends \backend\controllers\BackendController
], ],
]; ];
} }
/** /**
* Lists all User models. * Lists all User models.
* @return mixed * @return mixed
@ -55,8 +58,8 @@ class UserController extends \backend\controllers\BackendController
{ {
$searchModel = new UserSearch(); $searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams); $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [ return $this->render('index', [
'searchModel' => $searchModel, 'searchModel' => $searchModel,
@ -84,35 +87,48 @@ class UserController extends \backend\controllers\BackendController
public function actionCreate() public function actionCreate()
{ {
$model = new UserCreate(); $model = new UserCreate();
$accounts = Account::readAccounts(); $accounts = Account::readAccounts();
$trainers = Trainer::find()->all();
if ($model->load(Yii::$app->request->post()) && $model->save()) { if ($model->load(Yii::$app->request->post()) && $model->save()) {
$this->updateAccountAssignments($model); $this->updateAccountAssignments($model);
$this->updateTrainerAssignments($model);
return $this->redirect(['index' ]); return $this->redirect(['index' ]);
} }
return $this->render('create', [ return $this->render('create', [
'model' => $model, 'model' => $model,
'accounts' => $accounts, 'accounts' => $accounts,
'trainers' => $trainers,
]); ]);
} }
public function updateAccountAssignments($model){ public function updateAccountAssignments($model){
echo "saving accounts";
UserAccountAssignment::deleteAll(['id_user' => $model->id]); UserAccountAssignment::deleteAll(['id_user' => $model->id]);
foreach ( $model->selected_accounts as $id_account ){ foreach ( $model->selected_accounts as $id_account ){
echo "saving account";
$uaa = new UserAccountAssignment(); $uaa = new UserAccountAssignment();
$uaa->id_user = $model->id; $uaa->id_user = $model->id;
$uaa->id_account = $id_account; $uaa->id_account = $id_account;
$uaa->save(); $uaa->save();
} }
}
public function updateTrainerAssignments($model){
UserTrainerAssignment::deleteAll(['id_user' => $model->id]);
foreach ( $model->selected_trainers as $id_trainer ){
$uaa = new UserTrainerAssignment();
$uaa->id_user = $model->id;
$uaa->id_trainer = $id_trainer;
$uaa->save();
}
} }
/** /**
@ -124,7 +140,7 @@ class UserController extends \backend\controllers\BackendController
public function actionUpdate($id) public function actionUpdate($id)
{ {
$model = UserUpdate::findOne(['id' => $id]); $model = UserUpdate::findOne(['id' => $id]);
if ( Yii::$app->authManager->checkAccess($model->id, 'admin')){ if ( Yii::$app->authManager->checkAccess($model->id, 'admin')){
$model->role = 'admin'; $model->role = 'admin';
} else if ( Yii::$app->authManager->checkAccess($model->id, 'employee')){ } else if ( Yii::$app->authManager->checkAccess($model->id, 'employee')){
@ -132,28 +148,31 @@ class UserController extends \backend\controllers\BackendController
}else if ( Yii::$app->authManager->checkAccess($model->id, 'reception')){ }else if ( Yii::$app->authManager->checkAccess($model->id, 'reception')){
$model->role = 'reception'; $model->role = 'reception';
} }
if ( $model == null ){ if ( $model == null ){
throw new NotFoundHttpException('The requested page does not exist.'); throw new NotFoundHttpException('The requested page does not exist.');
} }
$accounts = Account::readAccounts(); $accounts = Account::readAccounts();
$this->applyAccounts($model); $this->applyAccounts($model);
$trainers = Trainer::find()->all();
$this->applyTrainers($model);
if ($model->load(Yii::$app->request->post()) && $model->save()) { if ($model->load(Yii::$app->request->post()) && $model->save()) {
$this->updateAccountAssignments($model); $this->updateAccountAssignments($model);
$this->updateTrainerAssignments($model);
return $this->redirect(['view', 'id' => $model->id]); return $this->redirect(['view', 'id' => $model->id]);
} else {
} }
return $this->render('update', [ return $this->render('update', [
'model' => $model, 'model' => $model,
'accounts' => $accounts, 'accounts' => $accounts,
'trainers' => $trainers,
]); ]);
} }
private function applyAccounts($model ){ private function applyAccounts($model ){
$assignedAccounts = $model->userAccountAssignments; $assignedAccounts = $model->userAccountAssignments;
foreach ($assignedAccounts as $acc ){ foreach ($assignedAccounts as $acc ){
@ -161,6 +180,13 @@ class UserController extends \backend\controllers\BackendController
} }
} }
private function applyTrainers($model ){
$assignedTrainers = $model->userTrainerAssignments;
foreach ($assignedTrainers as $acc ){
$model->selected_trainers[] = $acc->id_trainer;
}
}
/** /**
* Deletes an existing User model. * Deletes an existing User model.
* If deletion is successful, the browser will be redirected to the 'index' page. * If deletion is successful, the browser will be redirected to the 'index' page.
@ -171,12 +197,12 @@ class UserController extends \backend\controllers\BackendController
{ {
$user = $this->findModel($id); $user = $this->findModel($id);
$user->updateAttributes(['status' => User::STATUS_DELETED]); $user->updateAttributes(['status' => User::STATUS_DELETED]);
return $this->redirect(['index']); return $this->redirect(['index']);
} }
/** /**
* Creates a new User model. * Creates a new User model.
* If creation is successful, the browser will be redirected to the 'view' page. * If creation is successful, the browser will be redirected to the 'view' page.
@ -185,17 +211,17 @@ class UserController extends \backend\controllers\BackendController
public function actionRole() public function actionRole()
{ {
$model = new \backend\models\RoleForm(); $model = new \backend\models\RoleForm();
$model->availablePermissions = [ $model->availablePermissions = [
[ [
'name' => "reception.transfers", 'name' => "reception.transfers",
'description' => 'Tranzakciók' 'description' => 'Tranzakciók'
] ]
]; ];
if ($model->load(Yii::$app->request->post()) ) { if ($model->load(Yii::$app->request->post()) ) {
if ( $model->validate() && $model->save()){ if ( $model->validate() && $model->save()){
Yii::$app->session->setFlash('success', 'Jogosultságok elmentve'); Yii::$app->session->setFlash('success', 'Jogosultságok elmentve');
@ -209,7 +235,7 @@ class UserController extends \backend\controllers\BackendController
$model->permissions[] = $child->name; $model->permissions[] = $child->name;
} }
} }
return $this->render('role', [ return $this->render('role', [
'model' => $model, 'model' => $model,
]); ]);

View File

@ -9,9 +9,10 @@ class UserCreate extends User{
public $password_plain; public $password_plain;
public $password_repeat; public $password_repeat;
public $selected_accounts = []; public $selected_accounts = [];
public $selected_trainers = [];
public $role; public $role;
/** /**
* @inheritdoc * @inheritdoc
*/ */
@ -25,28 +26,34 @@ class UserCreate extends User{
} }
} }
], ],
['selected_trainers',function ($attribute, $params) {
if (!is_array($this->$attribute)) {
$this->addError($attribute, 'Invalid array');
}
}
],
['email' ,'email' ], ['email' ,'email' ],
['email' ,'unique' ], ['email' ,'unique' ],
['username' ,'unique' ], ['username' ,'unique' ],
[['password_plain' ,'password_repeat'] ,'string','min' =>6 ], [['password_plain' ,'password_repeat'] ,'string','min' =>6 ],
[['password_repeat'] ,'validatePasswordRepeat' ], [['password_repeat'] ,'validatePasswordRepeat' ],
[['role'], 'required'], [['role'], 'required'],
[['role'], 'string', 'max' => 20], [['role'], 'string', 'max' => 20],
['status', 'default', 'value' => self::STATUS_ACTIVE], ['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
]; ];
} }
public function validatePasswordRepeat($attribute,$params){ public function validatePasswordRepeat($attribute,$params){
if ( !$this->hasErrors()){ if ( !$this->hasErrors()){
if ( $this->password_plain != $this->password_repeat ){ if ( $this->password_plain != $this->password_repeat ){
$this->addError($attribute, Yii::t('app', 'Jelszó és jelszó újra nem egyezik!') ); $this->addError($attribute, Yii::t('app', 'Jelszó és jelszó újra nem egyezik!') );
} }
} }
} }
public function attributeLabels(){ public function attributeLabels(){
return [ return [
'status' => 'Státusz', 'status' => 'Státusz',
@ -55,10 +62,10 @@ class UserCreate extends User{
'created_at' =>'Létrehozás dátuma', 'created_at' =>'Létrehozás dátuma',
'password_plain' => Yii::t('app','Jelszó'), 'password_plain' => Yii::t('app','Jelszó'),
'password_repeat' => Yii::t('app','Jelszó újra'), 'password_repeat' => Yii::t('app','Jelszó újra'),
]; ];
} }
public function beforeSave($insert){ public function beforeSave($insert){
if ( parent::beforeSave($insert)){ if ( parent::beforeSave($insert)){
if ( $insert ){ if ( $insert ){
@ -70,12 +77,12 @@ class UserCreate extends User{
return false; return false;
} }
} }
public function afterSave($insert, $changedAttributes){ public function afterSave($insert, $changedAttributes){
parent::afterSave($insert, $changedAttributes); parent::afterSave($insert, $changedAttributes);
$am = Yii::$app->authManager; $am = Yii::$app->authManager;
$role = $am->getRole($this->role); $role = $am->getRole($this->role);
Yii::$app->authManager->assign($role, $this->id); Yii::$app->authManager->assign($role, $this->id);
} }
} }

View File

@ -9,9 +9,10 @@ class UserUpdate extends User {
public $password_plain; public $password_plain;
public $password_repeat; public $password_repeat;
public $selected_accounts = []; public $selected_accounts = [];
public $selected_trainers = [];
public $role; public $role;
/** /**
* @inheritdoc * @inheritdoc
* @formatter:off * @formatter:off
@ -21,25 +22,59 @@ class UserUpdate extends User {
return [ return [
[['username','email'], 'required' ], [['username','email'], 'required' ],
['email' ,'email' ], ['email' ,'email' ],
['email' ,'unique' , 'targetClass' => User::className(), 'targetAttribute' => 'email'], // ['email' ,'unique' , 'targetClass' => User::className(), 'targetAttribute' => 'email'],
['username' ,'unique', 'targetClass' => User::className(), 'targetAttribute' => 'username'], // ['username' ,'unique', 'targetClass' => User::className(), 'targetAttribute' => 'username'],
[['password_plain' ,'password_repeat'] ,'string','min' =>6 ], [['password_plain' ,'password_repeat'] ,'string','min' =>6 ],
[['password_repeat'] ,'validatePasswordRepeat' ], [['password_repeat'] ,'validatePasswordRepeat' ],
[['username'] ,'validateUsername' ],
[['email'] ,'validateEmail' ],
['selected_accounts',function ($attribute, $params) { ['selected_accounts',function ($attribute, $params) {
if (!is_array($this->$attribute)) { if (!is_array($this->$attribute)) {
$this->addError($attribute, 'Invalid array'); $this->addError($attribute, 'Invalid array');
} }
} }
], ],
['selected_trainers',function ($attribute, $params) {
if (!is_array($this->$attribute)) {
$this->addError($attribute, 'Invalid array');
}
}
],
[['role'], 'required'], [['role'], 'required'],
[['role'], 'string', 'max' => 20], [['role'], 'string', 'max' => 20],
['status', 'default', 'value' => self::STATUS_ACTIVE], ['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
]; ];
} }
public function validateEmail($attribute, $params){
/** @var User $user */
$user = User::find()
->andWhere(['email' => $this->email])->one();
if (isset($user)){
if ( $user->id != $this->id ){
$this->addError($attribute,'Az email cím már használatban van!');
}
}
}
public function validateUsername($attribute, $params){
/** @var User $user */
$user = User::find()
->andWhere(['username' => $this->username])->one();
if (isset($user)){
if ( $user->id != $this->id ){
$this->addError($attribute,'A felhasználónév már használatban van!');
}
}
}
/** /**
* @formatter:on * @formatter:on
*/ */
@ -53,14 +88,14 @@ class UserUpdate extends User {
} }
} }
public function attributeLabels() { public function attributeLabels() {
return [ return [
'status' => 'Státusz', 'status' => 'Státusz',
'email' => 'E-mail', 'email' => 'E-mail',
'username' => 'Felhasználónév', 'username' => 'Felhasználónév',
'created_at' => 'Létrehozás dátuma', 'created_at' => 'Létrehozás dátuma',
'password_plain' => Yii::t ( 'app', 'Jelszó' ), 'password_plain' => Yii::t ( 'app', 'Jelszó' ),
'password_repeat' => Yii::t ( 'app', 'Jelszó újra' ) 'password_repeat' => Yii::t ( 'app', 'Jelszó újra' )
] ]
; ;
} }
@ -78,7 +113,7 @@ class UserUpdate extends User {
} }
} }
public function afterSave($insert, $changedAttributes){ public function afterSave($insert, $changedAttributes){
parent::afterSave($insert, $changedAttributes); parent::afterSave($insert, $changedAttributes);
$am = Yii::$app->authManager; $am = Yii::$app->authManager;
$am->revokeAll($this->id); $am->revokeAll($this->id);
$role = $am->getRole($this->role); $role = $am->getRole($this->role);

View File

@ -1,5 +1,8 @@
<?php <?php
use backend\models\UserUpdate;
use common\models\Account;
use common\models\Trainer;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
use yii\grid\GridView; use yii\grid\GridView;
@ -8,11 +11,13 @@ use common\components\RoleDefinition;
use common\models\User; use common\models\User;
/* @var $this yii\web\View */ /* @var $this yii\web\View */
/* @var $model common\models\User */ /* @var $model UserUpdate */
/* @var $form yii\widgets\ActiveForm */ /* @var $form yii\widgets\ActiveForm */
/* @var $trainers Trainer[] */
/* @var $accounts Account[] */
?> ?>
<?php <?php
$roleOptions = RoleDefinition::roleLabels(); $roleOptions = RoleDefinition::roleLabels();
asort($roleOptions); asort($roleOptions);
@ -32,10 +37,11 @@ asort($roleOptions);
<?= $form->field($model, 'password_repeat')->passwordInput() ?> <?= $form->field($model, 'password_repeat')->passwordInput() ?>
<?= $form->field($model, 'role')->dropDownList($roleOptions) ?> <?= $form->field($model, 'role')->dropDownList($roleOptions) ?>
<?php <?php
$selectedAccounts = $model->selected_accounts; $selectedAccounts = $model->selected_accounts;
$selectedTrainers = $model->selected_trainers;
?> ?>
<h3>Engedélyezett kasszák</h3> <h3>Engedélyezett kasszák</h3>
@ -52,7 +58,7 @@ asort($roleOptions);
'checkboxOptions' => function ($model, $key, $index, $column) use ($selectedAccounts){ 'checkboxOptions' => function ($model, $key, $index, $column) use ($selectedAccounts){
$result = []; $result = [];
$result['value'] = $model->id_account ; $result['value'] = $model->id_account ;
if ( isset($selectedAccounts) ){ if ( isset($selectedAccounts) ){
if ( is_array($selectedAccounts) ){ if ( is_array($selectedAccounts) ){
if ( array_search($model->id_account , $selectedAccounts ) !== false){ if ( array_search($model->id_account , $selectedAccounts ) !== false){
@ -60,15 +66,47 @@ asort($roleOptions);
} }
} }
} }
return $result; return $result;
} }
], ],
[ 'attribute' => 'name' ], [ 'attribute' => 'name' ],
], ],
])?> ])?>
<h3>Engedélyezett edzők</h3>
<?php echo GridView::widget([
'dataProvider' => new ArrayDataProvider( [
'allModels' => $trainers,
'sort' => false,
'pagination' => false,
]),
'columns' => [
[
'class' => 'yii\grid\CheckboxColumn',
'name' => (new ReflectionClass( $model->classname() ))->getShortName() . '[selected_trainers]',
'checkboxOptions' => function ($model, $key, $index, $column) use ($selectedTrainers){
$result = [];
$result['value'] = $model->id ;
if ( isset($selectedTrainers) ){
if ( is_array($selectedTrainers) ){
if ( array_search($model->id , $selectedTrainers ) !== false){
$result['checked'] = 'checked' ;
}
}
}
return $result;
}
],
[ 'attribute' => 'name' ],
],
])?>
<div class="form-group"> <div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Mentés') : Yii::t('app', 'Mentés'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> <?= Html::submitButton( Yii::t('app', 'Mentés'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div> </div>
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>

View File

@ -17,6 +17,7 @@ $this->params['breadcrumbs'][] = $this->title;
<?= $this->render('_form', [ <?= $this->render('_form', [
'model' => $model, 'model' => $model,
'accounts' => $accounts, 'accounts' => $accounts,
'trainers' => $trainers,
]) ?> ]) ?>
</div> </div>

View File

@ -16,7 +16,8 @@ $this->params['breadcrumbs'][] = Yii::t('backend/user', 'Update');
<?= $this->render('_form', [ <?= $this->render('_form', [
'model' => $model, 'model' => $model,
'accounts' => $accounts 'accounts' => $accounts,
'trainers' => $trainers,
]) ?> ]) ?>
</div> </div>

View File

@ -1,118 +1,147 @@
<?php <?php
namespace common\components; namespace common\components;
use \Yii; use \Yii;
class RoleDefinition{ class RoleDefinition
{
public static $ROLE_ADMIN = "admin";
public static $ROLE_RECEPTION = "reception";
public static $ROLE_EMPLOYEE = "employee";
public static $ROLE_TRAINER = "trainer";
public static function roleLabels()
{
return [
'reception' => Yii::t('common/role', 'Reception'),
'admin' => Yii::t('common/role', 'Administrator'),
'employee' => Yii::t('common/role', 'Employee'),
'Trainer' => Yii::t('common/role', 'Edző'),
];
}
public static function roleLabels(){ public static function getRoleLabel($role)
return [ {
'reception' => Yii::t('common/role' ,'Reception'), $result = null;
'admin' => Yii::t('common/role' ,'Administrator'), $roleLabels = self::roleLabels();
'employee' => Yii::t('common/role' ,'Employee'), if (array_key_exists($role, $roleLabels)) {
'Trainer' => Yii::t('common/role' ,'Edző'), $result = $roleLabels[$role];
]; }
} return $result;
}
public static function getRoleLabel($role){
$result = null;
$roleLabels = self::roleLabels();
if ( array_key_exists($role, $roleLabels)){
$result = $roleLabels[$role];
}
return $result;
}
public static function roleDefinitions(){ public static function roleDefinitions()
return [ {
'employee' => [ return [
'canAllow' => [ 'employee'], 'employee' => [
], 'canAllow' => ['employee'],
'admin' => [ ],
'canAllow' => ['admin','reception','employee'], 'admin' => [
], 'canAllow' => ['admin', 'reception', 'employee'],
'reception' => [ ],
'canAllow' => [ ], 'reception' => [
], 'canAllow' => [],
]; ],
} ];
}
public static function getRoleDefinition($role){ public static function getRoleDefinition($role)
$defs = self::roleDefinitions(); {
$result = null; $defs = self::roleDefinitions();
if ( array_key_exists($role, $defs)){ $result = null;
$result = $defs[$role]; if (array_key_exists($role, $defs)) {
} $result = $defs[$role];
$result = $defs[$role]; }
return $result; $result = $defs[$role];
} return $result;
}
public static function getRolesCanAllow($role){ public static function getRolesCanAllow($role)
$result = []; {
$def = self::getRoleDefinition($role); $result = [];
if ( isset($def)){ $def = self::getRoleDefinition($role);
$result = $def['canAllow']; if (isset($def)) {
} $result = $def['canAllow'];
}
return $result; return $result;
} }
public static function can($role){ public static function can($role)
$result = false; {
if ( !Yii::$app->user->isGuest ){ $result = false;
if ( isset( $role)){ if (!Yii::$app->user->isGuest) {
if ( is_array($role)){ if (isset($role)) {
foreach ($role as $r){ if (is_array($role)) {
$result |= Yii::$app->user->can($r); foreach ($role as $r) {
} $result |= Yii::$app->user->can($r);
}else if ( is_string($role)){ }
$result = Yii::$app->user->can($role); } else if (is_string($role)) {
} $result = Yii::$app->user->can($role);
} }
} }
return $result; }
} return $result;
}
public static function isAdmin(){ public static function canAny($roles)
return self::can('admin'); {
} foreach ($roles as $role) {
if (self::can($role)) {
return true;
}
}
return false;
}
public static function isReception(){ public static function isAdmin()
return self::can('reception'); {
} return self::can('admin');
}
public static function isEmployee(){ public static function isReception()
return self::can('employee'); {
} return self::can('reception');
}
public static function isTrainer(){ public static function isEmployee()
return self::can('trainer'); {
} return self::can('employee');
}
public static function isTrainer()
{
return self::can('trainer');
}
public static function isLoggedUser(){ public static function isLoggedUser()
{
return self::isTrainer() || self::isAdmin() || self::isEmployee() return self::isTrainer() || self::isAdmin() || self::isEmployee()
|| self::isReception(); || self::isReception();
} }
/*
* [ /*
* 'role1' => 'template1', * [
* 'role2' => 'template2, * 'role1' => 'template1',
* ] * 'role2' => 'template2,
* */ * ]
public static function getRoleTemplate($templates){ * */
$result = ""; public static function getRoleTemplate($templates)
foreach ($templates as $role => $template ){ {
if ( Yii::$app->user->can($role)){ $result = "";
$result = $template; foreach ($templates as $role => $template) {
break; if (Yii::$app->user->can($role)) {
} $result = $template;
} break;
return $result; }
} }
return $result;
}
} }

View File

@ -12,22 +12,22 @@ use yii\helpers\ArrayHelper;
* This is the model class for table "account". * This is the model class for table "account".
* *
* @property integer $id_account * @property integer $id_account
* @property string $name * @property string $name
* @property integer $status * @property integer $status
* @property integer $type * @property integer $type
* @property string $created_at * @property string $created_at
* @property string $updated_at * @property string $updated_at
* @property integer $log_card_read_in_reception * @property integer $log_card_read_in_reception
*/ */
class Account extends \yii\db\ActiveRecord class Account extends \yii\db\ActiveRecord
{ {
const STATUS_DELETED = 0; const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10; const STATUS_ACTIVE = 10;
const TYPE_ALL = 0; const TYPE_ALL = 0;
const TYPE_VALUE_HIDDEN = 10; const TYPE_VALUE_HIDDEN = 10;
/** /**
* @inheritdoc * @inheritdoc
*/ */
@ -41,13 +41,15 @@ class Account extends \yii\db\ActiveRecord
*/ */
public function behaviors() public function behaviors()
{ {
return [ return [
[ 'class' => TimestampBehavior::className(), ['class' => TimestampBehavior::className(),
'value' => function(){ return date('Y-m-d H:i:s' ); } 'value' => function () {
] return date('Y-m-d H:i:s');
]; }
]
];
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
@ -55,8 +57,8 @@ class Account extends \yii\db\ActiveRecord
{ {
return [ return [
[['name', 'type'], 'required'], [['name', 'type'], 'required'],
[['name', ], 'unique'], [['name',], 'unique'],
[['status', 'type','log_card_read_in_reception'], 'integer'], [['status', 'type', 'log_card_read_in_reception'], 'integer'],
[['name'], 'string', 'max' => 64] [['name'], 'string', 'max' => 64]
]; ];
} }
@ -76,45 +78,51 @@ class Account extends \yii\db\ActiveRecord
'log_card_read_in_reception' => Yii::t('common/account', 'Log Card Read in Reception'), 'log_card_read_in_reception' => Yii::t('common/account', 'Log Card Read in Reception'),
]; ];
} }
public function getUserAccountAssignments(){ public function getUserAccountAssignments()
return $this->hasMany(UserAccountAssignment::className(), ['id_account' => 'id_account']); {
return $this->hasMany(UserAccountAssignment::className(), ['id_account' => 'id_account']);
} }
static function statuses() { static function statuses()
return [ {
self::STATUS_ACTIVE => Yii::t('common/account', 'Active'), return [
self::STATUS_DELETED => Yii::t('common/account', 'Inactive'), self::STATUS_ACTIVE => Yii::t('common/account', 'Active'),
]; self::STATUS_DELETED => Yii::t('common/account', 'Inactive'),
];
} }
public function getStatusHuman(){ public function getStatusHuman()
$result = null; {
$s = self::statuses(); $result = null;
if ( array_key_exists($this->status, $s)){ $s = self::statuses();
$result = $s[$this->status]; if (array_key_exists($this->status, $s)) {
} $result = $s[$this->status];
return $result; }
return $result;
} }
static function types() { static function types()
return [ {
self::TYPE_ALL => Yii::t('common/account', 'Account'), return [
self::TYPE_VALUE_HIDDEN => Yii::t('common/account', 'Only the name is visible'), self::TYPE_ALL => Yii::t('common/account', 'Account'),
]; self::TYPE_VALUE_HIDDEN => Yii::t('common/account', 'Only the name is visible'),
];
} }
public function getTypeHuman(){ public function getTypeHuman()
$result = null; {
$s = self::types(); $result = null;
if ( array_key_exists($this->type, $s)){ $s = self::types();
$result = $s[$this->type]; if (array_key_exists($this->type, $s)) {
} $result = $s[$this->type];
return $result; }
return $result;
} }
public function isInactive(){ public function isInactive()
return $this->status == self::STATUS_DELETED; {
return $this->status == self::STATUS_DELETED;
} }
/** /**
@ -126,76 +134,82 @@ class Account extends \yii\db\ActiveRecord
* three arm gate, but we want to track the customers. * three arm gate, but we want to track the customers.
* @return bool * @return bool
*/ */
public function isLogCardReadInReceptionOn(){ public function isLogCardReadInReceptionOn()
{
return $this->log_card_read_in_reception == 1; return $this->log_card_read_in_reception == 1;
} }
/** /**
* $param int $forceIncludeAccount id account, that should be included in list, even if it is inactive * $param int $forceIncludeAccount id account, that should be included in list, even if it is inactive
* @param null $forceIncludeAccount the next account should be included too, even if it is not * @param null $forceIncludeAccount the next account should be included too, even if it is not
* allowed for user * allowed for user
* @return array|null|\yii\db\ActiveRecord[] * @return array|null|\yii\db\ActiveRecord[]
*/ */
public static function readAccounts($forceIncludeAccount = null){ public static function readAccounts($forceIncludeAccount = null)
$accounts = null; {
$accounts = null;
if ( $forceIncludeAccount == null) {
$accounts = Account::find()->andWhere(['status' => Account::STATUS_ACTIVE])->all();
}else{
$accounts = Account::find()->andWhere( ['or', ['status' => Account::STATUS_ACTIVE], ['id_account' => $forceIncludeAccount ] ])->all();
}
return $accounts;
}
public static function read($forceIncludeAccount = null){
$accounts = null;
$query = Account::find();
$query->innerJoinWith('userAccountAssignments');
$query->andWhere(['user_account_assignment.id_user' => Yii::$app->user->id]);
if ( $forceIncludeAccount == null){ if ($forceIncludeAccount == null) {
$query->andWhere(['status' => Account::STATUS_ACTIVE])->all(); $accounts = Account::find()->andWhere(['status' => Account::STATUS_ACTIVE])->all();
}else{ } else {
$query->andWhere( ['or', ['status' => Account::STATUS_ACTIVE], ['id_account' => $forceIncludeAccount ] ])->all(); $accounts = Account::find()->andWhere(['or', ['status' => Account::STATUS_ACTIVE], ['id_account' => $forceIncludeAccount]])->all();
} }
$query->orderBy( ['name' => SORT_ASC]); return $accounts;
$accounts = $query->all();
return $accounts;
} }
public static function writeDefault($account){ public static function read($forceIncludeAccount = null)
$session = Yii::$app->session; {
$session->set('id_account', $account->id_account); $accounts = null;
$query = Account::find();
$query->innerJoinWith('userAccountAssignments');
$query->andWhere(['user_account_assignment.id_user' => Yii::$app->user->id]);
if ($forceIncludeAccount == null) {
$query->andWhere(['status' => Account::STATUS_ACTIVE])->all();
} else {
$query->andWhere(['or', ['status' => Account::STATUS_ACTIVE], ['id_account' => $forceIncludeAccount]])->all();
}
$query->orderBy(['name' => SORT_ASC]);
$accounts = $query->all();
return $accounts;
} }
public static function writeDefault($account)
{
$session = Yii::$app->session;
$session->set('id_account', $account->id_account);
}
/** read id_transfer from session (default account ) /** read id_transfer from session (default account )
* *
* @return int id_transfer * @return int id_transfer
* */ * */
public static function readDefault( ){ public static function readDefault()
$session = Yii::$app->session; {
$result = $session->get('id_account'); $session = Yii::$app->session;
return $result; $result = $session->get('id_account');
return $result;
} }
/** /**
* read default transfer object * read default transfer object
* return the default account or null, if not found * return the default account or null, if not found
* @return \common\models\Account * @return \common\models\Account
* */ * */
public static function readDefaultObject( ){ public static function readDefaultObject()
$account = null; {
$id_account = self::readDefault(); $account = null;
if ( isset($id_account)){ $id_account = self::readDefault();
$account = Account::findOne($id_account); if (isset($id_account)) {
} $account = Account::findOne($id_account);
return $account; }
return $account;
} }
@ -204,23 +218,24 @@ class Account extends \yii\db\ActiveRecord
* @param $idAccount integer The id of the account to read * @param $idAccount integer The id of the account to read
* @return array|null|\yii\db\ActiveRecord * @return array|null|\yii\db\ActiveRecord
*/ */
public static function readOne($idAccount){ public static function readOne($idAccount)
$accounts = null; {
$accounts = null;
$query = Account::find();
$query->innerJoinWith('userAccountAssignments'); $query = Account::find();
$query->andWhere(['user_account_assignment.id_user' => Yii::$app->user->id]); $query->innerJoinWith('userAccountAssignments');
$query->andWhere(['status' => Account::STATUS_ACTIVE]); $query->andWhere(['user_account_assignment.id_user' => Yii::$app->user->id]);
$query->andWhere(['account.id_account' => $idAccount]); $query->andWhere(['status' => Account::STATUS_ACTIVE]);
$accounts = $query->one(); $query->andWhere(['account.id_account' => $idAccount]);
$accounts = $query->one();
return $accounts;
} return $accounts;
public static function toAccaountMap($accounts){
return ArrayHelper::map( $accounts,'id_account','name' );
} }
public static function toAccaountMap($accounts)
{
return ArrayHelper::map($accounts, 'id_account', 'name');
}
} }

View File

@ -26,7 +26,7 @@ class User extends ActiveRecord implements IdentityInterface
{ {
const STATUS_DELETED = 0; const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10; const STATUS_ACTIVE = 10;
const ROLE_RECEPTION = 'receptionist'; const ROLE_RECEPTION = 'receptionist';
/** /**
@ -192,18 +192,22 @@ class User extends ActiveRecord implements IdentityInterface
{ {
$this->password_reset_token = null; $this->password_reset_token = null;
} }
public function getUserAccountAssignments(){ public function getUserAccountAssignments(){
return $this->hasMany(UserAccountAssignment::className(), ['id_user' =>'id']); return $this->hasMany(UserAccountAssignment::className(), ['id_user' =>'id']);
} }
public function getUserTrainerAssignments(){
return $this->hasMany(UserTrainerAssignment::className(), ['id_user' =>'id']);
}
static function statuses() { static function statuses() {
return [ return [
self::STATUS_ACTIVE => Yii::t('app', 'Aktív'), self::STATUS_ACTIVE => Yii::t('app', 'Aktív'),
self::STATUS_DELETED => Yii::t('app', 'Inaktív'), self::STATUS_DELETED => Yii::t('app', 'Inaktív'),
] ; ] ;
} }
public function getStatusHuman(){ public function getStatusHuman(){
$result = null; $result = null;
$s = self::statuses($this->status); $s = self::statuses($this->status);
@ -212,8 +216,8 @@ class User extends ActiveRecord implements IdentityInterface
} }
return $result; return $result;
} }
public function attributeLabels(){ public function attributeLabels(){
return [ return [
'status' => 'Státusz', 'status' => 'Státusz',
@ -224,14 +228,14 @@ class User extends ActiveRecord implements IdentityInterface
'statusHuman' => Yii::t('backend/user', 'Status'), 'statusHuman' => Yii::t('backend/user', 'Status'),
]; ];
} }
/** /**
* *
* *
* @return \yii\rbac\Role[]*/ * @return \yii\rbac\Role[]*/
public function getRoles(){ public function getRoles(){
$roles = \Yii::$app->authManager->getRolesByUser($this->id ); $roles = \Yii::$app->authManager->getRolesByUser($this->id );
return $roles; return $roles;
} }
/** /**
@ -239,28 +243,28 @@ class User extends ActiveRecord implements IdentityInterface
* */ * */
public function getRoleString(){ public function getRoleString(){
$roles = \Yii::$app->authManager->getRolesByUser($this->id ); $roles = \Yii::$app->authManager->getRolesByUser($this->id );
return implode(', ', array_map(function ($role) { return sprintf("%s", RoleDefinition::getRoleLabel($role->name)); }, $roles )); return implode(', ', array_map(function ($role) { return sprintf("%s", RoleDefinition::getRoleLabel($role->name)); }, $roles ));
} }
/** /**
* $param int $forceIncludeAccount id warehouse, that should be included in list, even if it is inactive * $param int $forceIncludeAccount id warehouse, that should be included in list, even if it is inactive
* */ * */
public static function read($forceIncludeObjectWithId = null){ public static function read($forceIncludeObjectWithId = null){
$users = null; $users = null;
$query = User::find(); $query = User::find();
if ( RoleDefinition::isReception()){ if ( RoleDefinition::isReception()){
$query->andWhere(['id' => Yii::$app->user->id ]); $query->andWhere(['id' => Yii::$app->user->id ]);
} }
if ( $forceIncludeObjectWithId == null){ if ( $forceIncludeObjectWithId == null){
$users = $query->andWhere(['status' => User::STATUS_ACTIVE])->all(); $users = $query->andWhere(['status' => User::STATUS_ACTIVE])->all();
}else{ }else{
$users = $query->andWhere( ['or', ['status' => User::STATUS_ACTIVE], ['id' => $forceIncludeObjectWithId ] ])->all(); $users = $query->andWhere( ['or', ['status' => User::STATUS_ACTIVE], ['id' => $forceIncludeObjectWithId ] ])->all();
} }
return $users; return $users;
} }
} }

View File

@ -3,6 +3,7 @@
namespace common\modules\event\models; namespace common\modules\event\models;
use common\components\Helper; use common\components\Helper;
use common\components\RoleDefinition;
use Yii; use Yii;
use yii\base\Model; use yii\base\Model;
use yii\data\ActiveDataProvider; use yii\data\ActiveDataProvider;
@ -86,6 +87,7 @@ class EventSearch extends Event
] ]
); );
$dataProvider = new ActiveDataProvider([ $dataProvider = new ActiveDataProvider([
'query' => $query, 'query' => $query,
'sort' => [ 'sort' => [

View File

@ -6823,6 +6823,11 @@
"set-immediate-shim": "~1.0.1" "set-immediate-shim": "~1.0.1"
} }
}, },
"jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"karma": { "karma": {
"version": "6.3.4", "version": "6.3.4",
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.4.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.4.tgz",

View File

@ -28,6 +28,7 @@
"@ngxs/logger-plugin": "^3.7.2", "@ngxs/logger-plugin": "^3.7.2",
"@ngxs/store": "^3.7.2", "@ngxs/store": "^3.7.2",
"bootstrap": "^5.1.1", "bootstrap": "^5.1.1",
"jwt-decode": "^3.1.2",
"moment": "^2.24.0", "moment": "^2.24.0",
"ngx-bootstrap": "^5.0.0", "ngx-bootstrap": "^5.0.0",
"ngx-toastr": "^14.1.3", "ngx-toastr": "^14.1.3",

View File

@ -1,31 +1,37 @@
import { Injectable } from "@angular/core"; import {Injectable} from "@angular/core";
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http"; import {HttpInterceptor, HttpRequest, HttpHandler, HttpEvent} from "@angular/common/http";
import { Observable } from "rxjs"; import {Observable} from "rxjs";
import {Store} from "@ngxs/store";
import {AppState} from "../state/app.state";
/* /*
The JWT interceptor intercepts the incoming requests from the application/user and adds JWT token to the request's Authorization header, only if the user is logged in. The JWT interceptor intercepts the incoming requests from the application/user and adds JWT token to the request's Authorization header, only if the user is logged in.
This JWT token in the request header is required to access the SECURE END API POINTS on the server This JWT token in the request header is required to access the SECURE END API POINTS on the server
*/ */
@Injectable() @Injectable()
export class JwtInterceptor implements HttpInterceptor{ export class JwtInterceptor implements HttpInterceptor {
constructor(){} constructor(private store: Store) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{ intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// check if the current user is logged in // check if the current user is logged in
// if the user making the request is logged in, he will have JWT token in it's local storage, which is set by Authorization Service during login process // if the user making the request is logged in, he will have JWT token in it's local storage, which is set by Authorization Service during login process
let currentUser = JSON.parse(localStorage.getItem('currentUser')); // let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if(currentUser && currentUser.token){
// clone the incoming request and add JWT token in the cloned request's Authorization Header const token = this.store.selectSnapshot<string>(AppState.getToken);
request = request.clone({
setHeaders: { if (token) {
Authorization: `Bearer ${currentUser.token}` // clone the incoming request and add JWT token in the cloned request's Authorization Header
} request = request.clone({
}); setHeaders: {
Authorization: `Bearer ${token}`
} }
});
// handle any other requests which went unhandled
return next.handle(request);
} }
}
// handle any other requests which went unhandled
return next.handle(request);
}
}

View File

@ -67,11 +67,11 @@ export class FitNavigationComponent implements OnInit {
if ( item.roles && item.roles.length ){ if ( item.roles && item.roles.length ){
let firstRole = item.roles[0]; let firstRole = item.roles[0];
if ( firstRole == '!'){ if ( firstRole == '!'){
return !this.authenticationService.user.value; return !this.authenticationService.isLoggedIn();
}else if ( firstRole == '*'){ }else if ( firstRole == '*'){
return true; return true;
}else if ( firstRole == '@'){ }else if ( firstRole == '@'){
return this.authenticationService.user.value; return this.authenticationService.isLoggedIn();
} }
} }

View File

@ -1,4 +1,7 @@
<fit-navigation></fit-navigation> <fit-navigation></fit-navigation>
<div class="container " > <div class="container " >
<div class="row ">
<div class="col-12">Bejelentkezve: {{username | async}}</div>
</div>
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>

View File

@ -1,4 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {Select} from "@ngxs/store";
import {AppState} from "../../state/app.state";
import {Observable} from "rxjs";
@Component({ @Component({
selector: 'app-secured-layout', selector: 'app-secured-layout',
@ -6,6 +9,7 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./secured-layout.component.scss'] styleUrls: ['./secured-layout.component.scss']
}) })
export class SecuredLayoutComponent implements OnInit { export class SecuredLayoutComponent implements OnInit {
@Select(AppState.getUsername) public username: Observable<string>;
constructor() { } constructor() { }

View File

@ -1,57 +1,71 @@
import { Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import { HttpClient } from "@angular/common/http"; import {HttpClient} from "@angular/common/http";
import { map } from 'rxjs/operators'; import {catchError, map} from 'rxjs/operators';
import {Endpoints} from "./endpoints"; import {Endpoints} from "./endpoints";
import {BehaviorSubject} from "rxjs"; import { throwError} from "rxjs";
import {PasswordChangeRequest} from "../app.types"; import {PasswordChangeRequest} from "../app.types";
import jwtDecode, {JwtPayload} from "jwt-decode";
import {Store} from "@ngxs/store";
import {LoginAction} from "../state/app.actions";
import {AppState} from "../state/app.state";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class AuthenticationService { export class AuthenticationService {
private _user: BehaviorSubject<any> = new BehaviorSubject(null); constructor(private http: HttpClient, private store: Store) {
constructor(private http: HttpClient){ store.dispatch(new LoginAction(this.getToken()))
let user = localStorage.getItem('currentUser' ); }
if ( user ){
this.user.next( JSON.stringify(user)); public getToken() {
} let currentUser = JSON.parse(localStorage.getItem('currentUser'));
return currentUser?.token;
} }
// login // login
login(username: string, password:string){ login(username: string, password: string) {
return this.http.post<any>(Endpoints.POST_USERS_AUTHENTICATE(), {username:username,password:password}) return this.http.post<any>(Endpoints.POST_USERS_AUTHENTICATE(), {username: username, password: password})
.pipe( .pipe(
// the backend service sends an instance of the user // the backend service sends an instance of the user
// user: any (because .post<any>) // user: any (because .post<any>)
map(user => { map(user => {
// login successful if the response has jwt token // login successful if the response has jwt token
if(user && user.token){ if (user && user.token) {
// store user details and jwt token in the local storage to keep the user logged in between page refreshes // store user details and jwt token in the local storage to keep the user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user)); localStorage.setItem('currentUser', JSON.stringify(user));
this.user.next(user); const decoded = jwtDecode<JwtPayload>(user.token);
console.info("decoded", decoded);
// this.user.next(user);
this.store.dispatch(new LoginAction(user.token));
} }
return user; return user;
}) }),
catchError(err => {
localStorage.removeItem('currentUser');
this.store.dispatch(new LoginAction(null));
return throwError(err);
}),
); );
} }
passwordChange(passwordChangeRequest: PasswordChangeRequest){ passwordChange(passwordChangeRequest: PasswordChangeRequest) {
return this.http.post<any>(Endpoints.POST_USER_PASSWORD_CHANGE(), passwordChangeRequest) return this.http.post<any>(Endpoints.POST_USER_PASSWORD_CHANGE(), passwordChangeRequest)
} }
get user() { // get user() {
return this._user; // return this._user;
} // }
//
public isLoggedIn(){ public isLoggedIn() {
return this.user.value; return this.store.selectSnapshot(AppState.getToken);
} }
// logout // logout
logout(){ logout() {
// remove user from local storage // remove user from local storage
localStorage.removeItem('currentUser'); localStorage.removeItem('currentUser');
this.user.next(null); this.store.dispatch(new LoginAction(null));
// this.user.next(null);
} }
} }

View File

@ -6,3 +6,9 @@ export class FilterTimeTableAction {
constructor(public idTrainer: number, public idEventType: number) {} constructor(public idTrainer: number, public idEventType: number) {}
} }
export class LoginAction {
// For debug / console output upon dev environment
static readonly type = "[App] LoginAction";
constructor(public token: string) {}
}

View File

@ -1,12 +1,15 @@
import {Action, Selector, State, StateContext, Store} from "@ngxs/store"; import {Action, Selector, State, StateContext} from "@ngxs/store";
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import { import {
FilterTimeTableAction, FilterTimeTableAction, LoginAction,
} from "./app.actions"; } from "./app.actions";
import {TimeTableFilter} from "../app.types"; import {TimeTableFilter} from "../app.types";
import jwtDecode, {JwtPayload} from "jwt-decode";
export interface AppStateModel { export interface AppStateModel {
username: string;
token: string;
filterTimeTable: FilterTimeTableAction; filterTimeTable: FilterTimeTableAction;
} }
@ -14,6 +17,8 @@ export interface AppStateModel {
@State<AppStateModel>({ @State<AppStateModel>({
name: "app", name: "app",
defaults: { defaults: {
username: null,
token: null,
filterTimeTable: { filterTimeTable: {
idTrainer: -1, idTrainer: -1,
idEventType: -1 idEventType: -1
@ -23,8 +28,7 @@ export interface AppStateModel {
export class AppState { export class AppState {
constructor( constructor() {
) {
} }
@Selector() @Selector()
@ -32,6 +36,17 @@ export class AppState {
return state.filterTimeTable; return state.filterTimeTable;
} }
@Selector()
public static getUsername(state: AppStateModel): string {
return state.username;
}
@Selector()
public static getToken(state: AppStateModel): string {
return state.token;
}
@Action(FilterTimeTableAction) @Action(FilterTimeTableAction)
dispatchFilterTimeTable(ctx: StateContext<AppStateModel>, {idEventType, idTrainer}: FilterTimeTableAction): void { dispatchFilterTimeTable(ctx: StateContext<AppStateModel>, {idEventType, idTrainer}: FilterTimeTableAction): void {
ctx.patchState({ ctx.patchState({
@ -42,4 +57,23 @@ export class AppState {
}); });
} }
@Action(LoginAction)
dispatchLogin(ctx: StateContext<AppStateModel>, {token}: LoginAction): void {
let username = null;
try {
const decoded = jwtDecode<JwtPayload & { username: string }>(token);
username = decoded?.username;
} catch (e) {
// user not logged in
token = null;
}
ctx.patchState({
username: username,
token: token
});
}
} }

View File

@ -54,6 +54,7 @@ class LoginController extends CustomerApiController
->issuedAt($time)// Configures the time that the token was issue (iat claim) ->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + 3600)// Configures the expiration time of the token (exp claim) ->expiresAt($time + 3600)// Configures the expiration time of the token (exp claim)
->withClaim('uid', $form->getCustomer()->getId())// Configures a new claim, called "uid" ->withClaim('uid', $form->getCustomer()->getId())// Configures a new claim, called "uid"
->withClaim('username', $form->getCustomer()->email)// Configures a new claim, called "username"
->getToken($signer, $key); // Retrieves the generated token ->getToken($signer, $key); // Retrieves the generated token
return $this->asJson([ return $this->asJson([