em = $em; $this->class = $class; $this->eventDispatcher = $eventDispatcher; $this->userEntityRepo = $this->em->getRepository($this->getClass()); $this->hg = $hg; $this->router = $router; $this->mailer = $mailer; $this->eb = $eb; $this->sm = $sm; $this->ts = $security; $this->net15_user_basis_user_activate_email_tpl = 'UserBasis/Default/Email/validate.email.html.twig'; $this->net15_user_basis_user_two_factor_email_tpl = 'UserBasis/Default/Email/two_factor.email.html.twig'; $this->passwordEncoder = $encoder; } public function getClass(): ?string { if (false !== strpos($this->class, ':')) { $metadata = $this->em->getClassMetadata($this->class); $this->class = $metadata->getName(); } return $this->class; } /** * Return current user or false * * @return bool|CustomUserInterface */ public function getActualUser(){ $u = $this->ts->getToken()->getUser(); if($u instanceof CustomUserInterface) return $u; return false; } /** * @param CustomUserInterface $user * @return bool */ public function quickUpdate(CustomUserInterface $user): bool { if($user === null) return false; try { if(!$this->em->contains($user)){ $r = $this->checkAndValidatePublicKey($user); if($r) $this->em->persist($user); else return false; } $this->em->flush(); } catch (OptimisticLockException $e) { //die('Exception : '.$e->getMessage()); //throw new Exception('Exception : '.$e->getMessage()); return false; } catch (ORMException $e) { return false; } return true; } /** * @param CustomUserInterface $user * @return bool */ public function checkAndValidatePublicKey(CustomUserInterface $user): bool { $attempts = 0; while(true){ $u = $this->getUserByPublicKey($user->getPublicKey()); if(is_null($u)) return true; $user->regeneratePublicKey(); $attempts++; if($attempts >= 20) return false; } return false; } /** * @param CustomUserInterface $user * @return bool */ public function update(CustomUserInterface $user): bool { if($user === null) return false; /* do some shit in here */ return $this->quickUpdate($user); } /** * User this function to register a new user * * @param CustomUserInterface $user * * @return bool * @throws \Exception */ public function registerUser(CustomUserInterface $user): bool { //cancel if user is already registered if(!empty($user->getId())) return false; /* * Dev: * Todo send validation email * */ $user->setConfirmationToken($this->hg->generateHumanHash(32)); $user->setHashIdentifier($this->generateUniqueIdentifier()); $user->setRoles(array($this->net15_user_basis_user_default_role)); $user->setSalt($this->hg->generateHumanHash(10)); $user->setLastLogin(new \DateTime()); $password = $this->passwordEncoder->encodePassword($user, $user->getPassword()); $user->setPassword($password); $r = $this->update($user); if(!$r) return false; $this ->eventDispatcher ->dispatch(UserCreatedEvent::NAME, new UserCreatedEvent($user,$this)); // $this->sendEmail($user); return true; } /** * @param $identifier * @return bool|CustomUserInterface */ public function getUserByIdentifier($identifier){ $repo = $this->userEntityRepo; /** * @var CustomUserInterface|null $user */ $user = $repo->findOneBy(array('hashIdentifier' =>$identifier)); if($user !== null){ return $user; } return false; } /** * @param string $email * @return CustomUserInterface|null */ public function getUserByEmail(string $email): ?CustomUserInterface { $repo = $this->userEntityRepo; /** * @var CustomUserInterface|null $user */ $user = $repo->findOneBy(array('email' =>$email)); if($user !== null){ return $user; } return null; } /** * @param string $str * * @return array|null */ public function getByRole(string $str): ?array { return $this->getByRoles([$str]); } /** * @param array $arr * @param null $name * @return null|CustomUserInterface[] */ public function getByRoles(array $arr, $name = null): ?array { $em = $this->em; $usersRepository = $em->getRepository($this->getClass()); if(is_null($name)) return $usersRepository->findAll();//todo set ROLES as entities many2many $qb = $usersRepository->createQueryBuilder('r'); $qb->setParameter("search", '%'.$name.'%'); $qb->andWhere("r.enabled = 1"); //->andWhere(":search MEMBER OF r.roles") // TODO ROLES $qb->where("r.firstname LIKE :search"); $qb->orWhere("r.middlename LIKE :search"); $qb->orWhere("r.lastname LIKE :search"); $qb->orWhere("r.email LIKE :search"); return $qb->getQuery()->getResult(); } /** * @param null|string $publicKey * @return CustomUserInterface|null */ public function getUserByPublicKey(?string $publicKey): ?CustomUserInterface { $repo = $this->userEntityRepo; /** * @var CustomUserInterface|null $user */ $user = $repo->findOneBy(array('publicKey' =>$publicKey)); if($user !== null){ return $user; } return null; } /** * @param $id * @return bool|CustomUserInterface */ public function getUserById($id){ $repo = $this->userEntityRepo; $user = $repo->findBy(['id' =>$id]); if (!$user instanceof CustomUserInterface) return null; if(!empty($user)){ return $user; } return false; } /** * @param CustomUserInterface $user * * @throws \Exception */ public function refreshLastSeen(CustomUserInterface $user): void { $user->setLastLogin(new \DateTime()); $this->quickUpdate($user); } /** * @param CustomUserInterface $user * @return bool */ public function resendValidation($user): bool { if(!$user instanceof CustomUserInterface) return false; if(!$user->isEnabled() || true == true){ $this->sendEmail($user); return true; } return false; } /** * @param CustomUserInterface $user */ private function sendEmail(CustomUserInterface $user): void { $message = new \Swift_Message(); $title = $this->sm->get('user_activate_email_title','default title'); $activate_url = $this->router->generate($this->sm->get('user_activate_account_route_name','activate_account',true), [], UrlGeneratorInterface::ABSOLUTE_URL) .'?h='.$user->getConfirmationToken().'&a='.$user->getHashIdentifier(); $args = array( 'user' => $user, 'title_email' => $title, 'activate_url' => $activate_url, ); $body = $this->eb->buildEmail('@'.$this->net15_user_basis_user_activate_email_tpl,$args); $message ->setTo(getenv('email_dev')) ->setSubject($title) ->setFrom($this->sm->get('mailing_sender','admin@default.com',true,"validation")) ->setContentType('text/html') ->setBody($body) ; $this->mailer->send($message); } public function sendEmailTwoFactor(CustomUserInterface $user): void { $message = new \Swift_Message(); $user->generateTwoFactorEmailCode(); $this->quickUpdate($user); $title = $this->sm->get('user_two_factor_email_title','Two factor authentication'); $args = array( 'user' => $user, 'title_email' => $title ); $body = $this->eb->buildEmail('@'.$this->net15_user_basis_user_two_factor_email_tpl,$args); $message ->setTo($user->getEmail()) ->setSubject($title) ->setFrom($this->sm->get('mailing_sender','admin@default.com',true,"validation")) ->setContentType('text/html') ->setBody($body) ; $this->mailer->send($message); } /** * @param $identifier * @return bool return TRUE if $identifier is UNIQUE, FALSE otherwise */ private function isIdentifierUnique($identifier): bool { $listUsers = $this->findByHashIdentifier($identifier); if(!empty($listUsers)){ return false; } return true; } /** * @param $identifier * * @return bool */ public function findByHashIdentifier($identifier): bool { if($identifier === '0' || $identifier === 0) return false; $repo = $this->userEntityRepo; $listUsers = $repo->findBy(array('hashIdentifier'=>$identifier)); /** * @var CustomUserInterface $user */ foreach ($listUsers as $user) { if($user->getHashIdentifier() !== 0){ $user->getHashIdentifier(); return true; } } return false; } /** * @return mixed|string */ private function generateUniqueIdentifier(){ $loop = true; $identifier = ''; while($loop){ $identifier = $this->hg->generateHumanHash(64); if($this->isIdentifierUnique($identifier)){ $loop = false; } } return $identifier; } //DEVICE MANAGER /** * @param CustomUserInterface $user * @return array|bool return array if there's nothing or if user isn't valid */ public function getDevices(CustomUserInterface $user){ $array = array(); if($user === null) return false; $infos = $user->getAuthorizedIps(); foreach($infos as $row){ if(is_array($row)) $array[] = $row; } return $array; } /** * @param CustomUserInterface $user * @param $ip * @param $computer * @return bool */ public function deleteDevice(CustomUserInterface $user, $ip, $computer): bool { if($user === null) return false; //iterate $infos = $user->getAuthorizedIps(); foreach($infos as $key=>$row){ if(is_array($row) && isset($row['ip']) && $row['ip'] === $ip && isset($row['computer']) && $row['computer'] === $computer){ unset($infos[$key]); $user->setAuthorizedIps($infos); $this->quickUpdate($user); return true; } } return false; } //SECURITY MANAGER /** * @param CustomUserInterface $user * @param $var * @return bool|mixed * @throws FatalErrorException */ public function getValue(CustomUserInterface $user, $var){ if(null === $user) return false; if(method_exists($this,'get'.$var)) { $frmla = 'get'.$var; return $this->$frmla($user); } else { throw new FatalErrorException('Attribute not found'); } } /** * @param CustomUserInterface $user * @param $var * @param $value * @return bool * @throws FatalErrorException */ public function setValue(CustomUserInterface $user, $var, $value): ?bool { if(null === $user) return false; if(method_exists($this,'set'.$var)) { $frmla = 'set'.$var; $vl = $this->$frmla($user, $value); $this->quickUpdate($user); return $vl; } throw new FatalErrorException('Attribute not found'); } /** * @param CustomUserInterface $user * @return bool */ protected function getTwoFactorAuth(CustomUserInterface $user): bool { return $user->isTwoFactorEmailAuthentication(); } /** * @param CustomUserInterface $user * @param $value * @return bool */ protected function setTwoFactorAuth(CustomUserInterface $user, $value): bool { $user->setTwoFactorEmailAuthentication((bool)$value); return true; } /** * @param CustomUserInterface $user * @return bool */ protected function getNeverRememberPlaces(CustomUserInterface $user): bool { return $user->isRememberPlaces(); } /** * @param CustomUserInterface $user * @param $value * @return bool */ protected function setNeverRememberPlaces(CustomUserInterface $user, $value): bool { $user->setRememberPlaces((bool)$value); return true; } /** * @param CustomUserInterface $user * @return bool */ protected function getLogMeAuth(CustomUserInterface $user): bool { return $user->isLogMe(); } /** * @param CustomUserInterface $user * @param $value * @return bool */ protected function setLogMeAuth(CustomUserInterface $user, $value): bool { $user->setLogMe((bool)$value); return true; } //VALIDATE USER /** * validate user if valid parameters * * @param $identifier * @param $hash * @return bool TRUE on valid user FALSE otherwise */ public function tryValidate($identifier, $hash): bool { if($identifier === '0' || $identifier === 0) return false; $repo = $this->userEntityRepo; $listUsers = $repo->findBy(array('hashIdentifier'=>$identifier)); /** * @var CustomUserInterface $user */ foreach ($listUsers as $user) { if($user->getConfirmationToken() === $hash && !$user->isEnabled()){ $user->setEnabled(true); $user->setHashIdentifier('0'); $this->quickUpdate($user); return true; } } return false; } /** * Resend validation email from an identifier * * @param $identifier * @return bool */ public function resendValidationFromIdentifier($identifier): bool { $user = $this->getUserByIdentifier($identifier); if($user instanceof CustomUserInterface) return $this->resendValidation($user); return false; } }