$links has_many LtiDeployment * @property Studip\OAuth2\Models\Client|null $oauth2_client has_one Studip\OAuth2\Models\Client */ class LtiTool extends SimpleORMap { /** * Configure the database mapping. */ protected static function configure($config = []) { $config['db_table'] = 'lti_tools'; $config['has_many']['deployments'] = [ //formerly: links 'class_name' => LtiDeployment::class, 'assoc_foreign_key' => 'tool_id', 'on_delete' => 'delete' ]; $config['has_one']['oauth2_client'] = [ 'class_name' => \Studip\OAuth2\Models\Client::class, 'foreign_key' => 'oauth2_client_id', 'on_delete' => 'delete' ]; parent::configure($config); } /** * Validates the data in the LtiTool instance. * * @return string[] An array with errors. The array is empty if all * fields are filled with valid data. */ public function validate() : array { $errors = []; if (!$this->name) { $errors[] = _('Es wurde kein Name angegeben.'); } if (!$this->launch_url) { $errors[] = _('Es wurde keine Launch-URL angegeben.'); } if (!in_array($this->lti_version, ['1.1', '1.3a'])) { $errors[] = _('Die ausgewählte LTI-Version ist ungültig.'); } if ($this->lti_version === '1.1') { if (!$this->consumer_key) { $errors[] = _('Es wurde kein Consumer-Key angegeben.'); } if (!$this->consumer_secret) { $errors[] = _('Es wurde kein Consumer-Secret angegeben.'); } } return $errors; } /** * Retrieves all LTI tools. * * @param bool $with_private_tools Whether to include all private tools (true) * or not (false). Defautls to false. * * @return array A list of all LTI tools. */ public static function findAll(bool $with_private_tools = false) : array { if ($with_private_tools) { return self::findBySQL("1 ORDER BY name"); } else { return self::findBySQL("`range_id` = 'global' ORDER BY name"); } } /** * Checks whether a user may have the permissions to edit the tool. * * @param string $user_id The ID of the user whose edit permissions shall be checked. * * @return bool True, if the user may edit the tool, false otherwise. */ public function isEditableByUser(?string $user_id = null) : bool { $user_id ??= User::findCurrent()->id; return $this->range_id === 'global' && $GLOBALS['perm']->have_perm('root') || ($this->range_id !== 'global' && $GLOBALS['perm']->have_studip_perm('tutor', $this->range_id)); } //ToolInterface implementation public function getToolData() : Tool { return new Tool( $this->id, $this->name, $this->launch_url, $this->oidc_init_url, $this->launch_url, $this->deep_linking_url ); } /** * Retrieves the keyring of the LTI tool or generates one, if explicitly requested. * * @param bool $generate Generates a new keyring for the tool if set to true. * Defaults to false. * * @return Keyring|null The keyring for the tool or null if no such keyring exists. */ public function getKeyring(bool $generate = false) : ?Keyring { $keyring = Keyring::findOneBySQL( "`range_type` = 'lti_tool' AND `range_id` = :tool_id", ['tool_id' => $this->id] ); if ($generate && !$keyring) { $keyring = Keyring::generate($this->id, 'lti_tool'); } return $keyring; } /** * Sets or updates the public key for the LTI tool. * * @param string $public_key The public key to set. * * @return bool True, if the public key could be set, false otherwise. */ public function updatePublicKey(string $public_key) : bool { if (!$public_key) { //No key? Then it cannot be set. return false; } $keyring = $this->getKeyring(); if ($keyring) { //Clear the fields for the passphrase and the private key: $keyring->passphrase = ''; $keyring->private_key = ''; //Store the new public key for the tool: $keyring->public_key = $public_key; } else { $keyring = Keyring::createFromPublicKey($public_key, 'lti_tool', $this->id); } return $keyring->store() !== false; } public function getLtiVersionString() : string { if ($this->lti_version === '1.3a') { return '1.3a'; } elseif ($this->lti_version === '1.1') { return '1.0/1.1'; } else { return _('unbekannt'); } } }