From 397596b12c1173e32b467ce8071809af4d1399fd Mon Sep 17 00:00:00 2001 From: Sang Nguyen <sang.nguyen@lcsa.vn> Date: Wed, 5 Mar 2025 08:43:15 +0700 Subject: [PATCH] upd: + add function csm create, update user role + add User Access Logic, Action, behavior, trait + Add workflow runtime Action, behavior, logic, trait --- README.md | 180 +----------------- base/helper/LogHelper.php | 28 +-- base/services/BaseService.php | 3 +- cnm/services/CnmService.php | 12 +- csm/actions/UserAccessAction.php | 16 ++ csm/command/CrawlController.php | 36 ++-- csm/command/PushController.php | 84 ++++++++ csm/enums/ApiEndpoint.php | 1 + csm/jobs/AssignUserRoleByObjectRoleJob.php | 2 +- csm/jobs/RevokeUserRoleByObjectRoleJob.php | 2 +- csm/models/LoginMethod.php | 23 +++ csm/services/CsmService.php | 78 +++++++- csm/services/UserService.php | 35 +++- csm/traits/UserTrait.php | 14 ++ mapper/behaviors/ObjectClauseBehavior.php | 8 +- mapper/services/ObjectClauseService.php | 12 +- mrbac/models/forms/ActionForm.php | 4 +- mrbac/models/forms/ModelForm.php | 2 +- mrbac/services/ModelService.php | 14 +- workflow/actions/WorkflowRuntimeIndex.php | 152 +++++++++++++++ .../behaviors/InitWorkflowChangeBehavior.php | 11 +- workflow/command/WorkflowController.php | 26 +++ workflow/services/WorkflowConfigService.php | 4 +- workflow/services/WorkflowRuntimeService.php | 26 ++- workflow/services/WorkflowService.php | 30 +-- workflow/traits/WorkflowRuntimeTrait.php | 14 ++ 26 files changed, 528 insertions(+), 289 deletions(-) create mode 100644 csm/actions/UserAccessAction.php create mode 100644 csm/command/PushController.php create mode 100644 csm/models/LoginMethod.php create mode 100644 csm/traits/UserTrait.php create mode 100644 workflow/actions/WorkflowRuntimeIndex.php create mode 100644 workflow/command/WorkflowController.php create mode 100644 workflow/traits/WorkflowRuntimeTrait.php diff --git a/README.md b/README.md index 3a44cde..94e3062 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ ``` docker-compose exec api composer require lsb/yii2-integrator ``` - ``` docker-compose exec api yii migrate-module ``` @@ -25,11 +24,11 @@ docker-compose exec api yii migrate-module "options": {} }, ``` - ``` Config local để dev khĂ´ng push change composer.json nĂ y lĂªn ``` + ### Add configuration console.php trong main project ``` @@ -39,183 +38,8 @@ Config local để dev khĂ´ng push change composer.json nĂ y lĂªn 'class' => 'yii\console\controllers\MigrateController', 'migrationPath' => [ '@lbs/workflow/migrations' - '@lbs/cnm/migrations' - '@lbs/mapper/migrations' - '@lbs/mrbac/migrations' - '@lbs/resource/migrations' ], 'migrationTable' => 'migration_module' ], ] -``` - -### Add configuration log.php trong main project - -``` - 'log' => [ - 'traceLevel' => YII_DEBUG ? 3 : 0, - 'targets' => [ - [ - 'class' => 'yii\log\FileTarget', - 'categories' => ['application-cnm'], // Custom category - 'logFile' => '@runtime/logs/integrate-cnm.log', // Custom log file - 'maxLogFiles' => 5, // Keep last 5 log files - ], - [ - 'class' => 'yii\log\FileTarget', - 'categories' => ['application-csm'], // Custom category - 'logFile' => '@runtime/logs/integrate-csm.log', // Custom log file - 'maxLogFiles' => 5, // Keep last 5 log files - ], - [ - 'class' => 'yii\log\FileTarget', - 'categories' => ['application-resource'], // Custom category - 'logFile' => '@runtime/logs/integrate-resource.log', // Custom log file - 'maxLogFiles' => 5, // Keep last 5 log files - ], - [ - 'class' => 'yii\log\FileTarget', - 'categories' => ['application-workflow'], // Custom category - 'logFile' => '@runtime/logs/integrate-workflow.log', // Custom log file - 'maxLogFiles' => 5, // Keep last 5 log files - ], - ], -] -``` - -### Add configuration for command - -``` -$config['bootstrap'][] = 'mrbac'; -$config['modules']['mrbac'] = [ - 'class' => \lsb\mrbac\Module::class, - 'modelPaths' => [ - "/app/models" => "app\\models", - ], - 'tenants' => [ 'LCS'] -]; -``` - -### Add configuration for gui mrbac - -``` -$config['bootstrap'][] = 'mrbac'; -$config['modules']['mrbac'] = [ - 'class' => \lsb\mrbac\Module::class, - 'modelPaths' => [ - "/app/models" => "app\\models", - ], - 'tenants' => [ 'LCS'] -]; -``` - -### Add configuration for gui csm - -``` -$config['bootstrap'][] = 'csmui'; -$config['modules']['csmui'] = [ - 'class' => \lsb\csm\Module::class, - 'queue' => 'queue', - 'modelPaths' => [ - "/app/models" => "app\\models", - ], - 'tenant' => 'LCS' -]; -``` - -### Modules guideline - -- #### Workflow -0. Define `workflow` object config in main app -```php -<?php -return [ - 'class' => \lsb\workflow\models\Workflow::class, - 'baseUrl' => getenv('WORKFLOW_BASE_URL'), - 'username' => getenv('WORKFLOW_USERNAME'), - 'password' => getenv('WORKFLOW_PASSWORD'), - 'appCode' => strtoupper(getenv('SERVICE_NAME')), -]; -``` - -1. Run migration to init `workflow_config` and `workflow_reference` and `workflow_runtime` - -`workfow_config`: use to define any version of workflow - -`workflow_reference`: use to define which version will applied in object - -`workflow_runtime`: use to store one by one which user handle current state - -2. Init main model need to run workflow with behaviors - -```php -public Foo extends Model { - public function behaviors() - { - return [ - 'initWorkflow' => [ - 'class' => InitWorkflowChangeBehavior::class, - 'silent_error' => true, - 'workflow_ref_code' => 'WORKFLOW_REF_CODE_FOO', // these code is used for identify which workflow need to use defined in workflow_reference - 'workflow_version' => 1, - 'instance_code' => function ($model) { - //TODO: Handle logic get the instance identity to compare with workflow engine - return 'MODEL_INSTANCE_CODE'; - }, - 'callback' => function ($model, $instanceCode, $workflowCode) { - //TODO: Handle logic after workflow initialized - } - ] - ]); - } - // Workflow will be initialized and started after Foo object saved. - // The runtime will be sync and use interface `getAllowAction`, `executeAction` to change node -} -``` - -3. Define workflow with `workflow-engine` and run command - -```shell -# these command use to mapping workflow version with ref code -$ docker-compose exec api php yii workflow/init <workflow_code> <ref_code> - -# example: -$ docker-compose exec api php yii workflow/init WORKFLOW_VERSION_1.0.1 WORKFLOW_REF_CODE_FOO -``` - -4. Define workflow callback controller and action to matches with `urls` declared in `workflow-engine` -5. Use workflow definitions interfaces In `WorkflowService` and `WorkflowRuntimeService` to handle - -```php -// Context: This Foo object instance have to run in 3 step -// + NEW: after created and start workflow -// + PROCESS: after execute action in `NEW` node -// + DONE: after execute action in `PROCESS` node -// --------- --------- --------- -// | NEW | ----> | PROCESS | ----> | DONE | -// --------- --------- --------- - -// Use basic step after Foo object initialized workflow -// At the moment `Foo` instance is in `NEW` - -// (1) Exec: WorkflowService::getAllowActions(<workflow_define>,<runtime_id>, <params>, <current_jwt>) -// -> Call `Workflow-engine` for return list available action -// -> these function will return list action and pick one <action_code> for next step -// -// (2) Exec: WorkflowService::executeActionAndSaveRuntimes(<workflow_define>,<runtime_id>, <action_code>, <note> , <current_jwt>) -// -> call `Workflow-engine` for execute <action_code> with <runtime_id> when success, this function call `workflow-engine` again to save `workflow_runtimes` -// -> these function will return state of current `instance` you must to save it. - -// And then the `Foo` instance will change to `PROCESS`. Repeat step (1), (2) and `Foo` instance get `DONE` - -// *** Attentions: -// 1. <workflow_define> must be defined. -// 2. <runtime_id> get from `workflow_runtime.runtime_id` . -// 3. <current_jwt> use current jwt to identity who handle in workflow. -// 4. Always call get workflow runtime after execute to ensure your version `workflow_runtime` data matches with `workflow-engine`. -// 6. Everytime and everywhere the `instance_code` must be unique. -// 5. while an error appeared in your process, workflow still run. -// 7. Never think about the opening a DB transaction in your code when you save this object, workflow can not check and get data throw `instance_code` if data isn't written in DB. - -// Thanks for your attention. Good luck !! =]] -``` +``` \ No newline at end of file diff --git a/base/helper/LogHelper.php b/base/helper/LogHelper.php index e8f1e53..aa8d7ee 100644 --- a/base/helper/LogHelper.php +++ b/base/helper/LogHelper.php @@ -8,28 +8,10 @@ use yii\helpers\BaseConsole; class LogHelper { - /** - * @param $message - * @param $tracing_key - * @param $options - * - ```php - * [ - * 'category' => 'application', - * 'fg' => BaseConsole::FG_BLACK - * ] - * ``` - * - `fg`: array $format An array containing formatting values. - * You can pass any of the `FG_*`, `BG_*` and `TEXT_*` constants - * and also [[xtermFgColor]] and [[xtermBgColor]] to specify a format. - * - `context`: string the category of the message. - * @return void - */ - public static function logMes($message, $tracing_key = [], $options = []) + public static function logMes($message, $tracing_key = null, $fg = 'lbs') { $bt = debug_backtrace(); $caller = $bt[1]['function'] ?? null; - $category = $options['category'] ?? 'application'; - $fg = $options['fg'] ?? ''; if (Yii::$app instanceof Application) { $date = \Yii::$app->formatter->asDatetime(time()); if (is_array($message)) { @@ -38,13 +20,13 @@ class LogHelper if(is_array($tracing_key)){ $tracing_key = implode("][", $tracing_key); } - Yii::error("[$caller][$date][$tracing_key]" . " " . $message, $category); - BaseConsole::output(BaseConsole::ansiFormat("[$caller][$date][$tracing_key]" . " " . $message, $fg)); + Yii::error("[$caller][$date][$tracing_key]" . " " . $message, $fg); + BaseConsole::output("[$caller][$date][$tracing_key]" . " " . $message); } else { if (is_string($message)) { - Yii::error("[$caller] " . $message, $category); + Yii::error("[$caller] " . $message, $fg); } else { - Yii::error("[$caller] " . json_encode($message), $category); + Yii::error("[$caller] " . json_encode($message), $fg); } } } diff --git a/base/services/BaseService.php b/base/services/BaseService.php index 23f2a64..e315a04 100644 --- a/base/services/BaseService.php +++ b/base/services/BaseService.php @@ -69,6 +69,7 @@ class BaseService // $request->withAddedHeader('Content-Type', $this->getContentType()->value); $endpoint = "{$this->baseUrl}{$endpoint}"; LogHelper::logMes("$endpoint: ", ["call"]); + LogHelper::logMes("header: ".json_encode($headers), ["call"]); LogHelper::logMes(json_encode($body), ["Call"]); $response = $this->_client->request($method->name, $endpoint, [ $contentType->value => $body, @@ -164,4 +165,4 @@ class BaseService { return new BaseService($baseUrl, $authenticator, $contentType); } -} \ No newline at end of file +} diff --git a/cnm/services/CnmService.php b/cnm/services/CnmService.php index 4c829ea..1ab3d39 100644 --- a/cnm/services/CnmService.php +++ b/cnm/services/CnmService.php @@ -52,7 +52,7 @@ class CnmService 'response' => json_encode($contents), ], ''); if (!$notifyHistory->save()) { - LogHelper::logMes("Save notify history failed!", $url, ['category' => 'application-cnm']); + LogHelper::logMes("Save notify history failed!"); } $rp[] = $contents; @@ -74,7 +74,7 @@ class CnmService 'response' => json_encode($contents), ], ''); if (!$notifyHistory->save()) { - LogHelper::logMes("Save notify history failed!", $url, ['category' => 'application-cnm']); + LogHelper::logMes("Save notify history failed!"); } $successSend = []; @@ -87,7 +87,7 @@ class CnmService if ($status >= 400 && $hasError) { $check = self::deleteUserDevice($key); if (!$check) { - LogHelper::logMes("Delete UserDeviceKey failed with code [ $key ] ", $url, ['category' => 'application-cnm']); + LogHelper::logMes("Delete UserDeviceKey failed with code [ $key ] "); } } else { $userCode = UserDeviceRegister::findOne(['device_token' => $key])->user_code ?? null; @@ -95,7 +95,7 @@ class CnmService } } } else { - LogHelper::logMes("Fail logic with response [ $cts ] ", $url, ['category' => 'application-cnm']); + LogHelper::logMes("Fail logic with response [ $cts ] "); } } } @@ -121,7 +121,7 @@ class CnmService foreach ($listUserCodes as $userCode => $content) { if (!isset($content['message'])) { $jeE = json_encode($content); - LogHelper::logMes("Create notification failed with content $jeE", $userCode, ['category' => 'application-cnm']); + LogHelper::logMes("Create notification failed with content $jeE"); continue; } $jsonMessage = json_decode($content['message'], true); @@ -143,7 +143,7 @@ class CnmService 'user_code' => $userCode, ], ''); if (!$notification->save()) { - LogHelper::logMes("Create notification failed with objectCode [ $objectCode ] and identity [ $identity ]", $userCode, ['category' => 'application-cnm']); + LogHelper::logMes("Create notification failed with objectCode [ $objectCode ] and identity [ $identity ]"); } } } diff --git a/csm/actions/UserAccessAction.php b/csm/actions/UserAccessAction.php new file mode 100644 index 0000000..a4ab3b4 --- /dev/null +++ b/csm/actions/UserAccessAction.php @@ -0,0 +1,16 @@ +<?php + +namespace lsb\csm\actions; + +use lsb\csm\services\UserService; +use yii\base\Action; + +class UserAccessAction extends Action +{ + public $modelClass; + + public function run() + { + return UserService::getUserAccess($this->modelClass); + } +} diff --git a/csm/command/CrawlController.php b/csm/command/CrawlController.php index 305e45b..dff636d 100644 --- a/csm/command/CrawlController.php +++ b/csm/command/CrawlController.php @@ -3,6 +3,8 @@ namespace lsb\csm\command; use lsb\base\helper\LogHelper; +use lsb\csm\models\Csm; +use lsb\csm\models\LoginMethod; use lsb\csm\models\Role; use lsb\csm\models\User; use lsb\csm\models\UserRole; @@ -22,7 +24,7 @@ class CrawlController extends Controller $app = CsmService::getApp($csm, $token); $roles = CsmService::getRoles($csm, $app['id'], $token); foreach ($roles as $role) { - LogHelper::logMes("init role : " . $role['role_name'], '', ['category' => 'application-csm']); + LogHelper::logMes("init role : " . $role['role_name']); $appRole = Role::findOne(['code' => $role['role_name']]); if (empty($appRole)) { $appRole = new Role(); @@ -32,7 +34,7 @@ class CrawlController extends Controller if (!$appRole->save()) { - LogHelper::logMes("errors: " . json_encode($appRole->errors), '', ['category' => 'application-csm']); + LogHelper::logMes("errors: " . json_encode($appRole->errors)); } $rolesMapping[$role['id']] = $appRole->id; } @@ -56,7 +58,7 @@ class CrawlController extends Controller $client = $user['client']; $appUser = User::findOne(['user_code' => $user['user_code']]); - LogHelper::logMes("init user : " . $user['user_code'], '', ['category' => 'application-csm']); + LogHelper::logMes("init user : " . $user['user_code']); if (empty($appUser)) { $appUser = new User(); } @@ -67,7 +69,7 @@ class CrawlController extends Controller $appUser->phone = $client['phone_number']; if (!$appUser->save()) { - LogHelper::logMes("errors: " . json_encode($appUser->errors), '', ['category' => 'application-csm']); + LogHelper::logMes("errors: " . json_encode($appUser->errors)); } $mappingUsers[$userId] = $appUser->id; @@ -109,9 +111,9 @@ class CrawlController extends Controller foreach ($userRoles as $key => $data) { - LogHelper::logMes("init user role: user_code - " . $key, '', ['category' => 'application-csm']); + LogHelper::logMes("init user role: user_code - " . $key); if (!isset($appUsers[$key])) { - LogHelper::logMes("init user role: user_code - $key failed !!", '', ['category' => 'application-csm']); + LogHelper::logMes("init user role: user_code - $key failed !!"); continue; } $appUser = $appUsers[$key]; @@ -119,20 +121,20 @@ class CrawlController extends Controller $appUserRoles = UserRole::findAll(['user_id' => $appUser['id']]); $appUserRoleIds = array_column($appUserRoles, 'role_id'); foreach ($data as $role) { - LogHelper::logMes("init user role: role - " . $role['role_name'], '', ['category' => 'application-csm']); + LogHelper::logMes("init user role: role - " . $role['role_name']); if (!isset($appRoles[$role['role_name']])) { - LogHelper::logMes("init user role failed " . $role['role_name'] . " not existed !!", '', ['category' => 'application-csm']); + LogHelper::logMes("init user role failed " . $role['role_name'] . " not existed !!"); continue; } $appRole = $appRoles[$role['role_name']]; if (in_array($appRole['id'], $appUserRoleIds)) { - LogHelper::logMes("UserRole is existed", '', ['category' => 'application-csm']); + LogHelper::logMes("UserRole is existed"); } else { $appUserRole = new UserRole(['user_id' => $appUser['id'], 'role_id' => $appRole['id']]); if (!$appUserRole->save()) { - LogHelper::logMes("errors: " . json_encode($appUserRole->errors), '', ['category' => 'application-csm']); + LogHelper::logMes("errors: " . json_encode($appUserRole->errors)); } else { - LogHelper::logMes("save success !!", '', ['category' => 'application-csm']); + LogHelper::logMes("save success !!"); } } if ($resetUserRoleObject) { @@ -167,12 +169,12 @@ class CrawlController extends Controller echo $tenantCode . "\n"; $csm = \Yii::$app->csm; $token = CsmService::getToken($csm); - LogHelper::logMes("Token: $token ", '', ['category' => 'application-csm']); + LogHelper::logMes("Token: $token "); self::resetIdentity($tenantCode); $tenant = CsmService::getTenant($csm, $tenantCode, $token); $app = CsmService::getApp($csm, $token); $tenantApp = CsmService::getTenantApp($csm, $tenant['id'], $app['id'], $token); - if(strpos($emails, ",")){ + if (strpos($emails, ",")) { $emails = explode(",", $emails); } else { $emails = [$emails]; @@ -184,8 +186,8 @@ class CrawlController extends Controller foreach ($users as $user) { - LogHelper::logMes("user: ".json_encode($user), '', ['category' => 'application-csm']); - LogHelper::logMes("reset user: $email - $password", '', ['category' => 'application-csm']); + LogHelper::logMes("user: " . json_encode($user)); + LogHelper::logMes("reset user: $email - $password"); $result = CsmService::updateUserPassword($csm, $user['id'], [ "email" => $email, "full_name" => $user['client']['full_name'], @@ -195,9 +197,9 @@ class CrawlController extends Controller "app_id" => $app['id'], "login_method" => $user['loginMethod'], ], $token); - LogHelper::logMes("result: " . json_encode($result), '', ['category' => 'application-csm']); + LogHelper::logMes("result: " . json_encode($result)); } } } -} \ No newline at end of file +} diff --git a/csm/command/PushController.php b/csm/command/PushController.php new file mode 100644 index 0000000..6751130 --- /dev/null +++ b/csm/command/PushController.php @@ -0,0 +1,84 @@ +<?php + +namespace lsb\csm\command; + +use lsb\base\helper\LogHelper; +use lsb\csm\models\Csm; +use lsb\csm\models\LoginMethod; +use lsb\csm\models\User; +use lsb\csm\services\CsmService; +use yii\console\Controller; + +class PushController extends Controller +{ + + public function actionCreateUser($email, $fullName, $phone, $password, $tenantCode, $appCode, $loginMethod = 1) + { + echo $tenantCode . "\n"; + /** + * @var $csm Csm + */ + $csm = \Yii::$app->csm; + $csm->appCode = $appCode; + $token = CsmService::getToken($csm); + $app = CsmService::getApp($csm, $token); + $tenant = CsmService::getTenant($csm, $tenantCode, $token); + switch ($loginMethod) { + case 2: + $loginMethod = new LoginMethod(true, false, true); + break; + case 3: + $loginMethod = new LoginMethod(true, true, true); + break; + case 4: + $loginMethod = new LoginMethod(false, false, true); + break; + case 5: + $loginMethod = new LoginMethod(false, true, true); + break; + case 6: + $loginMethod = new LoginMethod(false, true, false); + break; + case 1: + default: + $loginMethod = new LoginMethod(true, false, false); + } + CsmService::createUser($csm, $email, $fullName, $phone, $password, $loginMethod, $tenant['id'], $app['id'], $token); + } + + public function actionAddUserRole($username, $roleName, $tenantCode, $appCode, $isRemove = false) + { + /** + * @var $csm Csm + */ + $csm = \Yii::$app->csm; + $csm->appCode = $appCode; + $token = CsmService::getToken($csm); + + $app = CsmService::getApp($csm, $token); + $tenant = CsmService::getTenant($csm, $tenantCode, $token); + $tenantApp = CsmService::getTenantApp($csm, $tenant['id'], $app['id'], $token); + + $role = CsmService::getRoles($csm, $app['id'], $token, [ + 'filter[role_name]' => $roleName + ]); + LogHelper::logMes(json_encode($role)); + $role = $role[0] ?? []; + + $client = CsmService::getClient($csm, $tenant['id'], $token, [ + 'filter[email]' => $username, + ]); + $client = $client[0] ?? []; + LogHelper::logMes(json_encode($client)); + $users = CsmService::getUsers($csm, $tenantApp['id'], $token, [ + 'filter[client_id]' => $client['id'], + ]); + LogHelper::logMes(json_encode($users)); + $users = $users[0] ?? []; + + CsmService::updateUserRole($csm, $users['id'], [ + $role['id'] + ], $token, $isRemove); + } + +} diff --git a/csm/enums/ApiEndpoint.php b/csm/enums/ApiEndpoint.php index 3ba47b6..d1da2b1 100644 --- a/csm/enums/ApiEndpoint.php +++ b/csm/enums/ApiEndpoint.php @@ -11,6 +11,7 @@ enum ApiEndpoint: string implements Api case MSPCSM_TENANT = "/mspcsm/tenants"; case MSPCSM_TENANT_APP = "/mspcsm/tenant-apps"; case MSPCSM_USERS = "/mspcsm/users"; + case MSPCSM_CLIENTS = "/mspcsm/clients"; case MSPCSM_ROLES = "/mspcsm/roles"; case MSPCSM_USER_UPDATE_ROLE = "/mspcsm/users/update-role"; case MSPCSM_USER_ROLES = "/mspcsm/user-roles"; diff --git a/csm/jobs/AssignUserRoleByObjectRoleJob.php b/csm/jobs/AssignUserRoleByObjectRoleJob.php index c78c63c..b6f13f0 100644 --- a/csm/jobs/AssignUserRoleByObjectRoleJob.php +++ b/csm/jobs/AssignUserRoleByObjectRoleJob.php @@ -20,7 +20,7 @@ class AssignUserRoleByObjectRoleJob extends Model implements JobInterface $userRoles = UserService::findAllUserRoleByRole([$this->roleCode]); foreach ($userRoles as $userRole) { foreach ($this->objectIds as $objectId) { - LogHelper::logMes("Assign user_role:$userRole->id, object_id:$objectId, object_class:$this->objectClass", [$this->roleCode], ['category' => 'application-csm']); + LogHelper::logMes("Assign user_role:$userRole->id, object_id:$objectId, object_class:$this->objectClass", [$this->roleCode]); UserService::saveUserRoleObject($userRole->id, $objectId, $this->objectClass); } } diff --git a/csm/jobs/RevokeUserRoleByObjectRoleJob.php b/csm/jobs/RevokeUserRoleByObjectRoleJob.php index 266d049..7bc85be 100644 --- a/csm/jobs/RevokeUserRoleByObjectRoleJob.php +++ b/csm/jobs/RevokeUserRoleByObjectRoleJob.php @@ -20,7 +20,7 @@ class RevokeUserRoleByObjectRoleJob extends Model implements JobInterface $userRoles = UserService::findAllUserRoleByRole([$this->roleCode]); foreach ($userRoles as $userRole) { foreach ($this->objectIds as $objectId) { - LogHelper::logMes("Revoke user_role:$userRole->id, object_id:$objectId, object_class:$this->objectClass", [$this->roleCode], ['category' => 'application-csm']); + LogHelper::logMes("Revoke user_role:$userRole->id, object_id:$objectId, object_class:$this->objectClass", [$this->roleCode]); UserService::deleteUserRoleObject($userRole->id, $objectId, $this->objectClass); } } diff --git a/csm/models/LoginMethod.php b/csm/models/LoginMethod.php new file mode 100644 index 0000000..b1388b8 --- /dev/null +++ b/csm/models/LoginMethod.php @@ -0,0 +1,23 @@ +<?php + +namespace lsb\csm\models; + +class LoginMethod +{ + public $user_pass = true; + public $sso = false; + public $otp = false; + + /** + * @param bool $user_pass + * @param bool $sso + * @param bool $otp + */ + public function __construct(bool $user_pass, bool $sso, bool $otp) + { + $this->user_pass = $user_pass; + $this->sso = $sso; + $this->otp = $otp; + } + +} diff --git a/csm/services/CsmService.php b/csm/services/CsmService.php index 46fe5f2..337487e 100644 --- a/csm/services/CsmService.php +++ b/csm/services/CsmService.php @@ -13,15 +13,41 @@ use lsb\base\helper\RequestHelper; use lsb\base\services\BaseService; use lsb\csm\enums\ApiEndpoint; use lsb\csm\models\Csm; +use lsb\csm\models\LoginMethod; use yii\base\NotSupportedException; use yii\caching\CacheInterface; class CsmService { - public static function createUser(Csm $csm) + /** + * @param Csm $csm + * @param $email + * @param $full_name + * @param $phone + * @param $login_method + * @param $token + * @return mixed + * @throws \Psr\Http\Client\ClientExceptionInterface + */ + public static function createUser(Csm $csm, $email, $full_name, $phone, $password, LoginMethod $login_method, $tenantId, $appId, $token) { - throw new NotSupportedException("not support now."); + if (empty($login_method)) { + $login_method = new LoginMethod(true, false, false); + } + $body = [ + "email" => $email, + "full_name" => $full_name, + "phone" => $phone, + "password" => $password, + "login_method" => json_encode($login_method), + "tenant_id" => $tenantId, + "app_id" => $appId + ]; + $result = self::getBaseService($csm->baseUrl) + ->addAuthenticator(new HttpBearer($token)) + ->post(ApiEndpoint::MSPCSM_USERS->getEndPoint("/", $csm->appCode), $body); + return json_decode($result->getContents(), true); } public static function getApp(Csm $csm, $token) @@ -107,6 +133,26 @@ class CsmService return $items; } + public static function getClient(Csm $csm, $tenantId, $token, $extraFilter = []) + { + $filters = [ + 'filter[record_status]' => 'O', + 'filter[tenant_id]' => $tenantId, + 'page' => '-1', + 'per-page' => '-1', + 'sort' => '-checker_date', + 'keywords' => '', + 'fields' => '', + ]; + $filters = array_merge($filters, $extraFilter); + $result = self::getBaseService($csm->baseUrl) + ->addAuthenticator(new HttpBearer($token)) + ->get(ApiEndpoint::MSPCSM_CLIENTS->getEndPoint('?', RequestHelper::arrToParams($filters))); + $results = json_decode($result->getContents(), true); + $items = $results['items'] ?? []; + return $items; + } + public static function updateUserPassword(Csm $csm, $userId, $payload, $token) { @@ -117,9 +163,9 @@ class CsmService return $results; } - public static function getRoles(Csm $csm, $appId, $token) + public static function getRoles(Csm $csm, $appId, $token, $filters = []) { - $filters = [ + $filters = array_merge([ 'filter[record_status]' => 'O', 'filter[app_id]' => $appId, 'page' => '-1', @@ -127,7 +173,7 @@ class CsmService 'sort' => '-checker_date', 'keywords' => '', 'fields' => '', - ]; + ], $filters); $result = self::getBaseService($csm->baseUrl) ->addAuthenticator(new HttpBearer($token)) @@ -172,6 +218,26 @@ class CsmService return $items; } + /** + * @param Csm $csm + * @param $roleIds + * @param $token + * @return array|mixed + * @throws \Psr\Http\Client\ClientExceptionInterface + */ + public static function updateUserRole(Csm $csm, $userId, $roleIds, $token, $isRemove = false) + { + $payload = [ + "role" => $roleIds, + 'isRemove' => $isRemove + ]; + + $result = self::getBaseService($csm->baseUrl) + ->addAuthenticator(new HttpBearer($token)) + ->post(ApiEndpoint::MSPCSM_USER_UPDATE_ROLE->getEndPoint("/", $userId), $payload); + return json_decode($result->getContents(), true); + } + /** * @param Csm $csm * @return mixed @@ -181,7 +247,7 @@ class CsmService */ public static function getLogin(Csm $csm) { - $result = self::getBaseService($csm->gatewayUrl)->post(GatewayApi::API_ROOT->getEndPoint('/','authenticate'), [ + $result = self::getBaseService($csm->gatewayUrl)->post(GatewayApi::API_ROOT->getEndPoint('/', 'authenticate'), [ 'username' => $csm->username, 'password' => $csm->password, 'rememberMe' => false, diff --git a/csm/services/UserService.php b/csm/services/UserService.php index ab87386..d325adf 100644 --- a/csm/services/UserService.php +++ b/csm/services/UserService.php @@ -9,6 +9,8 @@ use lsb\csm\models\Role; use lsb\csm\models\User; use lsb\csm\models\UserRole; use lsb\csm\models\UserRoleObject; +use lsb\mrbac\models\FunctionCondition; +use lsb\mrbac\services\ModelAccessService; use yii\base\InvalidConfigException; use yii\db\ActiveRecord; use yii\web\NotFoundHttpException; @@ -194,11 +196,11 @@ class UserService if (empty($roleObject)) { $roleObject = new ObjectRole(['role_id' => $role->id, 'object_id' => $objectId, 'object_type' => $class]); if (!$roleObject->save()) { - LogHelper::logMes("save role object failed 'role_id' => $role->id, 'object_id' => $objectId, 'object_type' => $class: " . json_encode($roleObject->errors),'', ['category' => 'application-csm']); + LogHelper::logMes("save role object failed 'role_id' => $role->id, 'object_id' => $objectId, 'object_type' => $class: " . json_encode($roleObject->errors)); return; }; } else { - LogHelper::logMes("User role object failed 'role_id' => $role->id, 'object_id' => $objectId, 'object_type' => $class: existed. ",'', ['category' => 'application-csm']); + LogHelper::logMes("User role object failed 'role_id' => $role->id, 'object_id' => $objectId, 'object_type' => $class: existed. "); } } @@ -218,7 +220,7 @@ class UserService } $roleObject = new ObjectRole(['role_id' => $roleId, 'object_id' => $objectId, 'object_type' => $objectClass]); if (!$roleObject->save()) { - LogHelper::logMes("save role object failed 'role_id' => $roleId, 'object_id' => $objectId, 'object_type' => $objectClass: " . json_encode($roleObject->errors),'', ['category' => 'application-csm']); + LogHelper::logMes("save role object failed 'role_id' => $roleId, 'object_id' => $objectId, 'object_type' => $objectClass: " . json_encode($roleObject->errors)); }; } return true; @@ -254,7 +256,7 @@ class UserService $roleObject = ObjectRole::findOne(['role_id' => $role->id, 'object_id' => $objectId, 'object_type' => $class]); if (empty($roleObject)) { - LogHelper::logMes("Role $roleCode - object $objectId not found",'', ['category' => 'application-csm']); + LogHelper::logMes("Role $roleCode - object $objectId not found"); } else { $roleObject->delete(); } @@ -277,7 +279,7 @@ class UserService if (empty($userRole)) { $userRole = new UserRole(['user_id' => $user->id, 'role_id' => $role->id]); if (!$userRole->save()) { - LogHelper::logMes("save user role false $username, $roleCode, $objectId: " . json_encode($userRole->errors),'', ['category' => 'application-csm']); + LogHelper::logMes("save user role false $username, $roleCode, $objectId: " . json_encode($userRole->errors)); return; }; } @@ -302,7 +304,7 @@ class UserService if (empty($userRole)) { $userRole = new UserRole(['user_id' => $user->id, 'role_id' => $role->id]); if (!$userRole->save()) { - LogHelper::logMes("save user role false $username, $roleCode, $objectId: " . json_encode($userRole->errors),'', ['category' => 'application-csm']); + LogHelper::logMes("save user role false $username, $roleCode, $objectId: " . json_encode($userRole->errors)); return; } } @@ -319,11 +321,11 @@ class UserService if (empty($userRoleObject)) { $userRoleObject = new UserRoleObject(['user_role_id' => $userRoleId, 'object_id' => $objectId, 'object_type' => $objectClass]); if (!$userRoleObject->save()) { - LogHelper::logMes("save user role object failed 'user_role_id' => $userRoleId, 'object_id' => $objectId, 'object_type' => $objectClass: " . json_encode($userRoleObject->errors),'', ['category' => 'application-csm']); + LogHelper::logMes("save user role object failed 'user_role_id' => $userRoleId, 'object_id' => $objectId, 'object_type' => $objectClass: " . json_encode($userRoleObject->errors)); return; }; } else { - LogHelper::logMes("User role object failed 'user_role_id' => $userRoleId, 'object_id' => $objectId, 'object_type' => $objectClass: existed. ",'', ['category' => 'application-csm']); + LogHelper::logMes("User role object failed 'user_role_id' => $userRoleId, 'object_id' => $objectId, 'object_type' => $objectClass: existed. "); } } @@ -359,7 +361,7 @@ class UserService $userRoleObject = UserRoleObject::findOne(['user_role_id' => $userRole->id, 'object_id' => $objectId, 'object_type' => $class]); if (empty($userRoleObject)) { - LogHelper::logMes("User role object is not existed 'user_role_id' => $userRole->id, 'object_id' => $objectId, 'object_type' => $class: existed. ",'', ['category' => 'application-csm']); + LogHelper::logMes("User role object is not existed 'user_role_id' => $userRole->id, 'object_id' => $objectId, 'object_type' => $class: existed. "); } else { $userRoleObject = new UserRoleObject(['user_role_id' => $userRole->id, 'object_id' => $objectId, 'object_type' => $class]); $userRoleObject->delete(); @@ -382,4 +384,17 @@ class UserService { return User::findOne(['email' => $email]); } -} \ No newline at end of file + + + public static function getUserInstanceAccess(ActiveRecord $instance, $nodes = []) + { + $functionCondition = self::findAllObjectIdByObjectTypeAndRoleAndUserCode(AuthorizationService::getUserCode(), AuthorizationService::getRoles(), FunctionCondition::class); + return ModelAccessService::checkInstanceAccess($instance, $functionCondition, $nodes); + } + + public static function getUserAccess($modelClass) + { + $functionCondition = self::findAllObjectIdByObjectTypeAndRoleAndUserCode(AuthorizationService::getUserCode(), AuthorizationService::getRoles(), FunctionCondition::class); + return ModelAccessService::checkAccess($modelClass, $functionCondition); + } +} diff --git a/csm/traits/UserTrait.php b/csm/traits/UserTrait.php new file mode 100644 index 0000000..baa34e9 --- /dev/null +++ b/csm/traits/UserTrait.php @@ -0,0 +1,14 @@ +<?php + +namespace lsb\csm\traits; + + +use lsb\csm\services\UserService; + +trait UserTrait +{ + public function getAccessActions() + { + return UserService::getUserInstanceAccess($this); + } +} diff --git a/mapper/behaviors/ObjectClauseBehavior.php b/mapper/behaviors/ObjectClauseBehavior.php index 229d20d..4018370 100644 --- a/mapper/behaviors/ObjectClauseBehavior.php +++ b/mapper/behaviors/ObjectClauseBehavior.php @@ -104,15 +104,15 @@ class ObjectClauseBehavior extends \yii\base\Behavior $owner = $this->owner; foreach ($expressions as $expression) { $isOK = $expressionLanguage->evaluate($expression->clause, $nodes); - LogHelper::logMes("$this->objectClass evaluate $expression->clause: " . ($isOK ? 'true' : 'false'),'', ['category' => 'application-mapper']); - LogHelper::logMes("$this->objectClass node : " . json_encode($nodes),'', ['category' => 'application-mapper']); - LogHelper::logMes("$this->objectClass instance : " . json_encode($owner->getAttributes()),'', ['category' => 'application-mapper']); + LogHelper::logMes("$this->objectClass evaluate $expression->clause: " . ($isOK ? 'true' : 'false')); + LogHelper::logMes("$this->objectClass node : " . json_encode($nodes)); + LogHelper::logMes("$this->objectClass instance : " . json_encode($owner->getAttributes())); $result = $expression->result; switch ($expression->result_type) { case ObjectClauseService::TYPE_EXPRESSION: // if result type is a clause use Expression to re-evaluate again to get final result $result = $expressionLanguage->evaluate($expression->result, $nodes); - LogHelper::logMes("$this->objectClass re-evaluate $expression->result: $result",'', ['category' => 'application-mapper']); + LogHelper::logMes("$this->objectClass re-evaluate $expression->result: $result"); break; } diff --git a/mapper/services/ObjectClauseService.php b/mapper/services/ObjectClauseService.php index 98c5ab5..1b82b97 100644 --- a/mapper/services/ObjectClauseService.php +++ b/mapper/services/ObjectClauseService.php @@ -34,31 +34,31 @@ class ObjectClauseService { $expressionLanguage = new ExpressionLanguage(); $expressionLanguage->registerProvider(new ArrayExpressionLanguageProvider()); - LogHelper::logMes("$objectClass node : " . json_encode($nodes),'', ['category' => 'application-mapper']); + LogHelper::logMes("$objectClass node : " . json_encode($nodes)); $result = null; $expressions = ObjectClauseService::getModelClauses($objectClass); foreach ($expressions as $expression) { $isOK = $expressionLanguage->evaluate($expression->clause, $nodes); - LogHelper::logMes("$objectClass evaluate $expression->clause: " . ($isOK ? 'true' : 'false'),'', ['category' => 'application-mapper']); + LogHelper::logMes("$objectClass evaluate $expression->clause: " . ($isOK ? 'true' : 'false')); // these result must be bool and the clause must be a condition sentences if (is_bool($isOK) && $isOK) { $result = $expression->result; switch ($expression->result_type) { case ObjectClauseService::TYPE_EXPRESSION: // if result type is a clause use Expression to re-evaluate again to get final result - LogHelper::logMes("$objectClass re-evaluate $expression->result: $result",'', ['category' => 'application-mapper']); + LogHelper::logMes("$objectClass re-evaluate $expression->result: $result"); return $expressionLanguage->evaluate($expression->result, $nodes); case ObjectClauseService::TYPE_BOOLEAN: // if result type is a clause use Expression to re-evaluate again to get final result - LogHelper::logMes("$objectClass re-evaluate $expression->result: $result",'', ['category' => 'application-mapper']); + LogHelper::logMes("$objectClass re-evaluate $expression->result: $result"); return filter_var($expression->result, FILTER_VALIDATE_BOOL); break; case ObjectClauseService::TYPE_ARRAY: - LogHelper::logMes("$objectClass re-evaluate $expression->result: $result",'', ['category' => 'application-mapper']); + LogHelper::logMes("$objectClass re-evaluate $expression->result: $result"); return explode(',', $result); } - LogHelper::logMes("$objectClass re-evaluate $expression->result: $result",'', ['category' => 'application-mapper']); + LogHelper::logMes("$objectClass re-evaluate $expression->result: $result"); return $result; } } diff --git a/mrbac/models/forms/ActionForm.php b/mrbac/models/forms/ActionForm.php index 789fc1e..4a72a7e 100644 --- a/mrbac/models/forms/ActionForm.php +++ b/mrbac/models/forms/ActionForm.php @@ -36,11 +36,11 @@ class ActionForm extends Action foreach ($modelAction->getPlatformActions() as $plfAction) { $action = ModelService::initAction($plfAction->code, $plfAction->name, $this->description); if ($action->hasErrors()) { - LogHelper::logMes(json_encode($action->errors),'', ['category' => 'application-mrbac']); + LogHelper::logMes(json_encode($action->errors)); $this->addError('action', json_encode($action->errors)); return false; } - LogHelper::logMes("initModelFunction - $modelCode", $code, ['category' => 'application-mrbac']); + LogHelper::logMes("initModelFunction - $modelCode", $code); ModelService::initModelFunction($model, $action, strtoupper($this->name), $plfAction->slug); } } diff --git a/mrbac/models/forms/ModelForm.php b/mrbac/models/forms/ModelForm.php index 8eb1480..4fa1ef9 100644 --- a/mrbac/models/forms/ModelForm.php +++ b/mrbac/models/forms/ModelForm.php @@ -20,7 +20,7 @@ class ModelForm extends Model public function save($runValidation = true, $attributeNames = null) { - LogHelper::logMes(json_encode($this->selection),'', ['category' => 'application-mrbac']); + LogHelper::logMes(json_encode($this->selection)); foreach ($this->selection as $model) { list($code, $name) = explode("#", $model); ModelService::initModel($code, $name); diff --git a/mrbac/services/ModelService.php b/mrbac/services/ModelService.php index 0e02fd6..db7f9e1 100644 --- a/mrbac/services/ModelService.php +++ b/mrbac/services/ModelService.php @@ -90,7 +90,7 @@ class ModelService $model = new Model(['code' => $code, 'class' => $class]); } if (!$model->save()) { - LogHelper::logMes("init model code $code, class $class errors: " . json_encode($model->getErrors()),'', ['category' => 'application-mrbac']); + LogHelper::logMes("init model code $code, class $class errors: " . json_encode($model->getErrors())); }; return $model; } @@ -139,7 +139,7 @@ class ModelService 'description' => $description, ]); if (!$model->save()) { - LogHelper::logMes("init action code $code, name $name, description $description errors: " . json_encode($model->getErrors()),'', ['category' => 'application-mrbac']); + LogHelper::logMes("init action code $code, name $name, description $description errors: " . json_encode($model->getErrors())); }; return $model; } @@ -155,7 +155,7 @@ class ModelService { $model = Action::findOne(['code' => $code]); if (!$model) { - LogHelper::logMes("Action $code not found.",'', ['category' => 'application-mrbac']); + LogHelper::logMes("Action $code not found."); return; } return $model->delete(); @@ -224,7 +224,7 @@ class ModelService 'condition' => $expressionCondition, ]); if (!$condition->save()) { - LogHelper::logMes("init model condition code $code, name $expressionCondition, model $model->code errors: " . json_encode($model->getErrors()),'', ['category' => 'application-mrbac']); + LogHelper::logMes("init model condition code $code, name $expressionCondition, model $model->code errors: " . json_encode($model->getErrors())); }; return $condition; } @@ -246,7 +246,7 @@ class ModelService 'expression' => $expression, ]); if (!$model->save()) { - LogHelper::logMes("init model expression code $model->code, expression $expression errors: " . json_encode($model->getErrors()),'', ['category' => 'application-mrbac']); + LogHelper::logMes("init model expression code $model->code, expression $expression errors: " . json_encode($model->getErrors())); }; return $model; } @@ -271,7 +271,7 @@ class ModelService 'slug' => $slug, ]); if (!$modelFunction->save()) { - LogHelper::logMes("init model function 'model_id' => $model->id, 'action_id' => $action->id, 'name' => $name errors: " . json_encode($model->getErrors()),'', ['category' => 'application-mrbac']); + LogHelper::logMes("init model function 'model_id' => $model->id, 'action_id' => $action->id, 'name' => $name errors: " . json_encode($model->getErrors())); }; return $modelFunction; } @@ -326,7 +326,7 @@ class ModelService 'model_id' => $model->id, 'condition_id' => $condition->id, 'function_id' => $modelFunction->id, 'model_code' => $model->code, 'condition' => $condition->condition, 'function_code' => $modelFunction->name ]); if (!$obj->save()) { - LogHelper::logMes("init model Function condition 'model_id' => $model->id, 'condition_id' => $condition->id, 'function_id' => $modelFunction->id errors: " . json_encode($obj->getErrors()),'', ['category' => 'application-mrbac']); + LogHelper::logMes("init model Function condition 'model_id' => $model->id, 'condition_id' => $condition->id, 'function_id' => $modelFunction->id errors: " . json_encode($obj->getErrors())); }; return $obj; } diff --git a/workflow/actions/WorkflowRuntimeIndex.php b/workflow/actions/WorkflowRuntimeIndex.php new file mode 100644 index 0000000..4943741 --- /dev/null +++ b/workflow/actions/WorkflowRuntimeIndex.php @@ -0,0 +1,152 @@ +<?php + +namespace lsb\workflow\actions; + +use lsat\microbase\actions\IndexAction; +use lsat\microbase\components\ActiveDataProvider; +use lsb\base\enums\AuthStatusEnum; +use lsb\base\enums\RecordStatusEnum; +use lsb\base\services\AuthorizationService; +use lsb\workflow\models\WorkflowRuntime; +use lsb\workflow\services\WorkflowRuntimeService; +use Yii; +use yii\db\ActiveQuery; +use yii\db\Expression; + +class WorkflowRuntimeIndex extends IndexAction +{ + + public $objectIdAttribute = "id"; + public $objectInstanceCodeAttribute = "instance_code"; + + public $authStatus; + public $recordStatus; + + public $status; + + public $assign; + + /** + * @inheritdoc + */ + protected function prepareDataProvider() + { + $requestParams = Yii::$app->getRequest()->getBodyParams(); + if (empty($requestParams)) { + $requestParams = Yii::$app->getRequest()->getQueryParams(); + } + if ($this->prepareFilter !== null) { + $requestParams = call_user_func($this->prepareFilter, $requestParams); + } + $filter = null; + if ($this->dataFilter !== null) { + $this->dataFilter = Yii::createObject($this->dataFilter); + if ($this->dataFilter->load($requestParams)) { + $filter = $this->dataFilter->build(); + if ($filter === false) { + return $this->dataFilter; + } + } + } + + if ($this->prepareDataProvider !== null) { + return call_user_func($this->prepareDataProvider, $this, $filter); + } + + /* @var $modelClass \yii\db\BaseActiveRecord */ + $modelClass = $this->modelClass; + + $query = $modelClass::find(); + if (!empty($filter)) { + $query->andWhere($filter); + } + if (is_callable($this->prepareSearchQuery)) { + $query = call_user_func($this->prepareSearchQuery, $query, $requestParams); + } else { + $query = $this->prepareSearchQuery($query, $requestParams); + } + $pagination = [ + 'params' => $requestParams, + ]; + if (isset($requestParams['page']) && $requestParams['page'] == -1) { + $pagination = false; + } + return Yii::createObject([ + 'class' => ActiveDataProvider::className(), + 'query' => $query, + 'pagination' => $pagination, + 'sort' => [ + 'params' => $requestParams, + ], + ]); + } + + public function prepareSearchQuery(ActiveQuery $query, $requestParams): callable + { + $fields = ($this->modelClass)::getKeywordFields(); + $query = $query->alias('m'); + + $runtimeQuery = WorkflowRuntime::find() + ->select([ + 'w.object_id' + ])->alias('w'); + + $runtimeQuery->filterWhere([ + 'w.assign' => AuthorizationService::getUserCode(), + 'w.auth_status' => AuthStatusEnum::AUTH_STATUS_PROCESSING->value, + 'w.record_status' => RecordStatusEnum::TYPE_RECORD_STATUS_OPEN->value, + 'w.status' => 1, + 'w.object_type' => $this->modelClass, + ]) + ->andWhere(new Expression("w.object_id = m.{$this->objectIdAttribute}")) + ->andWhere(new Expression("w.instance_code = m.{$this->objectInstanceCodeAttribute}")); + $subquery = $runtimeQuery->createCommand()->rawSql; + + $query->andWhere("EXISTS ($subquery)"); + if (!$fields || empty($requestParams['keywords'])) { + return $query; + } + + if ($this->enableFulltextSearch) { + $keywordArr = explode(" ", $requestParams['keywords']); + return $query->andWhere($this->fulltextSearchField . " @@ to_tsquery(:keywords)", [ + ":keywords" => "'" . implode("'|'", $keywordArr) . "'" + ]); + } + + $queryArr = ['or']; + foreach ($fields as $field) { + $queryArr[] = ['like', $field, $requestParams['keywords']]; + } + return $query->andFilterWhere($queryArr); + } + + public function prepareFilter($requestParams): callable + { + $newRequestParams = $requestParams; + if (isset($requestParams['filter'])) { + foreach ($requestParams['filter'] as $key => $value) { + if (isset($value['ins'])) { + $valueFilter = explode(',', $value['ins']); + if (is_array($valueFilter)) { + foreach ($valueFilter as $item) { + $newRequestParams['filter'][$key]['in'][] = $item; + } + } + unset($newRequestParams['filter'][$key]['ins']); + } + if (isset($value['nins'])) { + $valueFilter = explode(',', $value['nins']); + if (is_array($valueFilter)) { + foreach ($valueFilter as $item) { + $newRequestParams['filter'][$key]['nin'][] = $item; + } + } + unset($newRequestParams['filter'][$key]['nins']); + } + } + } + + return $newRequestParams; + } +} diff --git a/workflow/behaviors/InitWorkflowChangeBehavior.php b/workflow/behaviors/InitWorkflowChangeBehavior.php index a6a1f88..82d386c 100644 --- a/workflow/behaviors/InitWorkflowChangeBehavior.php +++ b/workflow/behaviors/InitWorkflowChangeBehavior.php @@ -1,9 +1,9 @@ <?php namespace lsb\workflow\behaviors; -use lsb\base\helper\LogHelper; -use lsb\base\services\AuthorizationService; +use app\components\LogHelper; +use app\services\AuthorizationService; use lsb\workflow\models\Workflow; use lsb\workflow\services\WorkflowConfigService; use lsb\workflow\services\WorkflowService; @@ -42,7 +42,6 @@ class InitWorkflowChangeBehavior extends Behavior public $workflow_ref_code; public $workflow_version = 1; public $instance_code = null; - public $silent_error = false; /** * @var string @@ -51,6 +50,7 @@ class InitWorkflowChangeBehavior extends Behavior public $workflow_module = 'workflow'; public $callback = null; + public $silent_error = false; /** * Attach events to monitor attribute changes @@ -92,9 +92,10 @@ class InitWorkflowChangeBehavior extends Behavior } } catch (\Exception $e) { LogHelper::explainException($e); - if (!$this->silent_error) { + if ($this->silent_error) { throw $e; } } + } -} \ No newline at end of file +} diff --git a/workflow/command/WorkflowController.php b/workflow/command/WorkflowController.php new file mode 100644 index 0000000..3795aa1 --- /dev/null +++ b/workflow/command/WorkflowController.php @@ -0,0 +1,26 @@ +<?php + +namespace lsb\workflow\command; + +use app\components\LogHelper; +use lsat\microbase\models\User; +use lsb\workflow\services\WorkflowConfigService; +use yii\console\Controller; + +class WorkflowController extends Controller +{ + public function actionInit($workflowCode, $refCode, $tenantCode = 'SPVB') + { + \Yii::$app->user->setIdentity(new User([ + 'tenantCode' => $tenantCode, + ])); + $workflowCurrentCode = WorkflowConfigService::getWorkflowCode($refCode); + switch ($workflowCode) { + case $workflowCurrentCode: + LogHelper::logMes("Workflow $workflowCode - $refCode has been inited"); + return; + default: + WorkflowConfigService::createOrMapping($workflowCode, $refCode); + } + } +} diff --git a/workflow/services/WorkflowConfigService.php b/workflow/services/WorkflowConfigService.php index 381d032..91d5025 100644 --- a/workflow/services/WorkflowConfigService.php +++ b/workflow/services/WorkflowConfigService.php @@ -35,7 +35,7 @@ class WorkflowConfigService if (!$workflowConfig) { $workflowConfig = new WorkflowConfig(['workflow_code' => $workflowCode]); if (!$workflowConfig->save()) { - LogHelper::logMes("save WorkflowConfig errors: " . json_encode($workflowConfig->errors),'', ['category' => 'application-worlflow']); + LogHelper::logMes("save WorkflowConfig errors: " . json_encode($workflowConfig->errors)); $transaction->rollBack(); return; } @@ -44,7 +44,7 @@ class WorkflowConfigService $workflowConfigReference = new WorkflowConfigReference(['workflow_config_id' => $workflowConfig->id, 'ref_code' => $refCode]); if (!$workflowConfigReference->save()) { - LogHelper::logMes("save WorkflowConfigReference errors: " . json_encode($workflowConfigReference->errors),'', ['category' => 'application-worlflow']); + LogHelper::logMes("save WorkflowConfigReference errors: " . json_encode($workflowConfigReference->errors)); $transaction->rollBack(); return; } diff --git a/workflow/services/WorkflowRuntimeService.php b/workflow/services/WorkflowRuntimeService.php index 02feed3..c3e369d 100644 --- a/workflow/services/WorkflowRuntimeService.php +++ b/workflow/services/WorkflowRuntimeService.php @@ -2,7 +2,10 @@ namespace lsb\workflow\services; +use app\models\tstb\Transaction; +use app\services\AuthorizationService; use lsb\base\enums\AuthStatusEnum; +use lsb\base\enums\RecordStatusEnum; use lsb\workflow\models\Workflow; use lsb\workflow\models\WorkflowRuntime; use yii\web\NotFoundHttpException; @@ -37,6 +40,7 @@ class WorkflowRuntimeService { return WorkflowRuntime::findOne(['runtime_id' => $runtimeId, 'object_type' => $objectType]); } + public static function cleanWorkflowRuntime($objectId, $objectType) { return WorkflowRuntime::deleteAll(['object_id' => $objectId, 'object_type' => $objectType]); @@ -46,7 +50,7 @@ class WorkflowRuntimeService { $runtime = WorkflowRuntimeService::getRuntimeByUserCode($instanceCode, $userCode, $objectId, $objectType); if (!$runtime) { - throw new NotFoundHttpException("self handle runtume not found: $instanceCode, $userCode, $objectId, $objectType "); + throw new NotFoundHttpException("self handle runtime not found: $instanceCode, $userCode, $objectId, $objectType "); } $results = WorkflowService::getAllowActions($workflow, $runtime->runtime_id, $params, $token); if (!$results['status']) { @@ -54,10 +58,24 @@ class WorkflowRuntimeService } $action = array_shift($results['data']); - $result = WorkflowService::executeAction($workflow, $runtime->runtime_id, $action['code'], $message, $token); + $result = WorkflowService::executeAction($workflow, $runtime->runtime_id, $action['code'], $message, $token); WorkflowService::saveRuntime($workflow, $instanceCode, $workflowCode, $objectId, $objectType, $token); - if($callback && $callback instanceof \Closure){ + if ($callback && $callback instanceof \Closure) { call_user_func_array($callback, ['result' => $result, 'runtime' => $runtime]); } } -} \ No newline at end of file + + public static function getPendingWorkflowRuntime($objectId, $instanceCode, $userCode, $objectType) + { + return WorkflowRuntime::find()->where([ + 'object_id' => $objectId, + 'instance_code' => $instanceCode, + 'assign' => $userCode, + 'auth_status' => AuthStatusEnum::AUTH_STATUS_PROCESSING, + 'status' => 1, + 'record_status' => RecordStatusEnum::TYPE_RECORD_STATUS_OPEN + ])->andFilterWhere([ + 'object_type' => $objectType, + ]); + } +} diff --git a/workflow/services/WorkflowService.php b/workflow/services/WorkflowService.php index 2770034..39b1f97 100644 --- a/workflow/services/WorkflowService.php +++ b/workflow/services/WorkflowService.php @@ -21,7 +21,7 @@ class WorkflowService { public static function createWorkflow(Workflow $workflow, $instanceCode, $workflowCode, $token) { - LogHelper::logMes("createWorkflow: $workflowCode - $instanceCode ",'', ['category' => 'application-worlflow']); + LogHelper::logMes("createWorkflow: $workflowCode - $instanceCode "); $result = self::getBaseService($workflow->baseUrl) ->addAuthenticator(new HttpBearer($token)) ->post(ApiEndpoint::WORKFLOW_API->getEndPoint('/', 'create-workflow-runtime'), [ @@ -36,7 +36,7 @@ class WorkflowService public static function startWorkflow(Workflow $workflow, $instanceCode, $token, $version = 1) { - LogHelper::logMes("startWorkflow: $instanceCode",'', ['category' => 'application-worlflow']); + LogHelper::logMes("startWorkflow: $instanceCode"); $result = self::getBaseService($workflow->baseUrl) ->addAuthenticator(new HttpBearer($token)) ->post(ApiEndpoint::WORKFLOW_API->getEndPoint('/', 'approve-workflow-runtime'), [ @@ -45,13 +45,13 @@ class WorkflowService ]); $result = json_decode($result->getContents(), true); - LogHelper::logMes("startWorkflow: $instanceCode" . json_encode($result),'', ['category' => 'application-worlflow']); + LogHelper::logMes("startWorkflow: $instanceCode" . json_encode($result)); return $result; } public static function getRuntimes(Workflow $workflow, $instanceCode, $workflowCode, $token) { - LogHelper::logMes("getRuntimes: $instanceCode - $workflowCode ",'', ['category' => 'application-worlflow']); + LogHelper::logMes("getRuntimes: $instanceCode - $workflowCode "); $result = self::getBaseService($workflow->baseUrl) ->addAuthenticator(new HttpBearer($token)) ->post(ApiEndpoint::WORKFLOW_API->getEndPoint('/', 'wf-engine-runtime-version'), [ @@ -60,13 +60,13 @@ class WorkflowService ]); $result = json_decode($result->getContents(), true); - LogHelper::logMes("getRuntimes: $instanceCode - $workflowCode " . json_encode($result),'', ['category' => 'application-worlflow']); + LogHelper::logMes("getRuntimes: $instanceCode - $workflowCode " . json_encode($result)); return $result; } public static function getAllowActions(Workflow $workflow, $runtimeId, $params, $token) { - LogHelper::logMes("getAllowActions: $runtimeId ",'', ['category' => 'application-worlflow']); + LogHelper::logMes("getAllowActions: $runtimeId "); $result = self::getBaseService($workflow->baseUrl) ->addAuthenticator(new HttpBearer($token)) ->post(ApiEndpoint::WORKFLOW_API->getEndPoint('/', 'wf-engine-get-allowed-actions'), [ @@ -75,22 +75,23 @@ class WorkflowService ]); $result = json_decode($result->getContents(), true); - LogHelper::logMes("getAllowActions: $runtimeId" . json_encode($result),'', ['category' => 'application-worlflow']); + LogHelper::logMes("getAllowActions: $runtimeId" . json_encode($result)); return $result; } - public static function executeAction(Workflow $workflow, $runtimeId, $codeAction, $description, $token) + public static function executeAction(Workflow $workflow, $runtimeId, $codeAction, $description, $token, $extend = []) { - LogHelper::logMes("executeAction: $runtimeId - $codeAction - $description ", $runtimeId, ['category' => 'application-worlflow']); + LogHelper::logMes("executeAction: $runtimeId - $codeAction - $description ", $runtimeId); $result = self::getBaseService($workflow->baseUrl) ->addAuthenticator(new HttpBearer($token)) ->post(ApiEndpoint::WORKFLOW_API->getEndPoint('/', 'execute-action'), [ 'runtimeID' => $runtimeId, 'codeAction' => $codeAction, 'description' => $description, + "extent" => $extend ]); $result = json_decode($result->getContents(), true); - LogHelper::logMes("executeAction: $runtimeId - $codeAction - $description " . json_encode($result), $runtimeId, ['category' => 'application-worlflow']); + LogHelper::logMes("executeAction: $runtimeId - $codeAction - $description " . json_encode($result), $runtimeId); return $result; } @@ -108,8 +109,8 @@ class WorkflowService $runtimes = $runtimes['data'] ?? []; $versions = array_keys($runtimes); foreach ($versions as $version) { - $runtime_versions = $runtimes[$version] ?? []; - if(empty($runtime_versions) || !is_integer($runtime_versions)){ + $runtime_versions = $runtimes[$version]; + if(empty($runtime_versions)){ LogHelper::logMes("errors: no runtime version found" ,'', ['category' => 'application-worlflow']); continue; } @@ -150,7 +151,7 @@ class WorkflowService ]); $workflow_runtime->detachBehaviors(); if (!$workflow_runtime->save()) { - LogHelper::logMes("errors: " . json_encode($workflow_runtime->getErrors()),'', ['category' => 'application-worlflow']); + LogHelper::logMes("errors: " . json_encode($workflow_runtime->getErrors())); } } } @@ -191,5 +192,4 @@ class WorkflowService } return BaseService::getInstance($url, $auth, ContentType::CONTENT_TYPE_APPLICATION_JSON); } - -} \ No newline at end of file +} diff --git a/workflow/traits/WorkflowRuntimeTrait.php b/workflow/traits/WorkflowRuntimeTrait.php new file mode 100644 index 0000000..e9d447c --- /dev/null +++ b/workflow/traits/WorkflowRuntimeTrait.php @@ -0,0 +1,14 @@ +<?php + +namespace lsb\workflow\traits; + +use lsb\base\services\AuthorizationService; +use lsb\workflow\services\WorkflowRuntimeService; + +trait WorkflowRuntimeTrait +{ + public function getWorkflowRuntime() + { + return WorkflowRuntimeService::getPendingWorkflowRuntime($this->id, $this->instance_code, AuthorizationService::getUserCode(), get_class($this)); + } +} -- GitLab