| Total Complexity | 27 |
| Total Lines | 279 |
| Duplicated Lines | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
| 1 | <?php namespace Gvera\Controllers; |
||
| 39 | abstract class GvController |
||
| 40 | { |
||
| 41 | |||
| 42 | private ?string $method; |
||
| 43 | private ?string $name; |
||
| 44 | protected array $viewParams = array(); |
||
| 45 | protected HttpResponse $httpResponse; |
||
| 46 | protected HttpRequest $httpRequest; |
||
| 47 | protected DIContainer $diContainer; |
||
| 48 | protected bool $protectedController = false; |
||
| 49 | |||
| 50 | const DEFAULT_CONTROLLER = "Index"; |
||
| 51 | const DEFAULT_METHOD = 'index'; |
||
| 52 | private TwigService $twigService; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * GvController constructor. |
||
| 56 | * @param DIContainer $diContainer |
||
| 57 | * @param $controllerName |
||
| 58 | * @param $method |
||
| 59 | * @throws InvalidMethodException |
||
| 60 | * @throws ReflectionException |
||
| 61 | */ |
||
| 62 | public function __construct(DIContainer $diContainer, $controllerName, $method) |
||
| 63 | { |
||
| 64 | $this->diContainer = $diContainer; |
||
| 65 | $this->method = $method; |
||
| 66 | $this->name = $controllerName; |
||
| 67 | $this->httpRequest = $this->diContainer->get('httpRequest'); |
||
| 68 | $this->httpResponse = $this->diContainer->get('httpResponse'); |
||
| 69 | $config = $this->diContainer->get('config'); |
||
| 70 | $this->twigService = new TwigService( |
||
| 71 | $config, |
||
| 72 | __DIR__ . '/../Views/', |
||
| 73 | __DIR__ . '/../../var/cache/views/' |
||
| 74 | ); |
||
| 75 | |||
| 76 | if (!method_exists($this, $method)) { |
||
| 77 | throw new InvalidMethodException( |
||
| 78 | 'the method was not found on the controller', |
||
| 79 | [ |
||
| 80 | 'method' => $method, |
||
| 81 | 'controller' => $controllerName |
||
| 82 | ] |
||
| 83 | ); |
||
| 84 | } |
||
| 85 | } |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @param array $allowedHttpMethods |
||
| 89 | * @throws InvalidHttpMethodException |
||
| 90 | * @throws InvalidViewException |
||
| 91 | * @throws LoaderError |
||
| 92 | * @throws NotAllowedException |
||
| 93 | * @throws ReflectionException |
||
| 94 | * @throws RuntimeError |
||
| 95 | * @throws SyntaxError |
||
| 96 | */ |
||
| 97 | public function init(array $allowedHttpMethods = []):void |
||
| 98 | { |
||
| 99 | $this->preInit($allowedHttpMethods); |
||
| 100 | |||
| 101 | $methodName = $this->method; |
||
| 102 | $this->$methodName(); |
||
| 103 | |||
| 104 | $this->postInit(); |
||
| 105 | } |
||
| 106 | |||
| 107 | /** |
||
| 108 | * @param $allowedHttpMethods |
||
| 109 | * @throws InvalidHttpMethodException |
||
| 110 | * @throws ReflectionException |
||
| 111 | * @throws NotAllowedException |
||
| 112 | */ |
||
| 113 | protected function preInit($allowedHttpMethods) |
||
| 134 | } |
||
| 135 | } |
||
| 136 | |||
| 137 | /** |
||
| 138 | * @throws InvalidViewException |
||
| 139 | */ |
||
| 140 | protected function postInit() |
||
| 141 | { |
||
| 142 | if ($this->twigService->needsTwig($this->name, $this->method)) { |
||
| 143 | $this->httpResponse->response( |
||
| 144 | new Response($this->twigService->render($this->name, $this->method, $this->viewParams)) |
||
| 145 | ); |
||
| 146 | return; |
||
| 147 | } |
||
| 148 | |||
| 149 | if (count($this->viewParams) > 0) { |
||
| 150 | throw new InvalidViewException( |
||
| 151 | 'view params was set, but view could not be found ', |
||
| 152 | ['method' => $this->method,'controller ' => $this->name] |
||
| 153 | ); |
||
| 154 | } |
||
| 155 | } |
||
| 156 | |||
| 157 | /** |
||
| 158 | * @throws NotAllowedException |
||
| 159 | */ |
||
| 160 | public function checkIfPassIsGranted() |
||
| 161 | { |
||
| 162 | if (!$this->protectedController) { |
||
| 163 | return; |
||
| 164 | } |
||
| 165 | |||
| 166 | if (null !== $this->httpRequest->getAuthDetails()) { |
||
| 167 | $this->mustPassBasicAuthentication(); |
||
| 168 | return; |
||
| 169 | } |
||
| 170 | |||
| 171 | if (null !== $this->httpRequest->getBearerToken()) { |
||
| 172 | $this->mustPassTokenAuthentication(); |
||
| 173 | } |
||
| 174 | |||
| 175 | $this->mustPassSessionAuthentication(); |
||
| 176 | } |
||
| 177 | |||
| 178 | /** |
||
| 179 | * @throws NotAllowedException |
||
| 180 | * @throws Exception |
||
| 181 | */ |
||
| 182 | protected function mustPassSessionAuthentication() |
||
| 183 | { |
||
| 184 | $sessionStrategy = new SessionAuthenticationStrategy( |
||
| 185 | $this->getSession(), |
||
|
1 ignored issue
–
show
|
|||
| 186 | $this->getUserService(), |
||
|
1 ignored issue
–
show
|
|||
| 187 | $this->getEntityManager() |
||
|
1 ignored issue
–
show
|
|||
| 188 | ); |
||
| 189 | $context =new AuthenticationContext($sessionStrategy); |
||
| 190 | if (!$context->isUserLoggedIn()) { |
||
| 191 | throw new NotAllowedException(Locale::getLocale('user is not allowed')); |
||
| 192 | } |
||
| 193 | } |
||
| 194 | |||
| 195 | /** |
||
| 196 | * @throws NotAllowedException |
||
| 197 | */ |
||
| 198 | protected function mustPassBasicAuthentication() |
||
| 199 | { |
||
| 200 | $basicAuthStrategy = new BasicAuthenticationStrategy( |
||
| 201 | $this->getEntityManager(), |
||
| 202 | $this->getUserService(), |
||
| 203 | $this->httpRequest->getAuthDetails() |
||
| 204 | ); |
||
| 205 | $context = new AuthenticationContext($basicAuthStrategy); |
||
| 206 | if (!$context->isUserLoggedIn()) { |
||
| 207 | throw new NotAllowedException(Locale::getLocale('user is not allowed')); |
||
| 208 | } |
||
| 209 | } |
||
| 210 | |||
| 211 | /** |
||
| 212 | * @throws NotAllowedException |
||
| 213 | * @throws Exception |
||
| 214 | */ |
||
| 215 | public function mustPassTokenAuthentication() |
||
| 216 | { |
||
| 217 | $token = $this->httpRequest->getBearerToken(); |
||
| 218 | $jwtTokenStrategy = new JWTTokenAuthenticationStrategy($token, $this->getEntityManager()); |
||
| 219 | $context = new AuthenticationContext($jwtTokenStrategy); |
||
| 220 | if (!$context->isUserLoggedIn()) { |
||
| 221 | throw new NotAllowedException(Locale::getLocale('user is not allowed')); |
||
| 222 | } |
||
| 223 | } |
||
| 224 | |||
| 225 | /** |
||
| 226 | * @param int $errorCode |
||
| 227 | * @param string $message |
||
| 228 | */ |
||
| 229 | protected function badRequestWithError(int $errorCode, string $message):void |
||
| 230 | { |
||
| 231 | $this->httpResponse->response( |
||
| 232 | new JSONResponse( |
||
| 233 | ['error' => $errorCode,'message' => $message], |
||
| 234 | Response::HTTP_RESPONSE_BAD_REQUEST |
||
| 235 | ) |
||
| 236 | ); |
||
| 237 | } |
||
| 238 | |||
| 239 | /** |
||
| 240 | * @param int $errorCode |
||
| 241 | * @param string $message |
||
| 242 | */ |
||
| 243 | protected function unauthorizedWithError(int $errorCode, string $message):void |
||
| 244 | { |
||
| 245 | $this->httpResponse->response( |
||
| 246 | new PrintErrorResponse( |
||
| 247 | $errorCode, |
||
| 248 | $message, |
||
| 249 | Response::HTTP_RESPONSE_UNAUTHORIZED |
||
| 250 | ) |
||
| 251 | ); |
||
| 252 | } |
||
| 253 | |||
| 254 | protected function unauthorizedBasicAuth() |
||
| 255 | { |
||
| 256 | $this->httpResponse->response( |
||
| 257 | new Response( |
||
| 258 | '', |
||
| 259 | Response::CONTENT_TYPE_HTML, |
||
| 260 | Response::HTTP_RESPONSE_UNAUTHORIZED, |
||
| 261 | Response::BASIC_AUTH_ACCESS_DENIED |
||
| 262 | ) |
||
| 263 | ); |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * @param string $action |
||
| 268 | * @return boolean |
||
| 269 | */ |
||
| 270 | protected function isUserAllowed(string $action): bool |
||
| 271 | { |
||
| 272 | $repo = $this->getEntityManager()->getRepository(User::class); |
||
| 273 | $session = $this->getSession(); |
||
| 274 | $user = $repo->findOneById($session->get('user')['id']); |
||
| 275 | return $this->getUserService()->userCan($user, $action); |
||
| 276 | } |
||
| 277 | |||
| 278 | /** |
||
| 279 | * @return string |
||
| 280 | */ |
||
| 281 | protected function generateCSRFToken(): string |
||
| 282 | { |
||
| 283 | $session = $this->getSession(); |
||
| 284 | $token = $this->getCsrfFactory()->createToken(); |
||
|
1 ignored issue
–
show
|
|||
| 285 | $session->set(CSRFToken::ID, $token->getTokenValue()); |
||
| 286 | |||
| 287 | return $token->getTokenValue(); |
||
| 288 | } |
||
| 289 | |||
| 290 | /** |
||
| 291 | * @param $requestToken |
||
| 292 | * @throws InvalidCSRFException |
||
| 293 | */ |
||
| 294 | protected function validateCSRFToken($requestToken) |
||
| 305 | } |
||
| 306 | |||
| 307 | /** |
||
| 308 | * @param $name |
||
| 309 | * @param $arguments |
||
| 310 | * @return object |
||
| 311 | * @throws ReflectionException |
||
| 312 | * using magic methods to retrieve from DIContainer |
||
| 313 | */ |
||
| 314 | public function __call($name, $arguments): object |
||
| 315 | { |
||
| 318 | } |
||
| 319 | } |
||
| 320 |