tao-test/app/tao/controller/api/Users.php

320 lines
11 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2019 (original work) Open Assessment Technologies SA;
*
*/
namespace oat\tao\controller\api;
use common_Exception;
use common_exception_Error;
use common_exception_MethodNotAllowed;
use common_exception_MissingParameter;
use common_exception_RestApi;
use common_exception_ValidationFailed;
use common_Utils;
use core_kernel_classes_Resource;
use core_kernel_users_Exception;
use oat\generis\model\user\UserRdf;
use oat\oatbox\service\ServiceManager;
use tao_actions_CommonRestModule;
use tao_models_classes_LanguageService;
use tao_models_classes_RoleService;
use tao_models_classes_UserService;
use oat\generis\Helper\UserHashForEncryption;
/**
* @OA\Post(
* path="tao/api/users",
* summary="Create new user",
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(ref="#/components/schemas/tao.User.New")
* )
* ),
* @OA\Response(
* response="200",
* description="User created",
* @OA\JsonContent(ref="#/components/schemas/tao.CommonRestModule.CreatedResourceResponse")
* ),
* @OA\Response(
* response="400",
* description="Invalid request data",
* @OA\JsonContent(ref="#/components/schemas/tao.RestTrait.FailureResponse")
* )
* )
*/
class Users extends tao_actions_CommonRestModule
{
/**
* @OA\Schema(
* schema="tao.User.New",
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/tao.GenerisClass.Search"),
* @OA\Schema(ref="#/components/schemas/tao.User.Update")
* },
* @OA\Property(
* property="login",
* type="string",
* description="Login"
* ),
* required={"login", "password", "userLanguage", "roles"}
* )
* @OA\Schema(
* schema="tao.User.Update",
* type="object",
* @OA\Property(
* property="login",
* type="string",
* description="Login"
* ),
* @OA\Property(
* property="password",
* type="string",
* description="Password"
* ),
* @OA\Property(
* property="userLanguage",
* type="string",
* description="Interface language uri"
* ),
* @OA\Property(
* property="defaultLanguage",
* type="string",
* description="Default language uri"
* ),
* @OA\Property(
* property="firstName",
* type="string",
* description="First name"
* ),
* @OA\Property(
* property="lastName",
* type="string",
* description="Last name"
* ),
* @OA\Property(
* property="mail",
* type="string",
* description="Email"
* ),
* @OA\Property(
* property="roles",
* type="string",
* description="List of roles (URIs)"
* )
* )
*/
/**
* Optional Requirements for parameters to be sent on every service
*/
protected function getParametersRequirements()
{
return [
'post' => ['login', 'password', 'userLanguage', 'roles']
];
}
/**
* @return array
*/
protected function getGuardedProperties()
{
return ['login', 'password', 'roles', 'type'];
}
/**
* @return array
*/
protected function getParametersAliases()
{
return array_merge(parent::getParametersAliases(), [
'login' => UserRdf::PROPERTY_LOGIN,
'password' => UserRdf::PROPERTY_PASSWORD,
'userLanguage' => UserRdf::PROPERTY_UILG,
'defaultLanguage' => UserRdf::PROPERTY_DEFLG,
'firstName' => UserRdf::PROPERTY_FIRSTNAME,
'lastName' => UserRdf::PROPERTY_LASTNAME,
'mail' => UserRdf::PROPERTY_MAIL,
'roles' => UserRdf::PROPERTY_ROLES
]);
}
/**
* @param null $uri
* @return void
* @throws \common_exception_NotImplemented
*/
public function get($uri = null)
{
$this->returnFailure(new common_exception_RestApi('Not implemented'));
}
/**
* @param string $uri
* @return void
* @throws \common_exception_NotImplemented
*/
public function put($uri)
{
$this->returnFailure(new common_exception_RestApi('Not implemented'));
}
/**
* @param string $uri
* @return void
* @throws \common_exception_NotImplemented
*/
public function delete($uri = null)
{
$this->returnFailure(new common_exception_RestApi('Not implemented'));
}
/**
* @return void
* @throws common_Exception
*/
public function post()
{
/** @var tao_models_classes_UserService $userService */
$userService = ServiceManager::getServiceManager()->get(tao_models_classes_UserService::SERVICE_ID);
if (!$userService->getOption(tao_models_classes_UserService::OPTION_ALLOW_API)) {
$this->returnFailure(new common_exception_RestApi((new common_exception_MethodNotAllowed())->getMessage()));
return;
}
try {
$parameters = $this->getParameters();
$this->validateParameters($parameters);
$roles = $this->processRoles($parameters);
$login = $parameters[UserRdf::PROPERTY_LOGIN];
$plainPassword = $parameters[UserRdf::PROPERTY_PASSWORD];
unset($parameters[UserRdf::PROPERTY_PASSWORD]);
$guarded = array_intersect_key($this->getParametersAliases(), array_flip($this->getGuardedProperties()));
$parameters = array_filter($parameters, static function ($key) use ($guarded) {
return !in_array($key, $guarded, true);
}, ARRAY_FILTER_USE_KEY);
$this->processLanguages($parameters);
/** @var core_kernel_classes_Resource $user */
$user = $userService->addUser($login, $plainPassword, $this->getResource(array_shift($roles)));
foreach ($roles as $role) {
$userService->attachRole($user, $this->getResource($role));
}
$userService->attachProperties($user, $parameters);
$userService->triggerUpdatedEvent(
$user,
[UserRdf::PROPERTY_PASSWORD => $user->getProperty(UserRdf::PROPERTY_PASSWORD)],
UserHashForEncryption::hash($plainPassword)
);
$this->returnSuccess([
'success' => true,
'uri' => $user->getUri(),
], false);
} catch (common_exception_MissingParameter $e) {
$this->returnFailure(new common_exception_RestApi($e->getMessage()));
} catch (common_exception_ValidationFailed $e) {
$this->returnFailure(new common_exception_RestApi($e->getMessage()));
} catch (common_exception_Error $e) {
$this->returnFailure(new common_exception_RestApi($e->getMessage()));
} catch (core_kernel_users_Exception $e) {
$this->returnFailure(new common_exception_RestApi($e->getMessage()));
} catch (common_exception_RestApi $e) {
$this->returnFailure($e);
}
}
/**
* @param array $parameters
* @throws common_exception_ValidationFailed
*/
protected function validateParameters(array $parameters)
{
if (empty($parameters[UserRdf::PROPERTY_LOGIN])) {
throw new common_exception_ValidationFailed(null, __("Validation for field '%s' has failed. Should not be empty", $this->reverseSearchAlias(UserRdf::PROPERTY_LOGIN)));
}
}
/**
* @param array $parameters
* @return array
* @throws common_exception_MissingParameter
* @throws common_exception_ValidationFailed
*/
protected function processRoles(array $parameters)
{
$roles = $parameters[UserRdf::PROPERTY_ROLES];
if (!is_array($roles)) {
throw new common_exception_ValidationFailed(null, __("Validation for field '%s' has failed. List of values expected", 'roles'));
}
if (!count($roles)) {
throw new common_exception_MissingParameter('roles');
}
$roleService = tao_models_classes_RoleService::singleton();
foreach ($roles as $role) {
if (!common_Utils::isUri($role)) {
throw new common_exception_ValidationFailed(null, __("Validation for field '%s' has failed. Valid URI expected. Given: %s", 'roles', $role));
}
if (!array_key_exists($role, $roleService->getAllRoles())) {
throw new common_exception_ValidationFailed(null, __("Validation for field '%s' has failed. Valid role expected. Given: %s", 'roles', $role));
}
}
return $roles;
}
/**
* @param array $parameters
* @throws common_exception_ValidationFailed
* @throws common_exception_Error
*/
protected function processLanguages(array $parameters)
{
$uriProperties = array_intersect_key($this->getParametersAliases(), array_flip(['userLanguage', 'defaultLanguage']));
foreach ($parameters as $key => $value) {
if (!in_array($key, $uriProperties, true)) {
continue;
}
if (!common_Utils::isUri($value)) {
throw new common_exception_ValidationFailed(null, __("Validation for field '%s' has failed. Valid URI expected", array_search($key, $uriProperties, true)));
}
if (!tao_models_classes_LanguageService::getExistingLanguageUri($value)) {
throw new common_exception_ValidationFailed(null, __("Validation for field '%s' has failed. Language does not exist in the system", array_search($key, $uriProperties, true)));
}
}
}
}