<?php

/**
 * @author buchhofer
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is protected 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  2014 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 *
 */

namespace Sso\RestBundle\Controller;

use FOS\RestBundle\View\View;
use Symfony\Component\HttpFoundation\Request;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use FOS\RestBundle\Controller\Annotations\NamePrefix;
use FOS\RestBundle\Controller\Annotations\RequestParam;

/**
 * Class UserController
 * @package Sso\RestBundle\Controller
 *
 * @NamePrefix("api_rest_uaa_")
 */
class UserController extends AbstractController
{

    /**
     * *This service is used to get attributes from a specific application for a specific user!
     * This documentation only shows the decrypted request body!
     * The service expects a header authentication (x-wsse/servicetoken).*
     *
     * **Attention: to secure this service against replay attacks the x-wsse header is only valid for one request!**
     *
     * #Request (header)
     *
     *      Key                 | Value               | Description
     *      ------------------- | ------------------- | --------------------------------------
     *      x-wsse              |  (string)           | a generated x-wsse header
     *      servicetoken        |  (string)           | servicetoken to use this service
     *
     * ##x-wsse header example
     *
     *      UsernameToken Username="admin", PasswordDigest="inRgz7oomhSiWBWdKtLCT8wn7zM=", Nonce="ZDk5YWV3MTkxODVmOTMxNw==", Created="2015-12-28T10:27:37+01:00"
     *
     * ##Requests
     *
     *
     * **Request example XML**
     *
     *      POST /api/v1/users/applications/attributes.xml
     *
     *
     * **Example XML Request (decrypted)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *          <userApplicationAttributes>
     *              <userIdentifier>Mustermann</userIdentifier>
     *              <applicationTypes>
     *                  <application>
     *                      <name>Your App Name One</name>
     *                  <application>
     *                  <application>
     *                      <name>Your App Name Two</name>
     *                  <application>
     *              </applicationTypes>
     *          </userApplicationAttributes>
     *
     *
     * **Request example JSON**
     *
     *     POST /api/v1/logins.json
     *
     * **Example JSON Request (decrypted)**
     *
     *      {
     *       "userIdentifier": "Mustermann",
     *       "applicationTypes": [
     *           {
     *              "name": "Your App Name One"
     *           },
     *           {
     *              "name": "Your App Name Two"
     *           }
     *        ]
     *       }
     *
     *
     * ##Response Success 200 (verified)
     *
     * **Example XML Response 200 (body)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *       <response>
     *           <status>200</status>
     *           <message><![CDATA[OK]]></message>
     *           <trackId><![CDATA[29f9bb75d6]]></trackId>
     *           <durationSeconds><![CDATA[0.4535]]></durationSeconds>
     *           <loginStatus><![CDATA[verified]]></loginStatus>
     *           <userIdentifier><![CDATA[admin]]></userIdentifier>
     *           <username><![CDATA[admin]]></username>
     *           <userFirstname><![CDATA[7753aed5]]></userFirstname>
     *           <userLastname><![CDATA[eb521d95]]></userLastname>
     *           <lastLogin><![CDATA[2016-01-04T12:35:35+0100]]></lastLogin>
     *           <loginFails>2</loginFails>
     *           <applicationTypes>
     *              <application>
     *                  <name>Your App Name One</name>
     *                  <active>1</active>
     *                  <attribute>
     *                      <type>one</type>
     *                      <name>attribute name one</name>
     *                      <value>value one</value>
     *                  </attribute>
     *                  <attribute>
     *                      <type>one</type>
     *                      <name>attribute name two</name>
     *                      <value>value two</value>
     *                  </attribute>
     *             </application>
     *            <application>
     *               <Name>Your App Name Two</Name>
     *               <active>1</active>
     *               <attribute>
     *                   <type>one</type>
     *                   <name>attribute name one</name>
     *                   <value>value one</value>
     *               </attribute>
     *               <attribute>
     *                   <type>one</type>
     *                   <name>attribute name two</name>
     *                   <value>value two</value>
     *               </attribute>
     *            </application>
     *          <applicationTypes>
     *       </response>
     *
     * **Example JSON Response 200 (body)**
     *
     *       {
     *           "status": 200,
     *           "message": "OK",
     *           "trackId": "bfdff27708",
     *           "durationSeconds": "0.4736",
     *           "loginStatus": "verified",
     *           "userIdentifier": "admin",
     *           "username": "admin",
     *           "userFirstname": "7753aed5",
     *           "userLastname": "eb521d95",
     *           "lastLogin": "2016-01-04T12:35:48+0100",
     *           "loginFails": 0
     *           "applicationTypes": [
     *                  {
     *                     "name": "Your App Name One"
     *                  },
     *                  {
     *                     "name": "Your App Name Two"
     *                  }
     *              ]
     *       }
     *
     *
     * ##Response 406 (unverified)
     *
     * This status is returned when the user is authenticated by a different source e.g. LDAP
     *
     * **Example XML Response 406 (body)**
     *
     *       <?xml version="1.0" encoding="UTF-8"?>
     *       <response>
     *           <status>406</status>
     *           <message><![CDATA[Not Acceptable]]></message>
     *           <trackId><![CDATA[3b455a2691]]></trackId>
     *           <durationSeconds><![CDATA[0.4001]]></durationSeconds>
     *           <loginStatus><![CDATA[unverified]]></loginStatus>
     *           <userIdentifier><![CDATA[admin]]></userIdentifier>
     *           <username><![CDATA[admin]]></username>
     *           <userAuthId><![CDATA[LDAP-Test]]></userAuthId>
     *           <userLdapSearchAttributes><![CDATA[ldapAttribute]]></userLdapSearchAttributes>
     *           <userLdapSearchValue><![CDATA[ldapSearchValue]]></userLdapSearchValue>
     *           <userFirstname><![CDATA[7753aed5]]></userFirstname>
     *           <userLastname><![CDATA[eb521d95]]></userLastname>
     *           <lastLogin><![CDATA[2016-01-04T12:35:48+0100]]></lastLogin>
     *           <loginFails>0</loginFails>
     *       </response>
     *
     * **Example JSON Response 406 (body)**
     *
     *       {
     *           "status": 406,
     *           "message": "Not Acceptable",
     *           "trackId": "4e5b612c33",
     *           "durationSeconds": "0.3841",
     *           "loginStatus": "unverified",
     *           "userIdentifier": "admin",
     *           "username": "admin",
     *           "userAuthId": "LDAP-Test",
     *           "userLdapSearchAttributes": "ldapAttribute",
     *           "userLdapSearchValue": "ldapSearchValue",
     *           "userFirstname": "7753aed5",
     *           "userLastname": "eb521d95",
     *           "lastLogin": "2016-01-04T12:35:48+0100",
     *           "loginFails": 0
     *       }
     *
     * ##Response error
     *
     * **Example (header)**
     *
     *      401 Forbidden
     *
     * **Example JSON (body)**
     *
     *       {
     *       "status": 401,
     *       "message": "Forbidden",
     *       "trackId": "13562a3481",
     *       "count": 1,
     *       "errors": [
     *              {
     *              "code": 401,
     *              "message": "here is the error message",
     *              "trackId": "13562a3481",
     *              "type": "external",
     *              "exception": "not set",
     *              "debug": "not set"
     *              }
     *          ]
     *       }
     *
     *
     * **Example XML (body)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *       <response>
     *          <status>401</status>
     *          <message><![CDATA[Forbidden]]></message>
     *          <trackId><![CDATA[13562a3481]]></trackId>
     *          <count>1</count>
     *          <errors>
     *              <error>
     *                  <code>401</code>
     *                  <message><![CDATA[here is the error message]></message>
     *                  <trackId><![CDATA[13562a3481]]></trackId>
     *                  <type><![CDATA[external]]></type>
     *                  <exception><![CDATA[not set]]></exception>
     *                  <debug><![CDATA[not set]]></debug>
     *              </error>
     *          </errors>
     *       </response>
     *
     * @ApiDoc(
     *  resource=true,
     *  description="secured: add user (e.g. LDAP) login failed",
     *  statusCodes={
     *         200="Returned when successful",
     *         400="Bad request",
     *         401="Forbidden",
     *         406="Not Acceptable",
     *         403="Returned when the user is not authorized to do this request",
     *         500="Internal Server Error"
     *     },
     *   tags={
     *         "stable" = "#FF0000"
     *     }
     * )
     *
     *
     * @Secure(roles="ROLE_API")
     * @return View
     */
    public function postUserApplicationAttributesAction(Request $request)
    {
        $user = $this->getUser();
        $lastDigest = $user->getRestLastDigest();
        $encyptedBody = $request->getContent();

        $format = preg_match('/\.xml/i', $request->getUri()) ? 'xml' : 'json';

        return $this->restApiM()->worker()->user()->postApplicationAttributes()->init(
            $encyptedBody,
            $lastDigest,
            $format
        );
    }

