yandex360 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.ru.md CHANGED
@@ -58,7 +58,7 @@
58
58
  Добавьте эту строку в `Gemfile` вашего приложения:
59
59
 
60
60
  ```ruby
61
- gem 'yandex360', '~> 3.0'
61
+ gem 'yandex360', '~> 4.0'
62
62
  ```
63
63
 
64
64
  Затем выполните:
@@ -85,6 +85,11 @@ gem install yandex360
85
85
 
86
86
  ## Переход с 1.x
87
87
 
88
+ Пришли с 3.x? Ломающие изменения 4.0 перечислены в
89
+ [changelog](CHANGELOG.md): четыре ресурса обращались к эндпоинтам, которых не
90
+ существует, и исправлены.
91
+
92
+
88
93
  Два мажора произошли разом: 1.1.4 была последней опубликованной версией перед
89
94
  3.0.0. Здесь всё, что требует вашего внимания. Обоснования в
90
95
  [changelog](CHANGELOG.md).
@@ -387,9 +392,15 @@ users.auto_paginate.each {|user| puts user.nickname }
387
392
  first_fifty = client.users.list(org_id: 1234567, per_page: 25).auto_paginate.first(50)
388
393
  ```
389
394
 
390
- Доступно для `users`, `groups`, `departments`, `external_contacts` и двух
391
- списков почтовых ящиков. Аргументы исходного вызова, такие как `per_page`
392
- или `parent_id` у подразделений, переносятся на следующие страницы.
395
+ Пагинируются не все списки, и те, что пагинируются, делают это по-разному.
396
+ `users`, `groups`, `departments`, `external_contacts`, `domains`, `dns` и два
397
+ списка почтовых ящиков принимают `page` и `per_page`. `organizations` и оба
398
+ аудит-лога листаются токеном, поэтому принимают `page_size` и не принимают
399
+ `page`. Участники групп, права доступа к ящикам и сервисные приложения
400
+ отвечают целиком и не принимают ни того, ни другого.
401
+
402
+ Аргументы исходного вызова, такие как `per_page` или `parent_id` у
403
+ подразделений, переносятся на следующие страницы.
393
404
 
394
405
  ## Объекты ответа
395
406
 
@@ -537,7 +548,7 @@ Yandex 360, к которой относится. Покрыты все семн
537
548
  | | `client.external_contacts` | [Внешние контакты](#внешние-контакты) |
538
549
  | Домены | `client.domains` | [Домены](#домены) |
539
550
  | | `client.dns` | [DNS-записи](#dns-записи) |
540
- | Почта | `client.post_settings` | [Настройки почты](#настройки-почты) |
551
+ | Почта | `client.mail_settings` | [Настройки почты](#настройки-почты) |
541
552
  | | `client.mailboxes` | [Почтовые ящики](#почтовые-ящики) |
542
553
  | | `client.routing` | [Маршрутизация почты](#маршрутизация-почты) |
543
554
  | | `client.domain_policies` | [Политики домена](#политики-домена) |
@@ -570,6 +581,10 @@ puts "Email: #{org.email}"
570
581
  puts "План подписки: #{org.subscription_plan}"
571
582
  ```
572
583
 
584
+ У сервиса есть список и ничего уже, поэтому здесь поиск по нему, а не запрос
585
+ одной организации. Токен обычно даёт доступ к одной организации, так что на
586
+ практике это один запрос.
587
+
573
588
  ---
574
589
 
575
590
  ### Пользователи
@@ -900,53 +915,43 @@ client.external_contacts.delete(org_id: 1234567, contact_id: created.id)
900
915
 
901
916
  ### Домены
902
917
 
903
- Управление доменами организации и проверка владения.
904
-
905
- #### Получить список доменов
906
-
907
918
  ```ruby
908
- domains = client.domains.list(org_id: 1234567)
909
- domains.each do |domain|
910
- puts "Домен: #{domain.name}"
911
- puts "Статус: #{domain.status}"
912
- puts "Подтверждён: #{domain.verified}"
913
- end
914
- ```
915
-
916
- #### Добавить домен
919
+ domains = client.domains.list(org_id: 1234567, page: 1, per_page: 10)
920
+ domains.each {|domain| puts "#{domain.name} подтверждён=#{domain.verified}" }
917
921
 
