Fixes #6499 telehealth patient api update (#6501)
[openemr.git] / interface / modules / custom_modules / oe-module-comlink-telehealth / src / Controller / TeleHealthVideoRegistrationController.php
blobe1561e51fd915e715be98da2047470deba6dbda0
1 <?php
3 /**
4 * Communicates with the Comlink User provisioning api.
6 * TODO: @adunsulag look at having this class utilize TeleHealthProvisioningService as there is a bit of
7 * duplication there.
9 * @package openemr
10 * @link http://www.open-emr.org
11 * @author Stephen Nielson <snielson@discoverandchange.com>
12 * @copyright Copyright (c) 2022 Comlink Inc <https://comlinkinc.com/>
13 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 namespace Comlink\OpenEMR\Modules\TeleHealthModule\Controller;
18 use Comlink\OpenEMR\Modules\TeleHealthModule\Models\UserVideoRegistrationRequest;
19 use Comlink\OpenEMR\Modules\TeleHealthModule\Repository\TeleHealthPersonSettingsRepository;
20 use Comlink\OpenEMR\Modules\TeleHealthModule\Repository\TeleHealthProviderRepository;
21 use Comlink\OpenEMR\Modules\TeleHealthModule\Repository\TeleHealthUserRepository;
22 use Comlink\OpenEMR\Modules\TeleHealthModule\Services\TelehealthRegistrationCodeService;
23 use Comlink\OpenEMR\Modules\TeleHealthModule\Services\TeleHealthRemoteRegistrationService;
24 use GuzzleHttp\Client;
25 use GuzzleHttp\Exception\GuzzleException;
26 use OpenEMR\Common\Database\SqlQueryException;
27 use OpenEMR\Common\Logging\SystemLogger;
28 use OpenEMR\Common\Uuid\UuidRegistry;
29 use OpenEMR\Events\Patient\PatientCreatedEvent;
30 use OpenEMR\Events\Patient\PatientUpdatedEvent;
31 use OpenEMR\Events\User\UserCreatedEvent;
32 use OpenEMR\Events\User\UserUpdatedEvent;
33 use OpenEMR\Services\PatientService;
34 use OpenEMR\Services\UserService;
35 use Symfony\Component\EventDispatcher\EventDispatcher;
36 use Exception;
38 class TeleHealthVideoRegistrationController
40 /**
41 * Repository for saving / retrieving telehealth user settings.
42 * @var TeleHealthUserRepository
44 private $userRepository;
47 /**
48 * @var SystemLogger
50 private $logger;
52 /**
53 * @var TeleHealthProviderRepository
55 private $providerRepository;
58 /**
59 * @var TeleHealthRemoteRegistrationService
61 private $remoteService;
63 public function __construct(TeleHealthRemoteRegistrationService $remoteService, TeleHealthProviderRepository $repo)
65 // $this->userRepository = new TeleHealthUserRepository();
66 $this->remoteService = $remoteService;
67 $this->providerRepository = $repo;
68 $this->logger = new SystemLogger();
71 public function subscribeToEvents(EventDispatcher $eventDispatcher)
73 $eventDispatcher->addListener(PatientCreatedEvent::EVENT_HANDLE, [$this, 'onPatientCreatedEvent']);
74 $eventDispatcher->addListener(PatientUpdatedEvent::EVENT_HANDLE, [$this, 'onPatientUpdatedEvent']);
75 $eventDispatcher->addListener(UserCreatedEvent::EVENT_HANDLE, [$this, 'onUserCreatedEvent']);
76 $eventDispatcher->addListener(UserUpdatedEvent::EVENT_HANDLE, [$this, 'onUserUpdatedEvent']);
79 public function getUserRepository()
81 if (!isset($this->userRepository)) {
82 $this->userRepository = new TeleHealthUserRepository();
84 return $this->userRepository;
87 public function onPatientCreatedEvent(PatientCreatedEvent $event)
89 $patient = $event->getPatientData();
90 $this->logger->debug(
91 self::class . "->onPatientCreatedEvent received for patient ",
92 ['uuid' => $patient['uuid'] ?? null, 'patient' => $patient]
94 try {
95 $patient['uuid'] = UuidRegistry::uuidToString($patient['uuid']); // convert uuid to a string value
96 $this->createPatientRegistration($patient);
97 } catch (Exception $exception) {
98 $this->logger->errorLogCaller("Failed to create patient registration. Error: "
99 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'patient' => $patient['uuid']]);
103 public function onPatientUpdatedEvent(PatientUpdatedEvent $event)
105 try {
106 $patient = $event->getNewPatientData();
107 $oldPatient = $event->getDataBeforeUpdate();
108 // we need the patient uuid so we are going to grab it from the pid
109 $patientService = new PatientService();
110 $patient['uuid'] = UuidRegistry::uuidToString($oldPatient['uuid']); // convert uuid to a string value
111 $this->logger->debug(
112 self::class . "->onPatientUpdatedEvent received for patient ",
113 ['uuid' => $patient['uuid'] ?? null, 'patient' => $patient]
115 // let's grab the patient data and create the patient if its not registered
116 $apiUser = $this->getUserRepository()->getUser($patient['uuid']);
117 if (empty($apiUser)) {
118 $this->createPatientRegistration($patient);
120 } catch (Exception $exception) {
121 $this->logger->errorLogCaller("Failed to create patient registration. Error: "
122 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'patient' => $patient['uuid'] ?? '']);
126 public function onUserCreatedEvent(UserCreatedEvent $event)
128 try {
129 $user = $event->getUserData();
130 $userService = new UserService();
131 // our event doesn't have the uuid which is what we need
132 $userWithUuid = $userService->getUserByUsername($event->getUsername());
133 if (empty($userWithUuid)) {
134 throw new \InvalidArgumentException("Could not find user with username " . $event->getUsername());
137 // we need to find out if we
138 $providerRepo = $this->providerRepository;
139 // find out if the provider is enabled, if so we create the registration
140 $this->logger->debug(
141 self::class . "->onUserCreatedEvent received for user ",
142 ['username' => $event->getUsername(), 'userWithUuid' => $userWithUuid, 'uuid' => $userWithUuid['uuid'] ?? null]
144 if ($providerRepo->isEnabledProvider($userWithUuid['id'])) {
145 $this->createUserRegistration($userWithUuid);
146 } else {
147 $this->logger->debug(
148 self::class . "->onUserCreatedEvent skipping registration as user is not enrolled",
149 ['username' => $event->getUsername(), 'userWithUuid' => $userWithUuid, 'uuid' => $userWithUuid['uuid'] ?? null]
152 } catch (Exception $exception) {
153 $this->logger->errorLogCaller("Failed to create user registration. Error: "
154 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'user' => $user['uuid']]);
158 public function onUserUpdatedEvent(UserUpdatedEvent $event)
160 try {
161 $user = $event->getNewUserData();
162 $userService = new UserService();
163 // our event doesn't have the uuid which is what we need
164 $userWithUuid = $userService->getUser($event->getUserId());
165 if (empty($userWithUuid)) {
166 throw new \InvalidArgumentException("Could not find user with username " . $event->getUsername());
168 $this->logger->debug(self::class . "->onUserUpdatedEvent received for user ", ['uuid' => $userWithUuid['uuid'] ?? null]);
170 $providerRepo = $this->providerRepository;
172 // create the registration
173 $apiUser = $this->getUserRepository()->getUser($userWithUuid['uuid']);
175 if ($providerRepo->isEnabledProvider($userWithUuid['id'])) {
176 // create our registration if there is one
177 if (empty($apiUser)) {
178 $this->logger->debug(self::class . "->onUserUpdatedEvent registering user with comlink", ['uuid' => $userWithUuid['uuid'] ?? null]);
179 $this->createUserRegistration($userWithUuid);
180 } else {
181 if (!$apiUser->getIsActive()) {
182 $this->logger->debug(
183 self::class . "->onUserUpdatedEvent user auth record is suspended, activating",
184 ['uuid' => $userWithUuid['uuid'] ?? null]
186 // we need to activate the user
187 $this->resumeUser($apiUser->getUsername(), $apiUser->getAuthToken());
188 } else {
189 $this->logger->debug(
190 self::class . "->onUserUpdatedEvent user auth record is already active",
191 ['uuid' => $userWithUuid['uuid'] ?? null]
193 // TODO: if we ever want to update the password registration here we can do that here
194 // since we don't change the username and its a randomly generated password, there's no need to change
195 // the password.
198 } else {
199 // we need to find out if a registration exists... if it does we need to deactivate it
200 if (empty($apiUser)) {
201 $this->logger->debug(
202 self::class . "->onUserUpdatedEvent telehealth disabled and no auth record exists",
203 ['uuid' => $userWithUuid['uuid'] ?? null]
205 // we do nothing here if the provider is not enabled and there's no auth we just ignore this
206 } else if ($apiUser->getIsActive()) {
207 $this->logger->debug(
208 self::class . "->onUserUpdatedEvent telehealth is disabled but registration is active. suspending user",
209 ['uuid' => $userWithUuid['uuid'] ?? null]
211 $this->suspendUser($apiUser->getUsername(), $apiUser->getAuthToken());
214 } catch (Exception $exception) {
215 $this->logger->errorLogCaller("Failed to create user registration. Error: "
216 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'user' => $user]);
220 public function verifyProvisioningServiceIsValid()
222 return $this->remoteService->verifyProvisioningServiceIsValid();
225 public function createPatientRegistration($patient)
227 return $this->remoteService->createPatientRegistration($patient);
230 public function createUserRegistration($user)
232 return $this->remoteService->createUserRegistration($user);
236 * Allows the user repository to be set for testing or extension purposes
237 * @param TeleHealthUserRepository $userRepository
239 public function setTelehealthUserRepository(TeleHealthUserRepository $userRepository)
241 // TODO: @adunsulag refactor unit tests so we don't have this layer of indirections since this is only used in unit tests right now
242 $this->remoteService->setTelehealthUserRepository($userRepository);
246 * Returns if a registration should be created for the given provider id. This does not answer whether a registration
247 * exists, but whether the user passes the criteria for creating a registration record regardless of whether it exists or not.
248 * @param $providerId
249 * @return bool
251 public function shouldCreateRegistrationForProvider($providerId)
253 return $this->providerRepository->isEnabledProvider($providerId);
257 * Provisions a new user with the Comlink video api system
258 * @param UserVideoRegistrationRequest $request
259 * @return false|int returns false if the user fails to add, otherwise returns the integer id of the provisioned user
261 public function addNewUser(UserVideoRegistrationRequest $request)
263 return $this->remoteService->addNewUser($request);
267 * Updates an existing provisioned user with the Comlink video api system. Everything but username can be changed
268 * @param UserVideoRegistrationRequest $request
269 * @return false|int returns false if the user fails to update, otherwise returns the integer id of the updated user
271 public function updateUser(UserVideoRegistrationRequest $request)
273 return $this->remoteService->updateUserFromRequest($request);
276 public function suspendUser(string $username, string $password): bool
278 return $this->remoteService->suspendUser($username, $password);
281 public function resumeUser(string $username, string $password): bool
283 return $this->remoteService->resumeUser($username, $password);
286 public function deactivateUser(string $username, string $password)
288 return $this->remoteService->deactivateUser($username, $password);