Зміни в документі Версія 6: Налаштування

Остання зміна 2024/07/11 10:07 автором Ashterix

Від версії 22.1
редаговано Ashterix
дата 2024/05/16 11:32
Змінити коментар: Немає коментарів для цієї версії
До версії 23.1
редаговано Ashterix
дата 2024/05/16 11:33
Змінити коментар: Відкат до версії 21.2

Підсумок

Подробиці

Властивості сторінки
Вміст
... ... @@ -1,37 +1,18 @@
1 -(% class="box floatinginfobox" %)
2 -(((
3 -**Зміст**
1 +{{box cssClass="floatinginfobox" title="**Зміст**"}}
2 +{{toc/}}
3 +{{/box}}
4 4  
5 -(% class="wikitoc" %)
6 -* [[Блок security>>path:#H41143B43E43AA0]]
7 -** [[Параметр protected_methods>>path:#H41F43044043043C435442440]]
8 -** [[Параметр token_key_in_header>>path:#H41F43044043043C435442440-1]]
9 -** [[Параметр clients_tokens>>path:#H41F43044043043C435442440-2]]
10 -*** [[Токени в параметрах>>path:#H42243E43A43543D43843243F43044043043C435442440430445]]
11 -*** [[Токени в змінних оточення>>path:#H42243E43A43543D43843243743C45643D43D43844543E44243E44743543D43D44F]]
12 -*** [[Токени для користувача>>path:#H42243E43A43543D43843443B44F43A43E440438441442443432430447430]]
13 -**** [[Приклад власного валідатора токенів>>path:#H41F44043843A43B43043443243B43044143D43E43343E43243043B45643443044243E44043044243E43A43543D456432]]
14 -* [[Блок async>>path:#H41143B43E43AA0-1]]
15 -* [[Блок docs>>path:#H41143B43E43AA0-2]]
16 -** [[Секція response>>path:#H42143543A44645644F]]
17 -*** [[Параметр key_for_methods>>path:#H41F43044043043C435442440A0]]
18 -*** [[Параметр async_dsn_info>>path:#H41F43044043043C435442440A0-1]]
19 -**** [[Приклад документації >>path:#H41F44043843A43B43043443443E43A44343C43543D442430446456457]]
20 -*** [[Параметр validations>>path:#H41F43044043043C435442440A0-2]]
21 -**** [[Приклад документації >>path:#H41F44043843A43B43043443443E43A44343C43543D442430446456457-1]]
22 -)))
23 -
24 24  (% class="wikigeneratedid" %)
25 -Всі налаштування бандла знаходяться в файлі (% class="box code" %)config/packages/ufo_json_rpc.yaml(%%).
6 +Всі налаштування бандла знаходяться в файлі {{code language="none"}}config/packages/ufo_json_rpc.yaml{{/code}}.
26 26  
27 27  (% class="wikigeneratedid" %)
28 28  Є можливість налаштувати параметри захисту API та деякі параметри формату даних, що віддається при запиті документації.
29 29  
30 -= Блок (% class="box code" %)security(%%) =
11 += Блок {{code language="none"}}security{{/code}} =
31 31  
32 32  Наразі єдиним механізмом захисту доступу до вашого API є встановлення перевірки ключа доступу (api_token).
33 33  
34 -== Параметр (% class="box code" %)protected_methods(%%) ==
15 +== Параметр {{code language="none"}}protected_methods{{/code}} ==
35 35  
36 36  (% class="wikigeneratedid" %)
37 37  Цей параметр приймає масив назв http методів, які мають бути захищені.
... ... @@ -39,77 +39,31 @@
39 39  (% class="wikigeneratedid" %)
40 40  За замовченням ввімкнут захист лише для методу POST. Ви можете:
41 41  
42 -* вказати пустий масив (% class="box code" %)[](%%) щоб зробити API повністю відкритим
23 +* вказати пустий масив {{code language="none"}}[]{{/code}} щоб зробити API повністю відкритим
43 43  
44 -(% class="box" %)
45 -(((
46 -config/packages/ufo_json_rpc.yaml
25 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
26 +ufo_json_rpc:
27 + security:
28 + protected_methods: []
29 +{{/code}}
47 47  
48 -(% class="code" %)
49 -(((
50 -(% class="linenoswrapper" %)
51 -(((
52 -(% class="linenos" %)
53 -(((
54 -1
55 -2
56 -3\\
57 -)))
58 -
59 -(((
60 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
61 - (% style="font-weight: bold; color: #008000;" %)security(%%):
62 - (% style="font-weight: bold; color: #008000;" %)protected_methods(%%): []
63 -)))
64 -)))
65 -)))
66 -)))
67 -
68 68  * вказати додатково захист для методу GET, що зробить запит документації недоступним без токену в заголовках запиту
69 69  
70 -(% class="box" %)
71 -(((
72 -config/packages/ufo_json_rpc.yaml
33 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
34 +ufo_json_rpc:
35 + security:
36 + protected_methods: ['GET', 'POST']
37 +{{/code}}
73 73  
74 -(% class="code" %)
75 -(((
76 -(% class="linenoswrapper" %)
77 -(((
78 -(% class="linenos" %)
79 -(((
80 -1
81 -2
82 -3\\
83 -)))
39 +(% id="cke_bm_164641S" style="display:none" %) (%%)Якщо ви захищаєте ваш API через {{code language="none"}}protected_methods{{/code}}, вам необхідно налаштувати токени, по яким буде відкритий доступ.
84 84  
85 -(((
86 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
87 - (% style="font-weight: bold; color: #008000;" %)security(%%):
88 - (% style="font-weight: bold; color: #008000;" %)protected_methods(%%): [(% style="color: #BA2121;" %)'GET'(%%), (% style="color: #BA2121;" %)'POST'(%%)]
89 -)))
90 -)))
91 -)))
92 -)))
93 -
94 -(% id="cke_bm_164641S" style="display:none" %) (%%)Якщо ви захищаєте ваш API через (% class="box code" %)protected_methods(%%), вам необхідно налаштувати токени, по яким буде відкритий доступ.
95 -
96 96  Перш за все, треба визначитися з назвою токену.
97 97  
98 -== Параметр (% class="box code" %)token_key_in_header(%%) ==
43 +== Параметр {{code language="none"}}token_key_in_header{{/code}} ==
99 99  
100 -Компонент (% class="box code" %)RpcSecurity(%%) буде шукати в заголовках запиту специфічний ключ, який ви можете встановити в налаштуваннях пакету, значення за замовченням (% class="box code" %)token_key_in_header: 'Ufo-RPC-Token'(%%), ви можете встановити будь-яке інше значення яке відповідає наступним вимогам.
45 +Компонент {{code language="none"}}RpcSecurity{{/code}} буде шукати в заголовках запиту специфічний ключ, який ви можете встановити в налаштуваннях пакету, значення за замовченням {{code language="none"}}token_key_in_header: 'Ufo-RPC-Token'{{/code}}, ви можете встановити будь-яке інше значення яке відповідає наступним вимогам.
101 101  
102 -\\
103 -
104 -(% class="spoiler" %)
105 -(((
106 -(% class="spoilerTitle" %)
107 -(((
108 -Вимоги до формування заголовків протоколу HTTP
109 -)))
110 -
111 -(% class="spoilerContent hidden" %)
112 -(((
47 +{{spoiler title=" Вимоги до формування заголовків протоколу HTTP"}}
113 113  Вимоги до назв заголовків HTTP не є строго регульованими щодо капіталізації, оскільки HTTP заголовки нечутливі до регістру. Однак, існують деякі загальні практики і стандарти, які зазвичай дотримуються для кращої читабельності та узгодженості:
114 114  
115 115  - Капіталізація: Зазвичай назви HTTP заголовків пишуться з використанням CamelCase, де кожне слово починається з великої літери, наприклад, Content-Type, User-Agent, Accept-Encoding. Це не впливає на технічну обробку заголовків, але робить їх легше читати.
... ... @@ -116,15 +116,13 @@
116 116  - Унікальність: Кожен заголовок повинен мати унікальну назву у контексті одного HTTP запиту або відповіді. Не можна використовувати однакові назви для різних заголовків у тому самому запиті чи відповіді.
117 117  - Спеціальні заголовки: Існують заголовки, які використовуються специфічно для контролю поведінки кешування (Cache-Control), безпеки (Strict-Transport-Security), аутентифікації (Authorization), тощо.
118 118  - Норми RFC: Вимоги до заголовків регулюються документами RFC, які визначають стандарти для протоколів Інтернету. Наприклад, загальні заголовки і їхнє використання описані в RFC 7231.
119 -)))
120 -)))
54 +{{/spoiler}}
121 121  
122 122  
123 123  
124 124  
59 +== Параметр {{code language="none"}}clients_tokens{{/code}} ==
125 125  
126 -== Параметр (% class="box code" %)clients_tokens(%%) ==
127 -
128 128  Тепер слід вказати масив клієнтськіх токенів, які будуть мати доступ до API.
129 129  
130 130  Тут є певна варіативність.
... ... @@ -141,780 +141,352 @@
141 141  
142 142  Це погано з позиції безпеки, якщо код зберігається в публічному репозиторію, то до цього токену буде мати доступ кожен.
143 143  
144 -(% class="box" %)
145 -(((
146 -config/packages/ufo_json_rpc.yaml
147 -
148 -(% class="code" %)
149 -(((
150 -(% class="linenoswrapper" %)
151 -(((
152 -(% class="linenos" %)
153 -(((
154 -1
155 -2
156 -3
157 -4
158 -5
159 -6
160 -7\\
161 -)))
162 -
163 -(((
164 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
165 - (% style="font-weight: bold; color: #008000;" %)security(%%):
166 - (% style="font-weight: bold; color: #008000;" %)protected_methods(%%): [(% style="color: #BA2121;" %)'GET'(%%), (% style="color: #BA2121;" %)'POST'(%%)]
167 - (% style="font-weight: bold; color: #008000;" %)token_key_in_header(%%): (% style="color: #BA2121;" %)'Ufo-RPC-Token'(%%)
168 - (% style="font-weight: bold; color: #008000;" %)clients_tokens(%%):
169 - - (% style="color: #BA2121;" %)'ClientTokenExample'(%%) (% style="font-style: italic; color: #408080;" %)# hardcoded token example. Importantly!!! Replace or delete it!(%%)
77 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
78 +ufo_json_rpc:
79 + security:
80 + protected_methods: ['GET', 'POST']
81 + token_key_in_header: 'Ufo-RPC-Token'
82 + clients_tokens:
83 + - 'ClientTokenExample' # hardcoded token example. Importantly!!! Replace or delete it!
170 170  
171 -)))
172 -)))
173 -)))
174 -)))
85 +{{/code}}
175 175  
176 176  === Токени в змінних оточення ===
177 177  
178 178  Це найбільш доцільний механізм у разі, якщо ви розробляєте сервіс для розподіленого бекенду, що написаний на SOA (Сервіс-Орієнтована Архітектура). Зазвичай, в такому випадку, вам треба відкрити доступ до апі одному або обмеженій кількості клієнтських додатків і оновлення ключів не буде відбуватися занадто часто.
179 179  
180 -В такому випадку можна прописати токени в змінних оточення (файл (% class="box code" %).env.local(%%) під час локальної розробки). Цей механізм достатньо безпечний з боку збереження доступів.
91 +В такому випадку можна прописати токени в змінних оточення (файл {{code language="none"}}.env.local{{/code}} під час локальної розробки). Цей механізм достатньо безпечний з боку збереження доступів.
181 181  
182 182  (((
183 -(% class="box" %)
184 -(((
185 -.env.local
94 +{{code language="ini" layout="LINENUMBERS" title=".env.local"}}
95 +TOKEN_FOR_APP_1=9363074966579432364f8b73b3318f71
96 +TOKEN_FOR_APP_2=456fg87g8h98jmnb8675r4445n8up365
97 +{{/code}}
186 186  
187 -(% class="code" %)
188 -(((
189 -(% class="linenoswrapper" %)
190 -(((
191 -(% class="linenos" %)
192 -(((
193 -1
194 -2\\
99 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
100 +ufo_json_rpc:
101 + security:
102 + protected_methods: ['GET', 'POST']
103 + token_key_in_header: 'Ufo-RPC-Token'
104 + clients_tokens:
105 + - '%env(resolve:TOKEN_FOR_APP_1)%' # token example from .env.local
106 + - '%env(resolve:TOKEN_FOR_APP_2)%' # token example from .env.local
107 +{{/code}}
195 195  )))
196 196  
197 -(((
198 -(% style="color: #7D9029;" %)TOKEN_FOR_APP_1(% style="color: #666666;" %)=(% style="color: #BA2121;" %)9363074966579432364f8b73b3318f71(%%)
199 -(% style="color: #7D9029;" %)TOKEN_FOR_APP_2(% style="color: #666666;" %)=(% style="color: #BA2121;" %)456fg87g8h98jmnb8675r4445n8up365
200 -)))
201 -)))
202 -)))
203 -)))
204 -
205 -(% class="box" %)
206 -(((
207 -config/packages/ufo_json_rpc.yaml
208 -
209 -(% class="code" %)
210 -(((
211 -(% class="linenoswrapper" %)
212 -(((
213 -(% class="linenos" %)
214 -(((
215 -1
216 -2
217 -3
218 -4
219 -5
220 -6
221 -7\\
222 -)))
223 -
224 -(((
225 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
226 - (% style="font-weight: bold; color: #008000;" %)security(%%):
227 - (% style="font-weight: bold; color: #008000;" %)protected_methods(%%): [(% style="color: #BA2121;" %)'GET'(%%), (% style="color: #BA2121;" %)'POST'(%%)]
228 - (% style="font-weight: bold; color: #008000;" %)token_key_in_header(%%): (% style="color: #BA2121;" %)'Ufo-RPC-Token'(%%)
229 - (% style="font-weight: bold; color: #008000;" %)clients_tokens(%%):
230 - - (% style="color: #BA2121;" %)'%env(resolve:TOKEN_FOR_APP_1)%'(%%) (% style="font-style: italic; color: #408080;" %)# token example from .env.local(%%)
231 - - (% style="color: #BA2121;" %)'%env(resolve:TOKEN_FOR_APP_2)%'(%%) (% style="font-style: italic; color: #408080;" %)# token example from .env.local
232 -)))
233 -)))
234 -)))
235 -)))
236 -)))
237 -
238 238  === Токени для користувача ===
239 239  
240 240  Припускаю, що у вас може виникнути потреба зробити персональні ключі для користувачів вашого додатку, можливо ви захочете впровадити ліміти або інші обмеження.
241 241  В такому випадку вам не потрібно вказувати перелік токенів в конфігах, ви можете зберігати їх в базі даних або іншому місці згідно вашій бізнес-логіки. Єдина вимога, у вас має бути сервіс, який вміє перевіряти чи існує наданий токен.
242 242  
243 -Для того, щоб JsonRpcServer міг використовувати вашу логіку, доведеться реалізувати власний клас, що реалізує інтерфейс (% class="box code" %)Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator
115 +Для того, щоб JsonRpcServer міг використовувати вашу логіку, доведеться реалізувати власний клас, що реалізує інтерфейс {{code language="none"}}Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator{{/code}}
244 244  
245 -(% class="box" %)
246 -(((
247 -==== Приклад власного валідатора токенів ====
117 +{{code language="php" layout="LINENUMBERS" title="==== Приклад власного валідатора токенів ===="}}
118 +<?php
248 248  
249 -(% class="code" %)
250 -(((
251 -(% class="linenoswrapper" %)
252 -(((
253 -(% class="linenos" %)
254 -(((
255 -1
256 -2
257 -3
258 -4
259 -5
260 -6
261 -7
262 -8
263 -9
264 -10
265 -11
266 -12
267 -13
268 -14
269 -15
270 -16
271 -17
272 -18
273 -19
274 -20
275 -21
276 -22
277 -23
278 -24\\
279 -)))
120 +namespace App\Services\RpcSecurity;
280 280  
281 -(((
282 -(% style="color: #BC7A00;" %)<?php(%%)
283 -\\(% style="font-weight: bold; color: #008000;" %)namespace(%%) App\Services\RpcSecurity;
284 -\\(% style="font-weight: bold; color: #008000;" %)use(%%) App\Services\UserService;
285 -(% style="font-weight: bold; color: #008000;" %)use(%%) Symfony\Component\Security\Core\Exception\UserNotFoundException;
286 -(% style="font-weight: bold; color: #008000;" %)use(%%) Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator;
287 -(% style="font-weight: bold; color: #008000;" %)use(%%) Ufo\RpcError\RpcInvalidTokenException;
288 -\\(% style="font-weight: bold; color: #008000;" %)class(%%) (% style="font-weight: bold; color: #0000FF;" %)UserTokenValidator(%%) (% style="font-weight: bold; color: #008000;" %)implements(%%) ITokenValidator
122 +use App\Services\UserService;
123 +use Symfony\Component\Security\Core\Exception\UserNotFoundException;
124 +use Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator;
125 +use Ufo\RpcError\RpcInvalidTokenException;
126 +
127 +class UserTokenValidator implements ITokenValidator
289 289  {
290 -\\ (% style="font-weight: bold; color: #008000;" %)public(%%) (% style="font-weight: bold; color: #008000;" %)function(%%) (% style="color: #0000FF;" %)~_~_construct(%%)((% style="font-weight: bold; color: #008000;" %)protected(%%) UserService (% style="color: #19177C;" %)$userService(%%)) {}
291 -\\ (% style="font-weight: bold; color: #008000;" %)public(%%) (% style="font-weight: bold; color: #008000;" %)function(%%) (% style="color: #0000FF;" %)isValid(%%)(string (% style="color: #19177C;" %)$token(%%))(% style="color: #666666;" %):(%%) (% style="font-weight: bold; color: #008000;" %)true(%%)
129 +
130 + public function __construct(protected UserService $userService) {}
131 +
132 + public function isValid(string $token): true
292 292   {
293 - (% style="font-weight: bold; color: #008000;" %)try(%%) {
294 - (% style="color: #19177C;" %)$this(% style="color: #666666;" %)->(% style="color: #7D9029;" %)userService(% style="color: #666666;" %)->(% style="color: #7D9029;" %)getUserByToken(%%)((% style="color: #19177C;" %)$token(%%));
295 - (% style="font-weight: bold; color: #008000;" %)return(%%) (% style="font-weight: bold; color: #008000;" %)true(%%);
296 - } (% style="font-weight: bold; color: #008000;" %)catch(%%) (UserNotFoundException (% style="color: #19177C;" %)$e(%%)) {
297 - (% style="font-weight: bold; color: #008000;" %)throw(%%) (% style="font-weight: bold; color: #008000;" %)new(%%) RpcInvalidTokenException(previous(% style="color: #666666;" %):(%%) (% style="color: #19177C;" %)$e(%%));
134 + try {
135 + $this->userService->getUserByToken($token);
136 + return true;
137 + } catch (UserNotFoundException $e) {
138 + throw new RpcInvalidTokenException(previous: $e);
298 298   }
299 299   }
300 300  }
301 -)))
302 -)))
303 -)))
304 -)))
142 +{{/code}}
305 305  
306 306  (% class="box warningmessage" %)
307 307  (((
308 308  **ВАЖЛИВО!!!**
309 -Метод (% class="box code" %)isValid(%%) має повертати (% class="box code" %)true(%%) якщо токен існує і валідний, або викидати (% class="box code" %)Ufo\RpcError\RpcInvalidTokenException(%%) в іншому разі.
147 +Метод {{code language="none"}}isValid{{/code}} має повертати {{code language="none"}}true{{/code}} якщо токен існує і валідний, або викидати {{code language="none"}}Ufo\RpcError\RpcInvalidTokenException{{/code}} в іншому разі.
310 310  )))
311 311  
312 -Після цього вам потрібно в файлі (% class="box code" %)config/services.yaml(%%) прописати що класи, що мають залежність від інтерфейса (% class="box code" %)ITokenValidator(%%) мають приймати ваш новий клас.
150 +Після цього вам потрібно в файлі {{code language="none"}}config/services.yaml{{/code}} прописати що класи, що мають залежність від інтерфейса {{code language="none"}}ITokenValidator{{/code}} мають приймати ваш новий клас.
313 313  
314 -(% class="box" %)
315 -(((
316 -config/services.yaml
152 +{{code language="yaml" layout="LINENUMBERS" title="config/services.yaml"}}
153 +parameters:
154 + # some parameters list
155 + # ...
317 317  
318 -(% class="code" %)
319 -(((
320 -(% class="linenoswrapper" %)
321 -(((
322 -(% class="linenos" %)
323 -(((
324 -1
325 -2
326 -3
327 -4
328 -5
329 -6
330 -7
331 -8
332 -9
333 -10\\
334 -)))
157 +services:
158 + # some services list
159 + # ...
335 335  
336 -(((
337 -(% style="font-weight: bold; color: #008000;" %)parameters(%%):
338 - (% style="font-style: italic; color: #408080;" %)# some parameters list(%%)
339 - (% style="font-style: italic; color: #408080;" %)# ...(%%)
340 -\\(% style="font-weight: bold; color: #008000;" %)services(%%):
341 - (% style="font-style: italic; color: #408080;" %)# some services list(%%)
342 - (% style="font-style: italic; color: #408080;" %)# ...(%%)
343 -\\ (% style="font-weight: bold; color: #008000;" %)Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator(%%):
344 - (% style="font-weight: bold; color: #008000;" %)class(%%): App\Services\RpcSecurity\UserTokenValidator
345 -)))
346 -)))
347 -)))
348 -)))
161 + Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator:
162 + class: App\Services\RpcSecurity\UserTokenValidator
163 +{{/code}}
349 349  
350 -= Блок (% class="box code" %)async(%%) =
165 += Блок {{code language="none"}}async{{/code}} =
351 351  
352 -Цей блок для налаштування [[асинхронного транспорту>>path:/bin/view/docs/JsonRpcBundle/functionality/async/]].
167 +Цей блок для налаштування [[асинхронного транспорту>>doc:.functionality.async.WebHome]].
353 353  
354 -Додайте параметр (% class="box code" %)rpc_async(%%) який містить рядок у форматі DSN. Цей рядок є конфігурацією [[Symfony Messenger>>url:https://symfony.com/doc/current/messenger.html]], він вказує на асинхронний транспорт по якому RPC Server буде очікувати вхідні запити якщо у вас запущений консюмер ((% class="box code" %)php bin/console messenger:consume rpc_async(%%)). Для більш детального розуміння цього процесу читайте документацію [[Symfony Messenge>>url:https://symfony.com/doc/current/messenger.html]].
169 +Додайте параметр {{code language="none"}}rpc_async{{/code}} який містить рядок у форматі DSN. Цей рядок є конфігурацією [[Symfony Messenger>>https://symfony.com/doc/current/messenger.html]], він вказує на асинхронний транспорт по якому RPC Server буде очікувати вхідні запити якщо у вас запущений консюмер ({{code language="none"}}php bin/console messenger:consume rpc_async{{/code}}). Для більш детального розуміння цього процесу читайте документацію [[Symfony Messenge>>https://symfony.com/doc/current/messenger.html]].
355 355  
356 -(% class="box" %)
357 -(((
358 -config/packages/ufo_json_rpc.yaml
171 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
172 +ufo_json_rpc:
173 + async:
174 + rpc_async: '%env(resolve:RPC_TRANSPORT_DSN)%'
359 359  
360 -(% class="code" %)
361 -(((
362 -(% class="linenoswrapper" %)
363 -(((
364 -(% class="linenos" %)
365 -(((
366 -1
367 -2
368 -3
369 -4\\
370 -)))
176 +{{/code}}
371 371  
372 -(((
373 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
374 - (% style="font-weight: bold; color: #008000;" %)async(%%):
375 - (% style="font-weight: bold; color: #008000;" %)rpc_async(%%): (% style="color: #BA2121;" %)'%env(resolve:RPC_TRANSPORT_DSN)%'(%%)\\
376 -)))
377 -)))
378 -)))
379 -)))
380 -
381 381  (% class="box warningmessage" %)
382 382  (((
383 383  Це налаштування має на увазі, що у вас в змінних оточення встановлена змінна RPC_TRANSPORT_DSN що містить DSN рядок.
384 384  )))
385 385  
386 -= Блок (% class="box code" %)docs(%%) =
183 += Блок {{code language="none"}}docs{{/code}} =
387 387  
388 388  Це блок який налаштовує генерацію документації коли ви робите GET запит на RPC Server
389 389  
390 -== Секція (% class="box code" %)response(%%) ==
187 +== Секція {{code language="none"}}response{{/code}} ==
391 391  
392 392  Містить налаштування, що відповідають за вміст відповіді.
393 393  
394 -=== Параметр (% class="box code" %)key_for_methods(%%) ===
191 +=== Параметр {{code language="none"}}key_for_methods{{/code}} ===
395 395  
396 396  Цей параметр дозволяє вказати назву ключа у відповіді в якій буде віддаватися масив доступних сервісів.
397 397  
398 -Значення за замовченням (% class="box code" %)methods(%%). Може мати будь-яке значення типу рядок.
195 +Значення за замовченням {{code language="none"}}methods{{/code}}. Може мати будь-яке значення типу рядок.
399 399  
400 -(% class="box" %)
401 -(((
402 -config/packages/ufo_json_rpc.yaml
197 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
198 +ufo_json_rpc:
199 + docs:
200 + key_for_methods: methods
201 +{{/code}}
403 403  
404 -(% class="code" %)
405 -(((
406 -(% class="linenoswrapper" %)
407 -(((
408 -(% class="linenos" %)
409 -(((
410 -1
411 -2
412 -3\\
413 -)))
203 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
204 +ufo_json_rpc:
205 + docs:
206 + key_for_methods: services
207 +{{/code}}
414 414  
415 -(((
416 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
417 - (% style="font-weight: bold; color: #008000;" %)docs(%%):
418 - (% style="font-weight: bold; color: #008000;" %)key_for_methods(%%): methods
419 -)))
420 -)))
421 -)))
422 -)))
209 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
210 +ufo_json_rpc:
211 + docs:
212 + key_for_methods: some_custom_key
213 +{{/code}}
423 423  
424 -(% class="box" %)
425 -(((
426 -config/packages/ufo_json_rpc.yaml
215 +=== Параметр {{code language="none"}}async_dsn_info{{/code}} ===
427 427  
428 -(% class="code" %)
429 -(((
430 -(% class="linenoswrapper" %)
431 -(((
432 -(% class="linenos" %)
433 -(((
434 -1
435 -2
436 -3\\
437 -)))
438 -
439 -(((
440 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
441 - (% style="font-weight: bold; color: #008000;" %)docs(%%):
442 - (% style="font-weight: bold; color: #008000;" %)key_for_methods(%%): services
443 -)))
444 -)))
445 -)))
446 -)))
447 -
448 -(% class="box" %)
449 -(((
450 -config/packages/ufo_json_rpc.yaml
451 -
452 -(% class="code" %)
453 -(((
454 -(% class="linenoswrapper" %)
455 -(((
456 -(% class="linenos" %)
457 -(((
458 -1
459 -2
460 -3\\
461 -)))
462 -
463 -(((
464 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
465 - (% style="font-weight: bold; color: #008000;" %)docs(%%):
466 - (% style="font-weight: bold; color: #008000;" %)key_for_methods(%%): some_custom_key
467 -)))
468 -)))
469 -)))
470 -)))
471 -
472 -=== Параметр (% class="box code" %)async_dsn_info(%%) ===
473 -
474 474  Відповідає за відображення в документації інформації про асинхронний транспорт.
475 475  
476 -(% class="box" %)
477 -(((
478 -config/packages/ufo_json_rpc.yaml
219 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
220 +ufo_json_rpc:
221 + async_dsn_info: true # or false
222 +{{/code}}
479 479  
480 -(% class="code" %)
481 -(((
482 -(% class="linenoswrapper" %)
483 -(((
484 -(% class="linenos" %)
485 -(((
486 -1
487 -2\\
488 -)))
489 -
490 -(((
491 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
492 - (% style="font-weight: bold; color: #008000;" %)async_dsn_info(%%): true (% style="font-style: italic; color: #408080;" %)# or false
493 -)))
494 -)))
495 -)))
496 -)))
497 -
498 498  ==== **Приклад документації ** ====
499 499  
500 -(% class="box" %)
501 -(((
502 -GET: /api
503 -
504 -(% class="code" %)
505 -(((
506 -(% class="linenoswrapper" %)
507 -(((
508 -(% class="linenos" %)
509 -(((
510 -1
511 -2
512 -3
513 -4
514 -5
515 -6
516 -7
517 -8
518 -9
519 -10
520 -11
521 -12
522 -13
523 -14
524 -15
525 -16
526 -17
527 -18
528 -19
529 -20
530 -21
531 -22
532 -23
533 -24\\
534 -)))
535 -
536 -(((
226 +{{code language="json" layout="LINENUMBERS" title="GET: /api"}}
537 537  {
538 - (% style="font-weight: bold; color: #008000;" %)"envelope"(%%): (% style="color: #BA2121;" %)"JSON-RPC-2.0/UFO-RPC-6"(%%),
539 - (% style="font-weight: bold; color: #008000;" %)"contentType"(%%): (% style="color: #BA2121;" %)"application/json"(%%),
540 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)""(%%),
541 - (% style="font-weight: bold; color: #008000;" %)"transport"(%%): {
542 - (% style="font-weight: bold; color: #008000;" %)"sync"(%%): {
543 - (% style="font-weight: bold; color: #008000;" %)"scheme"(%%): (% style="color: #BA2121;" %)"http"(%%),
544 - (% style="font-weight: bold; color: #008000;" %)"host"(%%): (% style="color: #BA2121;" %)"example.com"(%%),
545 - (% style="font-weight: bold; color: #008000;" %)"path"(%%): (% style="color: #BA2121;" %)"/api"(%%),
546 - (% style="font-weight: bold; color: #008000;" %)"method"(%%): (% style="color: #BA2121;" %)"POST"(%%)
228 + "envelope": "JSON-RPC-2.0/UFO-RPC-6",
229 + "contentType": "application/json",
230 + "description": "",
231 + "transport": {
232 + "sync": {
233 + "scheme": "http",
234 + "host": "example.com",
235 + "path": "/api",
236 + "method": "POST"
547 547   },
548 - (% style="font-weight: bold; color: #008000;" %)"async"(%%): {
549 - (% style="font-weight: bold; color: #008000;" %)"scheme"(%%): (% style="color: #BA2121;" %)"amqp"(%%),
550 - (% style="font-weight: bold; color: #008000;" %)"user"(%%): (% style="color: #BA2121;" %)"{user}"(%%),
551 - (% style="font-weight: bold; color: #008000;" %)"pass"(%%): (% style="color: #BA2121;" %)"{pass}"(%%),
552 - (% style="font-weight: bold; color: #008000;" %)"host"(%%): (% style="color: #BA2121;" %)"async_rabbit"(%%),
553 - (% style="font-weight: bold; color: #008000;" %)"port"(%%): (% style="color: #666666;" %)5672(%%),
554 - (% style="font-weight: bold; color: #008000;" %)"path"(%%): (% style="color: #BA2121;" %)"/%2f/json-rpc"(%%)
238 + "async": {
239 + "scheme": "amqp",
240 + "user": "{user}",
241 + "pass": "{pass}",
242 + "host": "async_rabbit",
243 + "port": 5672,
244 + "path": "/%2f/json-rpc"
555 555   }
556 556   },
557 - (% style="font-weight: bold; color: #008000;" %)"methods"(%%): {
558 - (% style="border: 1px solid #FF0000;" %)...(%%)
247 + "methods": {
248 + ...
559 559   }
560 560  }
561 -)))
562 -)))
563 -)))
564 -)))
251 +{{/code}}
565 565  
566 -(% class="box infomessage" %)
567 -(((
253 +{{info}}
568 568  Не переймайтеся щодо безпеки ваших авторизаційних даних. що містяться в DSN.
569 569  
570 570  Документатор побудований таким чином, що перед виводом інформації про DSN він видаляє дані про користувача і його пароль, а також інші секретні дані, як то токени, секретні ключі, тощо.
571 571  
572 -Шаблон, по якому відбувається захист (% class="box code" %)/([\w\d_]*(?:secret|access|token|key)[_\w]*)=((?:\w|\d)+(?=&?))/(%%).
258 +Шаблон, по якому відбувається захист {{code language="none"}}/([\w\d_]*(?:secret|access|token|key)[_\w]*)=((?:\w|\d)+(?=&?))/{{/code}}.
573 573  
574 574  Приклад:
575 575  
576 -(% class="box" %)
577 -(((
578 -RPC_TRANSPORT_DSN=https://sqs.eu-west-3.amazonaws.com/123456789012/messages?access_key=AKIAIOSFODNN7EXAMPLE&secret_key=j17M97ffSVoKI0briFoo9a
579 -
580 -(% class="code" %)
581 -(((
582 -(% class="linenoswrapper" %)
583 -(((
584 -(% class="linenos" %)
585 -(((
586 -1
587 -2
588 -3
589 -4
590 -5
591 -6
592 -7
593 -8\\
594 -)))
595 -
596 -(((
262 +{{code language="json" layout="LINENUMBERS" title="RPC_TRANSPORT_DSN=https://sqs.eu-west-3.amazonaws.com/123456789012/messages?access_key=AKIAIOSFODNN7EXAMPLE&secret_key=j17M97ffSVoKI0briFoo9a"}}
597 597  {
598 - (% style="font-weight: bold; color: #008000;" %)"async"(%%): {
599 - (% style="font-weight: bold; color: #008000;" %)"scheme"(%%): (% style="color: #BA2121;" %)"https"(%%),
600 - (% style="font-weight: bold; color: #008000;" %)"host"(%%): (% style="color: #BA2121;" %)"sqs.eu-west-3.amazonaws.com"(%%),
601 - (% style="font-weight: bold; color: #008000;" %)"path"(%%): (% style="color: #BA2121;" %)"/123456789012/messages"(%%),
602 - (% style="font-weight: bold; color: #008000;" %)"query"(%%): (% style="color: #BA2121;" %)"access_key={access_key}&secret_key={secret_key}"(%%)
264 + "async": {
265 + "scheme": "https",
266 + "host": "sqs.eu-west-3.amazonaws.com",
267 + "path": "/123456789012/messages",
268 + "query": "access_key={access_key}&secret_key={secret_key}"
603 603   }
604 604  }
605 -)))
606 -)))
607 -)))
608 -)))
609 -)))
271 +{{/code}}
272 +{{/info}}
610 610  
611 -=== Параметр (% class="box code" %)validations(%%) ===
274 +=== Параметр {{code language="none"}}validations{{/code}} ===
612 612  
613 613  Відповідає за відображення в документації методів додаткових блоків, що вказують на вимоги до валідації даних.
614 614  
615 615  Наразі цей блок має два можливих налаштування:
616 616  
617 -* (% class="box code" %)json_schema: <bool>
618 -* (% class="box code" %)symfony_asserts: <bool>
280 +* {{code language="none"}}json_schema: <bool>{{/code}}
281 +* {{code language="none"}}symfony_asserts: <bool>{{/code}}
619 619  
620 -У всіх опцій в цьому параметрі значення за замовченням (% class="box code" %)false(%%), тобто ці блоки не будуть відображатися в документації.
621 -Якщо ви потребуєте якийсь з цих блоків інформації при запиті документації, то встановіть значення в (% class="box code" %)true(%%).
283 +У всіх опцій в цьому параметрі значення за замовченням {{code language="none"}}false{{/code}}, тобто ці блоки не будуть відображатися в документації.
284 +Якщо ви потребуєте якийсь з цих блоків інформації при запиті документації, то встановіть значення в {{code language="none"}}true{{/code}}.
622 622  
623 -(% class="box" %)
624 -(((
625 -config/packages/ufo_json_rpc.yaml
286 +{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
287 +ufo_json_rpc:
288 + docs:
289 + json_schema: true
290 + symfony_asserts: true
291 +{{/code}}
626 626  
627 -(% class="code" %)
628 -(((
629 -(% class="linenoswrapper" %)
630 -(((
631 -(% class="linenos" %)
632 -(((
633 -1
634 -2
635 -3
636 -4\\
637 -)))
638 -
639 -(((
640 -(% style="font-weight: bold; color: #008000;" %)ufo_json_rpc(%%):
641 - (% style="font-weight: bold; color: #008000;" %)docs(%%):
642 - (% style="font-weight: bold; color: #008000;" %)json_schema(%%): true
643 - (% style="font-weight: bold; color: #008000;" %)symfony_asserts(%%): true
644 -)))
645 -)))
646 -)))
647 -)))
648 -
649 649  ==== **Приклад документації ** ====
650 650  
651 651  (% class="box infomessage" %)
652 652  (((
653 653  В цьому прикладі я видалив вміст обʼєктів symfony_assertions для спрощення прикладу.
654 -Детальніше про валідацію методів дивись сторінку **[[path:/bin/view/docs/JsonRpcBundle/add_rpc_service/assertions/]]**
298 +Детальніше про валідацію методів дивись сторінку **[[Валідація процедур>>doc:.add_rpc_service.assertions.WebHome]]**
655 655  )))
656 656  
657 -(% class="box" %)
658 -(((
659 -GET: /api
660 -
661 -(% class="code" %)
662 -(((
663 -(% class="linenoswrapper" %)
664 -(((
665 -(% class="linenos" %)
666 -(((
667 -1
668 -2
669 -3
670 -4
671 -5
672 -6
673 -7
674 -8
675 -9
676 -10
677 -11
678 -12
679 -13
680 -14
681 -15
682 -16
683 -17
684 -18
685 -19
686 -20
687 -21
688 -22
689 -23
690 -24
691 -25
692 -26
693 -27
694 -28
695 -29
696 -30
697 -31
698 -32
699 -33
700 -34
701 -35
702 -36
703 -37
704 -38
705 -39
706 -40
707 -41
708 -42
709 -43
710 -44
711 -45
712 -46
713 -47
714 -48
715 -49
716 -50
717 -51
718 -52
719 -53
720 -54
721 -55
722 -56
723 -57
724 -58
725 -59
726 -60
727 -61
728 -62
729 -63
730 -64
731 -65
732 -66
733 -67
734 -68
735 -69
736 -70
737 -71
738 -72
739 -73
740 -74
741 -75
742 -76
743 -77
744 -78
745 -79
746 -80
747 -81
748 -82
749 -83
750 -84
751 -85
752 -86
753 -87
754 -88
755 -89
756 -90
757 -91
758 -92
759 -93
760 -94
761 -95
762 -96
763 -97
764 -98
765 -99
766 -100
767 -101
768 -102
769 -103
770 -104
771 -105
772 -106
773 -107
774 -108
775 -109
776 -110
777 -111
778 -112
779 -113
780 -114
781 -115
782 -116
783 -117
784 -118
785 -119
786 -120
787 -121
788 -122
789 -123
790 -124
791 -125
792 -126
793 -127\\
794 -)))
795 -
796 -(((
301 +{{code language="json" layout="LINENUMBERS" title="GET: /api"}}
797 797  {
798 - (% style="font-weight: bold; color: #008000;" %)"envelope"(%%): (% style="color: #BA2121;" %)"JSON-RPC-2.0/UFO-RPC-6"(%%),
799 - (% style="font-weight: bold; color: #008000;" %)"contentType"(%%): (% style="color: #BA2121;" %)"application/json"(%%),
800 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)""(%%),
801 - (% style="font-weight: bold; color: #008000;" %)"transport"(%%): {
802 - (% style="font-weight: bold; color: #008000;" %)"sync"(%%): {
803 - (% style="font-weight: bold; color: #008000;" %)"scheme"(%%): (% style="color: #BA2121;" %)"https"(%%),
804 - (% style="font-weight: bold; color: #008000;" %)"host"(%%): (% style="color: #BA2121;" %)"example.com"(%%),
805 - (% style="font-weight: bold; color: #008000;" %)"path"(%%): (% style="color: #BA2121;" %)"/api"(%%),
806 - (% style="font-weight: bold; color: #008000;" %)"method"(%%): (% style="color: #BA2121;" %)"POST"(%%)
303 + "envelope": "JSON-RPC-2.0/UFO-RPC-6",
304 + "contentType": "application/json",
305 + "description": "",
306 + "transport": {
307 + "sync": {
308 + "scheme": "https",
309 + "host": "example.com",
310 + "path": "/api",
311 + "method": "POST"
807 807   }
808 808   },
809 - (% style="font-weight: bold; color: #008000;" %)"methods"(%%): {
810 - (% style="font-weight: bold; color: #008000;" %)"getUserNameByUuid"(%%): {
811 - (% style="font-weight: bold; color: #008000;" %)"name"(%%): (% style="color: #BA2121;" %)"getUserNameByUuid"(%%),
812 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)"Get username by id"(%%),
813 - (% style="font-weight: bold; color: #008000;" %)"parameters"(%%): {
814 - (% style="font-weight: bold; color: #008000;" %)"userId"(%%): {
815 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
816 - (% style="font-weight: bold; color: #008000;" %)"name"(%%): (% style="color: #BA2121;" %)"userId"(%%),
817 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)"User id in uuid format"(%%),
818 - (% style="font-weight: bold; color: #008000;" %)"optional"(%%): (% style="font-weight: bold; color: #008000;" %)false(%%)
314 + "methods": {
315 + "getUserNameByUuid": {
316 + "name": "getUserNameByUuid",
317 + "description": "Get username by id",
318 + "parameters": {
319 + "userId": {
320 + "type": "string",
321 + "name": "userId",
322 + "description": "User id in uuid format",
323 + "optional": false
819 819   }
820 820   },
821 - (% style="font-weight: bold; color: #008000;" %)"returns"(%%): (% style="color: #BA2121;" %)"string"(%%),
822 - (% style="font-weight: bold; color: #008000;" %)"responseFormat"(%%): (% style="color: #BA2121;" %)"string"(%%),
823 - (% style="font-weight: bold; color: #008000;" %)"json_schema"(%%): {
824 - (% style="font-weight: bold; color: #008000;" %)"$schema"(%%): (% style="color: #BA2121;" %)"http:~/~/json-schema.org/draft-07/schema#"(%%),
825 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"object"(%%),
826 - (% style="font-weight: bold; color: #008000;" %)"properties"(%%): {
827 - (% style="font-weight: bold; color: #008000;" %)"userId"(%%): {
828 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%)
326 + "returns": "string",
327 + "responseFormat": "string",
328 + "json_schema": {
329 + "$schema": "http://json-schema.org/draft-07/schema#",
330 + "type": "object",
331 + "properties": {
332 + "userId": {
333 + "type": "string"
829 829   }
830 830   },
831 - (% style="font-weight: bold; color: #008000;" %)"required"(%%): [
832 - (% style="color: #BA2121;" %)"userId"(%%)
336 + "required": [
337 + "userId"
833 833   ]
834 834   },
835 - (% style="font-weight: bold; color: #008000;" %)"symfony_assertions"(%%): {
836 - (% style="font-weight: bold; color: #008000;" %)"userId"(%%): [
340 + "symfony_assertions": {
341 + "userId": [
837 837   {
838 - (% style="font-weight: bold; color: #008000;" %)"class"(%%): (% style="color: #BA2121;" %)"Symfony~\~\Component~\~\Validator~\~\Constraints~\~\Uuid"(%%),
839 - (% style="font-weight: bold; color: #008000;" %)"context"(%%): {}
343 + "class": "Symfony\\Component\\Validator\\Constraints\\Uuid",
344 + "context": {}
840 840   }
841 841   ]
842 842   }
843 843   },
844 - (% style="font-weight: bold; color: #008000;" %)"sendEmail"(%%): {
845 - (% style="font-weight: bold; color: #008000;" %)"name"(%%): (% style="color: #BA2121;" %)"sendEmail"(%%),
846 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)"Send mail"(%%),
847 - (% style="font-weight: bold; color: #008000;" %)"parameters"(%%): {
848 - (% style="font-weight: bold; color: #008000;" %)"email"(%%): {
849 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
850 - (% style="font-weight: bold; color: #008000;" %)"name"(%%): (% style="color: #BA2121;" %)"email"(%%),
851 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)""(%%),
852 - (% style="font-weight: bold; color: #008000;" %)"optional"(%%): (% style="font-weight: bold; color: #008000;" %)false(%%)
349 + "sendEmail": {
350 + "name": "sendEmail",
351 + "description": "Send mail",
352 + "parameters": {
353 + "email": {
354 + "type": "string",
355 + "name": "email",
356 + "description": "",
357 + "optional": false
853 853   },
854 - (% style="font-weight: bold; color: #008000;" %)"subject"(%%): {
855 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
856 - (% style="font-weight: bold; color: #008000;" %)"name"(%%): (% style="color: #BA2121;" %)"subject"(%%),
857 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)""(%%),
858 - (% style="font-weight: bold; color: #008000;" %)"optional"(%%): (% style="font-weight: bold; color: #008000;" %)false(%%)
359 + "subject": {
360 + "type": "string",
361 + "name": "subject",
362 + "description": "",
363 + "optional": false
859 859   },
860 - (% style="font-weight: bold; color: #008000;" %)"text"(%%): {
861 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
862 - (% style="font-weight: bold; color: #008000;" %)"name"(%%): (% style="color: #BA2121;" %)"text"(%%),
863 - (% style="font-weight: bold; color: #008000;" %)"description"(%%): (% style="color: #BA2121;" %)""(%%),
864 - (% style="font-weight: bold; color: #008000;" %)"optional"(%%): (% style="font-weight: bold; color: #008000;" %)false(%%)
365 + "text": {
366 + "type": "string",
367 + "name": "text",
368 + "description": "",
369 + "optional": false
865 865   }
866 866   },
867 - (% style="font-weight: bold; color: #008000;" %)"returns"(%%): (% style="color: #BA2121;" %)"boolean"(%%),
868 - (% style="font-weight: bold; color: #008000;" %)"responseFormat"(%%): (% style="color: #BA2121;" %)"boolean"(%%),
869 - (% style="font-weight: bold; color: #008000;" %)"json_schema"(%%): {
870 - (% style="font-weight: bold; color: #008000;" %)"$schema"(%%): (% style="color: #BA2121;" %)"http:~/~/json-schema.org/draft-07/schema#"(%%),
871 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"object"(%%),
872 - (% style="font-weight: bold; color: #008000;" %)"properties"(%%): {
873 - (% style="font-weight: bold; color: #008000;" %)"email"(%%): {
874 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
875 - (% style="font-weight: bold; color: #008000;" %)"format"(%%): (% style="color: #BA2121;" %)"email"(%%)
372 + "returns": "boolean",
373 + "responseFormat": "boolean",
374 + "json_schema": {
375 + "$schema": "http://json-schema.org/draft-07/schema#",
376 + "type": "object",
377 + "properties": {
378 + "email": {
379 + "type": "string",
380 + "format": "email"
876 876   },
877 - (% style="font-weight: bold; color: #008000;" %)"subject"(%%): {
878 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
879 - (% style="font-weight: bold; color: #008000;" %)"minLength"(%%): (% style="color: #666666;" %)1(%%),
880 - (% style="font-weight: bold; color: #008000;" %)"maxLength"(%%): (% style="color: #666666;" %)100(%%)
382 + "subject": {
383 + "type": "string",
384 + "minLength": 1,
385 + "maxLength": 100
881 881   },
882 - (% style="font-weight: bold; color: #008000;" %)"text"(%%): {
883 - (% style="font-weight: bold; color: #008000;" %)"type"(%%): (% style="color: #BA2121;" %)"string"(%%),
884 - (% style="font-weight: bold; color: #008000;" %)"minLength"(%%): (% style="color: #666666;" %)10(%%)
387 + "text": {
388 + "type": "string",
389 + "minLength": 10
885 885   }
886 886   },
887 - (% style="font-weight: bold; color: #008000;" %)"required"(%%): [
888 - (% style="color: #BA2121;" %)"email"(%%),
889 - (% style="color: #BA2121;" %)"subject"(%%),
890 - (% style="color: #BA2121;" %)"text"(%%)
392 + "required": [
393 + "email",
394 + "subject",
395 + "text"
891 891   ]
892 892   },
893 - (% style="font-weight: bold; color: #008000;" %)"symfony_assertions"(%%): {
894 - (% style="font-weight: bold; color: #008000;" %)"email"(%%): [
398 + "symfony_assertions": {
399 + "email": [
895 895   {
896 - (% style="font-weight: bold; color: #008000;" %)"class"(%%): (% style="color: #BA2121;" %)"Symfony~\~\Component~\~\Validator~\~\Constraints~\~\Email"(%%),
897 - (% style="font-weight: bold; color: #008000;" %)"context"(%%): {}
401 + "class": "Symfony\\Component\\Validator\\Constraints\\Email",
402 + "context": {}
898 898   }
899 899   ],
900 - (% style="font-weight: bold; color: #008000;" %)"subject"(%%): [
405 + "subject": [
901 901   {
902 - (% style="font-weight: bold; color: #008000;" %)"class"(%%): (% style="color: #BA2121;" %)"Symfony~\~\Component~\~\Validator~\~\Constraints~\~\NotBlank"(%%),
903 - (% style="font-weight: bold; color: #008000;" %)"context"(%%): {}
407 + "class": "Symfony\\Component\\Validator\\Constraints\\NotBlank",
408 + "context": {}
904 904   },
905 905   {
906 - (% style="font-weight: bold; color: #008000;" %)"class"(%%): (% style="color: #BA2121;" %)"Symfony~\~\Component~\~\Validator~\~\Constraints~\~\Length"(%%),
907 - (% style="font-weight: bold; color: #008000;" %)"context"(%%): {}
411 + "class": "Symfony\\Component\\Validator\\Constraints\\Length",
412 + "context": {}
908 908   }
909 909   ],
910 - (% style="font-weight: bold; color: #008000;" %)"text"(%%): [
415 + "text": [
911 911   {
912 - (% style="font-weight: bold; color: #008000;" %)"class"(%%): (% style="color: #BA2121;" %)"Symfony~\~\Component~\~\Validator~\~\Constraints~\~\NotBlank"(%%),
913 - (% style="font-weight: bold; color: #008000;" %)"context"(%%): {}
417 + "class": "Symfony\\Component\\Validator\\Constraints\\NotBlank",
418 + "context": {}
914 914   },
915 915   {
916 - (% style="font-weight: bold; color: #008000;" %)"class"(%%): (% style="color: #BA2121;" %)"Symfony~\~\Component~\~\Validator~\~\Constraints~\~\Length"(%%),
917 - (% style="font-weight: bold; color: #008000;" %)"context"(%%): {}
421 + "class": "Symfony\\Component\\Validator\\Constraints\\Length",
422 + "context": {}
918 918   }
919 919   ]
920 920   }
... ... @@ -921,7 +921,4 @@
921 921   }
922 922   }
923 923  }
924 -)))
925 -)))
926 -)))
927 -)))
429 +{{/code}}