    /**
     * *This service checks user credentials the request body must be highly encrypted! This documentation only shows the decrypted request body!
     * The service expects a header authentication (x-wsse/servicetoken).*
     *
     * **Attention: to secure this service against replay attacks the x-wsse header is only valid for one request!**
     *
     * #Request (header)
     *
     *      Key                 | Value               | Description
     *      ------------------- | ------------------- | --------------------------------------
     *      x-wsse              |  (string)           | a generated x-wsse header
     *      servicetoken        |  (string)           | servicetoken to use this service
     *
     * ##x-wsse header example
     *
     *      UsernameToken Username="admin", PasswordDigest="inRgz7oomhSiWBWdKtLCT8wn7zM=", Nonce="ZDk5YWV3MTkxODVmOTMxNw==", Created="2015-12-28T10:27:37+01:00"
     *
     * ##Requests
     *
     *
     * **Request example XML**
     *
     *      POST /api/v1/users/show.xml
     *
     *
     * **Example XML Request (decrypted)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *          <checkLogin>
     *              <userIdentifier>Mustermann</userIdentifier>
     *          </checkLogin>
     *
     *
     * **Request example JSON**
     *
     *     POST /api/v1/users/show.json
     *
     * **Example JSON Request (decrypted)**
     *
     *      {
     *       "userIdentifier": "Mustermann"
     *       }
     *
     *
     * ##Response Success 200 (verified)
     *
     * **Example XML Response 200 (body)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *       <response>
     *           <status>200</status>
     *           <message><![CDATA[OK]]></message>
     *           <trackId><![CDATA[29f9bb75d6]]></trackId>
     *           <durationSeconds><![CDATA[0.4535]]></durationSeconds>
     *           <userGuid><![CDATA[f68be1857dc322ca5d08614827bc9813]]></userIdentifier>
     *           <userIdentifier><![CDATA[admin]]></userIdentifier>
     *           <username><![CDATA[admin]]></username>
     *           <userFirstname><![CDATA[7753aed5]]></userFirstname>
     *           <userLastname><![CDATA[eb521d95]]></userLastname>
     *           <mfaEnabled>false</mfaEnabled>
     *           <forcePasswordReset>true</forcePasswordReset>
     *           <resetPasswordToken><![CDATA[JSDFJHIHSTWETFGDSHUHF8976DFHJKDFDFDFDFDFDFDF]]></resetPasswordToken>
     *           <resetPasswordTokenExpire><![CDATA[2016-01-04T12:35:48+0100]]></resetPasswordTokenExpire>
     *           <lastLogin><![CDATA[2016-01-04T12:35:35+0100]]></lastLogin>
     *           <loginFails>0</loginFails>
     *       </response>
     *
     * **Example JSON Response 200 (body)**
     *
     *       {
     *           "status": 200,
     *           "message": "OK",
     *           "trackId": "bfdff27708",
     *           "durationSeconds": "0.4736",
     *           "userGuid": "f68be1857dc322ca5d08614827bc9813",
     *           "userIdentifier": "admin",
     *           "username": "admin",
     *           "userFirstname": "7753aed5",
     *           "userLastname": "eb521d95",
     *           "mfaEnabled": false,
     *           "forcePasswordReset": true,
     *           "resetPasswordToken": "ABCDEFRWTZSHFGEFTHFHDHFHHFHHFJHFJHFZHFHHFJKUEPOPOIJ",
     *           "resetPasswordTokenExpire": "2018-05-07T12:35:48+0100"
     *           "lastLogin": "2016-01-04T12:35:48+0100",
     *           "loginFails": 0
     *       }
     *
     *
     * ##Response error
     *
     * **Example (header)**
     *
     *      401 Unauthorized
     *
     * **Example JSON (body)**
     *
     *       {
     *       "status": 401,
     *       "message": "Unauthorized",
     *       "trackId": "13562a3481",
     *       "count": 1,
     *       "errors": [
     *              {
     *              "code": 401,
     *              "message": "here is the error message",
     *              "trackId": "13562a3481",
     *              "type": "external",
     *              "exception": "not set",
     *              "debug": "not set"
     *              }
     *          ]
     *       }
     *
     *
     * **Example XML (body)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *       <response>
     *          <status>401</status>
     *          <message><![CDATA[Unauthorized]]></message>
     *          <trackId><![CDATA[13562a3481]]></trackId>
     *          <count>1</count>
     *          <errors>
     *              <error>
     *                  <code>401</code>
     *                  <message><![CDATA[here is the error message]></message>
     *                  <trackId><![CDATA[13562a3481]]></trackId>
     *                  <type><![CDATA[external]]></type>
     *                  <exception><![CDATA[not set]]></exception>
     *                  <debug><![CDATA[not set]]></debug>
     *              </error>
     *          </errors>
     *       </response>
     *
     * **Example (header)**
     *
     *      403 Forbidden
     *
     * This status is returned when the user tries to often to login with wrong credentials in a defined time delay
     *
     * **Example JSON (body)**
     *
     *       {
     *       "status": 403,
     *       "message": "Forbidden",
     *       "trackId": "13562a3481",
     *       "durationSeconds": 0.2656,
     *       "count": 1,
     *       "errors": [
     *              {
     *              "code": 403,
     *              "message": "user invalid",
     *              "trackId": "13562a3481",
     *              "type": "external",
     *              "exception": "not set",
     *              "debug": "not set"
     *              }
     *          ]
     *       }
     *
     *
     * **Example XML (body)**
     *
     *      <?xml version="1.0" encoding="UTF-8"?>
     *       <response>
     *          <status>403</status>
     *          <message><![CDATA[Forbidden]]></message>
     *          <trackId><![CDATA[13562a3481]]></trackId>
     *          <durationSeconds><![CDATA[0.2656]]></trackId>
     *          <count>1</count>
     *          <errors>
     *              <error>
     *                  <code>403</code>
     *                  <message><![CDATA[user invalid]></message>
     *                  <trackId><![CDATA[13562a3481]]></trackId>
     *                  <type><![CDATA[external]]></type>
     *                  <exception><![CDATA[not set]]></exception>
     *                  <debug><![CDATA[not set]]></debug>
     *              </error>
     *          </errors>
     *       </response>
     *
     * @ApiDoc(
     *  resource=true,
     *  description="secured: check user credentials",
     *  statusCodes={
     *         200="Returned when successful",
     *         400="Bad request",
     *         401="Unauthorized",
     *         406="Not Acceptable",
     *         403="Forbidden",
     *         500="Internal Server Error"
     *     },
     *   tags={
     *         "stable" = "#FF0000"
     *     }
     * )
     *
     *
     * @Secure(roles="ROLE_API")
     * @param Request $request
     * @return View
     * @throws \Exception
     */
    public function postUserShowAction(Request $request)
    {
        $user = $this->getUser();
        $lastDigest = $user->getRestLastDigest();
        $encyptedBody = $request->getContent();

        $format = preg_match('/\.xml/i', $request->getUri()) ? 'xml' : 'json';

        return $this->restApiM()->worker()->user()->postShow()->init($encyptedBody, $lastDigest, $format);
    }
}
