ILIAS  trunk Revision v11.0_alpha-1702-gfd3ecb7f852
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilCmiXapiAuthToken.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
31 {
32  public const DB_TABLE_NAME = 'cmix_token';
33 
34  public const OPENSSL_ENCRYPTION_METHOD = 'aes128';
35 
36  public const OPENSSL_IV = '1234567890123456';
37 
38  protected int $ref_id;
39 
40  protected int $obj_id;
41 
42  protected int $usr_id;
43 
44  protected string $token;
45 
46  protected string $valid_until;
47 
48  protected int $lrs_type_id;
49 
50  protected ?string $cmi5_session = null;
51 
52  protected string $cmi5_session_data;
53 
54  protected ?string $returned_for_cmi5_session = null;
55 
56  protected ilDBInterface $db;
57 
58  public function __construct()
59  {
60  global $DIC;
61  $this->db = $DIC->database();
62  }
63 
64  public function getRefId(): int
65  {
66  return $this->ref_id;
67  }
68 
69  public function setRefId(int $ref_id): void
70  {
71  $this->ref_id = $ref_id;
72  }
73 
74  public function getObjId(): int
75  {
76  return $this->obj_id;
77  }
78 
79  public function setObjId(int $obj_id): void
80  {
81  $this->obj_id = $obj_id;
82  }
83 
84  public function getUsrId(): int
85  {
86  return $this->usr_id;
87  }
88 
89  public function setUsrId(int $usr_id): void
90  {
91  $this->usr_id = $usr_id;
92  }
93 
94  public function getToken(): string
95  {
96  return $this->token;
97  }
98 
99  public function setToken(string $token): void
100  {
101  $this->token = $token;
102  }
103 
104  public function getValidUntil(): string
105  {
106  return $this->valid_until;
107  }
108 
109  public function setValidUntil(string $valid_until): void
110  {
111  $this->valid_until = $valid_until;
112  }
113 
114  public function getLrsTypeId(): int
115  {
116  return $this->lrs_type_id;
117  }
118 
119  public function setLrsTypeId(int $lrs_type_id): void
120  {
121  $this->lrs_type_id = $lrs_type_id;
122  }
123 
124  public function getCmi5Session(): ?string
125  {
126  return $this->cmi5_session;
127  }
128 
129  public function setCmi5Session(string $cmi5_session): void
130  {
131  $this->cmi5_session = $cmi5_session;
132  }
133 
134  public function getCmi5SessionData(): string
135  {
137  }
138 
139  public function setCmi5SessionData(string $cmi5_session_data): void
140  {
141  $this->cmi5_session_data = $cmi5_session_data;
142  }
143 
144  public function getReturnedForCmi5Session(): ?string
145  {
147  }
148 
149  public function setReturnedForCmi5Session(string $returned_for_cmi5_session): void
150  {
151  $this->returned_for_cmi5_session = $returned_for_cmi5_session;
152  }
153 
154  public function update(): void
155  {
156  $this->db->update(
157  self::DB_TABLE_NAME,
158  [
159  'valid_until' => array('timestamp', $this->getValidUntil()),
160  'ref_id' => array('integer', $this->getRefId()),
161  'obj_id' => array('integer', $this->getObjId()),
162  'usr_id' => array('integer', $this->getUsrId()),
163  'lrs_type_id' => array('integer', $this->getLrsTypeId()),
164  'cmi5_session' => array('text', $this->getCmi5Session()),
165  'returned_for_cmi5_session' => array('text', $this->getReturnedForCmi5Session()),
166  'cmi5_session_data' => array('clob', $this->getCmi5SessionData())
167  ],
168  [
169  'token' => array('text', $this->getToken()),
170  ]
171  );
172  }
173 
174  public static function insertToken($usrId, $refId, $objId, $lrsTypeId, $a_token, $a_time): void
175  {
176  global $DIC; /* @var \ILIAS\DI\Container $DIC */
177 
178  $DIC->database()->insert(
179  self::DB_TABLE_NAME,
180  array(
181  'token' => array('text', $a_token),
182  'valid_until' => array('timestamp', $a_time),
183  'ref_id' => array('integer', $refId),
184  'obj_id' => array('integer', $objId),
185  'usr_id' => array('integer', $usrId),
186  'lrs_type_id' => array('integer', $lrsTypeId)
187  )
188  );
189  // 'cmi5_session' defaults always to '' by inserting
190  // 'returned_for_cmi5_session' defaults always to '' by inserting
191  }
192 
193  public static function deleteTokenByObjIdAndUsrId(int $objId, int $usrId): void
194  {
195  global $DIC; /* @var \ILIAS\DI\Container $DIC */
196 
197  $query = "
198  DELETE FROM " . self::DB_TABLE_NAME . "
199  WHERE obj_id = %s AND usr_id = %s
200  ";
201 
202  $DIC->database()->manipulateF($query, array('integer', 'integer'), array($objId, $usrId));
203  }
204 
205  public static function deleteTokenByObjIdAndRefIdAndUsrId(int $objId, int $refId, int $usrId): void
206  {
207  global $DIC; /* @var \ILIAS\DI\Container $DIC */
208 
209  $query = "
210  DELETE FROM " . self::DB_TABLE_NAME . "
211  WHERE obj_id = %s AND ref_id = %s AND usr_id = %s
212  ";
213 
214  $DIC->database()->manipulateF($query, array('integer', 'integer', 'integer'), array($objId, $refId, $usrId));
215  }
216 
217  public function delete(): void
218  {
219  global $DIC; /* @var \ILIAS\DI\Container $DIC */
220 
221  $query = "
222  DELETE FROM " . self::DB_TABLE_NAME . "
223  WHERE obj_id = %s AND ref_id = %s AND usr_id = %s
224  ";
225 
226  $DIC->database()->manipulateF($query, array('integer', 'integer', 'integer'), array($this->getObjId(), $this->getRefId(), $this->getUsrId()));
227  }
228 
229  public static function deleteExpiredTokens(): void
230  {
231  global $DIC; /* @var \ILIAS\DI\Container $DIC */
232 
233  $query = "DELETE FROM " . self::DB_TABLE_NAME . " WHERE valid_until < CURRENT_TIMESTAMP";
234  $DIC->database()->manipulate($query);
235  }
236 
237 
238  public static function selectCurrentTimestamp(): string
239  {
240  global $DIC; /* @var \ILIAS\DI\Container $DIC */
241 
242  $query = "SELECT CURRENT_TIMESTAMP";
243  $result = $DIC->database()->query($query);
244  $row = $DIC->database()->fetchAssoc($result);
245 
246  return (string) $row['CURRENT_TIMESTAMP'];
247  }
248 
249  public static function createToken(): string
250  {
251  return (new \Ramsey\Uuid\UuidFactory())->uuid4()->toString();
252  }
253 
254  public static function fillToken(int $usrId, int $refId, int $objId, int $lrsTypeId = 0): string
255  {
256  //$seconds = $this->getTimeToDelete();
257  $seconds = 86400; // TODO: invalidation interval
258 
259  $nowTimeDT = self::selectCurrentTimestamp();
260 
261  $nowTime = new ilDateTime($nowTimeDT, IL_CAL_DATETIME);
262 
263  $nowTimeTS = $nowTime->get(IL_CAL_UNIX);
264  $newTimeTS = $nowTimeTS + $seconds;
265 
266  $newTime = new ilDateTime($newTimeTS, IL_CAL_UNIX);
267 
268  //self::deleteTokenByObjIdAndUsrId($object->getId(), $usrId);
269 
270  try {
271  $tokenObject = self::getInstanceByObjIdAndRefIdAndUsrId($objId, $refId, $usrId, false);
272  $tokenObject->setValidUntil($newTime->get(IL_CAL_DATETIME));
273  $tokenObject->update();
274 
275  $token = $tokenObject->getToken();
276  } catch (ilCmiXapiException $e) {
277  $token = self::createToken();
278  self::insertToken($usrId, $refId, $objId, $lrsTypeId, $token, $newTime->get(IL_CAL_DATETIME));
279  }
280 
281  // TODO: move to cronjob ;-)
282  // TODO: check cmi5 sessions of token and if not terminated -> abandoned statement
283  self::deleteExpiredTokens();
284 
285  return $token;
286  }
287 
291  public static function getInstanceByToken(string $token): \ilCmiXapiAuthToken
292  {
293  global $DIC; /* @var \ILIAS\DI\Container $DIC */
294 
295  $query = "
296  SELECT * FROM " . self::DB_TABLE_NAME . "
297  WHERE token = %s AND valid_until > CURRENT_TIMESTAMP
298  ";
299 
300  $res = $DIC->database()->queryF($query, array('text'), array($token));
301 
302  while ($row = $DIC->database()->fetchAssoc($res)) {
303  $tokenObject = new self();
304  $tokenObject->setToken($token);
305  $tokenObject->setValidUntil((string) $row['valid_until']);
306  $tokenObject->setUsrId((int) $row['usr_id']);
307  $tokenObject->setObjId((int) $row['obj_id']);
308  $tokenObject->setRefId((int) $row['ref_id']);
309  $tokenObject->setLrsTypeId((int) $row['lrs_type_id']);
310  $tokenObject->setCmi5Session((string) $row['cmi5_session']);
311  $tokenObject->setReturnedForCmi5Session((string) $row['returned_for_cmi5_session']);
312  $tokenObject->setCmi5SessionData((string) $row['cmi5_session_data']);
313 
314  return $tokenObject;
315  }
316 
317  throw new ilCmiXapiException('no valid token found for: ' . $token);
318  }
319 
323  public static function getInstanceByObjIdAndUsrId(int $objId, int $usrId, bool $checkValid = true): \ilCmiXapiAuthToken
324  {
325  global $DIC; /* @var \ILIAS\DI\Container $DIC */
326 
327  $query = "SELECT * FROM " . self::DB_TABLE_NAME . " WHERE obj_id = %s AND usr_id = %s";
328 
329  if ($checkValid) {
330  $query .= " AND valid_until > CURRENT_TIMESTAMP";
331  }
332 
333  $result = $DIC->database()->queryF($query, array('integer', 'integer'), array($objId, $usrId));
334 
335  $row = $DIC->database()->fetchAssoc($result);
336 
337  if ($row) {
338  $tokenObject = new self();
339  $tokenObject->setToken($row['token']);
340  $tokenObject->setValidUntil($row['valid_until']);
341  $tokenObject->setUsrId($row['usr_id']);
342  $tokenObject->setObjId($row['obj_id']);
343  $tokenObject->setRefId($row['ref_id']);
344  $tokenObject->setLrsTypeId($row['lrs_type_id']);
345  $tokenObject->setCmi5Session($row['cmi5_session']);
346  $tokenObject->setReturnedForCmi5Session($row['returned_for_cmi5_session']);
347  $tokenObject->setCmi5SessionData($row['cmi5_session_data']);
348 
349  return $tokenObject;
350  }
351 
352  throw new ilCmiXapiException('no valid token found for: ' . $objId . '/' . $usrId);
353  }
354 
358  public static function getInstanceByObjIdAndRefIdAndUsrId(int $objId, int $refId, int $usrId, bool $checkValid = true): \ilCmiXapiAuthToken
359  {
360  global $DIC; /* @var \ILIAS\DI\Container $DIC */
361 
362  $query = "SELECT * FROM " . self::DB_TABLE_NAME . " WHERE obj_id = %s AND ref_id = %s AND usr_id = %s";
363 
364  if ($checkValid) {
365  $query .= " AND valid_until > CURRENT_TIMESTAMP";
366  }
367 
368  $result = $DIC->database()->queryF($query, array('integer', 'integer', 'integer'), array($objId, $refId, $usrId));
369 
370  $row = $DIC->database()->fetchAssoc($result);
371 
372  if ($row) {
373  $tokenObject = new self();
374  $tokenObject->setToken($row['token']);
375  $tokenObject->setValidUntil($row['valid_until']);
376  $tokenObject->setUsrId((int) $row['usr_id']);
377  $tokenObject->setObjId((int) $row['obj_id']);
378  $tokenObject->setRefId((int) $row['ref_id']);
379  $tokenObject->setLrsTypeId((int) $row['lrs_type_id']);
380  $tokenObject->setCmi5Session($row['cmi5_session']);
381  $tokenObject->setReturnedForCmi5Session($row['returned_for_cmi5_session']);
382  $tokenObject->setCmi5SessionData((string) $row['cmi5_session_data']);
383 
384  return $tokenObject;
385  }
386 
387  throw new ilCmiXapiException('no valid token found for: ' . $objId . '/' . $usrId);
388  }
389 
393  public static function getCmi5SessionByUsrIdAndObjIdAndRefId(int $usrId, int $objId, ?int $refId = null): string
394  {
395  global $DIC;
396 
397  if (empty($refId)) {
398  $query = "SELECT cmi5_session FROM " . self::DB_TABLE_NAME . " WHERE usr_id = %s AND obj_id = %s";
399  $result = $DIC->database()->queryF($query, array('integer', 'integer'), array($usrId, $objId));
400  } else {
401  $query = "SELECT cmi5_session FROM " . self::DB_TABLE_NAME . " WHERE usr_id = %s AND obj_id = %s AND ref_id = %s";
402  $result = $DIC->database()->queryF($query, array('integer', 'integer', 'integer'), array($usrId, $objId, $refId));
403  }
404 
405  $row = $DIC->database()->fetchAssoc($result);
406 
407  if ($row && $row['cmi5_session'] != '') {
408  return $row['cmi5_session'];
409  }
410  throw new ilCmiXapiException('no valid cmi5_session found for: ' . $objId . '/' . $usrId);
411  }
412 
416  public static function getWacSalt(): string
417  {
418  include 'data/wacsalt.php';
419 
420  if (isset($salt)) {
421  return $salt;
422  }
423 
424  throw new ilCmiXapiException('no salt for encryption provided');
425  }
426 }
setValidUntil(string $valid_until)
$res
Definition: ltiservices.php:66
const IL_CAL_DATETIME
setCmi5SessionData(string $cmi5_session_data)
static getInstanceByToken(string $token)
static getCmi5SessionByUsrIdAndObjIdAndRefId(int $usrId, int $objId, ?int $refId=null)
$objId
Definition: xapitoken.php:57
$refId
Definition: xapitoken.php:58
static fillToken(int $usrId, int $refId, int $objId, int $lrsTypeId=0)
setLrsTypeId(int $lrs_type_id)
const IL_CAL_UNIX
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static getInstanceByObjIdAndRefIdAndUsrId(int $objId, int $refId, int $usrId, bool $checkValid=true)
global $DIC
Definition: shib_login.php:22
static deleteTokenByObjIdAndUsrId(int $objId, int $usrId)
setReturnedForCmi5Session(string $returned_for_cmi5_session)
static getInstanceByObjIdAndUsrId(int $objId, int $usrId, bool $checkValid=true)
setCmi5Session(string $cmi5_session)
static deleteTokenByObjIdAndRefIdAndUsrId(int $objId, int $refId, int $usrId)
static insertToken($usrId, $refId, $objId, $lrsTypeId, $a_token, $a_time)