-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ExApp UI Implementation (Part1) (#135)
This PR adds ability for ExApp to have entry in TopMenu and provide it's own page when clicking on it. * OCS API for specifying InitialStates, Scripts, Styles, TopMenu * Small corrections and refactoring of code that relates on UI * Small bug fixes to other parts of AppAPI, mostly for FileActions Menu. PR is ready, after merging this, one additional PR will be created that relates to this one. That PR will cover missing parts: * Docs, changelog update * FileActions Menu rework(icon specifying) * Fixes of stuff that will be found if any, related to UI * CI Actions and Makefile adjusting, to keep `js/proxy_js` folder * Fix of Proxying stuff Merging this PR will allow nc_py_api's PR to be finished on this theme and finish first example for testing. --------- Signed-off-by: Alexander Piskun <[email protected]> Signed-off-by: Andrey Borysenko <[email protected]> Co-authored-by: Andrey Borysenko <[email protected]>
- Loading branch information
1 parent
947c0ca
commit 5027722
Showing
39 changed files
with
2,158 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/js/ | ||
/js/*.* | ||
.code-workspace | ||
.DS_Store | ||
.idea/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OCA\AppAPI\Controller; | ||
|
||
use OC\Security\CSP\ContentSecurityPolicyNonceManager; | ||
use OCA\AppAPI\AppInfo\Application; | ||
use OCA\AppAPI\ProxyResponse; | ||
use OCA\AppAPI\Service\AppAPIService; | ||
use OCP\AppFramework\Controller; | ||
use OCP\AppFramework\Http\Attribute\NoAdminRequired; | ||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired; | ||
use OCP\AppFramework\Http\ContentSecurityPolicy; | ||
use OCP\AppFramework\Http\NotFoundResponse; | ||
use OCP\AppFramework\Http\Response; | ||
use OCP\Files\IMimeTypeDetector; | ||
use OCP\Http\Client\IResponse; | ||
use OCP\IRequest; | ||
|
||
class ExAppProxyController extends Controller { | ||
|
||
public function __construct( | ||
IRequest $request, | ||
private AppAPIService $service, | ||
private IMimeTypeDetector $mimeTypeHelper, | ||
private ContentSecurityPolicyNonceManager $nonceManager, | ||
private ?string $userId, | ||
) { | ||
parent::__construct(Application::APP_ID, $request); | ||
} | ||
|
||
private function createProxyResponse(string $path, IResponse $response, $cache = true): ProxyResponse { | ||
$content = $response->getBody(); | ||
$isHTML = pathinfo($path, PATHINFO_EXTENSION) === 'html'; | ||
if ($isHTML) { | ||
$nonce = $this->nonceManager->getNonce(); | ||
$content = str_replace( | ||
'<script', | ||
"<script nonce=\"$nonce\"", | ||
$content | ||
); | ||
} | ||
|
||
$mime = $response->getHeader('content-type'); | ||
if (empty($mime)) { | ||
$mime = $this->mimeTypeHelper->detectPath($path); | ||
if (pathinfo($path, PATHINFO_EXTENSION) === 'wasm') { | ||
$mime = 'application/wasm'; | ||
} | ||
} | ||
|
||
$proxyResponse = new ProxyResponse( | ||
data: $content, | ||
length: strlen($content), | ||
mimeType: $mime, | ||
); | ||
|
||
$headersToCopy = ['Content-Disposition', 'Last-Modified', 'Etag']; | ||
foreach ($headersToCopy as $element) { | ||
$headerValue = $response->getHeader($element); | ||
if (empty($headerValue)) { | ||
$proxyResponse->addHeader($element, $headerValue); | ||
} | ||
} | ||
|
||
if ($cache && !$isHTML) { | ||
$proxyResponse->cacheFor(3600); | ||
} | ||
|
||
$csp = new ContentSecurityPolicy(); | ||
$csp->addAllowedScriptDomain($this->request->getServerHost()); | ||
$csp->addAllowedScriptDomain('\'unsafe-eval\''); | ||
$csp->addAllowedScriptDomain('\'unsafe-inline\''); | ||
$csp->addAllowedFrameDomain($this->request->getServerHost()); | ||
$proxyResponse->setContentSecurityPolicy($csp); | ||
return $proxyResponse; | ||
} | ||
|
||
#[NoAdminRequired] | ||
#[NoCSRFRequired] | ||
public function ExAppGet(string $appId, string $other): Response { | ||
$exApp = $this->service->getExApp($appId); | ||
if ($exApp === null) { | ||
return new NotFoundResponse(); | ||
} | ||
if (!$exApp->getEnabled()) { | ||
return new NotFoundResponse(); | ||
} | ||
|
||
$response = $this->service->requestToExApp( | ||
$exApp, '/' . $other, $this->userId, 'GET', request: $this->request | ||
); | ||
if (is_array($response)) { | ||
$error_response = new Response(); | ||
return $error_response->setStatus(500); | ||
} | ||
return $this->createProxyResponse($other, $response); | ||
} | ||
|
||
#[NoAdminRequired] | ||
#[NoCSRFRequired] | ||
public function ExAppPost(string $appId, string $other): Response { | ||
$exApp = $this->service->getExApp($appId); | ||
if ($exApp === null) { | ||
return new NotFoundResponse(); | ||
} | ||
if (!$exApp->getEnabled()) { | ||
return new NotFoundResponse(); | ||
} | ||
|
||
$response = $this->service->aeRequestToExApp( | ||
$exApp, '/' . $other, $this->userId, | ||
params: $this->request->getParams(), | ||
request: $this->request | ||
); | ||
if (is_array($response)) { | ||
$error_response = new Response(); | ||
return $error_response->setStatus(500); | ||
} | ||
return $this->createProxyResponse($other, $response); | ||
} | ||
|
||
#[NoAdminRequired] | ||
#[NoCSRFRequired] | ||
public function ExAppPut(string $appId, string $other): Response { | ||
$exApp = $this->service->getExApp($appId); | ||
if ($exApp === null) { | ||
return new NotFoundResponse(); | ||
} | ||
if (!$exApp->getEnabled()) { | ||
return new NotFoundResponse(); | ||
} | ||
|
||
$response = $this->service->aeRequestToExApp( | ||
$exApp, '/' . $other, $this->userId, 'PUT', | ||
params: $this->request->getParams(), | ||
request: $this->request | ||
); | ||
if (is_array($response)) { | ||
$error_response = new Response(); | ||
return $error_response->setStatus(500); | ||
} | ||
return $this->createProxyResponse($other, $response); | ||
} | ||
} |
Oops, something went wrong.