id = filter_var($id, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]); $this->userId = filter_var($userId, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]); $this->key = self::isWellFormatted($key) ? $key : null; $this->rights = explode(',', $rights); $this->endDate = DateTime::createFromFormat('Y-m-d', $endDate); if ($this->endDate == false) { $this->endDate = null; } } public function getUserId() { return $this->userId; } public function getKey(){ return $this->key; } /** * testing if the apiKey is valid for a certain action * * @param string $action the action to test the apiKey against * @return boolean true if apiKey is valid for the action, false otherwise */ public function isValidFor(string $action) { // @todo add as validation: does the user exist and is 'active' (?) $today = new DateTime(); return ( $this->id != null && in_array($action, $this->rights) && ($this->endDate->format('Y-m-d') >= $today->format('Y-m-d')) ); } /** * request a specific apiKey from the db * * @param string $key the key to request * @return ApiKey found in the db, null otherwise */ public static function loadFromDb(string $key) { if (!self::isWellFormatted($key)) { return null; } $query = 'SELECT * FROM `cwsvjudo`.`participo_apiKeys` WHERE apiKey = :key;'; $params = [':key' => ['value' => $key, 'data_type' => PDO::PARAM_STR]]; $response = dbConnector::query($query, $params); // apiKeys are considered unique. so every other count is treated as error to prevent unprivileged access if (count($response) != 1) { return null; } return ApiKey::fromDbArray($response[0]); } public function addToDb() { $query = 'INSERT INTO `cwsvjudo`.`participo_apiKeys` (userId, apiKey, rights, endDate) VALUES (:userId, :apiKey, :rights, :endDate);'; $params = [ ':userId' => ['value' => $this->userId, 'data_type' => PDO::PARAM_INT], ':apiKey' => ['value' => $this->key, 'data_type' => PDO::PARAM_STR], ':rights' => ['value' => implode(',', $this->rights), 'data_type' => PDO::PARAM_STR], ':endDate' => ['value' => $this->endDate->format('Y-m-d'), 'data_type' => PDO::PARAM_STR] ]; $response = dbConnector::query($query, $params); // @todo use the response in an error handling/messaging } /** create an Api key from the return of an sql select * */ private static function fromDbArray(array $apiKey) { return new ApiKey( $apiKey['id'] ?? null, $apiKey['userId'] ?? null, $apiKey['apiKey'] ?? null, $apiKey['rights'] ?? null, $apiKey['endDate'] ?? null ); } private static $BASE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; /** * quick and dirty implementation of a convert_to_base62 * stolen from https://stackoverflow.com/a/4964352 * * @param [int] $num * @param integer $b * @return void */ private static function toBase($num, $b = 62) :string { // @todo What is with negative numbers? How are they supposed to be converted? $r = $num % $b ; $res = ApiKey::$BASE[$r]; $q = floor($num / $b); while ($q) { $r = $q % $b; $q = floor($q / $b); $res = ApiKey::$BASE[$r] . $res; } return $res; } /** * simple check if a string a well formatted apiKey * * Basically checks, if it consists only of 0-9, a-z or A-Z * * @param string $string string to check * @return boolean true if it is base62 encoded, false otherwise */ public static function isWellFormatted(string $string) { return (bool) preg_match('/^[0-9a-zA-Z]+$/', $string); } /** * provides a random api key value * * @return string a random api key value */ public static function create() { // @todo What is with negative numbers? How are they supposed to be converted? return ApiKey::toBase(random_int(0, PHP_INT_MAX)); } private static function createTable() { dbConnector::query("CREATE TABLE `cwsvjudo`.`participo_apiKeys` (`id` INT NOT NULL AUTO_INCREMENT COMMENT 'unique identifier' , `userId` INT NOT NULL COMMENT 'id of the user the key belongs to' , `apiKey` VARCHAR(16) NOT NULL COMMENT 'the apiKey itself' , `rights` INT NOT NULL COMMENT 'a comma separated list of rights for the key' , `endDate` DATE NOT NULL COMMENT 'endDate for the apiKey' , PRIMARY KEY (`id`), UNIQUE (`key`)); "); } }