918
- ```ruby
919
- domain = client.domains.add(
920
- org_id: 1234567,
921
- name: "example.ru"
922
- )
923
- puts "Добавлен домен: #{domain.name}"
924
- puts "Статус проверки: #{domain.status}"
922
+ client.domains.add(org_id: 1234567, name: "example.com")
923
+ client.domains.delete(org_id: 1234567, domain: "example.com")
925
924
  ```
926
925
 
927
- #### Получить информацию о домене
926
+ Эндпоинта для чтения одного домена нет, поэтому `find` обходит список. Это
927
+ стоит запроса на страницу, а не одного, отсюда и имя:
928
928
 
929
929
  ```ruby
930
- domain = client.domains.info(org_id: 1234567, domain: "example.ru")
931
- puts "Домен: #{domain.name}"
932
- puts "Статус: #{domain.status}"
933
- puts "Подтверждён: #{domain.verified}"
934
- puts "Email главного администратора: #{domain.master_admin}"
930
+ client.domains.find(org_id: 1234567, domain: "example.com")
935
931
  ```
936
932
 
937
- #### Подтвердить владение доменом
933
+ Статус подключения несёт методы подтверждения и их коды, то есть ровно то, что
934
+ нужно для подтверждения домена:
938
935
 
939
936
  ```ruby
940
- domain = client.domains.verify(org_id: 1234567, domain: "example.ru")
941
- puts "Статус проверки: #{domain.status}"
937
+ status = client.domains.connection_status(org_id: 1234567, domain: "example.com")
938
+ status.status
939
+ status.methods.each {|method| puts "#{method.method}: #{method.code}" }
942
940
  ```
943
941
 
944
- #### Удалить домен
942
+ Подпись DKIM:
945
943
 
946
944
  ```ruby
947
- client.domains.delete(org_id: 1234567, domain: "example.ru")
945
+ dkim = client.domains.dkim_status(org_id: 1234567, domain: "example.com")
946
+ dkim.enabled
947
+ dkim.public_key
948
+
949
+ client.domains.enable_dkim(org_id: 1234567, domain: "example.com")
950
+ client.domains.disable_dkim(org_id: 1234567, domain: "example.com")
948
951
  ```
949
952
 
953
+ Кириллические домены передаются в Punycode, как указано в документации API.
954
+
950
955
  ---
951
956
 
952
957
  ### DNS-записи
