ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilOpenIdConnectUserSync.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
11 {
12  const AUTH_MODE = 'oidc';
13 
17  protected $settings;
18 
22  protected $logger;
23 
27  private $writer;
31  private $user_info = [];
32 
36  private $ext_account = '';
37 
38 
42  private $int_account = '';
43 
47  private $usr_id = 0;
48 
49 
55  {
56  global $DIC;
57 
58  $this->settings = $settings;
59  $this->logger = $DIC->logger()->auth();
60 
61  $this->writer = new ilXmlWriter();
62 
63  $this->user_info = $user_info;
64  }
65 
69  public function setExternalAccount(string $ext_account)
70  {
71  $this->ext_account = $ext_account;
72  }
73 
77  public function setInternalAccount(string $int_account)
78  {
79  $this->int_account = $int_account;
80  $this->usr_id = ilObjUser::_lookupId($this->int_account);
81  }
82 
86  public function getUserId() : int
87  {
88  return $this->usr_id;
89  }
90 
94  public function needsCreation() : bool
95  {
96  $this->logger->dump($this->int_account, \ilLogLevel::DEBUG);
97  return strlen($this->int_account) == 0;
98  }
99 
104  public function updateUser()
105  {
106  if ($this->needsCreation() && !$this->settings->isSyncAllowed()) {
107  throw new ilOpenIdConnectSyncForbiddenException('No internal account given.');
108  }
109 
110  $this->transformToXml();
111 
112  $importParser = new ilUserImportParser();
113  $importParser->setXMLContent($this->writer->xmlDumpMem(false));
114 
115  $roles = $this->parseRoleAssignments();
116  $importParser->setRoleAssignment($roles);
117 
118  $importParser->setFolderId(USER_FOLDER_ID);
119  $importParser->startParsing();
120  $debug = $importParser->getProtocol();
121 
122 
123  // lookup internal account
125  self::AUTH_MODE,
126  $this->ext_account
127  );
129  return true;
130  }
131 
135  protected function transformToXml()
136  {
137  $this->writer->xmlStartTag('Users');
138 
139  if ($this->needsCreation()) {
140  $this->writer->xmlStartTag('User', ['Action' => 'Insert']);
141  $this->writer->xmlElement('Login', [], ilAuthUtils::_generateLogin($this->ext_account));
142  } else {
143  $this->writer->xmlStartTag(
144  'User',
145  [
146  'Id' => $this->getUserId(),
147  'Action' => 'Update'
148  ]
149  );
150  $this->writer->xmlElement('Login', [], $this->int_account);
151  }
152 
153  $this->writer->xmlElement('ExternalAccount', array(), $this->ext_account);
154  $this->writer->xmlElement('AuthMode', array('type' => self::AUTH_MODE), null);
155 
156  $this->parseRoleAssignments();
157 
158  if ($this->needsCreation()) {
159  $this->writer->xmlElement('Active', array(), "true");
160  $this->writer->xmlElement('TimeLimitOwner', array(), 7);
161  $this->writer->xmlElement('TimeLimitUnlimited', array(), 1);
162  $this->writer->xmlElement('TimeLimitFrom', array(), time());
163  $this->writer->xmlElement('TimeLimitUntil', array(), time());
164  }
165 
166  foreach ($this->settings->getProfileMappingFields() as $field => $lng_key) {
167  $connect_name = $this->settings->getProfileMappingFieldValue($field);
168  if (!$connect_name) {
169  $this->logger->debug('Ignoring unconfigured field: ' . $field);
170  continue;
171  }
172  if (!$this->needsCreation() && !$this->settings->getProfileMappingFieldUpdate($field)) {
173  $this->logger->debug('Ignoring ' . $field . ' for update.');
174  continue;
175  }
176 
177  $value = $this->valueFrom($connect_name);
178  if (!strlen($value)) {
179  $this->logger->debug('Cannot find user data in ' . $connect_name);
180  continue;
181  }
182 
183  switch ($field) {
184  case 'firstname':
185  $this->writer->xmlElement('Firstname', [], $value);
186  break;
187 
188  case 'lastname':
189  $this->writer->xmlElement('Lastname', [], $value);
190  break;
191 
192  case 'email':
193  $this->writer->xmlElement('Email', [], $value);
194  break;
195 
196  case 'birthday':
197  $this->writer->xmlElement('Birthday', [], $value);
198  break;
199  }
200  }
201  $this->writer->xmlEndTag('User');
202  $this->writer->xmlEndTag('Users');
203 
204  $this->logger->debug($this->writer->xmlDumpMem());
205  }
206 
211  protected function parseRoleAssignments() : array
212  {
213  $this->logger->debug('Parsing role assignments');
214 
215  $found_role = false;
216 
217  $roles_assignable[$this->settings->getRole()] = $this->settings->getRole();
218 
219 
220  $this->logger->dump($this->settings->getRoleMappings(), \ilLogLevel::DEBUG);
221 
222  foreach ($this->settings->getRoleMappings() as $role_id => $role_info) {
223  $this->logger->dump($role_id);
224  $this->logger->dump($role_info);
225 
226  list($role_attribute, $role_value) = explode('::', $role_info['value']);
227 
228  if (
229  !$role_attribute ||
230  !$role_value
231  ) {
232  $this->logger->debug('No valid role mapping configuration for: ' . $role_id);
233  continue;
234  }
235 
236  if (!isset($this->user_info->$role_attribute)) {
237  $this->logger->debug('No user info passed');
238  continue;
239  }
240 
241  if (
242  !$this->needsCreation() &&
243  !$role_info['update']
244  ) {
245  $this->logger->debug('No user role update for role: ' . $role_id);
246  continue;
247  }
248 
249  if (is_array($this->user_info->$role_attribute)) {
250  if (!in_array($role_value, $this->user_info->$role_attribute)) {
251  $this->logger->debug('User account has no ' . $role_value);
252  continue;
253  }
254  } elseif (strcmp($this->user_info->$role_attribute, $role_value) !== 0) {
255  $this->logger->debug('User account has no ' . $role_value);
256  continue;
257  }
258  $this->logger->debug('Matching role mapping for role_id: ' . $role_id);
259 
260  $found_role = true;
261  $roles_assignable[$role_id] = $role_id;
262  $long_role_id = ('il_' . IL_INST_ID . '_role_' . $role_id);
263 
264  $this->writer->xmlElement(
265  'Role',
266  [
267  'Id' => $long_role_id,
268  'Type' => 'Global',
269  'Action' => 'Assign'
270  ],
271  null
272  );
273  }
274 
275  if ($this->needsCreation() && !$found_role) {
276  $long_role_id = ('il_' . IL_INST_ID . '_role_' . $this->settings->getRole());
277 
278  // add default role
279  $this->writer->xmlElement(
280  'Role',
281  [
282  'Id' => $long_role_id,
283  'Type' => 'Global',
284  'Action' => 'Assign'
285  ],
286  null
287  );
288  }
289  return $roles_assignable;
290  }
291 
292 
296  protected function valueFrom(string $connect_name) : string
297  {
298  if (!$connect_name) {
299  return '';
300  }
301  if (!property_exists($this->user_info, $connect_name)) {
302  $this->logger->debug('Cannot find property ' . $connect_name . ' in user info ');
303  return '';
304  }
305  $val = $this->user_info->$connect_name;
306  return $val;
307  }
308 }
settings()
Definition: settings.php:2
global $DIC
Definition: saml.php:7
static _generateLogin($a_login)
generate free login by starting with a default string and adding postfix numbers
XML writer class.
static _lookupId($a_user_str)
Lookup id by login.
Class ilOpenIdConnectSettingsGUI.
parseRoleAssignments()
Parse role assignments.
static _checkExternalAuthAccount($a_auth, $a_account, $tryFallback=true)
check whether external account and authentication method matches with a user
Class ilOpenIdConnectSettingsGUI.
transformToXml()
transform user data to xml
const USER_FOLDER_ID
Class ilObjUserFolder.
__construct(\ilOpenIdConnectSettings $settings, $user_info)
ilOpenIdConnectUserSync constructor.