<?php
namespace CorporateTrainingBundle\Handler;
use AppBundle\Common\ArrayToolkit;
use Biz\User\CurrentUser;
use Biz\User\Dao\UserProfileDao;
use CorporateTrainingBundle\Biz\Post\Service\PostService;
use CorporateTrainingBundle\Component\EIMClient\DepartmentFactory;
use CorporateTrainingBundle\Component\EIMClient\UserFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class LoginSyncDepartmentHandler
{
/**
* @var ContainerInterface
*/
private $container;
/**
* @var Biz
*/
private $biz;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->biz = $this->container->get('biz');
}
/**
* Do the magic.
*/
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$request = $event->getRequest();
$userBind = $this->canSyncUserWithReturnUserBind();
if (empty($userBind)) {
return true;
}
list($user, $departmentIds) = $this->getUserSyncData($userBind);
$this->updateOrg($departmentIds);
$this->updateMobile($user);
$this->updatePost($user);
$this->updateHiredDate($user);
$this->updateAvatar($user);
$this->updateEmail($request, $user);
$this->updateName($user);
}
protected function canSyncUserWithReturnUserBind()
{
$currentUser = $this->biz['user'];
$userBinds = $this->getUserService()->findBindsByUserId($currentUser['id']);
if (empty($userBinds)) {
return [];
}
$syncSetting = $this->getSettingService()->get('sync_department_setting', []);
if (empty($syncSetting) || !$syncSetting['enable']) {
return [];
}
if (!in_array($syncSetting['type'], ['dingtalk', 'work_wechat', 'feishu'])) {
return [];
}
if (empty($syncSetting['autoUnlock'])) {
return [];
}
$userBind = [];
foreach ($userBinds as $userBind) {
if (!in_array($userBind['type'], ['dingtalk', 'work_wechat', 'feishu'])) {
continue;
}
$userBind = $userBind;
}
return $userBind;
}
protected function getUserSyncData($userBind)
{
$syncSetting = $this->getSettingService()->get('sync_department_setting', []);
$userClient = UserFactory::create($syncSetting);
$user = [];
$departmentIds = [];
if ('dingtalk' == $userBind['type']) {
$userId = $userClient->getUserIdByUnionId($userBind['fromId']);
if (!$userId) {
return;
}
$user = $userClient->get($userId);
$departments = [];
$departmentClient = DepartmentFactory::create($syncSetting);
foreach ($user['department'] as $departmentId) {
array_push($departments, $departmentClient->get($departmentId));
}
$departmentIds = ArrayToolkit::column($departments, 'id');
}
if ('work_wechat' == $userBind['type']) {
$user = $userClient->get($userBind['fromId']);
$departmentIds = $user['department'];
}
if ('feishu' == $userBind['type']) {
$user = $userClient->get($userBind['fromId']);
$departmentIds = $user['department_ids'];
}
return [$user, $departmentIds];
}
protected function updateOrg($departmentIds)
{
if (empty($departmentIds)) {
return true;
}
$currentUser = $this->biz['user'];
$orgs = $this->getOrgService()->findOrgsBySyncIds($departmentIds);
if (!empty($orgs)) {
if ($currentUser['orgIds'] != ArrayToolkit::column($orgs, 'id')) {
$this->getUserDao()->update($currentUser['id'], [
'orgIds' => ArrayToolkit::column($orgs, 'id'),
]
);
$this->getUserOrgService()->setUserOrgs($currentUser['id'], $orgs);
}
if ($currentUser['orgCodes'] != ArrayToolkit::column($orgs, 'orgCode')) {
$this->getUserDao()->update($currentUser['id'], [
'orgCodes' => ArrayToolkit::column($orgs, 'orgCode'),
]
);
}
}
}
protected function updatePost($user)
{
$currentUser = $this->biz['user'];
if (!empty($user['position'])) {
$post = $this->getPostService()->getPostByName($user['position']);
if (isset($post)) {
$this->getUserDao()->update($currentUser['id'], [
'postId' => $post['id'],
]);
}
}
}
protected function updateMobile($user)
{
$currentUser = $this->biz['user'];
if (!empty($user['mobile'])) {
$existedMobile = $this->getUserService()->getUserByVerifiedMobile($user['mobile']);
if (!empty($existedMobile) && $existedMobile['id'] != $currentUser['id']) {
$this->getUserDao()->update($existedMobile['id'], ['verifiedMobile' => '']);
$this->getUserProfileDao()->update(['id' => $existedMobile['id']], ['mobile' => '']);
$this->getUserDao()->update($currentUser['id'], ['verifiedMobile' => $user['mobile']]);
$this->getUserProfileDao()->update(['id' => $currentUser['id']], ['mobile' => $user['mobile']]);
}
}
}
protected function updateHiredDate($user)
{
$currentUser = $this->biz['user'];
if (!empty($user['hiredDate'])) {
$this->getUserDao()->update($currentUser['id'], [
'hireDate' => $user['hiredDate'] / 1000,
]);
}
}
protected function updateAvatar($user)
{
$currentUser = $this->biz['user'];
if (isset($user['avatar']) && isset($user['thumb_avatar'])) {
$this->getUserDao()->update($currentUser['id'], [
'smallAvatar' => $user['thumb_avatar'],
'mediumAvatar' => $user['avatar'],
'largeAvatar' => $user['avatar'],
]);
}
}
protected function updateEmail($request, $user)
{
$currentUser = $this->biz['user'];
$user['email'] = isset($user['email']) ? trim($user['email']) : '';
if (!empty($user['email'])) {
$emailIsExist = $this->getUserService()->getUserByEmail($user['email']);
if ($currentUser['email'] != $user['email'] && !$emailIsExist) {
$user = $this->getUserDao()->update($currentUser['id'], [
'email' => $user['email'],
]);
$this->kickUserLogout($currentUser['id']);
$currentUser = new CurrentUser();
$currentUser->fromArray($user);
$this->switchUser($request, $currentUser);
}
}
}
protected function updateName($user)
{
$currentUser = $this->biz['user'];
if (!empty($user['name'])) {
$userProfile = $this->getUserService()->getUserProfile($currentUser['id']);
if ($userProfile['truename'] != $user['name']) {
$this->getUserProfileDao()->update($currentUser['id'], [
'truename' => $user['name'],
]);
}
}
}
protected function kickUserLogout($userId)
{
$this->getSessionService()->clearByUserId($userId);
$tokens = $this->getTokenService()->findTokensByUserIdAndType($userId, 'mobile_login');
if (!empty($tokens)) {
foreach ($tokens as $token) {
$this->getTokenService()->destoryToken($token['token']);
}
}
}
/**
* switch current user.
*
* @param Request $request
*
* @return CurrentUser
*/
protected function switchUser($request, CurrentUser $user)
{
$user['currentIp'] = $request->getClientIp();
$token = new UsernamePasswordToken($user, null, 'main', $user['roles']);
$this->container->get('security.token_storage')->setToken($token);
$biz = $this->biz;
$biz['user'] = $user;
return $user;
}
/**
* @return UserDao
*/
protected function getUserDao()
{
return $this->biz->dao('User:UserDao');
}
/**
* @return UserProfileDao
*/
protected function getUserProfileDao()
{
return $this->biz->dao('User:UserProfileDao');
}
/**
* @return SettingService
*/
protected function getSettingService()
{
return $this->biz->service('System:SettingService');
}
/**
* @return SessionService
*/
protected function getSessionService()
{
return $this->biz->service('System:SessionService');
}
/**
* @return TokenService
*/
protected function getTokenService()
{
return $this->biz->service('User:TokenService');
}
/**
* @return SettingService
*/
protected function getUserService()
{
return $this->biz->service('User:UserService');
}
/**
* @return UserOrgService
*/
protected function getUserOrgService()
{
return $this->biz->service('User:UserOrgService');
}
/**
* @return OrgService
*/
protected function getOrgService()
{
return $this->biz->service('Org:OrgService');
}
/**
* @return PostService
*/
protected function getPostService()
{
return $this->biz->service('CorporateTrainingBundle:Post:PostService');
}
}