@@ -1024,53 +1029,51 @@ client.dns.delete(
1024
1029
 
1025
1030
  ### Настройки почты
1026
1031
 
1027
- Управление настройками электронной почты для пользователей, включая правила пересылки.
1028
-
1029
- #### Получить настройки почты пользователя
1032
+ Настройки отдельного сотрудника: автоматический сбор контактов, имя
1033
+ отправителя и подписи, правила автоответа и пересылки.
1030
1034
 
1031
1035
  ```ruby
1032
- settings = client.post_settings.list(org_id: 1234567, user_id: 987654321)
1033
- puts "Подпись: #{settings.signature}"
1034
- puts "Ответить на: #{settings.reply_to}"
1035
- ```
1036
+ # Автоматический сбор контактов
1037
+ book = client.mail_settings.address_book(org_id: 1234567, user_id: 987654321)
1038
+ book.collect_addresses
1036
1039
 
1037
- #### Обновить настройки почты
1040
+ client.mail_settings.update_address_book(
1041
+ org_id: 1234567, user_id: 987654321, collect_addresses: false
1042
+ )
1038
1043
 
1039
- ```ruby
1040
- updated = client.post_settings.update(
1044
+ # Имя отправителя, основной адрес и подписи
1045
+ info = client.mail_settings.sender_info(org_id: 1234567, user_id: 987654321)
1046
+ puts "#{info.from_name} <#{info.default_from}>"
1047
+ info.signs.each {|sign| puts sign.text }
1048
+
1049
+ client.mail_settings.update_sender_info(
1041
1050
  org_id: 1234567,
1042
1051
  user_id: 987654321,
1043
- signature: "С уважением,\nИван Иванов",
1044
- replyTo: "ivan.ivanov@example.ru"
1052
+ from_name: "Иван Иванов",
1053
+ sign_position: "under" # либо "bottom", значение по умолчанию
1045
1054
  )
1046
1055
  ```
1047
1056
 
1048
- #### Управление пересылкой почты
1057
+ Автоответы и пересылки это два вида одного правила, и приходят они вместе:
1049
1058
 
1050
1059
  ```ruby
1051
- # Получить список адресов пересылки
1052
- forwardings = client.post_settings.forwarding_list(
1053
- org_id: 1234567,
1054
- user_id: 987654321
1055
- )
1060
+ rules = client.mail_settings.rules(org_id: 1234567, user_id: 987654321)
1061
+ rules.autoreplies
1062
+ rules.forwards
1056
1063
 
1057
- forwardings.each do |forwarding|
1058
- puts "Пересылка на: #{forwarding.address}"
1059
- end
1060
-
1061
- # Добавить адрес пересылки
1062
- client.post_settings.add_forwarding(
1063
- org_id: 1234567,
1064
- user_id: 987654321,
1065
- address: "forward@example.ru"
1064
+ # Одно правило за вызов, одного вида. Автоответ:
1065
+ created = client.mail_settings.create_rule(
1066
+ org_id: 1234567, user_id: 987654321,
1067
+ rule_name: "В отпуске", text: "Вернусь в понедельник"
1066
1068
  )
1067
1069
 
1068
- # Удалить адрес пересылки
1069
- client.post_settings.delete_forwarding(
1070
- org_id: 1234567,
1071
- user_id: 987654321,
1072
- address: "forward@example.ru"
1070
+ # Либо пересылка:
1071
+ client.mail_settings.create_rule(
1072
+ org_id: 1234567, user_id: 987654321,
1073
+ rule_name: "В архив", address: "archive@example.com", with_store: true
1073
1074
  )
1075
+
1076
+ client.mail_settings.delete_rule(org_id: 1234567, user_id: 987654321, rule_id: created.rule_id)
1074
1077
  ```
1075
1078
 
1076
1079
  ---
@@ -1219,51 +1222,33 @@ puts "Список очищен"
1219
1222
 
1220
1223
  ### Двухфакторная аутентификация (2FA)
1221
1224
 
1222
- Управление настройками двухфакторной аутентификации для пользователей и всего домена.
1223
-
1224
- #### Включить 2FA для пользователя
1225
+ Обязательная 2FA для всей организации. Все три вызова идут по одному пути и
1226
+ различаются только глаголом, поэтому отдельных эндпоинтов для включения и
1227
+ выключения нет.
1225
1228
 
1226
1229
  ```ruby
1227
- result = client.two_fa.enable(org_id: 1234567, user_id: 987654321)
1228
- puts "2FA успешно включена"
1229
- ```
1230
-
1231
- #### Отключить 2FA для пользователя
1232
-
1233
- ```ruby
1234
- result = client.two_fa.disable(org_id: 1234567, user_id: 987654321)
1235
- puts "2FA успешно отключена"
1236
- ```
1237
-
1238
- #### Проверить статус 2FA пользователя
1230
+ settings = client.two_fa.status(org_id: 1234567)
1231
+ settings.enabled
1232
+ settings.duration # секунд, на которые сотрудник может отложить настройку
1233
+ settings.enabled_at
1239
1234
 
1240
- ```ruby
1241
- status = client.two_fa.status(org_id: 1234567, user_id: 987654321)
1242
- puts "2FA включена: #{status.enabled}"
1243
- puts "Есть TOTP: #{status.has_totp}"
1244
- ```
1245
-
1246
- #### Получить статус 2FA для всего домена
1235
+ # duration обязателен: значения по умолчанию у API нет.
1236
+ client.two_fa.enable(
1237
+ org_id: 1234567,
1238
+ duration: 3600,
1239
+ logout_users: true, # необязательно, завершает все сессии
1240
+ validation_method: "phone" # необязательно, "default" или "phone"
1241
+ )
1247
1242
 
1248
- ```ruby
1249
- domain_status = client.two_fa.domain_status(org_id: 1234567)
1250
- puts "2FA включена для домена: #{domain_status.enabled}"
1243
+ client.two_fa.disable(org_id: 1234567)
1251
1244
  ```
1252
1245
 
1253
- #### Настроить 2FA для всего домена
1246
+ Персональная 2FA находится не здесь. Она относится к сотруднику, поэтому живёт
1247
+ на `users`:
1254
1248
 
1255
1249
  ```ruby
1256
- # Включить 2FA для всего домена
1257
- result = client.two_fa.configure_domain(
1258
- org_id: 1234567,
1259
- enabled: true
1260
- )
1261
-
1262
- # Отключить 2FA для всего домена
1263
- result = client.two_fa.configure_domain(
1264
- org_id: 1234567,
1265
- enabled: false
1266
- )
1250
+ client.users.get2FA(org_id: 1234567, user_id: 987654321)
1251
+ client.users.delete_2fa_phone(org_id: 1234567, user_id: 987654321)
1267
1252
  ```
1268
1253
 
1269
1254
  ---
@@ -1379,7 +1364,7 @@ client.service_applications.delete(org_id: 1234567)
1379
1364
 
1380
1365
  ```ruby
1381
1366
  # Каталог
1382
- organizations.list
1367
+ organizations.list(page_size: 10, page_token: nil)
1383
1368
  organizations.info(org_id:)
1384
1369
  users.add(org_id:, dep_id:, **user_params)
1385
1370
  users.add_alias(org_id:, user_id:, user_alias:)
@@ -1407,6 +1392,7 @@ groups.info(org_id:, group_id:)
1407
1392
  groups.params(org_id:, group_id:) # deprecated, use info
1408
1393
  groups.list(org_id:, page: 1, per_page: 10)
1409
1394
  groups.users(org_id:, group_id:)
1395
+ groups.members(org_id:, group_id:)
1410
1396
  groups.create(org_id:, name:, **group_params)
1411
1397
  groups.delete(org_id:, group_id:)
1412
1398
  groups.delete_user(org_id:, group_id:, type:, user_id:)
@@ -1419,22 +1405,27 @@ external_contacts.update_emails(org_id:, contact_id:, emails:)
1419
1405
  external_contacts.update_phones(org_id:, contact_id:, phones:)
1420
1406
 
1421
1407
  # Домены
1422
- domains.list(org_id:)
1408
+ domains.list(org_id:, page: 1, per_page: 10)
1409
+ domains.find(org_id:, domain:)
1423
1410
  domains.add(org_id:, name:, **params)
1424
- domains.info(org_id:, domain:)
1425
1411
  domains.delete(org_id:, domain:)
1426
- domains.verify(org_id:, domain:)
1427
- dns.list(org_id:, domain:)
1412
+ domains.connection_status(org_id:, domain:)
1413
+ domains.dkim_status(org_id:, domain:)
1414
+ domains.enable_dkim(org_id:, domain:)
1415
+ domains.disable_dkim(org_id:, domain:)
1416
+ dns.list(org_id:, domain:, page: 1, per_page: 50)
1428
1417
  dns.create(org_id:, domain:, **params)
1429
1418
  dns.update(org_id:, domain:, record_id:, **params)
1430
1419
  dns.delete(org_id:, domain:, record_id:)
1431
1420
 
1432
1421
  # Почта
1433
- post_settings.list(org_id:, user_id:)
1434
- post_settings.update(org_id:, user_id:, **params)
1435
- post_settings.forwarding_list(org_id:, user_id:)
1436
- post_settings.add_forwarding(org_id:, user_id:, address:)
1437
- post_settings.delete_forwarding(org_id:, user_id:, address:)
1422
+ mail_settings.address_book(org_id:, user_id:)
1423
+ mail_settings.update_address_book(org_id:, user_id:, collect_addresses:)
1424
+ mail_settings.sender_info(org_id:, user_id:)
1425
+ mail_settings.update_sender_info(org_id:, user_id:, **params)
1426
+ mail_settings.rules(org_id:, user_id:)
1427
+ mail_settings.create_rule(org_id:, user_id:, **params)
1428
+ mail_settings.delete_rule(org_id:, user_id:, rule_id:)
1438
1429
  mailboxes.shared_list(org_id:, page: 1, per_page: 10)
1439
1430
  mailboxes.create_shared(org_id:, email:, name:, description:)
1440
1431
  mailboxes.shared_info(org_id:, resource_id:)
@@ -1456,11 +1447,10 @@ antispam.create(org_id, *strings)
1456
1447
  antispam.delete(org_id:)
1457
1448
 
1458
1449
  # Безопасность
1459
- two_fa.enable(org_id:, user_id:)
1460
- two_fa.disable(org_id:, user_id:)
1461
- two_fa.status(org_id:, user_id:)
1450
+ two_fa.status(org_id:)
1451
+ two_fa.enable(org_id:, duration:, logout_users: nil, validation_method: nil)
1452
+ two_fa.disable(org_id:)
1462
1453
  two_fa.domain_status(org_id:)
1463
- two_fa.configure_domain(org_id:, enabled:)
1464
1454
  sessions.info(org_id:)
1465
1455
  sessions.update(org_id:, auth_ttl:)
1466
1456
  sessions.logout(org_id:, user_id:)
@@ -83,8 +83,15 @@ module Yandex360
83
83
  AuditResource.new(self)
84
84
  end
85
85
 
86
+ def mail_settings
87
+ MailSettingsResource.new(self)
88
+ end
89
+
90
+ # Deprecated: the old name, for a resource that called paths the API does
91
+ # not have. Removed in 5.0.
86
92
  def post_settings
87
- PostSettingsResource.new(self)
93
+ warn "[yandex360] client.post_settings is deprecated, use client.mail_settings", uplevel: 1
94
+ mail_settings
88
95
  end
89
96
 
90
97
  def sessions
@@ -88,6 +88,12 @@ module Yandex360
88
88
  attribute :created_at, from: "createdAt"
89
89
  end
90
90
 
91
+ class GroupMembers < Record
92
+ attribute :departments
93
+ attribute :groups
94
+ attribute :users
95
+ end
96
+
91
97
  class Alias < Record
92
98
  attribute :alias
93
99
  attribute :id
@@ -104,6 +110,16 @@ module Yandex360
104
110
  attribute :status
105
111
  end
106
112
 
113
+ class DomainStatus < Record
114
+ attribute :status
115
+ attribute :methods
116
+ end
117
+
118
+ class DomainDkim < Record
119
+ attribute :enabled
120
+ attribute :public_key, from: "publicKey"
121
+ end
122
+
107
123
  class DnsRecord < Record
108
124
  attribute :record_id, from: "recordId"
109
125
  attribute :type
@@ -227,6 +243,32 @@ module Yandex360
227
243
  attribute :roles
228
244
  end
229
245
 
246
+ class Domain2FA < Record
247
+ attribute :enabled
248
+ attribute :duration
249
+ attribute :enabled_at, from: "enabledAt"
250
+ end
251
+
252
+ class MailAddressBook < Record
253
+ attribute :collect_addresses, from: "collectAddresses"
254
+ end
255
+
256
+ class MailSenderInfo < Record
257
+ attribute :from_name, from: "fromName"
258
+ attribute :default_from, from: "defaultFrom"
259
+ attribute :signs
260
+ attribute :sign_position, from: "signPosition"
261
+ end
262
+
263
+ class MailUserRules < Record
264
+ attribute :autoreplies
265
+ attribute :forwards
266
+ end
267
+
268
+ class MailRule < Record
269
+ attribute :rule_id, from: "ruleId"
270
+ end
271
+
230
272
  class MailboxTask < Record
231
273
  attribute :task_id, from: "taskId"
232
274
  attribute :status
@@ -6,7 +6,9 @@ module Yandex360
6
6
  def add_alias(org_id:, dep_id:, name:)
7
7
  validate_required_params({org_id: org_id, dep_id: dep_id, name: name}, %i[org_id dep_id name])
8
8
  dep_alias = {alias: name}
9
- DepartmentAlias.new post("/directory/v1/org/#{org_id}/departments/#{dep_id}/aliases", body: dep_alias).body
9
+ # The reply is the whole department, aliases included.
10
+ Department.new post("/directory/v1/org/#{org_id}/departments/#{dep_id}/aliases",
11
+ body: dep_alias).body
10
12
  end
11
13
 
12
14
  def update(org_id:, dep_id:, parent_id:, **params)
@@ -52,7 +54,8 @@ module Yandex360
52
54
 
53
55
  def delete_alias(org_id:, dep_id:, name:)
54
56
  validate_required_params({org_id: org_id, dep_id: dep_id, name: name}, %i[org_id dep_id name])
55
- Response.new delete_request("/directory/v1/org/#{org_id}/departments/#{dep_id}/aliases/#{name}").body
57
+ path = "/directory/v1/org/#{org_id}/departments/#{dep_id}/aliases/#{name}"
58
+ DepartmentAlias.new delete_request(path).body
56
59
  end
57
60
 
58
61
  def delete(org_id:, dep_id:)
@@ -4,10 +4,13 @@ module Yandex360
4
4
  class DnsResource < Resource
5
5
  include ParamBuilder
6
6
 
7
- def list(org_id:, domain:)
7
+ def list(org_id:, domain:, page: 1, per_page: 50)
8
8
  validate_required_params({org_id: org_id, domain: domain}, %i[org_id domain])
9
- resp = get("/directory/v1/org/#{org_id}/domains/#{domain}/dns")
10
- Collection.from_response(resp, key: "records", type: DnsRecord)
9
+ resp = get("/directory/v1/org/#{org_id}/domains/#{domain}/dns",
10
+ params: {page: page, perPage: per_page})
11
+ Collection.from_response(resp, key: "records", type: DnsRecord) do |next_page|
12
+ list(org_id: org_id, domain: domain, page: next_page, per_page: per_page)
13
+ end
11
14
  end
12
15
 
13
16
  def create(org_id:, domain:, **params)
@@ -1,13 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yandex360
4
+ # Domains, their connection status and their DKIM signature.
5
+ #
6
+ # There is no endpoint for reading one domain: the service offers a list and
7
+ # nothing narrower, so #find filters what the list returns.
8
+ #
9
+ # See https://yandex.ru/dev/api360/doc/ru/ref/DomainService/
4
10
  class DomainsResource < Resource
5
11
  include ParamBuilder
6
12
 
7
- def list(org_id:)
13
+ # per_page is capped at 10 by the API.
14
+ def list(org_id:, page: 1, per_page: 10)
8
15
  validate_required_params({org_id: org_id}, [:org_id])
9
- resp = get("/directory/v1/org/#{org_id}/domains")
10
- Collection.from_response(resp, key: "domains", type: Domain)
16
+ resp = get("/directory/v1/org/#{org_id}/domains", params: {page: page, perPage: per_page})
17
+ Collection.from_response(resp, key: "domains", type: Domain) do |next_page|
18
+ list(org_id: org_id, page: next_page, per_page: per_page)
19
+ end
20
+ end
21
+
22
+ # Walks the list until the name matches, because the API has nothing to ask
23
+ # for a single domain with. Costs one request per page rather than one.
24
+ def find(org_id:, domain:)
25
+ validate_required_params({org_id: org_id, domain: domain}, %i[org_id domain])
26
+ list(org_id: org_id).auto_paginate.find {|candidate| candidate.name == domain }
11
27
  end
12
28
 
13
29
  def add(org_id:, name:, **params)
@@ -16,19 +32,35 @@ module Yandex360
16
32
  Domain.new post("/directory/v1/org/#{org_id}/domains", body: domain).body
17
33
  end
18
34
 
19
- def info(org_id:, domain:)
35
+ def delete(org_id:, domain:)
20
36
  validate_required_params({org_id: org_id, domain: domain}, %i[org_id domain])
21
- Domain.new get("/directory/v1/org/#{org_id}/domains/#{domain}").body
37
+ Response.new delete_request(domain_path(org_id, domain)).body
22
38
  end
23
39
 
24
- def delete(org_id:, domain:)
25
- validate_required_params({org_id: org_id, domain: domain}, %i[org_id domain])
26
- Response.new delete_request("/directory/v1/org/#{org_id}/domains/#{domain}").body
40
+ # Carries the confirmation methods and their codes, which is what domain
41
+ # verification actually needs.
42
+ def connection_status(org_id:, domain:)
43
+ DomainStatus.new get("#{domain_path(org_id, domain)}/status").body
27
44
  end
28
45
 
29
- def verify(org_id:, domain:)
46
+ def dkim_status(org_id:, domain:)
47
+ DomainDkim.new get("#{domain_path(org_id, domain)}/dkim").body
48
+ end
49
+
50
+ def enable_dkim(org_id:, domain:)
51
+ Response.new post("#{domain_path(org_id, domain)}/dkim/enable", body: {}).body
52
+ end
53
+
54
+ def disable_dkim(org_id:, domain:)
55
+ Response.new post("#{domain_path(org_id, domain)}/dkim/disable", body: {}).body
56
+ end
57
+
58
+ private
59
+
60
+ # Cyrillic domains have to be given in Punycode, as the API documents.
61
+ def domain_path(org_id, domain)
30
62
  validate_required_params({org_id: org_id, domain: domain}, %i[org_id domain])
31
- Domain.new post("/directory/v1/org/#{org_id}/domains/#{domain}/verify", body: {}).body
63
+ "/directory/v1/org/#{org_id}/domains/#{domain}"
32
64
  end
33
65
  end
34
66
  end
@@ -46,6 +46,13 @@ module Yandex360
46
46
  Collection.from_response(resp, key: "users", type: User)
47
47
  end
48
48
 
49
+ # A group can hold departments and other groups as well as employees, and
50
+ # the endpoint answers all three. #users shows only one of them.
51
+ def members(org_id:, group_id:)
52
+ validate_required_params({org_id: org_id, group_id: group_id}, %i[org_id group_id])
53
+ GroupMembers.new get("/directory/v1/org/#{org_id}/groups/#{group_id}/members").body
54
+ end
55
+
49
56
  def create(org_id:, name:, **group_params)
50
57
  validate_required_params({org_id: org_id, name: name}, %i[org_id name])
51
58
  group = build_params({name: name}, group_params)
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yandex360
4
+ # Per-employee mail settings: automatic contact collection, the sender name
5
+ # and signatures, and the auto-reply and forwarding rules.
6
+ #
7
+ # All three live under /admin/v1/org/{orgId}/mail/users/{userId}/settings.
8
+ #
9
+ # See https://yandex.ru/dev/api360/doc/ru/ref/MailUserSettingsService/
10
+ class MailSettingsResource < Resource
11
+ include ParamBuilder
12
+
13
+ def address_book(org_id:, user_id:)
14
+ MailAddressBook.new get(settings_path(org_id, user_id, "address_book")).body
15
+ end
16
+
17
+ def update_address_book(org_id:, user_id:, collect_addresses:)
18
+ required = {org_id: org_id, user_id: user_id}
19
+ validate_required_params(required, %i[org_id user_id])
20
+ body = {collectAddresses: collect_addresses}
21
+ MailAddressBook.new post(settings_path(org_id, user_id, "address_book"), body: body).body
22
+ end
23
+
24
+ def sender_info(org_id:, user_id:)
25
+ MailSenderInfo.new get(settings_path(org_id, user_id, "sender_info")).body
26
+ end
27
+
28
+ # Accepts from_name, default_from, signs and sign_position; the API
29
+ # documents them in camelCase, so they are converted here.
30
+ def update_sender_info(org_id:, user_id:, **params)
31
+ validate_required_params({org_id: org_id, user_id: user_id}, %i[org_id user_id])
32
+ body = camelize(build_params({}, params))
33
+ MailSenderInfo.new post(settings_path(org_id, user_id, "sender_info"), body: body).body
34
+ end
35
+
36
+ # Auto-reply and forwarding rules arrive together, under separate keys.
37
+ def rules(org_id:, user_id:)
38
+ MailUserRules.new get(settings_path(org_id, user_id, "user_rules")).body
39
+ end
40
+
41
+ # One rule per call, and of one kind: an auto-reply takes rule_name and
42
+ # text, a forward takes rule_name, address and with_store.
43
+ def create_rule(org_id:, user_id:, **params)
44
+ validate_required_params({org_id: org_id, user_id: user_id}, %i[org_id user_id])
45
+ raise ArgumentError, "Provide the rule attributes" if params.empty?
46
+
47
+ body = camelize(build_params({}, params))
48
+ MailRule.new post(settings_path(org_id, user_id, "user_rules"), body: body).body
49
+ end
50
+
51
+ def delete_rule(org_id:, user_id:, rule_id:)
52
+ required = {org_id: org_id, user_id: user_id, rule_id: rule_id}
53
+ validate_required_params(required, %i[org_id user_id rule_id])
54
+ Response.new delete_request("#{settings_path(org_id, user_id, 'user_rules')}/#{rule_id}").body
55
+ end
56
+
57
+ private
58
+
59
+ def settings_path(org_id, user_id, setting)
60
+ validate_required_params({org_id: org_id, user_id: user_id}, %i[org_id user_id])
61
+ "/admin/v1/org/#{org_id}/mail/users/#{user_id}/settings/#{setting}"
62
+ end
63
+
64
+ # Callers write snake_case here as they do everywhere else in the gem.
65
+ def camelize(params)
66
+ params.transform_keys do |key|
67
+ head, *rest = key.to_s.split("_")
68
+ [head, *rest.map(&:capitalize)].join.to_sym
69
+ end
70
+ end
71
+ end
72
+ end
@@ -2,14 +2,24 @@
2
2
 
3
3
  module Yandex360
4
4
  class OrganizationsResource < Resource
5
- def list
6
- resp = get("/directory/v1/org")
7
- Collection.from_response(resp, key: "organizations", type: Organization)
5
+ # Pages by token rather than page number, so there is no page argument.
6
+ # page_size is capped at 100 by the API.
7
+ def list(page_size: 10, page_token: nil)
8
+ params = {pageSize: page_size}
9
+ params[:pageToken] = page_token unless page_token.nil?
10
+
11
+ resp = get("/directory/v1/org", params: params)
12
+ Collection.from_response(resp, key: "organizations", type: Organization) do |token|
13
+ list(page_size: page_size, page_token: token)
14
+ end
8
15
  end
9
16
 
17
+ # OrganizationsService offers a list and nothing narrower, so this walks
18
+ # it. The token usually reaches one organization, so it is a single
19
+ # request in practice, but it is a search rather than a fetch.
10
20
  def info(org_id:)
11
21
  validate_required_params({org_id: org_id}, [:org_id])
12
- Organization.new get("/directory/v1/org/#{org_id}").body
22
+ list.auto_paginate.find {|organization| organization.id.to_s == org_id.to_s }
13
23
  end
14
24
  end
15
25
  end