<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Sso\RestBundle\Controller\MultipleWs\Version2;

use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Request\ParamFetcher;
use FOS\RestBundle\View\View;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use FOS\RestBundle\Controller\Annotations\NamePrefix;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\FOSRestController;
use Sso\RestBundle\Worker\Worker as Worker;
use JMS\DiExtraBundle\Annotation as DI;
use FOS\RestBundle\Controller\Annotations\Get;
use LifeStyle\Tools\CachingBundle\Annotations\LsCache;

/**
 * Class ValidateController
 *
 * @NamePrefix("api_rest_")
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package    Sso\RestBundle\Controller
 */
class ValidateController extends FOSRestController
{
    /**
     * @DI\Inject("rest_worker_manager")
     * @var Worker
     */
    protected $woM;

    /**
     * **
     *
     * #Request (header)
     *
     *      Key                 | Value               | Description
     *      ------------------- | ------------------- | --------------------------------------
     *      username            |  (string)           | your username
     *      useridentifier      |  (string)           | your useridentifier for given username
     *      servicetoken        |  (string)           | your useridentifier for given username
     *
     * ####Requests
     *
     *
     * Request example
     *
     * Requests are generated through IDP/validateUserIdentifier and UserApplication/ShowDetails
     *
     * ####Response success
     *
     * Example (header)
     *
     *      200 OK
     *
     * Example JSON (body)
     *
     *         {
     *           "code": 200,
     *           "status": "OK",
     *           "trackId": "fb053a9c10",
     *           "date": "2017-01-13T10:54:32+01:00",
     *           "scriptTimeSec": 7.6242,
     *           "userType": {
     *             "guid": "94efe14d29217fe315a0de552af87246",
     *             "sessionLifeTime": "2017-01-13T17:27:38+00:00",
     *             "userToken": "6b7ec415abb6365abfadb2235bdf9103d9bed92f2eaaf36ed63b009bafe975834a4edc21222f9e961df5e914249467680ef5798d7d43bf998db48223d7610bef",
     *             "username": "m.hengstmann",
     *             "email": "m.hengstmann@life-style.de",
     *             "firstname": "Michael",
     *             "lastname": "Hengstmann",
     *             "active": 1,
     *             "deleted": 0,
     *             "authId": "",
     *             "mfaEnabled": 0
     *           },
     *           "applicationType": [
     *             {
     *               "name": "SsoAdmin",
     *               "active": 1,
     *               "attributeType": [
     *                 {
     *                   "type": "one",
     *                   "name": "TestAttribute1",
     *                   "value": "TestAttribute1Value"
     *                 }
     *               ],
     *               "applicationRoleType": [
     *                 {
     *                   "name": "TestRole1",
     *                   "description": "Test Role for SSO Admin Interface",
     *                   "active": 1
     *                 }
     *               ]
     *             }
     *           ],
     *           "objects": [
     *             {
     *               "typeName": "Root",
     *               "guid": "d106d322-0b49-4cc5-806f-2638e8e19800",
     *               "referenceId": "S0000001",
     *               "name": "All Sso",
     *               "treeId": "1",
     *               "scopeType": "parent"
     *             },
     *             {
     *               "typeName": "Division",
     *               "guid": "37a21be4-5c6a-4cbd-88bf-de8b6783c561",
     *               "referenceId": "S0000309",
     *               "name": "United Europe",
     *               "treeId": "1.01",
     *               "scopeType": "secondary"
     *             }
     *           ]
     *         }
     *
     * Example XML (body)
     *
     *         <?xml version="1.0" encoding="UTF-8"?>
     *         <userApplicationShowDetails>
     *           <code>200</code>
     *           <status><![CDATA[OK]]></status>
     *           <trackId><![CDATA[37d22a0f89]]></trackId>
     *           <date><![CDATA[2017-01-13T10:56:20+01:00]]></date>
     *           <scriptTimeSec>5.7274</scriptTimeSec>
     *           <userType>
     *             <guid><![CDATA[94efe14d29217fe315a0de552af87246]]></guid>
     *             <sessionLifeTime><![CDATA[2017-01-13T17:27:38+00:00]]></sessionLifeTime>
     *             <userToken><![CDATA[6b7ec415abb6365abfadb2235bdf9103d9bed92f2eaaf36ed63b009bafe975834a4edc21222f9e961df5e914249467680ef5798d7d43bf998db48223d7610bef]]></userToken>
     *             <username><![CDATA[m.hengstmann]]></username>
     *             <email><![CDATA[m.hengstmann@life-style.de]]></email>
     *             <firstname><![CDATA[Michael]]></firstname>
     *             <lastname><![CDATA[Hengstmann]]></lastname>
     *             <active>1</active>
     *             <deleted>0</deleted>
     *             <authId><![CDATA[]]></authId>
     *             <mfaEnabled>0</mfaEnabled>
     *           </userType>
     *           <applicationType>
     *             <name><![CDATA[SsoAdmin]]></name>
     *             <active>1</active>
     *             <attributeType>
     *               <type><![CDATA[one]]></type>
     *               <name><![CDATA[TestAttribute1]]></name>
     *               <value><![CDATA[TestAttribute1Value]]></value>
     *             </attributeType>
     *             <applicationRoleType>
     *               <name><![CDATA[TestRole1]]></name>
     *               <description><![CDATA[Test Role for SSO Admin Interface]]></description>
     *               <active>1</active>
     *             </applicationRoleType>
     *           </applicationType>
     *           <objects>
     *             <typeName><![CDATA[Root]]></typeName>
     *             <guid><![CDATA[d106d322-0b49-4cc5-806f-2638e8e19800]]></guid>
     *             <referenceId><![CDATA[S0000001]]></referenceId>
     *             <name><![CDATA[All Sso]]></name>
     *             <treeId><![CDATA[1]]></treeId>
     *             <scopeType><![CDATA[parent]]></scopeType>
     *           </objects>
     *           <objects>
     *             <typeName><![CDATA[Division]]></typeName>
     *             <guid><![CDATA[37a21be4-5c6a-4cbd-88bf-de8b6783c561]]></guid>
     *             <referenceId><![CDATA[S0000309]]></referenceId>
     *             <name><![CDATA[United Europe]]></name>
     *             <treeId><![CDATA[1.01]]></treeId>
     *             <scopeType><![CDATA[secondary]]></scopeType>
     *           </objects>
     *         </userApplicationShowDetails>
     *
     * #### Response partial error
     *
     *  Partial Error ( IDP returns okay but UserApplication got Error )
     *
     * Example (header)
     *
     *      200 Ok from IDP and 40x from ShowDetails
     *
     * Example JSON (body)
     *
     *      {
     *           "code": 200,
     *           "status": "OK",
     *           "trackId": "fb053a9c10",
     *           "date": "2017-01-13T10:54:32+01:00",
     *           "scriptTimeSec": 7.6242,
     *           "userType": {
     *             "guid": "94efe14d29217fe315a0de552af87246",
     *             "sessionLifeTime": "2017-01-13T17:27:38+00:00",
     *             "userToken": "6b7ec415abb6365abfadb2235bdf9103d9bed92f2eaaf36ed63b009bafe975834a4edc21222f9e961df5e914249467680ef5798d7d43bf998db48223d7610bef",
     *             "username": "m.hengstmann",
     *             "email": "m.hengstmann@life-style.de",
     *             "firstname": "Michael",
     *             "lastname": "Hengstmann",
     *             "active": 1,
     *             "deleted": 0,
     *             "authId": "",
     *             "mfaEnabled": 0
     *           },
     *           "applicationType": [],
     *           "objects": [
     *             {
     *               "typeName": "Root",
     *               "guid": "d106d322-0b49-4cc5-806f-2638e8e19800",
     *               "referenceId": "S0000001",
     *               "name": "All Sso",
     *               "treeId": "1",
     *               "scopeType": "parent"
     *             },
     *             {
     *               "typeName": "Division",
     *               "guid": "37a21be4-5c6a-4cbd-88bf-de8b6783c561",
     *               "referenceId": "S0000309",
     *               "name": "United Europe",
     *               "treeId": "1.01",
     *               "scopeType": "secondary"
     *             }
     *           ]
     *         }
     *
     * Example XML (body)
     *
     *         <?xml version="1.0" encoding="UTF-8"?>
     *         <userApplicationShowDetails>
     *           <code>200</code>
     *           <status><![CDATA[OK]]></status>
     *           <trackId><![CDATA[37d22a0f89]]></trackId>
     *           <date><![CDATA[2017-01-13T10:56:20+01:00]]></date>
     *           <scriptTimeSec>5.7274</scriptTimeSec>
     *           <userType>
     *             <guid><![CDATA[94efe14d29217fe315a0de552af87246]]></guid>
     *             <sessionLifeTime><![CDATA[2017-01-13T17:27:38+00:00]]></sessionLifeTime>
     *             <userToken><![CDATA[6b7ec415abb6365abfadb2235bdf9103d9bed92f2eaaf36ed63b009bafe975834a4edc21222f9e961df5e914249467680ef5798d7d43bf998db48223d7610bef]]></userToken>
     *             <username><![CDATA[m.hengstmann]]></username>
     *             <email><![CDATA[m.hengstmann@life-style.de]]></email>
     *             <firstname><![CDATA[Michael]]></firstname>
     *             <lastname><![CDATA[Hengstmann]]></lastname>
     *             <active>1</active>
     *             <deleted>0</deleted>
     *             <authId><![CDATA[]]></authId>
     *             <mfaEnabled>0</mfaEnabled>
     *           </userType>
     *           <objects>
     *             <typeName><![CDATA[Root]]></typeName>
     *             <guid><![CDATA[d106d322-0b49-4cc5-806f-2638e8e19800]]></guid>
     *             <referenceId><![CDATA[S0000001]]></referenceId>
     *             <name><![CDATA[All Sso]]></name>
     *             <treeId><![CDATA[1]]></treeId>
     *             <scopeType><![CDATA[parent]]></scopeType>
     *           </objects>
     *           <objects>
     *             <typeName><![CDATA[Division]]></typeName>
     *             <guid><![CDATA[37a21be4-5c6a-4cbd-88bf-de8b6783c561]]></guid>
     *             <referenceId><![CDATA[S0000309]]></referenceId>
     *             <name><![CDATA[United Europe]]></name>
     *             <treeId><![CDATA[1.01]]></treeId>
     *             <scopeType><![CDATA[secondary]]></scopeType>
     *           </objects>
     *         </userApplicationShowDetails>
     *
     * #### Response error
     *
     * IDP already returns Error so the hole call will fail
     *
     * Example (header)
     *
     *      400 Bad Request
     *
     * Example JSON (body)
     *
     *      {
     *        "code": 400,
     *        "status": "Bad Request",
     *        "trackId": "9cad76413c",
     *        "scriptTimeSec": 1.865,
     *        "count": 1,
     *        "errors": [
     *          {
     *            "code": 400,
     *            "status": "Bad Request",
     *            "message": "ErrorCode: ui002 ErrorRef: ui021 ShortMessage: Invalid credentials",
     *            "type": "external",
     *            "exception": "Wrong username or user-identifier",
     *            "debug": "not set"
     *          }
     *        ]
     *      }
     *
     * Example XML (body)
     *
     *         <?xml version="1.0" encoding="UTF-8"?>
     *         <response>
     *           <code>400</code>
     *           <status><![CDATA[Bad Request]]></status>
     *           <trackId><![CDATA[bc7bbca47c]]></trackId>
     *           <scriptTimeSec>7.9494</scriptTimeSec>
     *           <count>0</count>
     *           <errors>
     *             <error>
     *               <code>400</code>
     *               <status><![CDATA[Bad Request]]></status>
     *               <message><![CDATA[ErrorCode: ui002 ErrorRef: ui021 ShortMessage: Invalid credentials]]></message>
     *               <type><![CDATA[external]]></type>
     *               <exception><![CDATA[Wrong username or user-identifier]]></exception>
     *               <debug><![CDATA[not set]]></debug>
     *             </error>
     *           </errors>
     *
     * @ApiDoc(
     *  resource=true,
     *  description="secured: get objects for user",
     *  statusCodes={
     *         200="Returned when successful",
     *         400="Returned when an error occured",
     *         401="Unauthorized - Wrong credentials",
     *         403="Returned when the user is not authorized to do this request",
     *         500="Returned on internal server errors"
     *  },
     *  tags={
     *      "stable" = "#000",
     *      "cacheable" = "#0A0"
     *  },
     *  views = { "sso-ws-multiple" },
     *  input = "Sso\RestBundle\ModelRest\Request\MultipleWs\Version2\UserACL\Validate\Request",
     *  output={
     *          "class" = "Sso\RestBundle\ModelRest\Response\MultipleWs\Version2\UserACL\Response"
     *      },
     *  headers={
     *      {"name"="username", "description"="sso username"},
     *      {"name"="useridentifier", "description"="sso useridentifier"},
     *      {"name"="servicetoken", "description"="servicetoken"}
     *  }
     * )
     * @Get("/v2/sso-ws-multiple/validate/user/acl", name="_hr-core-ws_v2", options={ "method_prefix" = true })
     * @Secure(roles="ROLE_API")
     * @LsCache(cacheTTL=300, keyHeader=true)
     * @param Request $request
     * @return View
     */
    public function userACLAction(Request $request)
    {
        // get the scope tree result
        $request->query->set('identifier', $request->query->get('username'));
        $worker = $this->woM->multipleWs()->version1()->scope()->getScopeTreeObjects();
        if (null !== ($errorView = $worker->init($request))) {
            return $errorView;
        }
        $userApplicationAttributesView = $worker->getUserApplicationAttributes($request);

        if (200 != $userApplicationAttributesView->getStatusCode()) {
            $scopeTreeResult = $worker->buildResponse([]);
        } else {
            $scopeTreeResult = $worker->getObjectsByAttributes($request, $userApplicationAttributesView->getData());
        }

        // get the ACL result (with scope tree objects merged into)
        return $this->woM->multipleWs()->version2()->userACL()->validate()->init($request, $scopeTreeResult->getData());
    }
}
