You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DIContainer.php 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Bernhard Posselt <dev@bernhard-posselt.com>
  7. * @author Bjoern Schiessle <bjoern@schiessle.org>
  8. * @author Christoph Wurst <christoph@owncloud.com>
  9. * @author Joas Schilling <coding@schilljs.com>
  10. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  11. * @author Lukas Reschke <lukas@statuscode.ch>
  12. * @author Morris Jobke <hey@morrisjobke.de>
  13. * @author Robin McCorkell <robin@mccorkell.me.uk>
  14. * @author Roeland Jago Douma <roeland@famdouma.nl>
  15. * @author Sebastian Wessalowski <sebastian@wessalowski.org>
  16. * @author Thomas Müller <thomas.mueller@tmit.eu>
  17. * @author Thomas Tanghus <thomas@tanghus.net>
  18. *
  19. * @license AGPL-3.0
  20. *
  21. * This code is free software: you can redistribute it and/or modify
  22. * it under the terms of the GNU Affero General Public License, version 3,
  23. * as published by the Free Software Foundation.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU Affero General Public License for more details.
  29. *
  30. * You should have received a copy of the GNU Affero General Public License, version 3,
  31. * along with this program. If not, see <http://www.gnu.org/licenses/>
  32. *
  33. */
  34. namespace OC\AppFramework\DependencyInjection;
  35. use OC;
  36. use OC\AppFramework\Http;
  37. use OC\AppFramework\Http\Dispatcher;
  38. use OC\AppFramework\Http\Output;
  39. use OC\AppFramework\Middleware\MiddlewareDispatcher;
  40. use OC\AppFramework\Middleware\Security\CORSMiddleware;
  41. use OC\AppFramework\Middleware\OCSMiddleware;
  42. use OC\AppFramework\Middleware\Security\RateLimitingMiddleware;
  43. use OC\AppFramework\Middleware\Security\SecurityMiddleware;
  44. use OC\AppFramework\Middleware\SessionMiddleware;
  45. use OC\AppFramework\Utility\SimpleContainer;
  46. use OC\Core\Middleware\TwoFactorMiddleware;
  47. use OC\ServerContainer;
  48. use OCP\AppFramework\Http\IOutput;
  49. use OCP\AppFramework\IAppContainer;
  50. use OCP\AppFramework\QueryException;
  51. use OCP\AppFramework\Utility\IControllerMethodReflector;
  52. use OCP\AppFramework\Utility\ITimeFactory;
  53. use OCP\Files\Folder;
  54. use OCP\Files\IAppData;
  55. use OCP\GlobalScale\IConfig;
  56. use OCP\IL10N;
  57. use OCP\ILogger;
  58. use OCP\IRequest;
  59. use OCP\IServerContainer;
  60. use OCP\ISession;
  61. use OCP\IUserSession;
  62. use OCA\WorkflowEngine\Manager;
  63. class DIContainer extends SimpleContainer implements IAppContainer {
  64. /**
  65. * @var array
  66. */
  67. private $middleWares = array();
  68. /** @var ServerContainer */
  69. private $server;
  70. /**
  71. * Put your class dependencies in here
  72. * @param string $appName the name of the app
  73. * @param array $urlParams
  74. * @param ServerContainer|null $server
  75. */
  76. public function __construct($appName, $urlParams = array(), ServerContainer $server = null){
  77. parent::__construct();
  78. $this['AppName'] = $appName;
  79. $this['urlParams'] = $urlParams;
  80. $this->registerAlias('Request', IRequest::class);
  81. /** @var \OC\ServerContainer $server */
  82. if ($server === null) {
  83. $server = \OC::$server;
  84. }
  85. $this->server = $server;
  86. $this->server->registerAppContainer($appName, $this);
  87. // aliases
  88. $this->registerAlias('appName', 'AppName');
  89. $this->registerAlias('webRoot', 'WebRoot');
  90. $this->registerAlias('userId', 'UserId');
  91. /**
  92. * Core services
  93. */
  94. $this->registerService(IOutput::class, function($c){
  95. return new Output($this->getServer()->getWebRoot());
  96. });
  97. $this->registerService(Folder::class, function() {
  98. return $this->getServer()->getUserFolder();
  99. });
  100. $this->registerService(IAppData::class, function (SimpleContainer $c) {
  101. return $this->getServer()->getAppDataDir($c->query('AppName'));
  102. });
  103. $this->registerService(IL10N::class, function($c) {
  104. return $this->getServer()->getL10N($c->query('AppName'));
  105. });
  106. // Log wrapper
  107. $this->registerService(ILogger::class, function ($c) {
  108. return new OC\AppFramework\Logger($this->server->query(ILogger::class), $c->query('AppName'));
  109. });
  110. $this->registerService(IServerContainer::class, function ($c) {
  111. return $this->getServer();
  112. });
  113. $this->registerAlias('ServerContainer', IServerContainer::class);
  114. $this->registerService(\OCP\WorkflowEngine\IManager::class, function ($c) {
  115. return $c->query(Manager::class);
  116. });
  117. $this->registerService(\OCP\AppFramework\IAppContainer::class, function ($c) {
  118. return $c;
  119. });
  120. // commonly used attributes
  121. $this->registerService('UserId', function ($c) {
  122. return $c->query(IUserSession::class)->getSession()->get('user_id');
  123. });
  124. $this->registerService('WebRoot', function ($c) {
  125. return $c->query('ServerContainer')->getWebRoot();
  126. });
  127. $this->registerService('OC_Defaults', function ($c) {
  128. return $c->getServer()->getThemingDefaults();
  129. });
  130. $this->registerService(IConfig::class, function ($c) {
  131. return $c->query(OC\GlobalScale\Config::class);
  132. });
  133. $this->registerService('Protocol', function($c){
  134. /** @var \OC\Server $server */
  135. $server = $c->query('ServerContainer');
  136. $protocol = $server->getRequest()->getHttpProtocol();
  137. return new Http($_SERVER, $protocol);
  138. });
  139. $this->registerService('Dispatcher', function($c) {
  140. return new Dispatcher(
  141. $c['Protocol'],
  142. $c['MiddlewareDispatcher'],
  143. $c->query(IControllerMethodReflector::class),
  144. $c['Request']
  145. );
  146. });
  147. /**
  148. * App Framework default arguments
  149. */
  150. $this->registerParameter('corsMethods', 'PUT, POST, GET, DELETE, PATCH');
  151. $this->registerParameter('corsAllowedHeaders', 'Authorization, Content-Type, Accept');
  152. $this->registerParameter('corsMaxAge', 1728000);
  153. /**
  154. * Middleware
  155. */
  156. $app = $this;
  157. $this->registerService('SecurityMiddleware', function($c) use ($app){
  158. /** @var \OC\Server $server */
  159. $server = $app->getServer();
  160. return new SecurityMiddleware(
  161. $c['Request'],
  162. $server->query(IControllerMethodReflector::class),
  163. $server->getNavigationManager(),
  164. $server->getURLGenerator(),
  165. $server->getLogger(),
  166. $c['AppName'],
  167. $server->getUserSession()->isLoggedIn(),
  168. $server->getGroupManager()->isAdmin($this->getUserId()),
  169. $server->getContentSecurityPolicyManager(),
  170. $server->getCsrfTokenManager(),
  171. $server->getContentSecurityPolicyNonceManager(),
  172. $server->getAppManager(),
  173. $server->getL10N('lib')
  174. );
  175. });
  176. $this->registerService(OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware::class, function ($c) use ($app) {
  177. /** @var \OC\Server $server */
  178. $server = $app->getServer();
  179. return new OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware(
  180. $c->query(IControllerMethodReflector::class),
  181. $server->getSession(),
  182. $server->getUserSession(),
  183. $server->query(ITimeFactory::class)
  184. );
  185. });
  186. $this->registerService('BruteForceMiddleware', function($c) use ($app) {
  187. /** @var \OC\Server $server */
  188. $server = $app->getServer();
  189. return new OC\AppFramework\Middleware\Security\BruteForceMiddleware(
  190. $c->query(IControllerMethodReflector::class),
  191. $server->getBruteForceThrottler(),
  192. $server->getRequest()
  193. );
  194. });
  195. $this->registerService('RateLimitingMiddleware', function($c) use ($app) {
  196. /** @var \OC\Server $server */
  197. $server = $app->getServer();
  198. return new RateLimitingMiddleware(
  199. $server->getRequest(),
  200. $server->getUserSession(),
  201. $c->query(IControllerMethodReflector::class),
  202. $c->query(OC\Security\RateLimiting\Limiter::class)
  203. );
  204. });
  205. $this->registerService('CORSMiddleware', function($c) {
  206. return new CORSMiddleware(
  207. $c['Request'],
  208. $c->query(IControllerMethodReflector::class),
  209. $c->query(IUserSession::class),
  210. $c->getServer()->getBruteForceThrottler()
  211. );
  212. });
  213. $this->registerService('SessionMiddleware', function($c) use ($app) {
  214. return new SessionMiddleware(
  215. $c['Request'],
  216. $c->query(IControllerMethodReflector::class),
  217. $app->getServer()->getSession()
  218. );
  219. });
  220. $this->registerService('TwoFactorMiddleware', function (SimpleContainer $c) use ($app) {
  221. $twoFactorManager = $c->getServer()->getTwoFactorAuthManager();
  222. $userSession = $app->getServer()->getUserSession();
  223. $session = $app->getServer()->getSession();
  224. $urlGenerator = $app->getServer()->getURLGenerator();
  225. $reflector = $c->query(IControllerMethodReflector::class);
  226. $request = $app->getServer()->getRequest();
  227. return new TwoFactorMiddleware($twoFactorManager, $userSession, $session, $urlGenerator, $reflector, $request);
  228. });
  229. $this->registerService('OCSMiddleware', function (SimpleContainer $c) {
  230. return new OCSMiddleware(
  231. $c['Request']
  232. );
  233. });
  234. $this->registerService(OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware::class, function (SimpleContainer $c) {
  235. return new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware(
  236. $c['Request'],
  237. $c->query(IControllerMethodReflector::class)
  238. );
  239. });
  240. $middleWares = &$this->middleWares;
  241. $this->registerService('MiddlewareDispatcher', function(SimpleContainer $c) use (&$middleWares) {
  242. $dispatcher = new MiddlewareDispatcher();
  243. $dispatcher->registerMiddleware($c[OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware::class]);
  244. $dispatcher->registerMiddleware($c['CORSMiddleware']);
  245. $dispatcher->registerMiddleware($c['OCSMiddleware']);
  246. $dispatcher->registerMiddleware($c['SecurityMiddleware']);
  247. $dispatcher->registerMiddleware($c[OC\AppFramework\Middleware\Security\PasswordConfirmationMiddleware::class]);
  248. $dispatcher->registerMiddleware($c['TwoFactorMiddleware']);
  249. $dispatcher->registerMiddleware($c['BruteForceMiddleware']);
  250. $dispatcher->registerMiddleware($c['RateLimitingMiddleware']);
  251. $dispatcher->registerMiddleware(new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware(
  252. $c['Request'],
  253. $c->query(ISession::class),
  254. $c->query(\OCP\IConfig::class)
  255. ));
  256. foreach($middleWares as $middleWare) {
  257. $dispatcher->registerMiddleware($c[$middleWare]);
  258. }
  259. $dispatcher->registerMiddleware($c['SessionMiddleware']);
  260. return $dispatcher;
  261. });
  262. }
  263. /**
  264. * @return \OCP\IServerContainer
  265. */
  266. public function getServer()
  267. {
  268. return $this->server;
  269. }
  270. /**
  271. * @param string $middleWare
  272. * @return boolean|null
  273. */
  274. public function registerMiddleWare($middleWare) {
  275. $this->middleWares[] = $middleWare;
  276. }
  277. /**
  278. * used to return the appname of the set application
  279. * @return string the name of your application
  280. */
  281. public function getAppName() {
  282. return $this->query('AppName');
  283. }
  284. /**
  285. * @deprecated use IUserSession->isLoggedIn()
  286. * @return boolean
  287. */
  288. public function isLoggedIn() {
  289. return \OC::$server->getUserSession()->isLoggedIn();
  290. }
  291. /**
  292. * @deprecated use IGroupManager->isAdmin($userId)
  293. * @return boolean
  294. */
  295. public function isAdminUser() {
  296. $uid = $this->getUserId();
  297. return \OC_User::isAdminUser($uid);
  298. }
  299. private function getUserId() {
  300. return $this->getServer()->getSession()->get('user_id');
  301. }
  302. /**
  303. * @deprecated use the ILogger instead
  304. * @param string $message
  305. * @param string $level
  306. * @return mixed
  307. */
  308. public function log($message, $level) {
  309. switch($level){
  310. case 'debug':
  311. $level = ILogger::DEBUG;
  312. break;
  313. case 'info':
  314. $level = ILogger::INFO;
  315. break;
  316. case 'warn':
  317. $level = ILogger::WARN;
  318. break;
  319. case 'fatal':
  320. $level = ILogger::FATAL;
  321. break;
  322. default:
  323. $level = ILogger::ERROR;
  324. break;
  325. }
  326. \OCP\Util::writeLog($this->getAppName(), $message, $level);
  327. }
  328. /**
  329. * Register a capability
  330. *
  331. * @param string $serviceName e.g. 'OCA\Files\Capabilities'
  332. */
  333. public function registerCapability($serviceName) {
  334. $this->query('OC\CapabilitiesManager')->registerCapability(function() use ($serviceName) {
  335. return $this->query($serviceName);
  336. });
  337. }
  338. /**
  339. * @param string $name
  340. * @return mixed
  341. * @throws QueryException if the query could not be resolved
  342. */
  343. public function query($name) {
  344. try {
  345. return $this->queryNoFallback($name);
  346. } catch (QueryException $firstException) {
  347. try {
  348. return $this->getServer()->query($name);
  349. } catch (QueryException $secondException) {
  350. if ($firstException->getCode() === 1) {
  351. throw $secondException;
  352. }
  353. throw $firstException;
  354. }
  355. }
  356. }
  357. /**
  358. * @param string $name
  359. * @return mixed
  360. * @throws QueryException if the query could not be resolved
  361. */
  362. public function queryNoFallback($name) {
  363. $name = $this->sanitizeName($name);
  364. if ($this->offsetExists($name)) {
  365. return parent::query($name);
  366. } else {
  367. if ($this['AppName'] === 'settings' && strpos($name, 'OC\\Settings\\') === 0) {
  368. return parent::query($name);
  369. } else if ($this['AppName'] === 'core' && strpos($name, 'OC\\Core\\') === 0) {
  370. return parent::query($name);
  371. } else if (strpos($name, \OC\AppFramework\App::buildAppNamespace($this['AppName']) . '\\') === 0) {
  372. return parent::query($name);
  373. }
  374. }
  375. throw new QueryException('Could not resolve ' . $name . '!' .
  376. ' Class can not be instantiated', 1);
  377. }
  378. }