Fixes #5877 Comlink Telehealth Module (#5878)
[openemr.git] / interface / modules / custom_modules / oe-module-comlink-telehealth / src / Controller / TeleHealthVideoRegistrationController.php
blob86aa39a5c19c90f8a79f7bed9f55bfb8b2b40285
1 <?php
3 /**
4 * Communicates with the Comlink User provisioning api.
6 * @package openemr
7 * @link http://www.open-emr.org
8 * @author Stephen Nielson <snielson@discoverandchange.com>
9 * @copyright Copyright (c) 2022 Comlink Inc <https://comlinkinc.com/>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 namespace Comlink\OpenEMR\Modules\TeleHealthModule\Controller;
15 use Comlink\OpenEMR\Modules\TeleHealthModule\Models\UserVideoRegistrationRequest;
16 use Comlink\OpenEMR\Modules\TeleHealthModule\Repository\TeleHealthPersonSettingsRepository;
17 use Comlink\OpenEMR\Modules\TeleHealthModule\Repository\TeleHealthProviderRepository;
18 use Comlink\OpenEMR\Modules\TeleHealthModule\Repository\TeleHealthUserRepository;
19 use Comlink\OpenEMR\Modules\TeleHealthModule\Services\TelehealthRegistrationCodeService;
20 use Comlink\OpenEMR\Modules\TeleHealthModule\Services\TeleHealthRemoteRegistrationService;
21 use GuzzleHttp\Client;
22 use GuzzleHttp\Exception\GuzzleException;
23 use OpenEMR\Common\Database\SqlQueryException;
24 use OpenEMR\Common\Logging\SystemLogger;
25 use OpenEMR\Common\Uuid\UuidRegistry;
26 use OpenEMR\Events\Patient\PatientCreatedEvent;
27 use OpenEMR\Events\Patient\PatientUpdatedEvent;
28 use OpenEMR\Events\User\UserCreatedEvent;
29 use OpenEMR\Events\User\UserUpdatedEvent;
30 use OpenEMR\Services\PatientService;
31 use OpenEMR\Services\UserService;
32 use Symfony\Component\EventDispatcher\EventDispatcher;
33 use Exception;
35 class TeleHealthVideoRegistrationController
37 /**
38 * Repository for saving / retrieving telehealth user settings.
39 * @var TeleHealthUserRepository
41 private $userRepository;
44 /**
45 * @var SystemLogger
47 private $logger;
49 /**
50 * @var TeleHealthProviderRepository
52 private $providerRepository;
55 /**
56 * @var TeleHealthRemoteRegistrationService
58 private $remoteService;
60 public function __construct(TeleHealthRemoteRegistrationService $remoteService, TeleHealthProviderRepository $repo)
62 $this->userRepository = new TeleHealthUserRepository();
63 $this->remoteService = $remoteService;
64 $this->providerRepository = $repo;
65 $this->logger = new SystemLogger();
68 public function subscribeToEvents(EventDispatcher $eventDispatcher)
70 $eventDispatcher->addListener(PatientCreatedEvent::EVENT_HANDLE, [$this, 'onPatientCreatedEvent']);
71 $eventDispatcher->addListener(PatientUpdatedEvent::EVENT_HANDLE, [$this, 'onPatientUpdatedEvent']);
72 $eventDispatcher->addListener(UserCreatedEvent::EVENT_HANDLE, [$this, 'onUserCreatedEvent']);
73 $eventDispatcher->addListener(UserUpdatedEvent::EVENT_HANDLE, [$this, 'onUserUpdatedEvent']);
76 public function onPatientCreatedEvent(PatientCreatedEvent $event)
78 $patient = $event->getPatientData();
79 $this->logger->debug(
80 self::class . "->onPatientCreatedEvent received for patient ",
81 ['uuid' => $patient['uuid'] ?? null, 'patient' => $patient]
83 try {
84 $patient['uuid'] = UuidRegistry::uuidToString($patient['uuid']); // convert uuid to a string value
85 $this->createPatientRegistration($patient);
86 } catch (Exception $exception) {
87 $this->logger->errorLogCaller("Failed to create patient registration. Error: "
88 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'patient' => $patient['uuid']]);
92 public function onPatientUpdatedEvent(PatientUpdatedEvent $event)
94 try {
95 $patient = $event->getNewPatientData();
96 $oldPatient = $event->getDataBeforeUpdate();
97 // we need the patient uuid so we are going to grab it from the pid
98 $patientService = new PatientService();
100 $patient['uuid'] = UuidRegistry::uuidToString($oldPatient['uuid']); // convert uuid to a string value
101 $this->logger->debug(
102 self::class . "->onPatientUpdatedEvent received for patient ",
103 ['uuid' => $patient['uuid'] ?? null, 'patient' => $patient]
105 // let's grab the patient data and create the patient if its not registered
106 $apiUser = $this->userRepository->getUser($patient['uuid']);
107 if (empty($apiUser)) {
108 $this->createPatientRegistration($patient);
110 } catch (Exception $exception) {
111 $this->logger->errorLogCaller("Failed to create patient registration. Error: "
112 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'patient' => $patient['uuid']]);
116 public function onUserCreatedEvent(UserCreatedEvent $event)
118 try {
119 $user = $event->getUserData();
120 $userService = new UserService();
121 // our event doesn't have the uuid which is what we need
122 $userWithUuid = $userService->getUserByUsername($event->getUsername());
123 if (empty($userWithUuid)) {
124 throw new \InvalidArgumentException("Could not find user with username " . $event->getUsername());
127 // we need to find out if we
128 $providerRepo = $this->providerRepository;
129 // find out if the provider is enabled, if so we create the registration
130 $this->logger->debug(
131 self::class . "->onUserCreatedEvent received for user ",
132 ['username' => $event->getUsername(), 'userWithUuid' => $userWithUuid, 'uuid' => $userWithUuid['uuid'] ?? null]
134 if ($providerRepo->isEnabledProvider($userWithUuid['id'])) {
135 $this->createUserRegistration($userWithUuid);
136 } else {
137 $this->logger->debug(
138 self::class . "->onUserCreatedEvent skipping registration as user is not enrolled",
139 ['username' => $event->getUsername(), 'userWithUuid' => $userWithUuid, 'uuid' => $userWithUuid['uuid'] ?? null]
142 } catch (Exception $exception) {
143 $this->logger->errorLogCaller("Failed to create user registration. Error: "
144 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'user' => $user['uuid']]);
148 public function onUserUpdatedEvent(UserUpdatedEvent $event)
150 try {
151 $user = $event->getNewUserData();
152 $userService = new UserService();
153 // our event doesn't have the uuid which is what we need
154 $userWithUuid = $userService->getUser($event->getUserId());
155 if (empty($userWithUuid)) {
156 throw new \InvalidArgumentException("Could not find user with username " . $event->getUsername());
158 $this->logger->debug(self::class . "->onUserUpdatedEvent received for user ", ['uuid' => $userWithUuid['uuid'] ?? null]);
160 $providerRepo = $this->providerRepository;
162 // create the registration
163 $apiUser = $this->userRepository->getUser($userWithUuid['uuid']);
165 if ($providerRepo->isEnabledProvider($userWithUuid['id'])) {
166 // create our registration if there is one
167 if (empty($apiUser)) {
168 $this->logger->debug(self::class . "->onUserUpdatedEvent registering user with comlink", ['uuid' => $userWithUuid['uuid'] ?? null]);
169 $this->createUserRegistration($userWithUuid);
170 } else {
171 if (!$apiUser->getIsActive()) {
172 $this->logger->debug(
173 self::class . "->onUserUpdatedEvent user auth record is suspended, activating",
174 ['uuid' => $userWithUuid['uuid'] ?? null]
176 // we need to activate the user
177 $this->resumeUser($apiUser->getUsername(), $apiUser->getAuthToken());
178 } else {
179 $this->logger->debug(
180 self::class . "->onUserUpdatedEvent user auth record is already active",
181 ['uuid' => $userWithUuid['uuid'] ?? null]
183 // TODO: if we ever want to update the password registration here we can do that here
184 // since we don't change the username and its a randomly generated password, there's no need to change
185 // the password.
188 } else {
189 // we need to find out if a registration exists... if it does we need to deactivate it
190 if (empty($apiUser)) {
191 $this->logger->debug(
192 self::class . "->onUserUpdatedEvent telehealth disabled and no auth record exists",
193 ['uuid' => $userWithUuid['uuid'] ?? null]
195 // we do nothing here if the provider is not enabled and there's no auth we just ignore this
196 } else if ($apiUser->getIsActive()) {
197 $this->logger->debug(
198 self::class . "->onUserUpdatedEvent telehealth is disabled but registration is active. suspending user",
199 ['uuid' => $userWithUuid['uuid'] ?? null]
201 $this->suspendUser($apiUser->getUsername(), $apiUser->getAuthToken());
204 } catch (Exception $exception) {
205 $this->logger->errorLogCaller("Failed to create user registration. Error: "
206 . $exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'user' => $user]);
210 public function createPatientRegistration($patient)
212 return $this->remoteService->createPatientRegistration($patient);
215 public function createUserRegistration($user)
217 return $this->remoteService->createUserRegistration($user);
221 * Allows the user repository to be set for testing or extension purposes
222 * @param TeleHealthUserRepository $userRepository
224 public function setTelehealthUserRepository(TeleHealthUserRepository $userRepository)
226 // TODO: @adunsulag refactor unit tests so we don't have this layer of indirections since this is only used in unit tests right now
227 $this->remoteService->setTelehealthUserRepository($userRepository);
231 * Returns if a registration should be created for the given provider id. This does not answer whether a registration
232 * exists, but whether the user passes the criteria for creating a registration record regardless of whether it exists or not.
233 * @param $providerId
234 * @return bool
236 public function shouldCreateRegistrationForProvider($providerId)
238 return $this->providerRepository->isEnabledProvider($providerId);
242 * Provisions a new user with the Comlink video api system
243 * @param UserVideoRegistrationRequest $request
244 * @return false|int returns false if the user fails to add, otherwise returns the integer id of the provisioned user
246 public function addNewUser(UserVideoRegistrationRequest $request)
248 return $this->remoteService->addNewUser($request);
252 * Updates an existing provisioned user with the Comlink video api system. Everything but username can be changed
253 * @param UserVideoRegistrationRequest $request
254 * @return false|int returns false if the user fails to update, otherwise returns the integer id of the updated user
256 public function updateUser(UserVideoRegistrationRequest $request)
258 return $this->remoteService->updateUserFromRequest($request);
261 public function suspendUser(string $username, string $password): bool
263 return $this->remoteService->suspendUser($username, $password);
266 public function resumeUser(string $username, string $password): bool
268 return $this->remoteService->suspendUser($username, $password);
271 public function deactivateUser(string $username, string $password)
273 return $this->remoteService->deactivateUser($username, $password);