зеркало из https://github.com/nextcloud/server.git
Merge pull request #36363 from nextcloud/feat/app-framework/usesession-attribute
feat(app-framework): Add UseSession attribute to replace annotation
This commit is contained in:
Коммит
7269766e05
|
@ -41,6 +41,7 @@ use OCA\OAuth2\Db\AccessTokenMapper;
|
||||||
use OCA\OAuth2\Db\ClientMapper;
|
use OCA\OAuth2\Db\ClientMapper;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\Response;
|
use OCP\AppFramework\Http\Response;
|
||||||
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
||||||
use OCP\Defaults;
|
use OCP\Defaults;
|
||||||
|
@ -126,8 +127,8 @@ class ClientFlowLoginController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function showAuthPickerPage(string $clientIdentifier = '', string $user = '', int $direct = 0): StandaloneTemplateResponse {
|
public function showAuthPickerPage(string $clientIdentifier = '', string $user = '', int $direct = 0): StandaloneTemplateResponse {
|
||||||
$clientName = $this->getClientName();
|
$clientName = $this->getClientName();
|
||||||
$client = null;
|
$client = null;
|
||||||
|
@ -193,8 +194,8 @@ class ClientFlowLoginController extends Controller {
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @NoSameSiteCookieRequired
|
* @NoSameSiteCookieRequired
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function grantPage(string $stateToken = '',
|
public function grantPage(string $stateToken = '',
|
||||||
string $clientIdentifier = '',
|
string $clientIdentifier = '',
|
||||||
int $direct = 0): StandaloneTemplateResponse {
|
int $direct = 0): StandaloneTemplateResponse {
|
||||||
|
@ -243,10 +244,10 @@ class ClientFlowLoginController extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @UseSession
|
|
||||||
*
|
*
|
||||||
* @return Http\RedirectResponse|Response
|
* @return Http\RedirectResponse|Response
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function generateAppPassword(string $stateToken,
|
public function generateAppPassword(string $stateToken,
|
||||||
string $clientIdentifier = '') {
|
string $clientIdentifier = '') {
|
||||||
if (!$this->isValidToken($stateToken)) {
|
if (!$this->isValidToken($stateToken)) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ use OC\Core\Exception\LoginFlowV2NotFoundException;
|
||||||
use OC\Core\Service\LoginFlowV2Service;
|
use OC\Core\Service\LoginFlowV2Service;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
use OCP\AppFramework\Http\RedirectResponse;
|
use OCP\AppFramework\Http\RedirectResponse;
|
||||||
use OCP\AppFramework\Http\Response;
|
use OCP\AppFramework\Http\Response;
|
||||||
|
@ -97,8 +98,8 @@ class ClientFlowLoginV2Controller extends Controller {
|
||||||
/**
|
/**
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function landing(string $token, $user = ''): Response {
|
public function landing(string $token, $user = ''): Response {
|
||||||
if (!$this->loginFlowV2Service->startLoginFlow($token)) {
|
if (!$this->loginFlowV2Service->startLoginFlow($token)) {
|
||||||
return $this->loginTokenForbiddenResponse();
|
return $this->loginTokenForbiddenResponse();
|
||||||
|
@ -114,8 +115,8 @@ class ClientFlowLoginV2Controller extends Controller {
|
||||||
/**
|
/**
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function showAuthPickerPage($user = ''): StandaloneTemplateResponse {
|
public function showAuthPickerPage($user = ''): StandaloneTemplateResponse {
|
||||||
try {
|
try {
|
||||||
$flow = $this->getFlowByLoginToken();
|
$flow = $this->getFlowByLoginToken();
|
||||||
|
@ -145,10 +146,10 @@ class ClientFlowLoginV2Controller extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @UseSession
|
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @NoSameSiteCookieRequired
|
* @NoSameSiteCookieRequired
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function grantPage(string $stateToken): StandaloneTemplateResponse {
|
public function grantPage(string $stateToken): StandaloneTemplateResponse {
|
||||||
if (!$this->isValidStateToken($stateToken)) {
|
if (!$this->isValidStateToken($stateToken)) {
|
||||||
return $this->stateTokenForbiddenResponse();
|
return $this->stateTokenForbiddenResponse();
|
||||||
|
@ -222,8 +223,8 @@ class ClientFlowLoginV2Controller extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function generateAppPassword(string $stateToken): Response {
|
public function generateAppPassword(string $stateToken): Response {
|
||||||
if (!$this->isValidStateToken($stateToken)) {
|
if (!$this->isValidStateToken($stateToken)) {
|
||||||
return $this->stateTokenForbiddenResponse();
|
return $this->stateTokenForbiddenResponse();
|
||||||
|
|
|
@ -43,6 +43,7 @@ use OC\User\Session;
|
||||||
use OC_App;
|
use OC_App;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
use OCP\AppFramework\Http\RedirectResponse;
|
use OCP\AppFramework\Http\RedirectResponse;
|
||||||
use OCP\AppFramework\Http\TemplateResponse;
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
@ -105,10 +106,10 @@ class LoginController extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @UseSession
|
|
||||||
*
|
*
|
||||||
* @return RedirectResponse
|
* @return RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function logout() {
|
public function logout() {
|
||||||
$loginToken = $this->request->getCookie('nc_token');
|
$loginToken = $this->request->getCookie('nc_token');
|
||||||
if (!is_null($loginToken)) {
|
if (!is_null($loginToken)) {
|
||||||
|
@ -134,13 +135,13 @@ class LoginController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @UseSession
|
|
||||||
*
|
*
|
||||||
* @param string $user
|
* @param string $user
|
||||||
* @param string $redirect_url
|
* @param string $redirect_url
|
||||||
*
|
*
|
||||||
* @return TemplateResponse|RedirectResponse
|
* @return TemplateResponse|RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function showLoginForm(string $user = null, string $redirect_url = null): Http\Response {
|
public function showLoginForm(string $user = null, string $redirect_url = null): Http\Response {
|
||||||
if ($this->userSession->isLoggedIn()) {
|
if ($this->userSession->isLoggedIn()) {
|
||||||
return new RedirectResponse($this->urlGenerator->linkToDefaultPageUrl());
|
return new RedirectResponse($this->urlGenerator->linkToDefaultPageUrl());
|
||||||
|
@ -283,12 +284,12 @@ class LoginController extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @UseSession
|
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @BruteForceProtection(action=login)
|
* @BruteForceProtection(action=login)
|
||||||
*
|
*
|
||||||
* @return RedirectResponse
|
* @return RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function tryLogin(Chain $loginChain,
|
public function tryLogin(Chain $loginChain,
|
||||||
string $user,
|
string $user,
|
||||||
string $password,
|
string $password,
|
||||||
|
@ -368,12 +369,12 @@ class LoginController extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @UseSession
|
|
||||||
* @BruteForceProtection(action=sudo)
|
* @BruteForceProtection(action=sudo)
|
||||||
*
|
*
|
||||||
* @license GNU AGPL version 3 or any later version
|
* @license GNU AGPL version 3 or any later version
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function confirmPassword(string $password): DataResponse {
|
public function confirmPassword(string $password): DataResponse {
|
||||||
$loginName = $this->userSession->getLoginName();
|
$loginName = $this->userSession->getLoginName();
|
||||||
$loginResult = $this->userManager->checkPassword($loginName, $password);
|
$loginResult = $this->userManager->checkPassword($loginName, $password);
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace OC\Core\Controller;
|
||||||
use OC\Authentication\TwoFactorAuth\Manager;
|
use OC\Authentication\TwoFactorAuth\Manager;
|
||||||
use OC_User;
|
use OC_User;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\RedirectResponse;
|
use OCP\AppFramework\Http\RedirectResponse;
|
||||||
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
||||||
use OCP\Authentication\TwoFactorAuth\IActivatableAtLogin;
|
use OCP\Authentication\TwoFactorAuth\IActivatableAtLogin;
|
||||||
|
@ -110,13 +111,13 @@ class TwoFactorChallengeController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @UseSession
|
|
||||||
* @TwoFactorSetUpDoneRequired
|
* @TwoFactorSetUpDoneRequired
|
||||||
*
|
*
|
||||||
* @param string $challengeProviderId
|
* @param string $challengeProviderId
|
||||||
* @param string $redirect_url
|
* @param string $redirect_url
|
||||||
* @return StandaloneTemplateResponse|RedirectResponse
|
* @return StandaloneTemplateResponse|RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function showChallenge($challengeProviderId, $redirect_url) {
|
public function showChallenge($challengeProviderId, $redirect_url) {
|
||||||
$user = $this->userSession->getUser();
|
$user = $this->userSession->getUser();
|
||||||
$providerSet = $this->twoFactorManager->getProviderSet($user);
|
$providerSet = $this->twoFactorManager->getProviderSet($user);
|
||||||
|
@ -161,7 +162,6 @@ class TwoFactorChallengeController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @UseSession
|
|
||||||
* @TwoFactorSetUpDoneRequired
|
* @TwoFactorSetUpDoneRequired
|
||||||
*
|
*
|
||||||
* @UserRateThrottle(limit=5, period=100)
|
* @UserRateThrottle(limit=5, period=100)
|
||||||
|
@ -171,6 +171,7 @@ class TwoFactorChallengeController extends Controller {
|
||||||
* @param string $redirect_url
|
* @param string $redirect_url
|
||||||
* @return RedirectResponse
|
* @return RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function solveChallenge($challengeProviderId, $challenge, $redirect_url = null) {
|
public function solveChallenge($challengeProviderId, $challenge, $redirect_url = null) {
|
||||||
$user = $this->userSession->getUser();
|
$user = $this->userSession->getUser();
|
||||||
$provider = $this->twoFactorManager->getProvider($user, $challengeProviderId);
|
$provider = $this->twoFactorManager->getProvider($user, $challengeProviderId);
|
||||||
|
|
|
@ -33,6 +33,7 @@ use OC\Authentication\WebAuthn\Manager;
|
||||||
use OC\URLGenerator;
|
use OC\URLGenerator;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
use OCP\ISession;
|
use OCP\ISession;
|
||||||
|
@ -63,8 +64,8 @@ class WebAuthnController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function startAuthentication(string $loginName): JSONResponse {
|
public function startAuthentication(string $loginName): JSONResponse {
|
||||||
$this->logger->debug('Starting WebAuthn login');
|
$this->logger->debug('Starting WebAuthn login');
|
||||||
|
|
||||||
|
@ -87,8 +88,8 @@ class WebAuthnController extends Controller {
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
* @UseSession
|
|
||||||
*/
|
*/
|
||||||
|
#[UseSession]
|
||||||
public function finishAuthentication(string $data): JSONResponse {
|
public function finishAuthentication(string $data): JSONResponse {
|
||||||
$this->logger->debug('Validating WebAuthn login');
|
$this->logger->debug('Validating WebAuthn login');
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ return array(
|
||||||
'OCP\\AppFramework\\Db\\QBMapper' => $baseDir . '/lib/public/AppFramework/Db/QBMapper.php',
|
'OCP\\AppFramework\\Db\\QBMapper' => $baseDir . '/lib/public/AppFramework/Db/QBMapper.php',
|
||||||
'OCP\\AppFramework\\Db\\TTransactional' => $baseDir . '/lib/public/AppFramework/Db/TTransactional.php',
|
'OCP\\AppFramework\\Db\\TTransactional' => $baseDir . '/lib/public/AppFramework/Db/TTransactional.php',
|
||||||
'OCP\\AppFramework\\Http' => $baseDir . '/lib/public/AppFramework/Http.php',
|
'OCP\\AppFramework\\Http' => $baseDir . '/lib/public/AppFramework/Http.php',
|
||||||
|
'OCP\\AppFramework\\Http\\Attribute\\UseSession' => $baseDir . '/lib/public/AppFramework/Http/Attribute/UseSession.php',
|
||||||
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
|
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
|
||||||
'OCP\\AppFramework\\Http\\DataDisplayResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
|
'OCP\\AppFramework\\Http\\DataDisplayResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
|
||||||
'OCP\\AppFramework\\Http\\DataDownloadResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDownloadResponse.php',
|
'OCP\\AppFramework\\Http\\DataDownloadResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDownloadResponse.php',
|
||||||
|
|
|
@ -68,6 +68,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
||||||
'OCP\\AppFramework\\Db\\QBMapper' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/QBMapper.php',
|
'OCP\\AppFramework\\Db\\QBMapper' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/QBMapper.php',
|
||||||
'OCP\\AppFramework\\Db\\TTransactional' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/TTransactional.php',
|
'OCP\\AppFramework\\Db\\TTransactional' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/TTransactional.php',
|
||||||
'OCP\\AppFramework\\Http' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http.php',
|
'OCP\\AppFramework\\Http' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http.php',
|
||||||
|
'OCP\\AppFramework\\Http\\Attribute\\UseSession' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/UseSession.php',
|
||||||
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
|
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
|
||||||
'OCP\\AppFramework\\Http\\DataDisplayResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
|
'OCP\\AppFramework\\Http\\DataDisplayResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
|
||||||
'OCP\\AppFramework\\Http\\DataDownloadResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDownloadResponse.php',
|
'OCP\\AppFramework\\Http\\DataDownloadResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDownloadResponse.php',
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||||
*
|
*
|
||||||
|
@ -27,9 +30,11 @@ namespace OC\AppFramework\Middleware;
|
||||||
|
|
||||||
use OC\AppFramework\Utility\ControllerMethodReflector;
|
use OC\AppFramework\Utility\ControllerMethodReflector;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\Response;
|
use OCP\AppFramework\Http\Response;
|
||||||
use OCP\AppFramework\Middleware;
|
use OCP\AppFramework\Middleware;
|
||||||
use OCP\ISession;
|
use OCP\ISession;
|
||||||
|
use ReflectionMethod;
|
||||||
|
|
||||||
class SessionMiddleware extends Middleware {
|
class SessionMiddleware extends Middleware {
|
||||||
/** @var ControllerMethodReflector */
|
/** @var ControllerMethodReflector */
|
||||||
|
@ -49,8 +54,18 @@ class SessionMiddleware extends Middleware {
|
||||||
* @param string $methodName
|
* @param string $methodName
|
||||||
*/
|
*/
|
||||||
public function beforeController($controller, $methodName) {
|
public function beforeController($controller, $methodName) {
|
||||||
$useSession = $this->reflector->hasAnnotation('UseSession');
|
/**
|
||||||
if ($useSession) {
|
* Annotation deprecated with Nextcloud 26
|
||||||
|
*/
|
||||||
|
$hasAnnotation = $this->reflector->hasAnnotation('UseSession');
|
||||||
|
if ($hasAnnotation) {
|
||||||
|
$this->session->reopen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflectionMethod = new ReflectionMethod($controller, $methodName);
|
||||||
|
$hasAttribute = !empty($reflectionMethod->getAttributes(UseSession::class));
|
||||||
|
if ($hasAttribute) {
|
||||||
$this->session->reopen();
|
$this->session->reopen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,10 +77,21 @@ class SessionMiddleware extends Middleware {
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function afterController($controller, $methodName, Response $response) {
|
public function afterController($controller, $methodName, Response $response) {
|
||||||
$useSession = $this->reflector->hasAnnotation('UseSession');
|
/**
|
||||||
if ($useSession) {
|
* Annotation deprecated with Nextcloud 26
|
||||||
|
*/
|
||||||
|
$hasAnnotation = $this->reflector->hasAnnotation('UseSession');
|
||||||
|
if ($hasAnnotation) {
|
||||||
|
$this->session->close();
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflectionMethod = new ReflectionMethod($controller, $methodName);
|
||||||
|
$hasAttribute = !empty($reflectionMethod->getAttributes(UseSession::class));
|
||||||
|
if ($hasAttribute) {
|
||||||
$this->session->close();
|
$this->session->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||||
|
*
|
||||||
|
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCP\AppFramework\Http\Attribute;
|
||||||
|
|
||||||
|
use Attribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute for controller methods that need to read/write PHP session data
|
||||||
|
*
|
||||||
|
* @since 26.0.0
|
||||||
|
*/
|
||||||
|
#[Attribute]
|
||||||
|
class UseSession {
|
||||||
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ownCloud - App Framework
|
* ownCloud - App Framework
|
||||||
*
|
*
|
||||||
|
@ -14,84 +17,128 @@ namespace Test\AppFramework\Middleware;
|
||||||
use OC\AppFramework\Middleware\SessionMiddleware;
|
use OC\AppFramework\Middleware\SessionMiddleware;
|
||||||
use OC\AppFramework\Utility\ControllerMethodReflector;
|
use OC\AppFramework\Utility\ControllerMethodReflector;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\UseSession;
|
||||||
use OCP\AppFramework\Http\Response;
|
use OCP\AppFramework\Http\Response;
|
||||||
|
use OCP\IRequest;
|
||||||
|
use OCP\ISession;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use Test\TestCase;
|
||||||
|
|
||||||
class SessionMiddlewareTest extends \Test\TestCase {
|
class SessionMiddlewareTest extends TestCase {
|
||||||
/** @var ControllerMethodReflector */
|
private ControllerMethodReflector|MockObject $reflector;
|
||||||
private $reflector;
|
private ISession|MockObject $session;
|
||||||
|
private Controller $controller;
|
||||||
/** @var Controller */
|
private SessionMiddleware $middleware;
|
||||||
private $controller;
|
|
||||||
|
|
||||||
protected function setUp(): void {
|
protected function setUp(): void {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->reflector = new ControllerMethodReflector();
|
$this->reflector = $this->createMock(ControllerMethodReflector::class);
|
||||||
$this->controller = $this->createMock(Controller::class);
|
$this->session = $this->createMock(ISession::class);
|
||||||
|
$this->controller = new class('app', $this->createMock(IRequest::class)) extends Controller {
|
||||||
|
/**
|
||||||
|
* @UseSession
|
||||||
|
*/
|
||||||
|
public function withAnnotation() {
|
||||||
|
}
|
||||||
|
#[UseSession]
|
||||||
|
public function withAttribute() {
|
||||||
|
}
|
||||||
|
public function without() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$this->middleware = new SessionMiddleware(
|
||||||
|
$this->reflector,
|
||||||
|
$this->session,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testSessionNotClosedOnBeforeController(): void {
|
||||||
* @UseSession
|
$this->configureSessionMock(0, 1);
|
||||||
*/
|
$this->reflector->expects(self::once())
|
||||||
public function testSessionNotClosedOnBeforeController() {
|
->method('hasAnnotation')
|
||||||
$session = $this->getSessionMock(0, 1);
|
->with('UseSession')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
$this->reflector->reflect($this, __FUNCTION__);
|
$this->middleware->beforeController($this->controller, 'withAnnotation');
|
||||||
$middleware = new SessionMiddleware($this->reflector, $session);
|
|
||||||
$middleware->beforeController($this->controller, __FUNCTION__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testSessionNotClosedOnBeforeControllerWithAttribute(): void {
|
||||||
* @UseSession
|
$this->configureSessionMock(0, 1);
|
||||||
*/
|
$this->reflector->expects(self::once())
|
||||||
public function testSessionClosedOnAfterController() {
|
->method('hasAnnotation')
|
||||||
$session = $this->getSessionMock(1);
|
->with('UseSession')
|
||||||
|
->willReturn(false);
|
||||||
|
|
||||||
$this->reflector->reflect($this, __FUNCTION__);
|
$this->middleware->beforeController($this->controller, 'withAttribute');
|
||||||
$middleware = new SessionMiddleware($this->reflector, $session);
|
|
||||||
$middleware->afterController($this->controller, __FUNCTION__, new Response());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testSessionClosedOnAfterController(): void {
|
||||||
* @UseSession
|
$this->configureSessionMock(1);
|
||||||
*/
|
$this->reflector->expects(self::once())
|
||||||
public function testSessionReopenedAndClosedOnBeforeController() {
|
->method('hasAnnotation')
|
||||||
$session = $this->getSessionMock(1, 1);
|
->with('UseSession')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
$this->reflector->reflect($this, __FUNCTION__);
|
$this->middleware->afterController($this->controller, 'withAnnotation', new Response());
|
||||||
$middleware = new SessionMiddleware($this->reflector, $session);
|
|
||||||
$middleware->beforeController($this->controller, __FUNCTION__);
|
|
||||||
$middleware->afterController($this->controller, __FUNCTION__, new Response());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSessionClosedOnBeforeController() {
|
public function testSessionClosedOnAfterControllerWithAttribute(): void {
|
||||||
$session = $this->getSessionMock(0);
|
$this->configureSessionMock(1);
|
||||||
|
$this->reflector->expects(self::once())
|
||||||
|
->method('hasAnnotation')
|
||||||
|
->with('UseSession')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
$this->reflector->reflect($this, __FUNCTION__);
|
$this->middleware->afterController($this->controller, 'withAttribute', new Response());
|
||||||
$middleware = new SessionMiddleware($this->reflector, $session);
|
|
||||||
$middleware->beforeController($this->controller, __FUNCTION__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSessionNotClosedOnAfterController() {
|
public function testSessionReopenedAndClosedOnBeforeController(): void {
|
||||||
$session = $this->getSessionMock(0);
|
$this->configureSessionMock(1, 1);
|
||||||
|
$this->reflector->expects(self::exactly(2))
|
||||||
|
->method('hasAnnotation')
|
||||||
|
->with('UseSession')
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
$this->reflector->reflect($this, __FUNCTION__);
|
$this->middleware->beforeController($this->controller, 'withAnnotation');
|
||||||
$middleware = new SessionMiddleware($this->reflector, $session);
|
$this->middleware->afterController($this->controller, 'withAnnotation', new Response());
|
||||||
$middleware->afterController($this->controller, __FUNCTION__, new Response());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testSessionReopenedAndClosedOnBeforeControllerWithAttribute(): void {
|
||||||
* @return mixed
|
$this->configureSessionMock(1, 1);
|
||||||
*/
|
$this->reflector->expects(self::exactly(2))
|
||||||
private function getSessionMock(int $expectedCloseCount, int $expectedReopenCount = 0) {
|
->method('hasAnnotation')
|
||||||
$session = $this->getMockBuilder('\OC\Session\Memory')
|
->with('UseSession')
|
||||||
->disableOriginalConstructor()
|
->willReturn(false);
|
||||||
->getMock();
|
|
||||||
|
|
||||||
$session->expects($this->exactly($expectedCloseCount))
|
$this->middleware->beforeController($this->controller, 'withAttribute');
|
||||||
|
$this->middleware->afterController($this->controller, 'withAttribute', new Response());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSessionClosedOnBeforeController(): void {
|
||||||
|
$this->configureSessionMock(0);
|
||||||
|
$this->reflector->expects(self::once())
|
||||||
|
->method('hasAnnotation')
|
||||||
|
->with('UseSession')
|
||||||
|
->willReturn(false);
|
||||||
|
|
||||||
|
$this->middleware->beforeController($this->controller, 'without');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSessionNotClosedOnAfterController(): void {
|
||||||
|
$this->configureSessionMock(0);
|
||||||
|
$this->reflector->expects(self::once())
|
||||||
|
->method('hasAnnotation')
|
||||||
|
->with('UseSession')
|
||||||
|
->willReturn(false);
|
||||||
|
|
||||||
|
$this->middleware->afterController($this->controller, 'without', new Response());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function configureSessionMock(int $expectedCloseCount, int $expectedReopenCount = 0): void {
|
||||||
|
$this->session->expects($this->exactly($expectedCloseCount))
|
||||||
->method('close');
|
->method('close');
|
||||||
$session->expects($this->exactly($expectedReopenCount))
|
$this->session->expects($this->exactly($expectedReopenCount))
|
||||||
->method('reopen');
|
->method('reopen');
|
||||||
return $session;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче