Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
2.92% |
43 / 1472 |
|
0.00% |
0 / 94 |
CRAP | |
0.00% |
0 / 1 |
ApiController | |
2.92% |
43 / 1472 |
|
0.00% |
0 / 94 |
84298.98 | |
0.00% |
0 / 1 |
apiLogin | |
0.00% |
0 / 37 |
|
0.00% |
0 / 1 |
20 | |||
apiLogout | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
setUpServerMailHandler | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
42 | |||
apiForgot | |
0.00% |
0 / 82 |
|
0.00% |
0 / 1 |
12 | |||
apiResetPassword | |
0.00% |
0 / 87 |
|
0.00% |
0 / 1 |
42 | |||
apiSettingsGet | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
apiAppConfigSet | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
apiSettingsSet | |
0.00% |
0 / 55 |
|
0.00% |
0 / 1 |
110 | |||
apiSettingsCreate | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
validateSettingsCreate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
createSettingFromRequest | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
apiSettingsAccountPasswordSet | |
0.00% |
0 / 29 |
|
0.00% |
0 / 1 |
56 | |||
validatePasswordUpdate | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
apiSettingsAccountLocalizationSet | |
0.00% |
0 / 105 |
|
0.00% |
0 / 1 |
20 | |||
apiSettingsDesignSet | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
apiApplicationCreate | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
12 | |||
createDefaultAppSettings | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
validateApplicationCreate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
createApplicationFromRequest | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
apiInstallApplication | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
72 | |||
apiGroupGet | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
apiGroupUpdate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
updateGroupFromRequest | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
validateGroupCreate | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
apiGroupCreate | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
createGroupFromRequest | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
apiGroupDelete | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
validateGroupDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiGroupFind | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
apiAccountGet | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
apiAccountFind | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
apiAccountGroupFind | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
12 | |||
validateAccountCreate | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
42 | |||
apiAccountCreate | |
0.00% |
0 / 55 |
|
0.00% |
0 / 1 |
110 | |||
apiAccountRegister | |
0.00% |
0 / 240 |
|
0.00% |
0 / 1 |
1406 | |||
validateRegistration | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
42 | |||
apiDataChange | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
30 | |||
validateDataChange | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
createMediaDirForAccount | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
createProfileForAccount | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
createAccountFromRequest | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
12 | |||
apiAccountDelete | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
apiAccountUpdate | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
updateAccountFromRequest | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
apiModuleStatusUpdate | |
33.86% |
43 / 127 |
|
0.00% |
0 / 1 |
221.60 | |||
apiAccountPermissionGet | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
apiGroupPermissionGet | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
apiGroupPermissionDelete | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
apiAccountPermissionDelete | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
apiAddGroupPermission | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
20 | |||
apiAddAccountPermission | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
12 | |||
createAccountModelPermission | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validatePermissionCreate | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
createPermissionFromRequest | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
6 | |||
apiAccountPermissionUpdate | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
apiGroupPermissionUpdate | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
12 | |||
updatePermissionFromRequest | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
apiAddGroupToAccount | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
validateAddGroupToAccount | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
apiAddAccountToGroup | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
validateAddAccountToGroup | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
apiDeleteGroupFromAccount | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
apiDeleteAccountFromGroup | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
apiReInit | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
72 | |||
apiCheckForUpdates | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
42 | |||
apiUpdateFile | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
apiUpdate | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
downloadUpdate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
runUpdate | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
apiContactCreate | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
6 | |||
validateContactCreate | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
createContactFromRequest | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
apiSettingsDelete | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
validateSettingsDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiApplicationUpdate | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
updateApplicationFromRequest | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validateApplicationUpdate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiApplicationDelete | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
validateApplicationDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
validateGroupPermissionUpdate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
validateGroupPermissionDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
updateAccountPermissionFromRequest | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validateAccountPermissionUpdate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
validateAccountPermissionDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiContactUpdate | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
updateContactFromRequest | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validateContactUpdate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiContactDelete | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
validateContactDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiDataChangeCreate | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
createDataChangeFromRequest | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validateDataChangeCreate | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
apiDataChangeDelete | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
validateDataChangeDelete | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * Jingga |
4 | * |
5 | * PHP Version 8.1 |
6 | * |
7 | * @package Modules\Admin |
8 | * @copyright Dennis Eichhorn |
9 | * @license OMS License 2.0 |
10 | * @version 1.0.0 |
11 | * @link https://jingga.app |
12 | */ |
13 | declare(strict_types=1); |
14 | |
15 | namespace Modules\Admin\Controller; |
16 | |
17 | use Model\Setting; |
18 | use Model\SettingMapper; |
19 | use Modules\Admin\Models\Account; |
20 | use Modules\Admin\Models\AccountCredentialMapper; |
21 | use Modules\Admin\Models\AccountMapper; |
22 | use Modules\Admin\Models\AccountPermission; |
23 | use Modules\Admin\Models\AccountPermissionMapper; |
24 | use Modules\Admin\Models\App; |
25 | use Modules\Admin\Models\AppMapper; |
26 | use Modules\Admin\Models\Contact; |
27 | use Modules\Admin\Models\ContactMapper; |
28 | use Modules\Admin\Models\DataChange; |
29 | use Modules\Admin\Models\DataChangeMapper; |
30 | use Modules\Admin\Models\Group; |
31 | use Modules\Admin\Models\GroupMapper; |
32 | use Modules\Admin\Models\GroupPermission; |
33 | use Modules\Admin\Models\GroupPermissionMapper; |
34 | use Modules\Admin\Models\LocalizationMapper; |
35 | use Modules\Admin\Models\Module; |
36 | use Modules\Admin\Models\ModuleMapper; |
37 | use Modules\Admin\Models\ModuleStatusUpdateType; |
38 | use Modules\Admin\Models\NullAccount; |
39 | use Modules\Admin\Models\PermissionCategory; |
40 | use Modules\Admin\Models\SettingsEnum; |
41 | use Modules\Media\Models\Collection; |
42 | use Modules\Media\Models\CollectionMapper; |
43 | use Modules\Media\Models\UploadFile; |
44 | use Modules\Messages\Models\EmailMapper; |
45 | use phpOMS\Account\AccountStatus; |
46 | use phpOMS\Account\AccountType; |
47 | use phpOMS\Account\GroupStatus; |
48 | use phpOMS\Account\PermissionAbstract; |
49 | use phpOMS\Account\PermissionOwner; |
50 | use phpOMS\Account\PermissionType; |
51 | use phpOMS\Application\ApplicationInfo; |
52 | use phpOMS\Application\ApplicationManager; |
53 | use phpOMS\Application\ApplicationType; |
54 | use phpOMS\Auth\LoginReturnType; |
55 | use phpOMS\DataStorage\Database\Query\Builder; |
56 | use phpOMS\Localization\Localization; |
57 | use phpOMS\Message\Http\HttpRequest; |
58 | use phpOMS\Message\Http\HttpResponse; |
59 | use phpOMS\Message\Http\RequestMethod; |
60 | use phpOMS\Message\Http\RequestStatusCode; |
61 | use phpOMS\Message\Http\Rest; |
62 | use phpOMS\Message\Mail\Email; |
63 | use phpOMS\Message\Mail\MailHandler; |
64 | use phpOMS\Message\Mail\Smtp; |
65 | use phpOMS\Message\Mail\SubmitType; |
66 | use phpOMS\Message\NotificationLevel; |
67 | use phpOMS\Message\RequestAbstract; |
68 | use phpOMS\Message\ResponseAbstract; |
69 | use phpOMS\Model\Message\FormValidation; |
70 | use phpOMS\Model\Message\Reload; |
71 | use phpOMS\Module\ModuleInfo; |
72 | use phpOMS\Module\ModuleStatus; |
73 | use phpOMS\Security\EncryptionHelper; |
74 | use phpOMS\System\File\Local\File; |
75 | use phpOMS\System\MimeType; |
76 | use phpOMS\Uri\HttpUri; |
77 | use phpOMS\Uri\UriFactory; |
78 | use phpOMS\Utils\ArrayUtils; |
79 | use phpOMS\Utils\Parser\Markdown\Markdown; |
80 | use phpOMS\Utils\Parser\Php\ArrayParser; |
81 | use phpOMS\Utils\RnG\StringUtils as StringRng; |
82 | use phpOMS\Utils\StringUtils; |
83 | use phpOMS\Validation\Network\Email as EmailValidator; |
84 | use phpOMS\Version\Version; |
85 | |
86 | /** |
87 | * Admin controller class. |
88 | * |
89 | * This class is responsible for the basic admin activities such as managing accounts, groups, permissions and modules. |
90 | * |
91 | * @package Modules\Admin |
92 | * @license OMS License 2.0 |
93 | * @link https://jingga.app |
94 | * @since 1.0.0 |
95 | */ |
96 | final class ApiController extends Controller |
97 | { |
98 | /** |
99 | * Api method to login |
100 | * |
101 | * @param RequestAbstract $request Request |
102 | * @param ResponseAbstract $response Response |
103 | * @param array $data Generic data |
104 | * |
105 | * @return void |
106 | * |
107 | * @api |
108 | * |
109 | * @since 1.0.0 |
110 | */ |
111 | public function apiLogin(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
112 | { |
113 | $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); |
114 | |
115 | $login = AccountMapper::login( |
116 | $request->getDataString('user') ?? '', |
117 | $request->getDataString('pass') ?? '' |
118 | ); |
119 | |
120 | if ($login > LoginReturnType::OK) { |
121 | $this->app->sessionManager->set('UID', $login, true); |
122 | $response->set($request->uri->__toString(), new Reload()); |
123 | } elseif ($login === LoginReturnType::NOT_ACTIVATED) { |
124 | $response->header->status = RequestStatusCode::R_401; |
125 | $this->fillJsonResponse( |
126 | $request, |
127 | $response, |
128 | NotificationLevel::WARNING, |
129 | '', |
130 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'NOT_ACTIVATED'), |
131 | null |
132 | ); |
133 | } elseif ($login === LoginReturnType::WRONG_INPUT_EXCEEDED) { |
134 | $response->header->status = RequestStatusCode::R_401; |
135 | $this->fillJsonResponse( |
136 | $request, |
137 | $response, |
138 | NotificationLevel::WARNING, |
139 | '', |
140 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'WRONG_INPUT_EXCEEDED'), |
141 | null |
142 | ); |
143 | } else { |
144 | $response->header->status = RequestStatusCode::R_401; |
145 | $this->fillJsonResponse( |
146 | $request, |
147 | $response, |
148 | NotificationLevel::WARNING, |
149 | '', |
150 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'LOGIN_ERROR'), |
151 | null |
152 | ); |
153 | } |
154 | } |
155 | |
156 | /** |
157 | * Api method to login |
158 | * |
159 | * @param RequestAbstract $request Request |
160 | * @param ResponseAbstract $response Response |
161 | * @param array $data Generic data |
162 | * |
163 | * @return void |
164 | * |
165 | * @api |
166 | * |
167 | * @since 1.0.0 |
168 | */ |
169 | public function apiLogout(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
170 | { |
171 | $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); |
172 | |
173 | $this->app->sessionManager->remove('UID'); |
174 | $this->app->sessionManager->save(); |
175 | |
176 | $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); |
177 | $response->set($request->uri->__toString(), [ |
178 | 'status' => NotificationLevel::OK, |
179 | 'title' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'LogoutSuccessfulTitle'), |
180 | 'message' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'LogoutSuccessfulMsg'), |
181 | 'response' => null, |
182 | ]); |
183 | } |
184 | |
185 | /** |
186 | * Create basic server mail handler |
187 | * |
188 | * @return MailHandler |
189 | * |
190 | * @since 1.0.0 |
191 | **/ |
192 | public function setUpServerMailHandler() : MailHandler |
193 | { |
194 | /** @var \Model\Setting[] $emailSettings */ |
195 | $emailSettings = $this->app->appSettings->get( |
196 | names: [ |
197 | SettingsEnum::MAIL_SERVER_OUT, |
198 | SettingsEnum::MAIL_SERVER_PORT_OUT, |
199 | SettingsEnum::MAIL_SERVER_TYPE, |
200 | SettingsEnum::MAIL_SERVER_USER, |
201 | SettingsEnum::MAIL_SERVER_PASS, |
202 | SettingsEnum::MAIL_SERVER_TLS, |
203 | ], |
204 | module: 'Admin' |
205 | ); |
206 | |
207 | if (empty($emailSettings)) { |
208 | /** @var \Model\Setting[] $emailSettings */ |
209 | $emailSettings = $this->app->appSettings->get( |
210 | names: [ |
211 | SettingsEnum::MAIL_SERVER_OUT, |
212 | SettingsEnum::MAIL_SERVER_PORT_OUT, |
213 | SettingsEnum::MAIL_SERVER_TYPE, |
214 | SettingsEnum::MAIL_SERVER_USER, |
215 | SettingsEnum::MAIL_SERVER_PASS, |
216 | SettingsEnum::MAIL_SERVER_TLS, |
217 | ], |
218 | module: 'Admin' |
219 | ); |
220 | } |
221 | |
222 | $handler = new MailHandler(); |
223 | $handler->setMailer($emailSettings[SettingsEnum::MAIL_SERVER_TYPE]->content ?? SubmitType::MAIL); |
224 | $handler->useAutoTLS = (bool) ($emailSettings[SettingsEnum::MAIL_SERVER_TLS]->content ?? false); |
225 | |
226 | if (($emailSettings[SettingsEnum::MAIL_SERVER_TYPE]->content ?? SubmitType::MAIL) === SubmitType::SMTP) { |
227 | $smtp = new Smtp(); |
228 | $handler->smtp = $smtp; |
229 | } |
230 | |
231 | if (!empty($port = $emailSettings[SettingsEnum::MAIL_SERVER_PORT_OUT]->content)) { |
232 | $handler->port = (int) $port; |
233 | } |
234 | |
235 | $handler->host = $emailSettings[SettingsEnum::MAIL_SERVER_OUT]->content ?? 'localhost'; |
236 | $handler->hostname = $emailSettings[SettingsEnum::MAIL_SERVER_OUT]->content ?? ''; |
237 | $handler->username = $emailSettings[SettingsEnum::MAIL_SERVER_USER]->content ?? ''; |
238 | $handler->password = $emailSettings[SettingsEnum::MAIL_SERVER_PASS]->isEncrypted && !empty($_SERVER['OMS_PRIVATE_KEY_I'] ?? '') |
239 | ? EncryptionHelper::decryptShared($emailSettings[SettingsEnum::MAIL_SERVER_PASS]->content ?? '', $_SERVER['OMS_PRIVATE_KEY_I']) |
240 | : $emailSettings[SettingsEnum::MAIL_SERVER_PASS]->content ?? ''; |
241 | |
242 | return $handler; |
243 | } |
244 | |
245 | /** |
246 | * Api method to send forgotten password email |
247 | * |
248 | * @param RequestAbstract $request Request |
249 | * @param ResponseAbstract $response Response |
250 | * @param array $data Generic data |
251 | * |
252 | * @return void |
253 | * |
254 | * @api |
255 | * |
256 | * @since 1.0.0 |
257 | */ |
258 | public function apiForgot(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
259 | { |
260 | /** @var \Modules\Admin\Models\Account $account */ |
261 | $account = $request->hasData('user') |
262 | ? AccountMapper::get()->where('login', (string) $request->getData('user'))->execute() |
263 | : AccountMapper::get()->where('email', (string) $request->getData('email'))->execute(); |
264 | |
265 | /** @var \Model\Setting[] $forgotten */ |
266 | $forgotten = $this->app->appSettings->get( |
267 | names: [SettingsEnum::LOGIN_FORGOTTEN_DATE, SettingsEnum::LOGIN_FORGOTTEN_COUNT], |
268 | module: 'Admin', |
269 | account: $account->id |
270 | ); |
271 | |
272 | if ((int) $forgotten[SettingsEnum::LOGIN_FORGOTTEN_COUNT]->content > 3) { |
273 | $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); |
274 | $response->set($request->uri->__toString(), [ |
275 | 'status' => NotificationLevel::ERROR, |
276 | 'title' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'PasswordResetTitle'), |
277 | 'message' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'PasswordResetMsg'), |
278 | 'response' => null, |
279 | ]); |
280 | } |
281 | |
282 | $token = (string) \random_bytes(64); |
283 | $handler = $this->setUpServerMailHandler(); |
284 | $resetLink = UriFactory::build('{/base}/reset?user=' . $account->id . '&token=' . $token); |
285 | |
286 | /** @var \Model\Setting[] $emailSettings */ |
287 | $emailSettings = $this->app->appSettings->get( |
288 | names: [SettingsEnum::MAIL_SERVER_ADDR, SettingsEnum::LOGIN_MAIL_FORGOT_PASSWORD_TEMPLATE], |
289 | module: 'Admin' |
290 | ); |
291 | |
292 | /** @var \Modules\Messages\Models\Email $mail */ |
293 | $mail = EmailMapper::get() |
294 | ->with('l11n') |
295 | ->where('id', (int) $emailSettings[SettingsEnum::LOGIN_MAIL_FORGOT_PASSWORD_TEMPLATE]->content) |
296 | ->where('l11n/language', $response->header->l11n->language) |
297 | ->execute(); |
298 | |
299 | $mail->setFrom($emailSettings[SettingsEnum::MAIL_SERVER_ADDR]->content); |
300 | $mail->addTo($account->email); |
301 | |
302 | // @todo: load default l11n if no translation is available |
303 | $mailL11n = $mail->getL11nByLanguage($response->header->l11n->language); |
304 | |
305 | $mail->subject = $mailL11n->subject; |
306 | |
307 | // @todo: improve, the /tld link could be api.myurl.com which of course is not the url of the respective app. |
308 | // Maybe store the uri in the $app model? or store all urls in the config file |
309 | $mail->body = \str_replace( |
310 | [ |
311 | '{reset_link}', |
312 | '{user_name}', |
313 | ], |
314 | [ |
315 | $resetLink, |
316 | $account->login, |
317 | ], |
318 | $mailL11n->body |
319 | ); |
320 | |
321 | $mail->bodyAlt = \str_replace( |
322 | [ |
323 | '{reset_link}', |
324 | '{user_name}', |
325 | ], |
326 | [ |
327 | $resetLink, |
328 | $account->login, |
329 | ], |
330 | $mailL11n->bodyAlt |
331 | ); |
332 | |
333 | $handler->send($mail); |
334 | |
335 | $this->app->appSettings->set([ |
336 | [ |
337 | 'name' => SettingsEnum::LOGIN_FORGOTTEN_DATE, |
338 | 'module' => self::NAME, |
339 | 'account' => $account->id, |
340 | 'content' => (string) \time(), |
341 | ], |
342 | [ |
343 | 'name' => SettingsEnum::LOGIN_FORGOTTEN_COUNT, |
344 | 'module' => self::NAME, |
345 | 'account' => $account->id, |
346 | 'content' => (string) (((int) $forgotten[SettingsEnum::LOGIN_FORGOTTEN_COUNT]->content) + 1), |
347 | ], |
348 | [ |
349 | 'name' => SettingsEnum::LOGIN_FORGOTTEN_TOKEN, |
350 | 'module' => self::NAME, |
351 | 'account' => $account->id, |
352 | 'content' => $token, |
353 | ], |
354 | ], true); |
355 | |
356 | /* |
357 | if (!empty($emailSettings[SettingsEnum::MAIL_SERVER_CERT]->content) |
358 | && !empty($emailSettings[SettingsEnum::MAIL_SERVER_KEY]->content) |
359 | ) { |
360 | $mail->sign( |
361 | $emailSettings[SettingsEnum::MAIL_SERVER_CERT]->content, |
362 | $emailSettings[SettingsEnum::MAIL_SERVER_KEY]->content, |
363 | $emailSettings[SettingsEnum::MAIL_SERVER_KEYPASS]->content |
364 | ); |
365 | } |
366 | */ |
367 | |
368 | // $handler->send($mail); |
369 | |
370 | $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); |
371 | $response->set($request->uri->__toString(), [ |
372 | 'status' => NotificationLevel::OK, |
373 | 'title' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'PasswordResetTitle'), |
374 | 'message' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'PasswordResetEmailMsg'), |
375 | 'response' => null, |
376 | ]); |
377 | } |
378 | |
379 | /** |
380 | * Api method to reset the password |
381 | * |
382 | * @param RequestAbstract $request Request |
383 | * @param ResponseAbstract $response Response |
384 | * @param array $data Generic data |
385 | * |
386 | * @return void |
387 | * |
388 | * @api |
389 | * |
390 | * @since 1.0.0 |
391 | */ |
392 | public function apiResetPassword(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
393 | { |
394 | /** @var \Model\Setting[] $forgotten */ |
395 | $forgotten = $this->app->appSettings->get( |
396 | names: [SettingsEnum::LOGIN_FORGOTTEN_DATE, SettingsEnum::LOGIN_FORGOTTEN_TOKEN], |
397 | module: self::NAME, |
398 | account: (int) $request->getData('user') |
399 | ); |
400 | |
401 | $date = new \DateTime($forgotten[SettingsEnum::LOGIN_FORGOTTEN_DATE]->content); |
402 | $token = $forgotten[SettingsEnum::LOGIN_FORGOTTEN_TOKEN]->content; |
403 | |
404 | if ($date->getTimestamp() < \time() - 60 * 10 |
405 | || !$request->hasData('token') |
406 | || $request->getData('token') !== $token |
407 | ) { |
408 | $response->header->status = RequestStatusCode::R_405; |
409 | $response->set($request->uri->__toString(), [ |
410 | 'status' => NotificationLevel::OK, |
411 | 'title' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'PasswordResetTitle'), |
412 | 'message' => $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'PasswordResetInvalidMsg'), |
413 | 'response' => null, |
414 | ]); |
415 | |
416 | return; |
417 | } |
418 | |
419 | /** @var \Modules\Admin\Models\Account $account */ |
420 | $account = AccountMapper::get()->where('id', (int) $request->getData('user'))->execute(); |
421 | |
422 | $account->generatePassword($pass = StringRng::generateString(10, 14, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_-+=/\\{}<>?')); |
423 | |
424 | AccountMapper::update()->execute($account); |
425 | |
426 | $handler = $this->setUpServerMailHandler(); |
427 | |
428 | /** @var \Model\Setting[] $emailSettings */ |
429 | $emailSettings = $this->app->appSettings->get( |
430 | names: [SettingsEnum::MAIL_SERVER_ADDR, SettingsEnum::LOGIN_MAIL_FORGOT_PASSWORD_TEMPLATE], |
431 | module: 'Admin' |
432 | ); |
433 | |
434 | /** @var \Modules\Messages\Models\Email $mail */ |
435 | $mail = EmailMapper::get() |
436 | ->with('l11n') |
437 | ->where('id', (int) $emailSettings[SettingsEnum::LOGIN_MAIL_FORGOT_PASSWORD_TEMPLATE]->content) |
438 | ->where('l11n/language', $response->header->l11n->language) |
439 | ->execute(); |
440 | |
441 | $mail->setFrom($emailSettings[SettingsEnum::MAIL_SERVER_ADDR]->content); |
442 | $mail->addTo($account->email); |
443 | |
444 | // @todo: load default l11n if no translation is available |
445 | $mailL11n = $mail->getL11nByLanguage($response->header->l11n->language); |
446 | |
447 | $mail->subject = $mailL11n->subject; |
448 | |
449 | // @todo: improve, the /tld link could be api.myurl.com which of course is not the url of the respective app. |
450 | // Maybe store the uri in the $app model? or store all urls in the config file |
451 | $mail->body = \str_replace( |
452 | [ |
453 | '{new_password}', |
454 | '{user_name}', |
455 | ], |
456 | [ |
457 | $pass, |
458 | $account->login, |
459 | ], |
460 | $mailL11n->body |
461 | ); |
462 | |
463 | $mail->bodyAlt = \str_replace( |
464 | [ |
465 | '{new_password}', |
466 | '{user_name}', |
467 | ], |
468 | [ |
469 | $pass, |
470 | $account->login, |
471 | ], |
472 | $mailL11n->bodyAlt |
473 | ); |
474 | |
475 | $handler->send($mail); |
476 | |
477 | $this->app->appSettings->set([ |
478 | [ |
479 | 'name' => SettingsEnum::LOGIN_FORGOTTEN_COUNT, |
480 | 'module' => self::NAME, |
481 | 'account' => $account->id, |
482 | 'content' => '0', |
483 | ], |
484 | [ |
485 | 'name' => SettingsEnum::LOGIN_FORGOTTEN_TOKEN, |
486 | 'module' => self::NAME, |
487 | 'account' => $account->id, |
488 | 'content' => '', |
489 | ], |
490 | ], true); |
491 | |
492 | if (!empty($emailSettings[SettingsEnum::MAIL_SERVER_CERT]->content) |
493 | && !empty($emailSettings[SettingsEnum::MAIL_SERVER_KEY]->content) |
494 | ) { |
495 | $mail->sign( |
496 | $emailSettings[SettingsEnum::MAIL_SERVER_CERT]->content, |
497 | $emailSettings[SettingsEnum::MAIL_SERVER_KEY]->content, |
498 | $emailSettings[SettingsEnum::MAIL_SERVER_KEYPASS]->content |
499 | ); |
500 | } |
501 | |
502 | $handler->send($mail); |
503 | |
504 | $response->header->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); |
505 | $response->set($request->uri->__toString(), [ |
506 | 'status' => NotificationLevel::OK, |
507 | 'title' => 'Password Reset', |
508 | 'message' => 'You received a new password.', |
509 | 'response' => null, |
510 | ]); |
511 | } |
512 | |
513 | /** |
514 | * Api method to get settings |
515 | * |
516 | * @param RequestAbstract $request Request |
517 | * @param ResponseAbstract $response Response |
518 | * @param array $data Generic data |
519 | * |
520 | * @return void |
521 | * |
522 | * @api |
523 | * |
524 | * @since 1.0.0 |
525 | */ |
526 | public function apiSettingsGet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
527 | { |
528 | $response->set( |
529 | $request->uri->__toString(), |
530 | [ |
531 | 'response' => $this->app->appSettings->get( |
532 | $request->getDataInt('id'), |
533 | $request->getDataString('name'), |
534 | $request->getDataInt('unit'), |
535 | $request->getDataInt('app'), |
536 | $request->getDataString('module'), |
537 | $request->getDataInt('group'), |
538 | $request->getDataInt('account') |
539 | ), |
540 | ] |
541 | ); |
542 | } |
543 | |
544 | /** |
545 | * Set app config |
546 | * |
547 | * @param RequestAbstract $request Request |
548 | * @param ResponseAbstract $response Response |
549 | * @param array $data Generic data |
550 | * |
551 | * @return void |
552 | * |
553 | * @api |
554 | * |
555 | * @since 1.0.0 |
556 | */ |
557 | public function apiAppConfigSet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
558 | { |
559 | $dataSettings = $request->getDataJson('settings'); |
560 | |
561 | $config = include __DIR__ . '/../../../config.php'; |
562 | |
563 | foreach ($dataSettings as $data) { |
564 | $config = ArrayUtils::setArray($data['path'], $config, $data['value'], '/', true); |
565 | } |
566 | |
567 | \file_put_contents(__DIR__ . '/../../../config.php', "<?php\ndeclare(strict_types=1);\nreturn " . ArrayParser::serializeArray($config) . ';'); |
568 | |
569 | $this->createStandardUpdateResponse($request, $response, $dataSettings); |
570 | } |
571 | |
572 | /** |
573 | * Api method for modifying settings |
574 | * |
575 | * @param RequestAbstract $request Request |
576 | * @param ResponseAbstract $response Response |
577 | * @param array $data Generic data |
578 | * |
579 | * @return void |
580 | * |
581 | * @api |
582 | * |
583 | * @since 1.0.0 |
584 | */ |
585 | public function apiSettingsSet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
586 | { |
587 | $dataSettings = $request->getDataJson('settings'); |
588 | |
589 | foreach ($dataSettings as $data) { |
590 | $id = isset($data['id']) && !empty($data['id']) ? (int) $data['id'] : null; |
591 | $name = $data['name'] ?? null; |
592 | $content = $data['content'] ?? null; |
593 | $unit = $data['unit'] ?? null; |
594 | $app = $data['app'] ?? null; |
595 | $module = $data['module'] ?? null; |
596 | $pattern = $data['pattern'] ?? ''; |
597 | $encrypted = $data['encrypted'] ?? null; |
598 | $group = isset($data['group']) ? (int) $data['group'] : null; |
599 | $account = isset($data['account']) ? (int) $data['account'] : null; |
600 | |
601 | /** @var \Model\Setting $old */ |
602 | $old = $this->app->appSettings->get($id, $name, $unit, $app, $module, $group, $account); |
603 | if ($old->id === 0) { |
604 | $internalResponse = new HttpResponse(); |
605 | $internalRequest = new HttpRequest($request->uri); |
606 | |
607 | $internalRequest->header->account = $request->header->account; |
608 | $internalRequest->setData('id', $id); |
609 | $internalRequest->setData('name', $name); |
610 | $internalRequest->setData('content', $content); |
611 | $internalRequest->setData('pattern', $pattern); |
612 | $internalRequest->setData('unit', $unit); |
613 | $internalRequest->setData('app', $app); |
614 | $internalRequest->setData('module', $module); |
615 | $internalRequest->setData('group', $group); |
616 | $internalRequest->setData('account', $account); |
617 | $internalRequest->setData('encrypted', $encrypted); |
618 | |
619 | $this->apiSettingsCreate($internalRequest, $internalResponse, $data); |
620 | |
621 | continue; |
622 | } |
623 | |
624 | $new = clone $old; |
625 | |
626 | $new->name = $name ?? $new->name; |
627 | $new->isEncrypted = $encrypted ?? $new->isEncrypted; |
628 | $new->content = $new->isEncrypted && !empty($content) && !empty($_SERVER['OMS_PRIVATE_KEY_I'] ?? '') |
629 | ? EncryptionHelper::encryptShared($content, $_SERVER['OMS_PRIVATE_KEY_I']) |
630 | : $content ?? $new->content; |
631 | $new->unit = $unit ?? $new->unit; |
632 | $new->app = $app ?? $new->app; |
633 | $new->module = $module ?? $new->module; |
634 | $new->group = $group ?? $new->group; |
635 | $new->account = $account ?? $new->account; |
636 | |
637 | // @todo: this function call seems stupid, it should just pass the $new object. |
638 | $this->app->appSettings->set([ |
639 | [ |
640 | 'id' => $new->id, |
641 | 'name' => $new->name, |
642 | 'content' => $new->content, |
643 | 'unit' => $new->unit, |
644 | 'app' => $new->app, |
645 | 'module' => $new->module, |
646 | 'group' => $new->group, |
647 | 'account' => $new->account, |
648 | 'isEncrypted' => $new->isEncrypted, |
649 | ], |
650 | ], false); |
651 | |
652 | $this->updateModel($request->header->account, $old, $new, SettingMapper::class, 'settings', $request->getOrigin()); |
653 | } |
654 | |
655 | $this->createStandardUpdateResponse($request, $response, $dataSettings); |
656 | } |
657 | |
658 | /** |
659 | * Api method for modifying settings |
660 | * |
661 | * @param RequestAbstract $request Request |
662 | * @param ResponseAbstract $response Response |
663 | * @param array $data Generic data |
664 | * |
665 | * @return void |
666 | * |
667 | * @api |
668 | * |
669 | * @since 1.0.0 |
670 | */ |
671 | public function apiSettingsCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
672 | { |
673 | if (!empty($val = $this->validateSettingsCreate($request))) { |
674 | $response->header->status = RequestStatusCode::R_400; |
675 | $this->createInvalidCreateResponse($request, $response, $val); |
676 | |
677 | return; |
678 | } |
679 | |
680 | $setting = $this->createSettingFromRequest($request); |
681 | $this->createModel($request->header->account, $setting, SettingMapper::class, 'setting', $request->getOrigin()); |
682 | $this->createStandardCreateResponse($request, $response, $setting); |
683 | } |
684 | |
685 | /** |
686 | * Validate password update request |
687 | * |
688 | * @param RequestAbstract $request Request |
689 | * |
690 | * @return array<string, bool> |
691 | * |
692 | * @since 1.0.0 |
693 | */ |
694 | private function validateSettingsCreate(RequestAbstract $request) : array |
695 | { |
696 | $val = []; |
697 | if (($val['name'] = !$request->hasData('name'))) { |
698 | return $val; |
699 | } |
700 | |
701 | return []; |
702 | } |
703 | |
704 | /** |
705 | * Method to create group from request. |
706 | * |
707 | * @param RequestAbstract $request Request |
708 | * |
709 | * @return Setting |
710 | * |
711 | * @since 1.0.0 |
712 | */ |
713 | private function createSettingFromRequest(RequestAbstract $request) : Setting |
714 | { |
715 | return new Setting( |
716 | id: $request->getDataInt('id') ?? 0, |
717 | name: $request->getDataString('name') ?? '', |
718 | content: $request->getDataString('content') ?? '', |
719 | pattern: $request->getDataString('pattern') ?? '', |
720 | unit: $request->getDataInt('unit'), |
721 | app: $request->getDataInt('app'), |
722 | module: $request->getDataString('module'), |
723 | group: $request->getDataInt('group'), |
724 | account: $request->getDataInt('account'), |
725 | isEncrypted: $request->getDataBool('encrypted') ?? false |
726 | ); |
727 | } |
728 | |
729 | /** |
730 | * Api method for modifying account password |
731 | * |
732 | * @param RequestAbstract $request Request |
733 | * @param ResponseAbstract $response Response |
734 | * @param array $data Generic data |
735 | * |
736 | * @return void |
737 | * |
738 | * @api |
739 | * |
740 | * @since 1.0.0 |
741 | */ |
742 | public function apiSettingsAccountPasswordSet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
743 | { |
744 | // has required data |
745 | if (!empty($val = $this->validatePasswordUpdate($request))) { |
746 | $response->data['password_update'] = new FormValidation($val); |
747 | $response->header->status = RequestStatusCode::R_400; |
748 | |
749 | return; |
750 | } |
751 | |
752 | $requestAccount = $request->header->account; |
753 | |
754 | // request account is valid |
755 | if ($requestAccount <= 0) { |
756 | $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); |
757 | $response->header->status = RequestStatusCode::R_403; |
758 | |
759 | return; |
760 | } |
761 | |
762 | /** @var Account $account */ |
763 | $account = AccountMapper::get() |
764 | ->where('id', $requestAccount) |
765 | ->execute(); |
766 | |
767 | // test old password is correct |
768 | if ($account->login === null |
769 | || AccountMapper::login($account->login, (string) $request->getData('oldpass')) !== $requestAccount |
770 | ) { |
771 | $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); |
772 | $response->header->status = RequestStatusCode::R_403; |
773 | |
774 | return; |
775 | } |
776 | |
777 | // test password repetition |
778 | if (((string) $request->getData('newpass')) !== ((string) $request->getData('reppass'))) { |
779 | $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); |
780 | $response->header->status = RequestStatusCode::R_403; |
781 | |
782 | return; |
783 | } |
784 | |
785 | // test password complexity |
786 | /** @var \Model\Setting $complexity */ |
787 | $complexity = $this->app->appSettings->get(names: SettingsEnum::PASSWORD_PATTERN, module: 'Admin'); |
788 | if (\preg_match($complexity->content, (string) $request->getData('newpass')) !== 1) { |
789 | $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); |
790 | $response->header->status = RequestStatusCode::R_403; |
791 | |
792 | return; |
793 | } |
794 | |
795 | $account->generatePassword((string) $request->getData('newpass')); |
796 | |
797 | AccountMapper::update()->execute($account); |
798 | |
799 | $this->createStandardUpdateResponse($request, $response, $account); |
800 | } |
801 | |
802 | /** |
803 | * Validate password update request |
804 | * |
805 | * @param RequestAbstract $request Request |
806 | * |
807 | * @return array<string, bool> |
808 | * |
809 | * @since 1.0.0 |
810 | */ |
811 | private function validatePasswordUpdate(RequestAbstract $request) : array |
812 | { |
813 | $val = []; |
814 | if (($val['oldpass'] = !$request->hasData('oldpass')) |
815 | || ($val['newpass'] = !$request->hasData('newpass')) |
816 | || ($val['reppass'] = !$request->hasData('reppass')) |
817 | ) { |
818 | return $val; |
819 | } |
820 | |
821 | return []; |
822 | } |
823 | |
824 | /** |
825 | * Api method for modifying account localization |
826 | * |
827 | * @param RequestAbstract $request Request |
828 | * @param ResponseAbstract $response Response |
829 | * @param array $data Generic data |
830 | * |
831 | * @return void |
832 | * |
833 | * @api |
834 | * |
835 | * @since 1.0.0 |
836 | */ |
837 | public function apiSettingsAccountLocalizationSet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
838 | { |
839 | $requestAccount = $request->header->account; |
840 | $accountId = (int) $request->getData('account_id'); |
841 | |
842 | if ($requestAccount !== $accountId |
843 | && !$this->app->accountManager->get($accountId)->hasPermission( |
844 | PermissionType::MODIFY, |
845 | $this->app->unitId, |
846 | $this->app->appId, |
847 | self::NAME, |
848 | PermissionCategory::ACCOUNT_SETTINGS, |
849 | $accountId |
850 | ) |
851 | ) { |
852 | $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); |
853 | $response->header->status = RequestStatusCode::R_403; |
854 | |
855 | return; |
856 | } |
857 | |
858 | /** @var \Modules\Admin\Models\Account $account */ |
859 | $account = AccountMapper::get() |
860 | ->with('l11n') |
861 | ->where('id', $accountId) |
862 | ->execute(); |
863 | |
864 | if (($request->getDataString('localization_load') ?? '-1') !== '-1') { |
865 | $locale = \explode('_', $request->getDataString('localization_load') ?? ''); |
866 | $old = clone $account->l11n; |
867 | |
868 | $account->l11n->loadFromLanguage($locale[0], $locale[1]); |
869 | |
870 | $this->updateModel($request->header->account, $old, $account->l11n, LocalizationMapper::class, 'l11n', $request->getOrigin()); |
871 | $this->createStandardUpdateResponse($request, $response, $account->l11n); |
872 | |
873 | return; |
874 | } |
875 | |
876 | $old = clone $account->l11n; |
877 | |
878 | $dataSettings = $request->getLike('settings_(.*)'); |
879 | |
880 | $account->l11n->setCountry($dataSettings['settings_country']); |
881 | $account->l11n->setLanguage($dataSettings['settings_language']); |
882 | $account->l11n->setTemperature($dataSettings['settings_temperature']); |
883 | |
884 | $account->l11n->setTimezone($dataSettings['settings_timezone']); |
885 | $account->l11n->setDatetime( |
886 | [ |
887 | 'very_short' => $dataSettings['settings_timeformat_vs'], |
888 | 'short' => $dataSettings['settings_timeformat_s'], |
889 | 'medium' => $dataSettings['settings_timeformat_m'], |
890 | 'long' => $dataSettings['settings_timeformat_l'], |
891 | 'very_long' => $dataSettings['settings_timeformat_vl'], |
892 | ] |
893 | ); |
894 | |
895 | $account->l11n->setCurrency($dataSettings['settings_currency']); |
896 | $account->l11n->setCurrencyFormat($dataSettings['settings_currencyformat']); |
897 | |
898 | $account->l11n->setDecimal($dataSettings['settings_decimal']); |
899 | $account->l11n->setThousands($dataSettings['settings_thousands']); |
900 | |
901 | $account->l11n->setPrecision( |
902 | [ |
903 | 'very_short' => $dataSettings['settings_precision_vs'], |
904 | 'short' => $dataSettings['settings_precision_s'], |
905 | 'medium' => $dataSettings['settings_precision_m'], |
906 | 'long' => $dataSettings['settings_precision_l'], |
907 | 'very_long' => $dataSettings['settings_precision_vl'], |
908 | ] |
909 | ); |
910 | |
911 | $account->l11n->setWeight( |
912 | [ |
913 | 'very_light' => $dataSettings['settings_weight_vl'], |
914 | 'light' => $dataSettings['settings_weight_l'], |
915 | 'medium' => $dataSettings['settings_weight_m'], |
916 | 'heavy' => $dataSettings['settings_weight_h'], |
917 | 'very_heavy' => $dataSettings['settings_weight_vh'], |
918 | ] |
919 | ); |
920 | |
921 | $account->l11n->setSpeed( |
922 | [ |
923 | 'very_slow' => $dataSettings['settings_speed_vs'], |
924 | 'slow' => $dataSettings['settings_speed_s'], |
925 | 'medium' => $dataSettings['settings_speed_m'], |
926 | 'fast' => $dataSettings['settings_speed_f'], |
927 | 'very_fast' => $dataSettings['settings_speed_vf'], |
928 | 'sea' => $dataSettings['settings_speed_sea'], |
929 | ] |
930 | ); |
931 | |
932 | $account->l11n->setLength( |
933 | [ |
934 | 'very_short' => $dataSettings['settings_length_vs'], |
935 | 'short' => $dataSettings['settings_length_s'], |
936 | 'medium' => $dataSettings['settings_length_m'], |
937 | 'long' => $dataSettings['settings_length_l'], |
938 | 'very_long' => $dataSettings['settings_length_vl'], |
939 | 'sea' => $dataSettings['settings_length_sea'], |
940 | ] |
941 | ); |
942 | |
943 | $account->l11n->setArea( |
944 | [ |
945 | 'very_small' => $dataSettings['settings_area_vs'], |
946 | 'small' => $dataSettings['settings_area_s'], |
947 | 'medium' => $dataSettings['settings_area_m'], |
948 | 'large' => $dataSettings['settings_area_l'], |
949 | 'very_large' => $dataSettings['settings_area_vl'], |
950 | ] |
951 | ); |
952 | |
953 | $account->l11n->setVolume( |
954 | [ |
955 | 'very_small' => $dataSettings['settings_volume_vs'], |
956 | 'small' => $dataSettings['settings_volume_s'], |
957 | 'medium' => $dataSettings['settings_volume_m'], |
958 | 'large' => $dataSettings['settings_volume_l'], |
959 | 'very_large' => $dataSettings['settings_volume_vl'], |
960 | 'tablespoon' => $dataSettings['settings_volume_tablespoon'], |
961 | 'teaspoon' => $dataSettings['settings_volume_teaspoon'], |
962 | 'glass' => $dataSettings['settings_volume_glass'], |
963 | ] |
964 | ); |
965 | |
966 | $this->updateModel($request->header->account, $old, $account->l11n, LocalizationMapper::class, 'l11n', $request->getOrigin()); |
967 | $this->createStandardUpdateResponse($request, $response, $account->l11n); |
968 | } |
969 | |
970 | /** |
971 | * Routing end-point for application behaviour. |
972 | * |
973 | * @param RequestAbstract $request Request |
974 | * @param ResponseAbstract $response Response |
975 | * @param array $data Generic data |
976 | * |
977 | * @return void |
978 | * |
979 | * @api |
980 | * |
981 | * @since 1.0.0 |
982 | */ |
983 | public function apiSettingsDesignSet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
984 | { |
985 | $uploadedFiles = $request->files; |
986 | |
987 | if (!empty($uploadedFiles)) { |
988 | $upload = new UploadFile(); |
989 | $upload->preserveFileName = false; |
990 | $upload->outputDir = __DIR__ . '/../../../Web/Backend/img'; |
991 | |
992 | $status = $upload->upload($uploadedFiles, ['logo.png'], true); |
993 | } |
994 | |
995 | $this->createStandardUpdateResponse($request, $response, []); |
996 | } |
997 | |
998 | /** |
999 | * Api method to install a application |
1000 | * |
1001 | * @param RequestAbstract $request Request |
1002 | * @param ResponseAbstract $response Response |
1003 | * @param array $data Generic data |
1004 | * |
1005 | * @return void |
1006 | * |
1007 | * @api |
1008 | * |
1009 | * @since 1.0.0 |
1010 | */ |
1011 | public function apiApplicationCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1012 | { |
1013 | if (!empty($val = $this->validateApplicationCreate($request))) { |
1014 | $response->header->status = RequestStatusCode::R_400; |
1015 | $this->createInvalidCreateResponse($request, $response, $val); |
1016 | |
1017 | return; |
1018 | } |
1019 | |
1020 | $app = $this->createApplicationFromRequest($request); |
1021 | $this->createModel($request->header->account, $app, AppMapper::class, 'application', $request->getOrigin()); |
1022 | |
1023 | $this->createDefaultAppSettings($app, $request); |
1024 | |
1025 | /** @var \Model\Setting $setting */ |
1026 | $setting = $this->app->appSettings->get(null, SettingsEnum::GROUP_GENERATE_AUTOMATICALLY_APP); |
1027 | if ($setting->content === '1') { |
1028 | $newRequest = new HttpRequest(); |
1029 | $newRequest->header->account = $request->header->account; |
1030 | $newRequest->setData('name', 'app:' . \strtolower($app->name)); |
1031 | $newRequest->setData('status', GroupStatus::ACTIVE); |
1032 | $this->apiGroupCreate($newRequest, $response, $data); |
1033 | } |
1034 | |
1035 | $this->createStandardCreateResponse($request, $response, $app); |
1036 | } |
1037 | |
1038 | /** |
1039 | * Create default settings for new app |
1040 | * |
1041 | * @param App $app Application to create new settings for |
1042 | * @param RequestAbstract $request Request used to create the app |
1043 | * |
1044 | * @return void |
1045 | * |
1046 | * @since 1.0.0 |
1047 | */ |
1048 | private function createDefaultAppSettings(App $app, RequestAbstract $request) : void |
1049 | { |
1050 | $settings = []; |
1051 | $settings[] = new Setting(0, SettingsEnum::REGISTRATION_ALLOWED, '0', '\\d+', app: $app->id, module: 'Admin'); |
1052 | $settings[] = new Setting(0, SettingsEnum::APP_DEFAULT_GROUPS, '[]', app: $app->id, module: 'Admin'); |
1053 | |
1054 | foreach ($settings as $setting) { |
1055 | $this->createModel($request->header->account, $setting, SettingMapper::class, 'setting', $request->getOrigin()); |
1056 | } |
1057 | } |
1058 | |
1059 | /** |
1060 | * Validate app create request |
1061 | * |
1062 | * @param RequestAbstract $request Request |
1063 | * |
1064 | * @return array<string, bool> |
1065 | * |
1066 | * @since 1.0.0 |
1067 | */ |
1068 | private function validateApplicationCreate(RequestAbstract $request) : array |
1069 | { |
1070 | $val = []; |
1071 | if (($val['name'] = !$request->hasData('name'))) { |
1072 | return $val; |
1073 | } |
1074 | |
1075 | return []; |
1076 | } |
1077 | |
1078 | /** |
1079 | * Method to create task from request. |
1080 | * |
1081 | * @param RequestAbstract $request Request |
1082 | * |
1083 | * @return App Returns the created application from the request |
1084 | * |
1085 | * @since 1.0.0 |
1086 | */ |
1087 | private function createApplicationFromRequest(RequestAbstract $request) : App |
1088 | { |
1089 | $app = new App(); |
1090 | $app->name = $request->getDataString('name') ?? ''; |
1091 | $app->type = $request->getDataInt('type') ?? ApplicationType::WEB; |
1092 | $app->defaultUnit = $request->getDataInt('default_unit'); |
1093 | |
1094 | return $app; |
1095 | } |
1096 | |
1097 | /** |
1098 | * Api method to install a application |
1099 | * |
1100 | * @param RequestAbstract $request Request |
1101 | * @param ResponseAbstract $response Response |
1102 | * @param array $data Generic data |
1103 | * |
1104 | * @return void |
1105 | * |
1106 | * @api |
1107 | * |
1108 | * @since 1.0.0 |
1109 | */ |
1110 | public function apiInstallApplication(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1111 | { |
1112 | $appManager = new ApplicationManager($this->app); |
1113 | |
1114 | $app = \rtrim($request->getDataString('appSrc') ?? '', '/\\ '); |
1115 | if (!\is_dir(__DIR__ . '/../../../' . $app)) { |
1116 | $response->header->status = RequestStatusCode::R_400; |
1117 | return; |
1118 | } |
1119 | |
1120 | $appInfo = new ApplicationInfo(__DIR__ . '/../../../' . $app . '/info.json'); |
1121 | $appInfo->load(); |
1122 | |
1123 | // handle dependencies |
1124 | $dependencies = $appInfo->getDependencies(); |
1125 | $installed = $this->app->moduleManager->getInstalledModules(); |
1126 | |
1127 | foreach ($dependencies as $key => $version) { |
1128 | if (!isset($installed[$key])) { |
1129 | $this->app->moduleManager->install($key); |
1130 | } |
1131 | } |
1132 | |
1133 | // handle app installation |
1134 | $result = $appManager->install( |
1135 | __DIR__ . '/../../../' . $app, |
1136 | __DIR__ . '/../../../' . ($request->getDataString('appDest') ?? ''), |
1137 | $request->getDataString('theme') ?? 'Default' |
1138 | ); |
1139 | |
1140 | // handle providing |
1141 | if ($result) { |
1142 | $providing = $appInfo->getProviding(); |
1143 | |
1144 | foreach ($providing as $key => $version) { |
1145 | if (isset($installed[$key])) { |
1146 | $this->app->moduleManager->installProviding($app, $key); |
1147 | } |
1148 | } |
1149 | } |
1150 | |
1151 | // handle Routes of already installed modules |
1152 | foreach ($installed as $module => $data) { |
1153 | $class = '\Modules\\' . $module . '\Admin\Status'; |
1154 | |
1155 | $moduleInfo = new ModuleInfo(__DIR__ . '/../../../Modules/' . $module . '/info.json'); |
1156 | $moduleInfo->load(); |
1157 | |
1158 | $class::activateRoutes($moduleInfo, $appInfo); |
1159 | $class::activateHooks($moduleInfo, $appInfo); |
1160 | } |
1161 | } |
1162 | |
1163 | /** |
1164 | * Api method to get a group |
1165 | * |
1166 | * @param RequestAbstract $request Request |
1167 | * @param ResponseAbstract $response Response |
1168 | * @param array $data Generic data |
1169 | * |
1170 | * @return void |
1171 | * |
1172 | * @api |
1173 | * |
1174 | * @since 1.0.0 |
1175 | */ |
1176 | public function apiGroupGet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1177 | { |
1178 | /** @var \Modules\Admin\Models\Group $group */ |
1179 | $group = GroupMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
1180 | $this->createStandardReturnResponse($request, $response, $group); |
1181 | } |
1182 | |
1183 | /** |
1184 | * Api method for modifying a group |
1185 | * |
1186 | * @param RequestAbstract $request Request |
1187 | * @param ResponseAbstract $response Response |
1188 | * @param array $data Generic data |
1189 | * |
1190 | * @return void |
1191 | * |
1192 | * @api |
1193 | * |
1194 | * @since 1.0.0 |
1195 | */ |
1196 | public function apiGroupUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1197 | { |
1198 | /** @var \Modules\Admin\Models\Group $old */ |
1199 | $old = GroupMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
1200 | $new = $this->updateGroupFromRequest($request, clone $old); |
1201 | |
1202 | $this->updateModel($request->header->account, $old, $new, GroupMapper::class, 'group', $request->getOrigin()); |
1203 | $this->createStandardUpdateResponse($request, $response, $new); |
1204 | } |
1205 | |
1206 | /** |
1207 | * Method to update group from request. |
1208 | * |
1209 | * @param RequestAbstract $request Request |
1210 | * |
1211 | * @return Group |
1212 | * |
1213 | * @since 1.0.0 |
1214 | */ |
1215 | private function updateGroupFromRequest(RequestAbstract $request, Group $group) : Group |
1216 | { |
1217 | $group->name = $request->getDataString('name') ?? $group->name; |
1218 | $group->setStatus($request->getDataInt('status') ?? $group->getStatus()); |
1219 | $group->description = Markdown::parse($request->getDataString('description') ?? $group->descriptionRaw); |
1220 | $group->descriptionRaw = $request->getDataString('description') ?? $group->descriptionRaw; |
1221 | |
1222 | return $group; |
1223 | } |
1224 | |
1225 | /** |
1226 | * Validate group create request |
1227 | * |
1228 | * @param RequestAbstract $request Request |
1229 | * |
1230 | * @return array<string, bool> |
1231 | * |
1232 | * @since 1.0.0 |
1233 | */ |
1234 | private function validateGroupCreate(RequestAbstract $request) : array |
1235 | { |
1236 | $val = []; |
1237 | if (($val['name'] = !$request->hasData('name')) |
1238 | || ($val['status'] = !GroupStatus::isValidValue((int) $request->getData('status'))) |
1239 | ) { |
1240 | return $val; |
1241 | } |
1242 | |
1243 | return []; |
1244 | } |
1245 | |
1246 | /** |
1247 | * Api method to create a group |
1248 | * |
1249 | * @param RequestAbstract $request Request |
1250 | * @param ResponseAbstract $response Response |
1251 | * @param array $data Generic data |
1252 | * |
1253 | * @return void |
1254 | * |
1255 | * @api |
1256 | * |
1257 | * @since 1.0.0 |
1258 | */ |
1259 | public function apiGroupCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1260 | { |
1261 | if (!empty($val = $this->validateGroupCreate($request))) { |
1262 | $response->header->status = RequestStatusCode::R_400; |
1263 | $this->createInvalidCreateResponse($request, $response, $val); |
1264 | |
1265 | return; |
1266 | } |
1267 | |
1268 | $group = $this->createGroupFromRequest($request); |
1269 | $this->createModel($request->header->account, $group, GroupMapper::class, 'group', $request->getOrigin()); |
1270 | $this->createStandardCreateResponse($request, $response, $group); |
1271 | } |
1272 | |
1273 | /** |
1274 | * Method to create group from request. |
1275 | * |
1276 | * @param RequestAbstract $request Request |
1277 | * |
1278 | * @return Group |
1279 | * |
1280 | * @since 1.0.0 |
1281 | */ |
1282 | private function createGroupFromRequest(RequestAbstract $request) : Group |
1283 | { |
1284 | $group = new Group(); |
1285 | $group->createdBy = new NullAccount($request->header->account); |
1286 | $group->name = $request->getDataString('name') ?? ''; |
1287 | $group->setStatus($request->getDataInt('status') ?? GroupStatus::INACTIVE); |
1288 | $group->description = Markdown::parse($request->getDataString('description') ?? ''); |
1289 | $group->descriptionRaw = $request->getDataString('description') ?? ''; |
1290 | |
1291 | return $group; |
1292 | } |
1293 | |
1294 | /** |
1295 | * Api method to delete a group |
1296 | * |
1297 | * @param RequestAbstract $request Request |
1298 | * @param ResponseAbstract $response Response |
1299 | * @param array $data Generic data |
1300 | * |
1301 | * @return void |
1302 | * |
1303 | * @api |
1304 | * |
1305 | * @since 1.0.0 |
1306 | */ |
1307 | public function apiGroupDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1308 | { |
1309 | if (!empty($val = $this->validateGroupDelete($request))) { |
1310 | $response->header->status = RequestStatusCode::R_400; |
1311 | $this->createInvalidDeleteResponse($request, $response, $val); |
1312 | |
1313 | return; |
1314 | } |
1315 | |
1316 | if (((int) $request->getData('id')) === 3) { |
1317 | // admin group cannot be deleted |
1318 | $this->createInvalidDeleteResponse($request, $response, []); |
1319 | |
1320 | return; |
1321 | } |
1322 | |
1323 | /** @var \Modules\Admin\Models\Group $group */ |
1324 | $group = GroupMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
1325 | $this->deleteModel($request->header->account, $group, GroupMapper::class, 'group', $request->getOrigin()); |
1326 | $this->createStandardDeleteResponse($request, $response, $group); |
1327 | } |
1328 | |
1329 | /** |
1330 | * Validate Group delete request |
1331 | * |
1332 | * @param RequestAbstract $request Request |
1333 | * |
1334 | * @return array<string, bool> |
1335 | * |
1336 | * @todo: implement |
1337 | * |
1338 | * @since 1.0.0 |
1339 | */ |
1340 | private function validateGroupDelete(RequestAbstract $request) : array |
1341 | { |
1342 | $val = []; |
1343 | if (($val['id'] = !$request->hasData('id'))) { |
1344 | return $val; |
1345 | } |
1346 | |
1347 | return []; |
1348 | } |
1349 | |
1350 | /** |
1351 | * Api method to find groups |
1352 | * |
1353 | * @param RequestAbstract $request Request |
1354 | * @param ResponseAbstract $response Response |
1355 | * @param array $data Generic data |
1356 | * |
1357 | * @return void |
1358 | * |
1359 | * @api |
1360 | * |
1361 | * @since 1.0.0 |
1362 | */ |
1363 | public function apiGroupFind(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1364 | { |
1365 | /** @var \Modules\Admin\Models\Group[] $groups */ |
1366 | $groups = GroupMapper::getAll() |
1367 | ->where('name', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE') |
1368 | ->execute(); |
1369 | |
1370 | $response->header->set('Content-Type', MimeType::M_JSON, true); |
1371 | $response->set( |
1372 | $request->uri->__toString(), |
1373 | \array_values($groups) |
1374 | ); |
1375 | } |
1376 | |
1377 | /** |
1378 | * Api method to get an accoung |
1379 | * |
1380 | * @param RequestAbstract $request Request |
1381 | * @param ResponseAbstract $response Response |
1382 | * @param array $data Generic data |
1383 | * |
1384 | * @return void |
1385 | * |
1386 | * @api |
1387 | * |
1388 | * @since 1.0.0 |
1389 | */ |
1390 | public function apiAccountGet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1391 | { |
1392 | /** @var Account $account */ |
1393 | $account = AccountMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
1394 | $this->createStandardReturnResponse($request, $response, $account); |
1395 | } |
1396 | |
1397 | /** |
1398 | * Api method to find accounts |
1399 | * |
1400 | * @param RequestAbstract $request Request |
1401 | * @param ResponseAbstract $response Response |
1402 | * @param array $data Generic data |
1403 | * |
1404 | * @return void |
1405 | * |
1406 | * @api |
1407 | * |
1408 | * @since 1.0.0 |
1409 | */ |
1410 | public function apiAccountFind(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1411 | { |
1412 | /** @var \Modules\Admin\Models\Account[] $accounts */ |
1413 | $accounts = AccountMapper::getAll() |
1414 | ->where('login', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE') |
1415 | ->where('email', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1416 | ->where('name1', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1417 | ->where('name2', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1418 | ->where('name3', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1419 | ->execute(); |
1420 | |
1421 | $response->header->set('Content-Type', MimeType::M_JSON, true); |
1422 | $response->set( |
1423 | $request->uri->__toString(), |
1424 | \array_values($accounts) |
1425 | ); |
1426 | } |
1427 | |
1428 | /** |
1429 | * Api method to find accounts and or groups |
1430 | * |
1431 | * @param RequestAbstract $request Request |
1432 | * @param ResponseAbstract $response Response |
1433 | * @param array $data Generic data |
1434 | * |
1435 | * @return void |
1436 | * |
1437 | * @api |
1438 | * |
1439 | * @since 1.0.0 |
1440 | */ |
1441 | public function apiAccountGroupFind(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1442 | { |
1443 | /** @var Account[] $accounts */ |
1444 | $accounts = AccountMapper::getAll() |
1445 | ->where('login', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE') |
1446 | ->where('email', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1447 | ->where('name1', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1448 | ->where('name2', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1449 | ->where('name3', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE', 'OR') |
1450 | ->execute(); |
1451 | |
1452 | $data = []; |
1453 | |
1454 | foreach ($accounts as $account) { |
1455 | /** @var array $temp */ |
1456 | $temp = $account->jsonSerialize(); |
1457 | $temp['type_prefix'] = 'a'; |
1458 | $temp['type_name'] = 'Account'; |
1459 | |
1460 | $data[] = $temp; |
1461 | } |
1462 | |
1463 | /** @var Group[] $groups */ |
1464 | $groups = GroupMapper::getAll() |
1465 | ->where('name', '%' . ($request->getDataString('search') ?? '') . '%', 'LIKE') |
1466 | ->execute(); |
1467 | |
1468 | foreach ($groups as $group) { |
1469 | /** @var array $temp */ |
1470 | $temp = $group->jsonSerialize(); |
1471 | $temp['name'] = [$temp['name']]; |
1472 | $temp['email'] = '---'; |
1473 | $temp['type_prefix'] = 'g'; |
1474 | $temp['type_name'] = 'Group'; |
1475 | |
1476 | $data[] = $temp; |
1477 | } |
1478 | |
1479 | $response->header->set('Content-Type', MimeType::M_JSON, true); |
1480 | $response->set($request->uri->__toString(), $data); |
1481 | } |
1482 | |
1483 | /** |
1484 | * Method to validate account creation from request |
1485 | * |
1486 | * @param RequestAbstract $request Request |
1487 | * |
1488 | * @return array<string, bool> |
1489 | * |
1490 | * @since 1.0.0 |
1491 | */ |
1492 | private function validateAccountCreate(RequestAbstract $request) : array |
1493 | { |
1494 | $val = []; |
1495 | if (($val['name1'] = !$request->hasData('name1')) |
1496 | || ($val['type'] = !AccountType::isValidValue((int) $request->getData('type'))) |
1497 | || ($val['status'] = !AccountStatus::isValidValue((int) $request->getData('status'))) |
1498 | || ($val['email'] = $request->hasData('email') && !EmailValidator::isValid((string) $request->getData('email'))) |
1499 | ) { |
1500 | return $val; |
1501 | } |
1502 | |
1503 | return []; |
1504 | } |
1505 | |
1506 | /** |
1507 | * Api method to create an account |
1508 | * |
1509 | * @param RequestAbstract $request Request |
1510 | * @param ResponseAbstract $response Response |
1511 | * @param array $data Generic data |
1512 | * |
1513 | * @return void |
1514 | * |
1515 | * @api |
1516 | * |
1517 | * @since 1.0.0 |
1518 | */ |
1519 | public function apiAccountCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1520 | { |
1521 | if (!empty($val = $this->validateAccountCreate($request))) { |
1522 | $response->header->status = RequestStatusCode::R_400; |
1523 | $this->createInvalidCreateResponse($request, $response, $val); |
1524 | |
1525 | return; |
1526 | } |
1527 | |
1528 | $account = $this->createAccountFromRequest($request); |
1529 | $this->createModel($request->header->account, $account, AccountCredentialMapper::class, 'account', $request->getOrigin()); |
1530 | |
1531 | if ($request->hasData('create_profile')) { |
1532 | $this->createProfileForAccount($account, $request); |
1533 | } |
1534 | |
1535 | $collection = $this->createMediaDirForAccount($account->id, $account->login ?? '', $request->header->account); |
1536 | $this->createModel($request->header->account, $collection, CollectionMapper::class, 'collection', $request->getOrigin()); |
1537 | |
1538 | // find default groups and create them |
1539 | $defaultGroupIds = []; |
1540 | |
1541 | if ($request->hasData('app')) { |
1542 | /** @var \Model\Setting $defaultGroupSettings */ |
1543 | $defaultGroupSettings = $this->app->appSettings->get( |
1544 | names: SettingsEnum::APP_DEFAULT_GROUPS, |
1545 | app: (int) $request->getData('app'), |
1546 | module: 'Admin' |
1547 | ); |
1548 | |
1549 | if (!empty($defaultGroupSettings)) { |
1550 | $temp = \json_decode($defaultGroupSettings->content, true); |
1551 | if (!\is_array($temp)) { |
1552 | $temp = []; |
1553 | } |
1554 | |
1555 | $defaultGroupIds = \array_merge($defaultGroupIds, $temp); |
1556 | } |
1557 | } |
1558 | |
1559 | if ($request->hasData('unit')) { |
1560 | /** @var \Model\Setting $defaultGroupSettings */ |
1561 | $defaultGroupSettings = $this->app->appSettings->get( |
1562 | names: SettingsEnum::UNIT_DEFAULT_GROUPS, |
1563 | unit: (int) $request->getData('unit'), |
1564 | module: 'Admin' |
1565 | ); |
1566 | |
1567 | if (!empty($defaultGroupSettings)) { |
1568 | $temp = \json_decode($defaultGroupSettings->content, true); |
1569 | if (!\is_array($temp)) { |
1570 | $temp = []; |
1571 | } |
1572 | |
1573 | $defaultGroupIds = \array_merge($defaultGroupIds, $temp); |
1574 | } |
1575 | } |
1576 | |
1577 | if (!empty($defaultGroupIds)) { |
1578 | $this->createModelRelation( |
1579 | $account->id, |
1580 | $account->id, |
1581 | $defaultGroupIds, |
1582 | AccountMapper::class, |
1583 | 'groups', |
1584 | 'account', |
1585 | $request->getOrigin() |
1586 | ); |
1587 | } |
1588 | |
1589 | $this->fillJsonResponse( |
1590 | $request, |
1591 | $response, |
1592 | NotificationLevel::OK, |
1593 | '', |
1594 | \str_replace( |
1595 | '{url}', |
1596 | UriFactory::build('{/base}/admin/account/settings?{?}&id=' . $account->id), |
1597 | $this->app->l11nManager->getText($response->header->l11n->language, '0', '0', 'SuccessfulCreate' |
1598 | )), |
1599 | $account |
1600 | ); |
1601 | } |
1602 | |
1603 | /** |
1604 | * Api method to register an account |
1605 | * |
1606 | * @param RequestAbstract $request Request |
1607 | * @param ResponseAbstract $response Response |
1608 | * @param array $data Generic data |
1609 | * |
1610 | * @return void |
1611 | * |
1612 | * @api |
1613 | * |
1614 | * @since 1.0.0 |
1615 | */ |
1616 | public function apiAccountRegister(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
1617 | { |
1618 | if ($request->header->account === 0) { |
1619 | $request->header->account = 1; |
1620 | } |
1621 | |
1622 | if (!empty($val = $this->validateRegistration($request))) { |
1623 | $response->header->status = RequestStatusCode::R_400; |
1624 | |
1625 | $this->fillJsonResponse( |
1626 | $request, |
1627 | $response, |
1628 | NotificationLevel::ERROR, |
1629 | '', |
1630 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'FormDataInvalid'), |
1631 | $val |
1632 | ); |
1633 | |
1634 | return; |
1635 | } |
1636 | |
1637 | /** @var \Modules\Admin\Models\App */ |
1638 | $app = AppMapper::get() |
1639 | ->where('id', (int) $request->getData('app')) |
1640 | ->execute(); |
1641 | |
1642 | /** @var \Model\Setting $allowed */ |
1643 | $allowed = $this->app->appSettings->get( |
1644 | names: SettingsEnum::REGISTRATION_ALLOWED, |
1645 | app: (int) $request->getData('app'), |
1646 | module: 'Admin' |
1647 | ); |
1648 | |
1649 | if ($allowed->content !== '1') { |
1650 | $response->header->status = RequestStatusCode::R_400; |
1651 | |
1652 | $this->fillJsonResponse( |
1653 | $request, |
1654 | $response, |
1655 | NotificationLevel::ERROR, |
1656 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationTitle'), |
1657 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationNotAllowed'), |
1658 | [] |
1659 | ); |
1660 | |
1661 | $response->header->status = RequestStatusCode::R_400; |
1662 | |
1663 | return; |
1664 | } |
1665 | |
1666 | /** @var \Model\Setting $complexity */ |
1667 | $complexity = $this->app->appSettings->get(names: SettingsEnum::PASSWORD_PATTERN, module: 'Admin'); |
1668 | if ($request->hasData('password') |
1669 | && \preg_match($complexity->content, (string) $request->getData('password')) !== 1 |
1670 | ) { |
1671 | $response->header->status = RequestStatusCode::R_400; |
1672 | |
1673 | $this->fillJsonResponse( |
1674 | $request, |
1675 | $response, |
1676 | NotificationLevel::ERROR, |
1677 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationTitle'), |
1678 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationInvalidPasswordFormat'), |
1679 | [] |
1680 | ); |
1681 | |
1682 | $response->header->status = RequestStatusCode::R_403; |
1683 | |
1684 | return; |
1685 | } |
1686 | |
1687 | // Check if account already exists |
1688 | /** @var Account $emailAccount */ |
1689 | $emailAccount = AccountMapper::get() |
1690 | ->where('email', (string) $request->getData('email')) |
1691 | ->execute(); |
1692 | |
1693 | /** @var Account $loginAccount */ |
1694 | $loginAccount = AccountMapper::get() |
1695 | ->where('login', (string) ($request->getData('user') ?? $request->getData('email'))) |
1696 | ->execute(); |
1697 | |
1698 | /** @var null|Account $account */ |
1699 | $account = null; |
1700 | |
1701 | // email already in use |
1702 | if ($emailAccount->id > 0 |
1703 | && $emailAccount->login !== null |
1704 | && AccountMapper::login($emailAccount->login, (string) $request->getData('password')) !== LoginReturnType::OK |
1705 | ) { |
1706 | $response->header->status = RequestStatusCode::R_400; |
1707 | |
1708 | $this->fillJsonResponse( |
1709 | $request, |
1710 | $response, |
1711 | NotificationLevel::OK, |
1712 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationTitle'), |
1713 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationEmailInUse'), |
1714 | [] |
1715 | ); |
1716 | |
1717 | $response->header->status = RequestStatusCode::R_400; |
1718 | |
1719 | return; |
1720 | } elseif ($emailAccount->id > 0) { |
1721 | $account = $emailAccount; |
1722 | } |
1723 | |
1724 | // login already in use by different email |
1725 | if ($account === null |
1726 | && $loginAccount->id > 0 |
1727 | && $loginAccount->getEmail() !== $request->getData('email') |
1728 | ) { |
1729 | $response->header->status = RequestStatusCode::R_400; |
1730 | |
1731 | $this->fillJsonResponse( |
1732 | $request, |
1733 | $response, |
1734 | NotificationLevel::ERROR, |
1735 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationTitle'), |
1736 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationLoginInUse'), |
1737 | [] |
1738 | ); |
1739 | |
1740 | $response->header->status = RequestStatusCode::R_400; |
1741 | |
1742 | return; |
1743 | } elseif ($account === null |
1744 | && $loginAccount->id > 0 |
1745 | && $loginAccount->login !== null |
1746 | && AccountMapper::login($loginAccount->login, (string) $request->getData('password')) !== LoginReturnType::OK |
1747 | ) { |
1748 | $account = $loginAccount; |
1749 | } |
1750 | |
1751 | // Already registered |
1752 | if ($account !== null) { |
1753 | /** @var Account $account */ |
1754 | $account = AccountMapper::get() |
1755 | ->with('groups') |
1756 | ->where('id', $account->id) |
1757 | ->execute(); |
1758 | |
1759 | $defaultGroupIds = []; |
1760 | |
1761 | if ($request->hasData('app')) { |
1762 | /** @var \Model\Setting $defaultGroupSettings */ |
1763 | $defaultGroupSettings = $this->app->appSettings->get( |
1764 | names: SettingsEnum::APP_DEFAULT_GROUPS, |
1765 | app: (int) $request->getDataInt('app'), |
1766 | module: 'Admin' |
1767 | ); |
1768 | |
1769 | if (!empty($defaultGroupSettings)) { |
1770 | $temp = \json_decode($defaultGroupSettings->content, true); |
1771 | if (!\is_array($temp)) { |
1772 | $temp = []; |
1773 | } |
1774 | |
1775 | $defaultGroupIds = \array_merge( |
1776 | $defaultGroupIds, |
1777 | $temp |
1778 | ); |
1779 | } |
1780 | } |
1781 | |
1782 | if ($request->hasData('unit')) { |
1783 | /** @var \Model\Setting $defaultGroupSettings */ |
1784 | $defaultGroupSettings = $this->app->appSettings->get( |
1785 | names: SettingsEnum::UNIT_DEFAULT_GROUPS, |
1786 | app: (int) $request->getDataInt('unit'), |
1787 | module: 'Admin' |
1788 | ); |
1789 | |
1790 | if (!empty($defaultGroupSettings)) { |
1791 | $temp = \json_decode($defaultGroupSettings->content, true); |
1792 | if (!\is_array($temp)) { |
1793 | $temp = []; |
1794 | } |
1795 | |
1796 | $defaultGroupIds = \array_merge( |
1797 | $defaultGroupIds, |
1798 | $temp |
1799 | ); |
1800 | } |
1801 | } |
1802 | |
1803 | foreach ($defaultGroupIds as $index => $id) { |
1804 | if ($account->hasGroup($id)) { |
1805 | unset($defaultGroupIds[$index]); |
1806 | } |
1807 | } |
1808 | |
1809 | if (empty($defaultGroupIds) |
1810 | && $account->getStatus() === AccountStatus::INACTIVE |
1811 | ) { |
1812 | $response->header->status = RequestStatusCode::R_400; |
1813 | |
1814 | // Account not active |
1815 | $this->fillJsonResponse( |
1816 | $request, |
1817 | $response, |
1818 | NotificationLevel::ERROR, |
1819 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationTitle'), |
1820 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationNotActivated'), |
1821 | [] |
1822 | ); |
1823 | |
1824 | $response->header->status = RequestStatusCode::R_403; |
1825 | |
1826 | return; |
1827 | } |
1828 | |
1829 | if (!empty($defaultGroupIds)) { |
1830 | // Create missing account / group relationships |
1831 | $this->createModelRelation( |
1832 | $account->id, |
1833 | $account->id, |
1834 | $defaultGroupIds, |
1835 | AccountMapper::class, |
1836 | 'groups', |
1837 | 'registration', |
1838 | $request->getOrigin() |
1839 | ); |
1840 | } |
1841 | } else { |
1842 | // New account |
1843 | $request->setData('status', AccountStatus::INACTIVE, true); |
1844 | $request->setData('type', AccountType::USER, true); |
1845 | $request->setData('create_profile', (string) true); |
1846 | $request->setData('name1', $request->hasData('name1') |
1847 | ? ($request->getDataString('name1') |
1848 | ) |
1849 | : ($request->hasData('user') |
1850 | ? $request->getDataString('user') |
1851 | : \explode('@', $request->getDataString('email') ?? '')[0]) |
1852 | , true); |
1853 | |
1854 | $request->setData('user', $request->hasData('user') |
1855 | ? $request->getDataString('user') |
1856 | : $request->getDataString('email') |
1857 | , true); |
1858 | |
1859 | $this->apiAccountCreate($request, $response, $data); |
1860 | |
1861 | /** @var Account $account */ |
1862 | $account = $response->getDataArray($request->uri->__toString())['response']; |
1863 | |
1864 | // Create confirmation pending entry |
1865 | $dataChange = new DataChange(); |
1866 | $dataChange->type = 'account'; |
1867 | $dataChange->createdBy = $account->id; |
1868 | $dataChange->data = '{"status": ' . AccountStatus::ACTIVE . '}'; |
1869 | |
1870 | $tries = 0; |
1871 | do { |
1872 | $dataChange->reHash(); |
1873 | $this->createModel($account->id, $dataChange, DataChangeMapper::class, 'datachange', $request->getOrigin()); |
1874 | |
1875 | ++$tries; |
1876 | } while ($dataChange->id === 0 && $tries < 5); |
1877 | |
1878 | $handler = $this->setUpServerMailHandler(); |
1879 | |
1880 | /** @var \Model\Setting[] $emailSettings */ |
1881 | $emailSettings = $this->app->appSettings->get( |
1882 | names: [SettingsEnum::MAIL_SERVER_ADDR, SettingsEnum::LOGIN_MAIL_REGISTRATION_TEMPLATE], |
1883 | module: 'Admin' |
1884 | ); |
1885 | |
1886 | /** @var \Modules\Messages\Models\Email $mail */ |
1887 | $mail = EmailMapper::get() |
1888 | ->with('l11n') |
1889 | ->where('id', (int) $emailSettings[SettingsEnum::LOGIN_MAIL_REGISTRATION_TEMPLATE]->content) |
1890 | ->where('l11n/language', $response->header->l11n->language) |
1891 | ->execute(); |
1892 | |
1893 | $mail->setFrom($emailSettings[SettingsEnum::MAIL_SERVER_ADDR]->content); |
1894 | $mail->addTo((string) $request->getData('email')); |
1895 | |
1896 | // @todo: load default l11n if no translation is available |
1897 | $mailL11n = $mail->getL11nByLanguage($response->header->l11n->language); |
1898 | |
1899 | $mail->subject = $mailL11n->subject; |
1900 | |
1901 | // @todo: improve, the /tld link could be api.myurl.com which of course is not the url of the respective app. |
1902 | // Maybe store the uri in the $app model? or store all urls in the config file |
1903 | $mail->body = \str_replace( |
1904 | [ |
1905 | '{confirmation_link}', |
1906 | '{user_name}', |
1907 | ], |
1908 | [ |
1909 | UriFactory::hasQuery('/' . \strtolower($app->name)) |
1910 | ? UriFactory::build('{/' . \strtolower($app->name) . '}/' . \strtolower($app->name) . '/signup/confirmation?hash=' . $dataChange->getHash()) |
1911 | : UriFactory::build('{/tld}/{/lang}/' . \strtolower($app->name) . '/signup/confirmation?hash=' . $dataChange->getHash()), |
1912 | $account->login, |
1913 | ], |
1914 | $mailL11n->body |
1915 | ); |
1916 | |
1917 | $mail->bodyAlt = \str_replace( |
1918 | [ |
1919 | '{confirmation_link}', |
1920 | '{user_name}', |
1921 | ], |
1922 | [ |
1923 | UriFactory::hasQuery('/' . \strtolower($app->name)) |
1924 | ? UriFactory::build('{/' . \strtolower($app->name) . '}/' . \strtolower($app->name) . '/signup/confirmation?hash=' . $dataChange->getHash()) |
1925 | : UriFactory::build('{/tld}/{/lang}/' . \strtolower($app->name) . '/signup/confirmation?hash=' . $dataChange->getHash()), |
1926 | $account->login, |
1927 | ], |
1928 | $mailL11n->bodyAlt |
1929 | ); |
1930 | |
1931 | $handler->send($mail); |
1932 | } |
1933 | |
1934 | // Create client |
1935 | if ($request->hasData('client')) { |
1936 | $client = $this->app->moduleManager->get('ClientManagement', 'Api') |
1937 | ->findClientForAccount($account->id, $request->getDataInt('unit')); |
1938 | |
1939 | if ($client === null) { |
1940 | $internalRequest = new HttpRequest(); |
1941 | $internalResponse = new HttpResponse(); |
1942 | |
1943 | $internalRequest->header->account = $account->id; |
1944 | $internalRequest->setData('account', $account->id); |
1945 | $internalRequest->setData('number', 100000 + $account->id); |
1946 | $internalRequest->setData('address', $request->getDataString('address') ?? ''); |
1947 | $internalRequest->setData('postal', $request->getDataString('postal') ?? ''); |
1948 | $internalRequest->setData('city', $request->getDataString('city') ?? ''); |
1949 | $internalRequest->setData('country', $request->getDataString('country')); |
1950 | $internalRequest->setData('state', $request->getDataString('state') ?? ''); |
1951 | $internalRequest->setData('vat_id', $request->getDataString('vat_id') ?? ''); |
1952 | $internalRequest->setData('unit', $request->getDataInt('unit')); |
1953 | |
1954 | $this->app->moduleManager->get('ClientManagement', 'Api')->apiClientCreate($internalRequest, $internalResponse); |
1955 | } |
1956 | } |
1957 | |
1958 | $this->fillJsonResponse( |
1959 | $request, |
1960 | $response, |
1961 | NotificationLevel::OK, |
1962 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationTitle'), |
1963 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'RegistrationSuccessful'), |
1964 | $account |
1965 | ); |
1966 | } |
1967 | |
1968 | /** |
1969 | * Method to validate account registration from request |
1970 | * |
1971 | * @param RequestAbstract $request Request |
1972 | * |
1973 | * @return array<string, bool> |
1974 | * |
1975 | * @since 1.0.0 |
1976 | */ |
1977 | private function validateRegistration(RequestAbstract $request) : array |
1978 | { |
1979 | $val = []; |
1980 | if (($val['email'] = $request->hasData('email') |
1981 | && !EmailValidator::isValid((string) $request->getData('email'))) |
1982 | || ($val['unit'] = !$request->hasData('unit')) |
1983 | || ($val['app'] = !$request->hasData('app')) |
1984 | || ($val['password'] = !$request->hasData('password')) |
1985 | ) { |
1986 | return $val; |
1987 | } |
1988 | |
1989 | return []; |
1990 | } |
1991 | |
1992 | /** |
1993 | * Api method to perform a pending model change |
1994 | * |
1995 | * @param RequestAbstract $request Request |
1996 | * @param ResponseAbstract $response Response |
1997 | * @param array $data Generic data |
1998 | * |
1999 | * @return void |
2000 | * |
2001 | * @api |
2002 | * @todo: maybe move to job/workflow??? This feels very much like a job/event especially if we make the 'type' an event-trigger |
2003 | * |
2004 | * @since 1.0.0 |
2005 | */ |
2006 | public function apiDataChange(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2007 | { |
2008 | if (!empty($val = $this->validateDataChange($request))) { |
2009 | $response->data['data_change'] = new FormValidation($val); |
2010 | $response->header->status = RequestStatusCode::R_400; |
2011 | |
2012 | return; |
2013 | } |
2014 | |
2015 | /** @var DataChange $dataChange */ |
2016 | $dataChange = DataChangeMapper::get()->where('hash', (string) $request->getData('hash'))->execute(); |
2017 | if ($dataChange->id === 0) { |
2018 | $response->header->status = RequestStatusCode::R_400; |
2019 | |
2020 | return; |
2021 | } |
2022 | |
2023 | switch ($dataChange->type) { |
2024 | case 'account': |
2025 | /** @var Account $old */ |
2026 | $old = AccountMapper::get()->where('id', $dataChange->createdBy)->execute(); |
2027 | $new = clone $old; |
2028 | |
2029 | $data = \json_decode($dataChange->data, true); |
2030 | if (!\is_array($data)) { |
2031 | break; |
2032 | } |
2033 | |
2034 | $new->setStatus((int) ($data['status'] ?? -1)); |
2035 | |
2036 | $this->updateModel($dataChange->createdBy, $old, $new, AccountMapper::class, 'datachange', $request->getOrigin()); |
2037 | $this->deleteModel($dataChange->createdBy, $dataChange, DataChangeMapper::class, 'datachange', $request->getOrigin()); |
2038 | |
2039 | break; |
2040 | } |
2041 | } |
2042 | |
2043 | /** |
2044 | * Method to validate account registration from request |
2045 | * |
2046 | * @param RequestAbstract $request Request |
2047 | * |
2048 | * @return array<string, bool> |
2049 | * |
2050 | * @since 1.0.0 |
2051 | */ |
2052 | private function validateDataChange(RequestAbstract $request) : array |
2053 | { |
2054 | $val = []; |
2055 | if (($val['hash'] = !$request->hasData('hash'))) { |
2056 | return $val; |
2057 | } |
2058 | |
2059 | return []; |
2060 | } |
2061 | |
2062 | /** |
2063 | * Create directory for an account |
2064 | * |
2065 | * @param int $id Account id |
2066 | * @param string $name Name of the directory/account |
2067 | * @param int $createdBy Creator of the directory |
2068 | * |
2069 | * @return Collection |
2070 | * |
2071 | * @since 1.0.0 |
2072 | */ |
2073 | private function createMediaDirForAccount(int $id, string $name, int $createdBy) : Collection |
2074 | { |
2075 | $collection = new Collection(); |
2076 | $collection->name = ((string) $id) . ' ' . $name; |
2077 | $collection->setVirtualPath('/Accounts'); |
2078 | $collection->setPath('/Modules/Media/Files/Accounts/' . ((string) $id)); |
2079 | $collection->createdBy = new NullAccount($createdBy); |
2080 | |
2081 | return $collection; |
2082 | } |
2083 | |
2084 | /** |
2085 | * Create profile for account |
2086 | * |
2087 | * @param Account $account Account to create profile for |
2088 | * @param RequestAbstract $request Request |
2089 | * |
2090 | * @return void |
2091 | * |
2092 | * @api |
2093 | * |
2094 | * @since 1.0.0 |
2095 | */ |
2096 | private function createProfileForAccount(Account $account, RequestAbstract $request) : void |
2097 | { |
2098 | // @todo: why do we need the following lines? |
2099 | if (($request->getDataString('password') ?? '') === '' |
2100 | || ($request->getDataString('user') ?? '') === '' |
2101 | ) { |
2102 | return; |
2103 | } |
2104 | |
2105 | $request->setData('iaccount-idlist', $account->id); |
2106 | |
2107 | $internalResponse = new HttpResponse(); |
2108 | |
2109 | $this->app->moduleManager->get('Profile', 'Api')->apiProfileCreate($request, $internalResponse); |
2110 | } |
2111 | |
2112 | /** |
2113 | * Method to create an account from a request |
2114 | * |
2115 | * @param RequestAbstract $request Request |
2116 | * |
2117 | * @return Account |
2118 | * |
2119 | * @since 1.0.0 |
2120 | */ |
2121 | private function createAccountFromRequest(RequestAbstract $request) : Account |
2122 | { |
2123 | $account = new Account(); |
2124 | $account->login = $request->getDataString('user') ?? ''; |
2125 | $account->name1 = $request->getDataString('name1') ?? ''; |
2126 | $account->name2 = $request->getDataString('name2') ?? ''; |
2127 | $account->name3 = $request->getDataString('name3') ?? ''; |
2128 | $account->setStatus($request->getDataInt('status') ?? AccountStatus::INACTIVE); |
2129 | $account->setType($request->getDataInt('type') ?? AccountType::USER); |
2130 | $account->setEmail($request->getDataString('email') ?? ''); |
2131 | $account->generatePassword($request->getDataString('password') ?? ''); |
2132 | |
2133 | if (!$request->hasData('locale')) { |
2134 | $account->l11n = Localization::fromJson( |
2135 | $this->app->l11nServer === null |
2136 | ? $request->header->l11n->toArray() |
2137 | : $this->app->l11nServer->toArray() |
2138 | ); |
2139 | } else { |
2140 | $locale = \explode('_', $request->getdataString('locale') ?? ''); |
2141 | |
2142 | $account->l11n |
2143 | ->loadFromLanguage( |
2144 | $locale[0] ?? $this->app->l11nServer->language, |
2145 | $locale[1] ?? $this->app->l11nServer->country |
2146 | ); |
2147 | } |
2148 | |
2149 | return $account; |
2150 | } |
2151 | |
2152 | /** |
2153 | * Api method to delete an account |
2154 | * |
2155 | * @param RequestAbstract $request Request |
2156 | * @param ResponseAbstract $response Response |
2157 | * @param array $data Generic data |
2158 | * |
2159 | * @return void |
2160 | * |
2161 | * @api |
2162 | * |
2163 | * @since 1.0.0 |
2164 | */ |
2165 | public function apiAccountDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2166 | { |
2167 | /** @var Account $account */ |
2168 | $account = AccountMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2169 | $this->deleteModel($request->header->account, $account, AccountMapper::class, 'account', $request->getOrigin()); |
2170 | $this->createStandardDeleteResponse($request, $response, $account); |
2171 | } |
2172 | |
2173 | /** |
2174 | * Api method to update an account |
2175 | * |
2176 | * @param RequestAbstract $request Request |
2177 | * @param ResponseAbstract $response Response |
2178 | * @param array $data Generic data |
2179 | * |
2180 | * @return void |
2181 | * |
2182 | * @api |
2183 | * |
2184 | * @since 1.0.0 |
2185 | */ |
2186 | public function apiAccountUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2187 | { |
2188 | /** @var Account $old */ |
2189 | $old = AccountMapper::get() |
2190 | ->where('id', (int) $request->getData('id')) |
2191 | ->execute(); |
2192 | |
2193 | $new = $this->updateAccountFromRequest($request, clone $old); |
2194 | $this->updateModel($request->header->account, $old, $new, AccountMapper::class, 'account', $request->getOrigin()); |
2195 | $this->createStandardUpdateResponse($request, $response, $new); |
2196 | } |
2197 | |
2198 | /** |
2199 | * Method to update an account from a request |
2200 | * |
2201 | * @param RequestAbstract $request Request |
2202 | * @param Account $account Account |
2203 | * @param bool $allowPassword Allow to change password |
2204 | * |
2205 | * @return Account |
2206 | * |
2207 | * @since 1.0.0 |
2208 | */ |
2209 | private function updateAccountFromRequest(RequestAbstract $request, Account $account, bool $allowPassword = false) : Account |
2210 | { |
2211 | $account->login = $request->getDataString('user') ?? $account->login; |
2212 | $account->name1 = $request->getDataString('name1') ?? $account->name1; |
2213 | $account->name2 = $request->getDataString('name2') ?? $account->name2; |
2214 | $account->name3 = $request->getDataString('name3') ?? $account->name3; |
2215 | $account->setEmail($request->getDataString('email') ?? $account->getEmail()); |
2216 | $account->setStatus($request->getDataInt('status') ?? $account->getStatus()); |
2217 | $account->setType($request->getDataInt('type') ?? $account->getType()); |
2218 | |
2219 | if ($allowPassword && $request->hasData('password')) { |
2220 | $account->generatePassword((string) $request->getData('password')); |
2221 | } |
2222 | |
2223 | return $account; |
2224 | } |
2225 | |
2226 | /** |
2227 | * Api method to update the module settigns |
2228 | * |
2229 | * @param RequestAbstract $request Request |
2230 | * @param ResponseAbstract $response Response |
2231 | * @param array $data Generic data |
2232 | * |
2233 | * @return void |
2234 | * |
2235 | * @api |
2236 | * |
2237 | * @since 1.0.0 |
2238 | */ |
2239 | public function apiModuleStatusUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2240 | { |
2241 | $module = $request->getDataString('module') ?? ''; |
2242 | $status = (int) $request->getData('status'); |
2243 | |
2244 | if (empty($module) || empty($status)) { |
2245 | $this->fillJsonResponse( |
2246 | $request, |
2247 | $response, |
2248 | NotificationLevel::WARNING, |
2249 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleStatusTitle'), |
2250 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'UnknownModuleOrStatusChange'), |
2251 | [] |
2252 | ); |
2253 | |
2254 | $response->header->status = RequestStatusCode::R_403; |
2255 | return; |
2256 | } |
2257 | |
2258 | /** @var \Modules\Admin\Models\Module $old */ |
2259 | $old = ModuleMapper::get()->where('id', $module)->execute(); |
2260 | |
2261 | $this->app->eventManager->triggerSimilar( |
2262 | 'PRE:Module:Admin-module-status-update', '', |
2263 | [ |
2264 | $request->header->account, |
2265 | ['status' => $status, 'module' => $module], |
2266 | ] |
2267 | ); |
2268 | switch ($status) { |
2269 | case ModuleStatusUpdateType::ACTIVATE: |
2270 | $done = $module === 'Admin' ? false : $this->app->moduleManager->activate($module); |
2271 | $msg = $done |
2272 | ? $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleActivatedSuccessful') |
2273 | : $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleActivatedFailure'); |
2274 | |
2275 | $new = clone $old; |
2276 | $new->setStatus(ModuleStatusUpdateType::ACTIVATE); |
2277 | ModuleMapper::update()->execute($new); |
2278 | |
2279 | break; |
2280 | case ModuleStatusUpdateType::DEACTIVATE: |
2281 | $done = $module === 'Admin' ? false : $this->app->moduleManager->deactivate($module); |
2282 | $msg = $done |
2283 | ? $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleDeactivatedSuccessful') |
2284 | : $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleDeactivatedFailure'); |
2285 | |
2286 | $new = clone $old; |
2287 | $new->setStatus(ModuleStatusUpdateType::DEACTIVATE); |
2288 | ModuleMapper::update()->execute($new); |
2289 | |
2290 | break; |
2291 | case ModuleStatusUpdateType::INSTALL: |
2292 | $done = $this->app->moduleManager->isInstalled($module); |
2293 | $msg = $done |
2294 | ? $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleInstalledSuccessful') |
2295 | : $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleInstalledFailure'); |
2296 | |
2297 | if ($done) { |
2298 | break; |
2299 | } |
2300 | |
2301 | if (!\is_file(__DIR__ . '/../../../Modules/' . $module . '/info.json')) { |
2302 | $msg = $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'UnknownModuleChange'); |
2303 | $done = false; |
2304 | break; |
2305 | } |
2306 | |
2307 | $moduleInfo = new ModuleInfo(__DIR__ . '/../../../Modules/' . $module . '/info.json'); |
2308 | $moduleInfo->load(); |
2309 | |
2310 | // install dependencies |
2311 | $dependencies = $moduleInfo->getDependencies(); |
2312 | foreach ($dependencies as $key => $_) { |
2313 | $iResponse = new HttpResponse(); |
2314 | $iRequest = new HttpRequest(new HttpUri('')); |
2315 | $iRequest->header->account = 1; |
2316 | $iRequest->setData('status', ModuleStatusUpdateType::INSTALL); |
2317 | $iRequest->setData('module', $key); |
2318 | |
2319 | $this->apiModuleStatusUpdate($iRequest, $iResponse); |
2320 | } |
2321 | |
2322 | // install module |
2323 | $moduleObj = new Module(); |
2324 | $moduleObj->id = $module; |
2325 | $moduleObj->theme = 'Default'; |
2326 | $moduleObj->path = $moduleInfo->getDirectory(); |
2327 | $moduleObj->version = $moduleInfo->getVersion(); |
2328 | $moduleObj->name = $moduleInfo->getExternalName(); |
2329 | |
2330 | $moduleObj->setStatus(ModuleStatus::AVAILABLE); |
2331 | |
2332 | $this->createModel($request->header->account, $moduleObj, ModuleMapper::class, 'module', $request->getOrigin()); |
2333 | |
2334 | $done = $this->app->moduleManager->install($module); |
2335 | $msg = $done |
2336 | ? $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleInstalledSuccessful') |
2337 | : $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleInstalledFailure'); |
2338 | |
2339 | $old = clone $moduleObj; |
2340 | $moduleObj->setStatus(ModuleStatus::ACTIVE); |
2341 | |
2342 | $this->updateModel($request->header->account, $old, $moduleObj, ModuleMapper::class, 'module', $request->getOrigin()); |
2343 | |
2344 | $queryLoad = new Builder($this->app->dbPool->get('insert')); |
2345 | $queryLoad->insert('module_load_pid', 'module_load_type', 'module_load_from', 'module_load_for', 'module_load_file') |
2346 | ->into('module_load'); |
2347 | |
2348 | $load = $moduleInfo->getLoad(); |
2349 | foreach ($load as $val) { |
2350 | foreach ($val['pid'] as $pid) { |
2351 | $queryLoad->values( |
2352 | \sha1(\str_replace('/', '', $pid)), |
2353 | (int) $val['type'], |
2354 | $val['from'], |
2355 | $val['for'], |
2356 | $val['file'] |
2357 | ); |
2358 | } |
2359 | } |
2360 | |
2361 | if (!empty($queryLoad->getValues())) { |
2362 | $queryLoad->execute(); |
2363 | } |
2364 | |
2365 | // install receiving from application (receiving from module is already installed during the module installation) |
2366 | $appManager = new ApplicationManager($this->app); |
2367 | $receiving = $appManager->getProvidingForModule($module); |
2368 | foreach ($receiving as $app => $modules) { |
2369 | foreach ($modules as $module) { |
2370 | $this->app->moduleManager->installProviding('/Web/' . $app, $module); |
2371 | } |
2372 | } |
2373 | |
2374 | break; |
2375 | case ModuleStatusUpdateType::UNINSTALL: |
2376 | $done = $module === 'Admin' ? false : $this->app->moduleManager->uninstall($module); |
2377 | $msg = $done |
2378 | ? $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleUninstalledSuccessful') |
2379 | : $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleUninstalledFailure'); |
2380 | |
2381 | $new = clone $old; |
2382 | $new->setStatus(ModuleStatusUpdateType::DELETE); |
2383 | ModuleMapper::delete()->execute($new); |
2384 | |
2385 | break; |
2386 | default: |
2387 | $done = false; |
2388 | $msg = $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'UnknownModuleStatusChange'); |
2389 | $response->header->status = RequestStatusCode::R_400; |
2390 | } |
2391 | |
2392 | if ($done) { |
2393 | $new = ModuleMapper::get()->where('id', $module)->execute(); |
2394 | |
2395 | $this->app->eventManager->triggerSimilar( |
2396 | 'POST:Module:Admin-module-status-update', '', |
2397 | [ |
2398 | $request->header->account, |
2399 | $old, $new, |
2400 | StringUtils::intHash(ModuleMapper::class), 'module-status', |
2401 | self::NAME, |
2402 | $module, |
2403 | '', |
2404 | $request->getOrigin(), |
2405 | ] |
2406 | ); |
2407 | } else { |
2408 | $response->header->status = RequestStatusCode::R_400; |
2409 | } |
2410 | |
2411 | $this->fillJsonResponse( |
2412 | $request, |
2413 | $response, |
2414 | $done ? NotificationLevel::OK : NotificationLevel::WARNING, |
2415 | $this->app->l11nManager->getText($response->header->l11n->language, 'Admin', 'Api', 'ModuleStatusTitle'), |
2416 | $msg, |
2417 | [] |
2418 | ); |
2419 | } |
2420 | |
2421 | /** |
2422 | * Api method to get a user permission |
2423 | * |
2424 | * @param RequestAbstract $request Request |
2425 | * @param ResponseAbstract $response Response |
2426 | * @param array $data Generic data |
2427 | * |
2428 | * @return void |
2429 | * |
2430 | * @api |
2431 | * |
2432 | * @since 1.0.0 |
2433 | */ |
2434 | public function apiAccountPermissionGet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2435 | { |
2436 | /** @var AccountPermission $account */ |
2437 | $account = AccountPermissionMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2438 | $this->createStandardReturnResponse($request, $response, $account); |
2439 | } |
2440 | |
2441 | /** |
2442 | * Api method to get a group permission |
2443 | * |
2444 | * @param RequestAbstract $request Request |
2445 | * @param ResponseAbstract $response Response |
2446 | * @param array $data Generic data |
2447 | * |
2448 | * @return void |
2449 | * |
2450 | * @api |
2451 | * |
2452 | * @since 1.0.0 |
2453 | */ |
2454 | public function apiGroupPermissionGet(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2455 | { |
2456 | /** @var GroupPermission $group */ |
2457 | $group = GroupPermissionMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2458 | $this->createStandardReturnResponse($request, $response, $group); |
2459 | } |
2460 | |
2461 | /** |
2462 | * Api method to delete a group permission |
2463 | * |
2464 | * @param RequestAbstract $request Request |
2465 | * @param ResponseAbstract $response Response |
2466 | * @param array $data Generic data |
2467 | * |
2468 | * @return void |
2469 | * |
2470 | * @api |
2471 | * |
2472 | * @since 1.0.0 |
2473 | */ |
2474 | public function apiGroupPermissionDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2475 | { |
2476 | if (!empty($val = $this->validateGroupPermissionDelete($request))) { |
2477 | $response->header->status = RequestStatusCode::R_400; |
2478 | $this->createInvalidDeleteResponse($request, $response, $val); |
2479 | |
2480 | return; |
2481 | } |
2482 | |
2483 | /** @var GroupPermission $permission */ |
2484 | $permission = GroupPermissionMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2485 | |
2486 | if ($permission->getGroup() === 3) { |
2487 | // admin group cannot be deleted |
2488 | $this->createInvalidDeleteResponse($request, $response, []); |
2489 | |
2490 | return; |
2491 | } |
2492 | |
2493 | $this->deleteModel($request->header->account, $permission, GroupPermissionMapper::class, 'group-permission', $request->getOrigin()); |
2494 | $this->createStandardDeleteResponse($request, $response, $permission); |
2495 | } |
2496 | |
2497 | /** |
2498 | * Api method to delete a user permission |
2499 | * |
2500 | * @param RequestAbstract $request Request |
2501 | * @param ResponseAbstract $response Response |
2502 | * @param array $data Generic data |
2503 | * |
2504 | * @return void |
2505 | * |
2506 | * @api |
2507 | * |
2508 | * @since 1.0.0 |
2509 | */ |
2510 | public function apiAccountPermissionDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2511 | { |
2512 | if (!empty($val = $this->validateAccountPermissionDelete($request))) { |
2513 | $response->header->status = RequestStatusCode::R_400; |
2514 | $this->createInvalidDeleteResponse($request, $response, $val); |
2515 | |
2516 | return; |
2517 | } |
2518 | |
2519 | /** @var AccountPermission $permission */ |
2520 | $permission = AccountPermissionMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2521 | $this->deleteModel($request->header->account, $permission, AccountPermissionMapper::class, 'user-permission', $request->getOrigin()); |
2522 | $this->createStandardDeleteResponse($request, $response, $permission); |
2523 | } |
2524 | |
2525 | /** |
2526 | * Api method to add a permission to a group |
2527 | * |
2528 | * @param RequestAbstract $request Request |
2529 | * @param ResponseAbstract $response Response |
2530 | * @param array $data Generic data |
2531 | * |
2532 | * @return void |
2533 | * |
2534 | * @api |
2535 | * |
2536 | * @since 1.0.0 |
2537 | */ |
2538 | public function apiAddGroupPermission(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2539 | { |
2540 | if (!empty($val = $this->validatePermissionCreate($request))) { |
2541 | $response->header->status = RequestStatusCode::R_400; |
2542 | $this->createInvalidCreateResponse($request, $response, $val); |
2543 | |
2544 | return; |
2545 | } |
2546 | |
2547 | if (((int) $request->getData('permissionref')) === 3) { |
2548 | // admin group cannot be deleted |
2549 | $this->createInvalidUpdateResponse($request, $response, []); |
2550 | |
2551 | return; |
2552 | } |
2553 | |
2554 | $permission = $this->createPermissionFromRequest($request); |
2555 | |
2556 | if (!($permission instanceof GroupPermission)) { |
2557 | $response->data['permission_create'] = new FormValidation($val); |
2558 | $response->header->status = RequestStatusCode::R_400; |
2559 | |
2560 | return; |
2561 | } |
2562 | |
2563 | $this->createModel($request->header->account, $permission, GroupPermissionMapper::class, 'group-permission', $request->getOrigin()); |
2564 | $this->createStandardCreateResponse($request, $response, $permission); |
2565 | } |
2566 | |
2567 | /** |
2568 | * Api method to add a permission to a account |
2569 | * |
2570 | * @param RequestAbstract $request Request |
2571 | * @param ResponseAbstract $response Response |
2572 | * @param array $data Generic data |
2573 | * |
2574 | * @return void |
2575 | * |
2576 | * @api |
2577 | * |
2578 | * @since 1.0.0 |
2579 | */ |
2580 | public function apiAddAccountPermission(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2581 | { |
2582 | if (!empty($val = $this->validatePermissionCreate($request))) { |
2583 | $response->header->status = RequestStatusCode::R_400; |
2584 | $this->createInvalidCreateResponse($request, $response, $val); |
2585 | |
2586 | return; |
2587 | } |
2588 | |
2589 | $permission = $this->createPermissionFromRequest($request); |
2590 | |
2591 | if (!($permission instanceof AccountPermission)) { |
2592 | $response->data['permission_create'] = new FormValidation($val); |
2593 | $response->header->status = RequestStatusCode::R_400; |
2594 | |
2595 | return; |
2596 | } |
2597 | |
2598 | $this->createModel($request->header->account, $permission, AccountPermissionMapper::class, 'account-permission', $request->getOrigin()); |
2599 | $this->createStandardCreateResponse($request, $response, $permission); |
2600 | } |
2601 | |
2602 | /** |
2603 | * Api method to add a permission to a account-model combination |
2604 | * |
2605 | * @param PermissionAbstract $permission Permission to create for account-model combination |
2606 | * @param int $account Account creating this model |
2607 | * @param string $ip Ip |
2608 | * |
2609 | * @return void |
2610 | * |
2611 | * @api |
2612 | * |
2613 | * @since 1.0.0 |
2614 | */ |
2615 | public function createAccountModelPermission(PermissionAbstract $permission, int $account, string $ip) : void |
2616 | { |
2617 | $this->createModel($account, $permission, AccountPermissionMapper::class, 'account-permission', $ip); |
2618 | } |
2619 | |
2620 | /** |
2621 | * Validate permission create request |
2622 | * |
2623 | * @param RequestAbstract $request Request |
2624 | * |
2625 | * @return array<string, bool> |
2626 | * |
2627 | * @since 1.0.0 |
2628 | */ |
2629 | private function validatePermissionCreate(RequestAbstract $request) : array |
2630 | { |
2631 | $val = []; |
2632 | if (($val['permissionowner'] = !PermissionOwner::isValidValue((int) $request->getData('permissionowner'))) |
2633 | || ($val['permissionref'] = !\is_numeric($request->getData('permissionref'))) |
2634 | ) { |
2635 | return $val; |
2636 | } |
2637 | |
2638 | return []; |
2639 | } |
2640 | |
2641 | /** |
2642 | * Method to create a permission from request. |
2643 | * |
2644 | * @param RequestAbstract $request Request |
2645 | * |
2646 | * @return AccountPermission|GroupPermission |
2647 | * |
2648 | * @since 1.0.0 |
2649 | */ |
2650 | public function createPermissionFromRequest(RequestAbstract $request) : PermissionAbstract |
2651 | { |
2652 | /** @var AccountPermission|GroupPermission $permission */ |
2653 | $permission = ($request->getDataInt('permissionowner')) === PermissionOwner::GROUP |
2654 | ? new GroupPermission((int) $request->getData('permissionref')) |
2655 | : new AccountPermission((int) $request->getData('permissionref')); |
2656 | |
2657 | $permission->unit = $request->getDataInt('permissionunit'); |
2658 | $permission->app = $request->getDataInt('permissionapp'); |
2659 | $permission->module = $request->getDataString('permissionmodule'); |
2660 | $permission->category = $request->getDataInt('permissioncategory'); |
2661 | $permission->element = $request->getDataInt('permissionelement'); |
2662 | $permission->component = $request->getDataInt('permissioncomponent'); |
2663 | $permission->setPermission( |
2664 | ($request->getDataInt('permissionread') ?? 0) |
2665 | | ($request->getDataInt('permissioncreate') ?? 0) |
2666 | | ($request->getDataInt('permissionupdate') ?? 0) |
2667 | | ($request->getDataInt('permissiondelete') ?? 0) |
2668 | | ($request->getDataInt('permissionpermission') ?? 0) |
2669 | ); |
2670 | |
2671 | return $permission; |
2672 | } |
2673 | |
2674 | /** |
2675 | * Api method to update a account permission |
2676 | * |
2677 | * @param RequestAbstract $request Request |
2678 | * @param ResponseAbstract $response Response |
2679 | * @param array $data Generic data |
2680 | * |
2681 | * @return void |
2682 | * |
2683 | * @api |
2684 | * |
2685 | * @since 1.0.0 |
2686 | */ |
2687 | public function apiAccountPermissionUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2688 | { |
2689 | if (!empty($val = $this->validateAccountPermissionUpdate($request))) { |
2690 | $response->header->status = RequestStatusCode::R_400; |
2691 | $this->createInvalidUpdateResponse($request, $response, $val); |
2692 | |
2693 | return; |
2694 | } |
2695 | |
2696 | /** @var AccountPermission $old */ |
2697 | $old = AccountPermissionMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2698 | |
2699 | /** @var AccountPermission $new */ |
2700 | $new = $this->updatePermissionFromRequest($request, clone $old); |
2701 | |
2702 | $this->updateModel($request->header->account, $old, $new, AccountPermissionMapper::class, 'account-permission', $request->getOrigin()); |
2703 | $this->createStandardUpdateResponse($request, $response, $new); |
2704 | } |
2705 | |
2706 | /** |
2707 | * Api method to update a group permission |
2708 | * |
2709 | * @param RequestAbstract $request Request |
2710 | * @param ResponseAbstract $response Response |
2711 | * @param array $data Generic data |
2712 | * |
2713 | * @return void |
2714 | * |
2715 | * @api |
2716 | * |
2717 | * @since 1.0.0 |
2718 | */ |
2719 | public function apiGroupPermissionUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2720 | { |
2721 | if (!empty($val = $this->validateGroupPermissionUpdate($request))) { |
2722 | $response->header->status = RequestStatusCode::R_400; |
2723 | $this->createInvalidUpdateResponse($request, $response, $val); |
2724 | |
2725 | return; |
2726 | } |
2727 | |
2728 | /** @var GroupPermission $old */ |
2729 | $old = GroupPermissionMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
2730 | |
2731 | if ($old->getGroup() === 3) { |
2732 | // admin group cannot be deleted |
2733 | $this->createInvalidUpdateResponse($request, $response, []); |
2734 | |
2735 | return; |
2736 | } |
2737 | |
2738 | /** @var GroupPermission $new */ |
2739 | $new = $this->updatePermissionFromRequest($request, clone $old); |
2740 | |
2741 | $this->updateModel($request->header->account, $old, $new, GroupPermissionMapper::class, 'group-permission', $request->getOrigin()); |
2742 | $this->createStandardUpdateResponse($request, $response, $new); |
2743 | } |
2744 | |
2745 | /** |
2746 | * Method to update a group permission from a request |
2747 | * |
2748 | * @param RequestAbstract $request Request |
2749 | * @param PermissionAbstract $permission Permission model |
2750 | * |
2751 | * @return PermissionAbstract |
2752 | * |
2753 | * @since 1.0.0 |
2754 | */ |
2755 | private function updatePermissionFromRequest(RequestAbstract $request, PermissionAbstract $permission) : PermissionAbstract |
2756 | { |
2757 | $permission->unit = $request->getDataInt('permissionunit') ?? $permission->unit; |
2758 | $permission->app = $request->getDataInt('permissionapp') ?? $permission->app; |
2759 | $permission->module = $request->getDataString('permissionmodule') ?? $permission->module; |
2760 | $permission->category = $request->getDataInt('permissioncategory') ?? $permission->category; |
2761 | $permission->element = $request->getDataInt('permissionelement') ?? $permission->element; |
2762 | $permission->component = $request->getDataInt('permissioncomponent') ?? $permission->component; |
2763 | $permission->setPermission(($request->getDataInt('permissioncreate') ?? 0) |
2764 | | ($request->getDataInt('permissionread') ?? 0) |
2765 | | ($request->getDataInt('permissionupdate') ?? 0) |
2766 | | ($request->getDataInt('permissiondelete') ?? 0) |
2767 | | ($request->getDataInt('permissionpermission') ?? 0)); |
2768 | |
2769 | return $permission; |
2770 | } |
2771 | |
2772 | /** |
2773 | * Api method to add a group to an account |
2774 | * |
2775 | * @param RequestAbstract $request Request |
2776 | * @param ResponseAbstract $response Response |
2777 | * @param array $data Generic data |
2778 | * |
2779 | * @return void |
2780 | * |
2781 | * @api |
2782 | * |
2783 | * @since 1.0.0 |
2784 | */ |
2785 | public function apiAddGroupToAccount(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2786 | { |
2787 | if (!empty($val = $this->validateAddGroupToAccount($request))) { |
2788 | $response->header->status = RequestStatusCode::R_400; |
2789 | $this->createInvalidAddResponse($request, $response, $val); |
2790 | |
2791 | return; |
2792 | } |
2793 | |
2794 | $account = (int) $request->getData('account'); |
2795 | $groups = [$request->getDataInt('account-list') ?? 0]; |
2796 | |
2797 | $this->createModelRelation($request->header->account, $account, $groups, AccountMapper::class, 'groups', 'account-group', $request->getOrigin()); |
2798 | $this->createStandardAddResponse($request, $response, $groups); |
2799 | } |
2800 | |
2801 | /** |
2802 | * Validate adding a group to an account request |
2803 | * |
2804 | * @param RequestAbstract $request Request |
2805 | * |
2806 | * @return array<string, bool> |
2807 | * |
2808 | * @since 1.0.0 |
2809 | */ |
2810 | private function validateAddGroupToAccount(RequestAbstract $request) : array |
2811 | { |
2812 | $val = []; |
2813 | if (($val['account'] = !$request->hasData('account')) |
2814 | || ($val['accountlist'] = !$request->hasData('account-list')) |
2815 | ) { |
2816 | return $val; |
2817 | } |
2818 | |
2819 | return []; |
2820 | } |
2821 | |
2822 | /** |
2823 | * Api method to add an account to a group |
2824 | * |
2825 | * @param RequestAbstract $request Request |
2826 | * @param ResponseAbstract $response Response |
2827 | * @param array $data Generic data |
2828 | * |
2829 | * @return void |
2830 | * |
2831 | * @api |
2832 | * |
2833 | * @since 1.0.0 |
2834 | */ |
2835 | public function apiAddAccountToGroup(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2836 | { |
2837 | if (!empty($val = $this->validateAddAccountToGroup($request))) { |
2838 | $response->header->status = RequestStatusCode::R_400; |
2839 | $this->createInvalidAddResponse($request, $response, $val); |
2840 | |
2841 | return; |
2842 | } |
2843 | |
2844 | $group = (int) $request->getData('group'); |
2845 | $accounts = [$request->getDataInt('group-list') ?? 0]; |
2846 | |
2847 | $this->createModelRelation($request->header->account, $group, $accounts, GroupMapper::class, 'accounts', 'group-account', $request->getOrigin()); |
2848 | $this->createStandardAddResponse($request, $response, $accounts); |
2849 | } |
2850 | |
2851 | /** |
2852 | * Validate adding an account to a group request |
2853 | * |
2854 | * @param RequestAbstract $request Request |
2855 | * |
2856 | * @return array<string, bool> |
2857 | * |
2858 | * @since 1.0.0 |
2859 | */ |
2860 | private function validateAddAccountToGroup(RequestAbstract $request) : array |
2861 | { |
2862 | $val = []; |
2863 | if (($val['group'] = !$request->hasData('group')) |
2864 | || ($val['grouplist'] = !$request->hasData('group-list')) |
2865 | ) { |
2866 | return $val; |
2867 | } |
2868 | |
2869 | return []; |
2870 | } |
2871 | |
2872 | /** |
2873 | * Api method to add a group to an account |
2874 | * |
2875 | * @param RequestAbstract $request Request |
2876 | * @param ResponseAbstract $response Response |
2877 | * @param array $data Generic data |
2878 | * |
2879 | * @return void |
2880 | * |
2881 | * @api |
2882 | * |
2883 | * @since 1.0.0 |
2884 | */ |
2885 | public function apiDeleteGroupFromAccount(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2886 | { |
2887 | $account = (int) $request->getData('account'); |
2888 | $groups = \array_map('intval', $request->getDataList('igroup-idlist')); |
2889 | |
2890 | if (\in_array(3, $groups) && $account === $request->header->account) { |
2891 | // admin group cannot be deleted |
2892 | $this->createInvalidRemoveResponse($request, $response, []); |
2893 | |
2894 | return; |
2895 | } |
2896 | |
2897 | $this->deleteModelRelation($request->header->account, $account, $groups, AccountMapper::class, 'groups', 'account-group', $request->getOrigin()); |
2898 | $this->createStandardRemoveResponse($request, $response, $groups); |
2899 | } |
2900 | |
2901 | /** |
2902 | * Api method to add an account to a group |
2903 | * |
2904 | * @param RequestAbstract $request Request |
2905 | * @param ResponseAbstract $response Response |
2906 | * @param array $data Generic data |
2907 | * |
2908 | * @return void |
2909 | * |
2910 | * @api |
2911 | * |
2912 | * @since 1.0.0 |
2913 | */ |
2914 | public function apiDeleteAccountFromGroup(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2915 | { |
2916 | $group = (int) $request->getData('group'); |
2917 | $accounts = \array_map('intval', $request->getDataList('iaccount-idlist')); |
2918 | |
2919 | if (\in_array($request->header->account, $accounts) && $group === 3) { |
2920 | // admin group cannot be deleted |
2921 | $this->createInvalidRemoveResponse($request, $response, []); |
2922 | |
2923 | return; |
2924 | } |
2925 | |
2926 | $this->deleteModelRelation($request->header->account, $group, $accounts, GroupMapper::class, 'accounts', 'group-account', $request->getOrigin()); |
2927 | $this->createStandardRemoveResponse($request, $response, $accounts); |
2928 | } |
2929 | |
2930 | /** |
2931 | * Api re-init routes |
2932 | * |
2933 | * @param RequestAbstract $request Request |
2934 | * @param ResponseAbstract $response Response |
2935 | * @param array $data Generic data |
2936 | * |
2937 | * @return void |
2938 | * |
2939 | * @api |
2940 | * |
2941 | * @since 1.0.0 |
2942 | */ |
2943 | public function apiReInit(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2944 | { |
2945 | $directories = \glob(__DIR__ . '/../../../Web/*', \GLOB_ONLYDIR); |
2946 | |
2947 | if ($directories !== false) { |
2948 | foreach ($directories as $directory) { |
2949 | if (\is_file($path = $directory . '/Routes.php')) { |
2950 | \file_put_contents($path, '<?php return [];'); |
2951 | } |
2952 | |
2953 | if (\is_file($path = $directory . '/Hooks.php')) { |
2954 | \file_put_contents($path, '<?php return [];'); |
2955 | } |
2956 | } |
2957 | } |
2958 | |
2959 | if (\is_file($path = __DIR__ . '/../../../Cli/Routes.php')) { |
2960 | \file_put_contents($path, '<?php return [];'); |
2961 | } |
2962 | |
2963 | if (\is_file($path = __DIR__ . '/../../../Socket/Routes.php')) { |
2964 | \file_put_contents($path, '<?php return [];'); |
2965 | } |
2966 | |
2967 | $installedModules = $this->app->moduleManager->getActiveModules(); |
2968 | foreach ($installedModules as $name => $module) { |
2969 | $this->app->moduleManager->reInit($name); |
2970 | } |
2971 | } |
2972 | |
2973 | /** |
2974 | * Api check for updates |
2975 | * |
2976 | * @param RequestAbstract $request Request |
2977 | * @param ResponseAbstract $response Response |
2978 | * @param array $data Generic data |
2979 | * |
2980 | * @return void |
2981 | * |
2982 | * @api |
2983 | * |
2984 | * @since 1.0.0 |
2985 | */ |
2986 | public function apiCheckForUpdates(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
2987 | { |
2988 | // this is only a temp... in the future this logic will change but for current purposes this is the easiest way to implement updates |
2989 | $request = new HttpRequest(new HttpUri('https://api.github.com/repos/Karaka/Updates/contents')); |
2990 | $request->setMethod(RequestMethod::GET); |
2991 | $request->header->set('User-Agent', 'spl1nes'); |
2992 | |
2993 | $updateFilesJson = Rest::request($request)->getJsonData(); |
2994 | |
2995 | /** @var array<string, array<string, mixed>> */ |
2996 | $toUpdate = []; |
2997 | |
2998 | foreach ($updateFilesJson as $file) { |
2999 | $name = \explode('_', $file['name']); |
3000 | $path = ''; |
3001 | |
3002 | if (\is_dir(__DIR__ . '/../../../' . $name[0])) { |
3003 | $path = __DIR__ . '/../../../' . $name[0]; |
3004 | } elseif (\is_dir(__DIR__ . '/../../' . $name[0])) { |
3005 | $path = __DIR__ . '/../../' . $name[0]; |
3006 | } |
3007 | |
3008 | if ($path === '') { |
3009 | return; |
3010 | } |
3011 | |
3012 | $currentVersion = ''; |
3013 | $remoteVersion = \substr($file[1], 0, -5); |
3014 | |
3015 | if (Version::compare($currentVersion, $remoteVersion) < 0) { |
3016 | $toUpdate[$name[0]][$remoteVersion] = $file; |
3017 | |
3018 | \uksort($toUpdate[$name[0]], [Version::class, 'compare']); |
3019 | } |
3020 | } |
3021 | |
3022 | $this->apiUpdate($toUpdate); |
3023 | } |
3024 | |
3025 | /** |
3026 | * Api update file |
3027 | * |
3028 | * @param RequestAbstract $request Request |
3029 | * @param ResponseAbstract $response Response |
3030 | * @param array $data Generic data |
3031 | * |
3032 | * @return void |
3033 | * |
3034 | * @api |
3035 | * |
3036 | * @since 1.0.0 |
3037 | */ |
3038 | public function apiUpdateFile(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3039 | { |
3040 | $this->apiUpdate([[ |
3041 | 'name' => 'temp.json', |
3042 | 'download_url' => 'https://raw.githubusercontent.com/Karaka-Management/' . ($request->getDataString('url') ?? ''), |
3043 | ]]); |
3044 | } |
3045 | |
3046 | /** |
3047 | * Update the system or a module |
3048 | * |
3049 | * @param array $toUpdate Array of updte resources |
3050 | * |
3051 | * @return void |
3052 | * |
3053 | * @since 1.0.0 |
3054 | */ |
3055 | private function apiUpdate(array $toUpdate) : void |
3056 | { |
3057 | // this is only a temp... in the future this logic will change but for current purposes this is the easiest way to implement updates |
3058 | |
3059 | foreach ($toUpdate as $update) { |
3060 | $dest = __DIR__ . '/../Updates/' . \explode('.', $update['name'])[0]; |
3061 | \mkdir($dest); |
3062 | $this->downloadUpdate($update['download_url'], $dest . '/' . $update['name']); |
3063 | $this->runUpdate($dest . '/' . $update['name']); |
3064 | } |
3065 | } |
3066 | |
3067 | /** |
3068 | * Package to download |
3069 | * |
3070 | * @param string $url Url to download from |
3071 | * @param string $dest Local destination of the download |
3072 | * |
3073 | * @return void |
3074 | * |
3075 | * @since 1.0.0 |
3076 | */ |
3077 | private function downloadUpdate(string $url, string $dest) : void |
3078 | { |
3079 | // this is only a temp... in the future this logic will change but for current purposes this is the easiest way to implement updates |
3080 | $request = new HttpRequest(new HttpUri($url)); |
3081 | $request->setMethod(RequestMethod::GET); |
3082 | |
3083 | $updateFile = Rest::request($request)->getBody(); |
3084 | File::put($dest, $updateFile); |
3085 | } |
3086 | |
3087 | /** |
3088 | * Run the update |
3089 | * |
3090 | * @param string $updateFile Update file/package |
3091 | * |
3092 | * @return void |
3093 | * |
3094 | * @since 1.0.0 |
3095 | */ |
3096 | private function runUpdate(string $updateFile) : void |
3097 | { |
3098 | } |
3099 | |
3100 | /** |
3101 | * Routing end-point for application behaviour. |
3102 | * |
3103 | * @param RequestAbstract $request Request |
3104 | * @param ResponseAbstract $response Response |
3105 | * @param array $data Generic data |
3106 | * |
3107 | * @return void |
3108 | * |
3109 | * @api |
3110 | * |
3111 | * @since 1.0.0 |
3112 | */ |
3113 | public function apiContactCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3114 | { |
3115 | if (!empty($val = $this->validateContactCreate($request))) { |
3116 | $response->header->status = RequestStatusCode::R_400; |
3117 | $this->createInvalidCreateResponse($request, $response, $val); |
3118 | |
3119 | return; |
3120 | } |
3121 | |
3122 | $contact = $this->createContactFromRequest($request); |
3123 | |
3124 | $this->createModel($request->header->account, $contact, ContactMapper::class, 'account_contact', $request->getOrigin()); |
3125 | |
3126 | $this->createModelRelation( |
3127 | $request->header->account, |
3128 | (int) $request->getData('account'), |
3129 | $contact->id, |
3130 | AccountMapper::class, 'contacts', '', $request->getOrigin() |
3131 | ); |
3132 | |
3133 | $this->createStandardCreateResponse($request, $response, $contact); |
3134 | } |
3135 | |
3136 | /** |
3137 | * Validate contact element create request |
3138 | * |
3139 | * @param RequestAbstract $request Request |
3140 | * |
3141 | * @return array<string, bool> |
3142 | * |
3143 | * @since 1.0.0 |
3144 | */ |
3145 | public function validateContactCreate(RequestAbstract $request) : array |
3146 | { |
3147 | $val = []; |
3148 | if (($val['account'] = !$request->hasData('account')) |
3149 | || ($val['type'] = !\is_numeric($request->getData('type'))) |
3150 | || ($val['content'] = !$request->hasData('content')) |
3151 | ) { |
3152 | return $val; |
3153 | } |
3154 | |
3155 | return []; |
3156 | } |
3157 | |
3158 | /** |
3159 | * Method to create a account element from request. |
3160 | * |
3161 | * @param RequestAbstract $request Request |
3162 | * |
3163 | * @return Contact |
3164 | * |
3165 | * @since 1.0.0 |
3166 | */ |
3167 | public function createContactFromRequest(RequestAbstract $request) : Contact |
3168 | { |
3169 | /** @var Contact $element */ |
3170 | $element = new Contact(); |
3171 | $element->setType($request->getDataInt('type') ?? 0); |
3172 | $element->setSubtype($request->getDataInt('subtype') ?? 0); |
3173 | $element->content = $request->getDataString('content') ?? ''; |
3174 | $element->account = $request->getDataInt('account') ?? 0; |
3175 | |
3176 | return $element; |
3177 | } |
3178 | |
3179 | /** |
3180 | * Api method to delete Settings |
3181 | * |
3182 | * @param RequestAbstract $request Request |
3183 | * @param ResponseAbstract $response Response |
3184 | * @param array $data Generic data |
3185 | * |
3186 | * @return void |
3187 | * |
3188 | * @api |
3189 | * |
3190 | * @since 1.0.0 |
3191 | */ |
3192 | public function apiSettingsDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3193 | { |
3194 | if (!empty($val = $this->validateSettingsDelete($request))) { |
3195 | $response->header->status = RequestStatusCode::R_400; |
3196 | $this->createInvalidDeleteResponse($request, $response, $val); |
3197 | |
3198 | return; |
3199 | } |
3200 | |
3201 | $settings = SettingMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
3202 | $this->deleteModel($request->header->account, $settings, SettingMapper::class, 'settings', $request->getOrigin()); |
3203 | $this->createStandardDeleteResponse($request, $response, $settings); |
3204 | } |
3205 | |
3206 | /** |
3207 | * Validate Settings delete request |
3208 | * |
3209 | * @param RequestAbstract $request Request |
3210 | * |
3211 | * @return array<string, bool> |
3212 | * |
3213 | * @todo: implement |
3214 | * |
3215 | * @since 1.0.0 |
3216 | */ |
3217 | private function validateSettingsDelete(RequestAbstract $request) : array |
3218 | { |
3219 | $val = []; |
3220 | if (($val['id'] = !$request->hasData('id'))) { |
3221 | return $val; |
3222 | } |
3223 | |
3224 | return []; |
3225 | } |
3226 | |
3227 | /** |
3228 | * Api method to update Application |
3229 | * |
3230 | * @param RequestAbstract $request Request |
3231 | * @param ResponseAbstract $response Response |
3232 | * @param array $data Generic data |
3233 | * |
3234 | * @return void |
3235 | * |
3236 | * @api |
3237 | * |
3238 | * @since 1.0.0 |
3239 | */ |
3240 | public function apiApplicationUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3241 | { |
3242 | if (!empty($val = $this->validateApplicationUpdate($request))) { |
3243 | $response->header->status = RequestStatusCode::R_400; |
3244 | $this->createInvalidUpdateResponse($request, $response, $val); |
3245 | |
3246 | return; |
3247 | } |
3248 | |
3249 | /** @var App $old */ |
3250 | $old = AppMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
3251 | $new = $this->updateApplicationFromRequest($request, clone $old); |
3252 | |
3253 | $this->updateModel($request->header->account, $old, $new, AppMapper::class, 'application', $request->getOrigin()); |
3254 | $this->createStandardUpdateResponse($request, $response, $new); |
3255 | } |
3256 | |
3257 | /** |
3258 | * Method to update Application from request. |
3259 | * |
3260 | * @param RequestAbstract $request Request |
3261 | * @param App $new Model to modify |
3262 | * |
3263 | * @return App |
3264 | * |
3265 | * @todo: implement |
3266 | * |
3267 | * @since 1.0.0 |
3268 | */ |
3269 | public function updateApplicationFromRequest(RequestAbstract $request, App $new) : App |
3270 | { |
3271 | return $new; |
3272 | } |
3273 | |
3274 | /** |
3275 | * Validate Application update request |
3276 | * |
3277 | * @param RequestAbstract $request Request |
3278 | * |
3279 | * @return array<string, bool> |
3280 | * |
3281 | * @todo: implement |
3282 | * |
3283 | * @since 1.0.0 |
3284 | */ |
3285 | private function validateApplicationUpdate(RequestAbstract $request) : array |
3286 | { |
3287 | $val = []; |
3288 | if (($val['id'] = !$request->hasData('id'))) { |
3289 | return $val; |
3290 | } |
3291 | |
3292 | return []; |
3293 | } |
3294 | |
3295 | /** |
3296 | * Api method to delete Application |
3297 | * |
3298 | * @param RequestAbstract $request Request |
3299 | * @param ResponseAbstract $response Response |
3300 | * @param array $data Generic data |
3301 | * |
3302 | * @return void |
3303 | * |
3304 | * @api |
3305 | * |
3306 | * @since 1.0.0 |
3307 | */ |
3308 | public function apiApplicationDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3309 | { |
3310 | if (!empty($val = $this->validateApplicationDelete($request))) { |
3311 | $response->header->status = RequestStatusCode::R_400; |
3312 | $this->createInvalidDeleteResponse($request, $response, $val); |
3313 | |
3314 | return; |
3315 | } |
3316 | |
3317 | /** @var \Modules\Admin\Models\App $application */ |
3318 | $application = AppMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
3319 | $this->deleteModel($request->header->account, $application, AppMapper::class, 'application', $request->getOrigin()); |
3320 | $this->createStandardDeleteResponse($request, $response, $application); |
3321 | } |
3322 | |
3323 | /** |
3324 | * Validate Application delete request |
3325 | * |
3326 | * @param RequestAbstract $request Request |
3327 | * |
3328 | * @return array<string, bool> |
3329 | * |
3330 | * @todo: implement |
3331 | * |
3332 | * @since 1.0.0 |
3333 | */ |
3334 | private function validateApplicationDelete(RequestAbstract $request) : array |
3335 | { |
3336 | $val = []; |
3337 | if (($val['id'] = !$request->hasData('id'))) { |
3338 | return $val; |
3339 | } |
3340 | |
3341 | return []; |
3342 | } |
3343 | |
3344 | /** |
3345 | * Validate GroupPermission update request |
3346 | * |
3347 | * @param RequestAbstract $request Request |
3348 | * |
3349 | * @return array<string, bool> |
3350 | * |
3351 | * @todo: implement |
3352 | * |
3353 | * @since 1.0.0 |
3354 | */ |
3355 | private function validateGroupPermissionUpdate(RequestAbstract $request) : array |
3356 | { |
3357 | $val = []; |
3358 | if (($val['id'] = !$request->hasData('id'))) { |
3359 | return $val; |
3360 | } |
3361 | |
3362 | return []; |
3363 | } |
3364 | |
3365 | /** |
3366 | * Validate GroupPermission delete request |
3367 | * |
3368 | * @param RequestAbstract $request Request |
3369 | * |
3370 | * @return array<string, bool> |
3371 | * |
3372 | * @todo: implement |
3373 | * |
3374 | * @since 1.0.0 |
3375 | */ |
3376 | private function validateGroupPermissionDelete(RequestAbstract $request) : array |
3377 | { |
3378 | $val = []; |
3379 | if (($val['id'] = !$request->hasData('id'))) { |
3380 | return $val; |
3381 | } |
3382 | |
3383 | return []; |
3384 | } |
3385 | |
3386 | /** |
3387 | * Method to update AccountPermission from request. |
3388 | * |
3389 | * @param RequestAbstract $request Request |
3390 | * @param AccountPermission $new Model to modify |
3391 | * |
3392 | * @return AccountPermission |
3393 | * |
3394 | * @todo: implement |
3395 | * |
3396 | * @since 1.0.0 |
3397 | */ |
3398 | public function updateAccountPermissionFromRequest(RequestAbstract $request, AccountPermission $new) : AccountPermission |
3399 | { |
3400 | return $new; |
3401 | } |
3402 | |
3403 | /** |
3404 | * Validate AccountPermission update request |
3405 | * |
3406 | * @param RequestAbstract $request Request |
3407 | * |
3408 | * @return array<string, bool> |
3409 | * |
3410 | * @todo: implement |
3411 | * |
3412 | * @since 1.0.0 |
3413 | */ |
3414 | private function validateAccountPermissionUpdate(RequestAbstract $request) : array |
3415 | { |
3416 | $val = []; |
3417 | if (($val['id'] = !$request->hasData('id'))) { |
3418 | return $val; |
3419 | } |
3420 | |
3421 | return []; |
3422 | } |
3423 | |
3424 | /** |
3425 | * Validate AccountPermission delete request |
3426 | * |
3427 | * @param RequestAbstract $request Request |
3428 | * |
3429 | * @return array<string, bool> |
3430 | * |
3431 | * @todo: implement |
3432 | * |
3433 | * @since 1.0.0 |
3434 | */ |
3435 | private function validateAccountPermissionDelete(RequestAbstract $request) : array |
3436 | { |
3437 | $val = []; |
3438 | if (($val['id'] = !$request->hasData('id'))) { |
3439 | return $val; |
3440 | } |
3441 | |
3442 | return []; |
3443 | } |
3444 | |
3445 | /** |
3446 | * Api method to update Contact |
3447 | * |
3448 | * @param RequestAbstract $request Request |
3449 | * @param ResponseAbstract $response Response |
3450 | * @param array $data Generic data |
3451 | * |
3452 | * @return void |
3453 | * |
3454 | * @api |
3455 | * |
3456 | * @since 1.0.0 |
3457 | */ |
3458 | public function apiContactUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3459 | { |
3460 | if (!empty($val = $this->validateContactUpdate($request))) { |
3461 | $response->header->status = RequestStatusCode::R_400; |
3462 | $this->createInvalidUpdateResponse($request, $response, $val); |
3463 | |
3464 | return; |
3465 | } |
3466 | |
3467 | /** @var Contact $old */ |
3468 | $old = ContactMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
3469 | $new = $this->updateContactFromRequest($request, clone $old); |
3470 | |
3471 | $this->updateModel($request->header->account, $old, $new, ContactMapper::class, 'contact', $request->getOrigin()); |
3472 | $this->createStandardUpdateResponse($request, $response, $new); |
3473 | } |
3474 | |
3475 | /** |
3476 | * Method to update Contact from request. |
3477 | * |
3478 | * @param RequestAbstract $request Request |
3479 | * @param Contact $new Model to modify |
3480 | * |
3481 | * @return Contact |
3482 | * |
3483 | * @todo: implement |
3484 | * |
3485 | * @since 1.0.0 |
3486 | */ |
3487 | public function updateContactFromRequest(RequestAbstract $request, Contact $new) : Contact |
3488 | { |
3489 | return $new; |
3490 | } |
3491 | |
3492 | /** |
3493 | * Validate Contact update request |
3494 | * |
3495 | * @param RequestAbstract $request Request |
3496 | * |
3497 | * @return array<string, bool> |
3498 | * |
3499 | * @todo: implement |
3500 | * |
3501 | * @since 1.0.0 |
3502 | */ |
3503 | private function validateContactUpdate(RequestAbstract $request) : array |
3504 | { |
3505 | $val = []; |
3506 | if (($val['id'] = !$request->hasData('id'))) { |
3507 | return $val; |
3508 | } |
3509 | |
3510 | return []; |
3511 | } |
3512 | |
3513 | /** |
3514 | * Api method to delete Contact |
3515 | * |
3516 | * @param RequestAbstract $request Request |
3517 | * @param ResponseAbstract $response Response |
3518 | * @param array $data Generic data |
3519 | * |
3520 | * @return void |
3521 | * |
3522 | * @api |
3523 | * |
3524 | * @since 1.0.0 |
3525 | */ |
3526 | public function apiContactDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3527 | { |
3528 | if (!empty($val = $this->validateContactDelete($request))) { |
3529 | $response->header->status = RequestStatusCode::R_400; |
3530 | $this->createInvalidDeleteResponse($request, $response, $val); |
3531 | |
3532 | return; |
3533 | } |
3534 | |
3535 | /** @var \Modules\Admin\Models\Contact $contact */ |
3536 | $contact = ContactMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
3537 | $this->deleteModel($request->header->account, $contact, ContactMapper::class, 'contact', $request->getOrigin()); |
3538 | $this->createStandardDeleteResponse($request, $response, $contact); |
3539 | } |
3540 | |
3541 | /** |
3542 | * Validate Contact delete request |
3543 | * |
3544 | * @param RequestAbstract $request Request |
3545 | * |
3546 | * @return array<string, bool> |
3547 | * |
3548 | * @todo: implement |
3549 | * |
3550 | * @since 1.0.0 |
3551 | */ |
3552 | private function validateContactDelete(RequestAbstract $request) : array |
3553 | { |
3554 | $val = []; |
3555 | if (($val['id'] = !$request->hasData('id'))) { |
3556 | return $val; |
3557 | } |
3558 | |
3559 | return []; |
3560 | } |
3561 | |
3562 | /** |
3563 | * Api method to create Data |
3564 | * |
3565 | * @param RequestAbstract $request Request |
3566 | * @param ResponseAbstract $response Response |
3567 | * @param array $data Generic data |
3568 | * |
3569 | * @return void |
3570 | * |
3571 | * @api |
3572 | * |
3573 | * @since 1.0.0 |
3574 | */ |
3575 | public function apiDataChangeCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3576 | { |
3577 | if (!empty($val = $this->validateDataChangeCreate($request))) { |
3578 | $response->header->status = RequestStatusCode::R_400; |
3579 | $this->createInvalidCreateResponse($request, $response, $val); |
3580 | |
3581 | return; |
3582 | } |
3583 | |
3584 | $data = $this->createDataChangeFromRequest(); |
3585 | $this->createModel($request->header->account, $data, DataChangeMapper::class, 'data', $request->getOrigin()); |
3586 | $this->createStandardCreateResponse($request, $response, $data); |
3587 | } |
3588 | |
3589 | /** |
3590 | * Method to create DataChange from request. |
3591 | * |
3592 | * @return DataChange |
3593 | * |
3594 | * @todo: implement |
3595 | * |
3596 | * @since 1.0.0 |
3597 | */ |
3598 | private function createDataChangeFromRequest() : DataChange |
3599 | { |
3600 | return new DataChange(); |
3601 | } |
3602 | |
3603 | /** |
3604 | * Validate Data create request |
3605 | * |
3606 | * @param RequestAbstract $request Request |
3607 | * |
3608 | * @return array<string, bool> |
3609 | * |
3610 | * @todo: implement |
3611 | * |
3612 | * @since 1.0.0 |
3613 | */ |
3614 | private function validateDataChangeCreate(RequestAbstract $request) : array |
3615 | { |
3616 | $val = []; |
3617 | if (($val['id'] = ($request->header->account < 1))) { |
3618 | return $val; |
3619 | } |
3620 | |
3621 | return []; |
3622 | } |
3623 | |
3624 | /** |
3625 | * Api method to delete DataChange |
3626 | * |
3627 | * @param RequestAbstract $request Request |
3628 | * @param ResponseAbstract $response Response |
3629 | * @param array $data Generic data |
3630 | * |
3631 | * @return void |
3632 | * |
3633 | * @api |
3634 | * |
3635 | * @since 1.0.0 |
3636 | */ |
3637 | public function apiDataChangeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void |
3638 | { |
3639 | if (!empty($val = $this->validateDataChangeDelete($request))) { |
3640 | $response->header->status = RequestStatusCode::R_400; |
3641 | $this->createInvalidDeleteResponse($request, $response, $val); |
3642 | |
3643 | return; |
3644 | } |
3645 | |
3646 | /** @var \Modules\Admin\Models\DataChange $data */ |
3647 | $data = DataChangeMapper::get()->where('id', (int) $request->getData('id'))->execute(); |
3648 | $this->deleteModel($request->header->account, $data, DataChangeMapper::class, 'data', $request->getOrigin()); |
3649 | $this->createStandardDeleteResponse($request, $response, $data); |
3650 | } |
3651 | |
3652 | /** |
3653 | * Validate DataChange delete request |
3654 | * |
3655 | * @param RequestAbstract $request Request |
3656 | * |
3657 | * @return array<string, bool> |
3658 | * |
3659 | * @todo: implement |
3660 | * |
3661 | * @since 1.0.0 |
3662 | */ |
3663 | private function validateDataChangeDelete(RequestAbstract $request) : array |
3664 | { |
3665 | $val = []; |
3666 | if (($val['id'] = !$request->hasData('id'))) { |
3667 | return $val; |
3668 | } |
3669 | |
3670 | return []; |
3671 | } |
3672 | } |