Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: sync changes for Apps management migration to settings #417

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
1 change: 0 additions & 1 deletion appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
'requirements' => ['other' => '.+'], 'defaults' => ['other' => '']],

// ExApps actions
['name' => 'ExAppsPage#viewApps', 'url' => '/apps', 'verb' => 'GET' , 'root' => '/apps'],
['name' => 'ExAppsPage#listCategories', 'url' => '/apps/categories', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#listApps', 'url' => '/apps/list', 'verb' => 'GET' , 'root' => ''],
['name' => 'ExAppsPage#enableApp', 'url' => '/apps/enable/{appId}', 'verb' => 'GET' , 'root' => ''],
Expand Down
2 changes: 1 addition & 1 deletion js/app_api-adminSettings.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/app_api-adminSettings.js.map

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions js/app_api-main.js

This file was deleted.

55 changes: 0 additions & 55 deletions js/app_api-main.js.LICENSE.txt

This file was deleted.

1 change: 0 additions & 1 deletion js/app_api-main.js.map

This file was deleted.

2 changes: 0 additions & 2 deletions js/app_api-src_views_Apps_vue.js

This file was deleted.

1 change: 0 additions & 1 deletion js/app_api-src_views_Apps_vue.js.map

This file was deleted.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

This file was deleted.

This file was deleted.

This file was deleted.

37 changes: 0 additions & 37 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@
use OCP\Files\Events\Node\NodeTouchedEvent;
use OCP\Files\Events\Node\NodeWrittenEvent;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use OCP\SabrePluginEvent;
use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;
Expand Down Expand Up @@ -110,9 +104,7 @@ public function register(IRegistrationContext $context): void {
}

public function boot(IBootContext $context): void {
$server = $context->getServerContainer();
try {
$context->injectFn($this->registerExAppsManagementNavigation(...));
$context->injectFn($this->registerExAppsMenuEntries(...));
} catch (NotFoundExceptionInterface|ContainerExceptionInterface|Throwable) {
}
Expand All @@ -127,35 +119,6 @@ public function registerDavAuth(): void {
});
}

/**
* Register ExApps management navigation entry right after default Apps management link.
*
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function registerExAppsManagementNavigation(IUserSession $userSession): void {
$container = $this->getContainer();
/** @var IGroupManager $groupManager */
$groupManager = $container->get(IGroupManager::class);
/** @var IUser $user */
$user = $userSession->getUser();
if ($groupManager->isInGroup($user->getUID(), 'admin')) {
$container->get(INavigationManager::class)->add(function () use ($container) {
$urlGenerator = $container->get(IURLGenerator::class);
$l10n = $container->get(IL10N::class);
return [
'id' => self::APP_ID,
'type' => 'settings',
'order' => 6,
'href' => $urlGenerator->linkToRoute('app_api.ExAppsPage.viewApps'),
'icon' => $urlGenerator->imagePath('app_api', 'app-dark.svg'),
'target' => '_blank',
'name' => $l10n->t('External Apps'),
];
});
}
}

private function registerExAppsMenuEntries(): void {
$container = $this->getContainer();
$menuEntryService = $container->get(TopMenuService::class);
Expand Down
103 changes: 19 additions & 84 deletions lib/Controller/ExAppsPageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest;
Expand All @@ -37,89 +34,22 @@
* ExApps actions controller similar to default one with project-specific changes and additions
*/
class ExAppsPageController extends Controller {
private IInitialState $initialStateService;
private IConfig $config;
private AppAPIService $service;
private DaemonConfigService $daemonConfigService;
private DockerActions $dockerActions;
private CategoryFetcher $categoryFetcher;
private IFactory $l10nFactory;
private ExAppFetcher $exAppFetcher;
private IL10N $l10n;
private LoggerInterface $logger;
private IAppManager $appManager;

public function __construct(
IRequest $request,
IConfig $config,
IInitialState $initialStateService,
AppAPIService $service,
DaemonConfigService $daemonConfigService,
DockerActions $dockerActions,
CategoryFetcher $categoryFetcher,
IFactory $l10nFactory,
ExAppFetcher $exAppFetcher,
IL10N $l10n,
LoggerInterface $logger,
IAppManager $appManager,
private readonly IConfig $config,
private readonly AppAPIService $service,
private readonly DaemonConfigService $daemonConfigService,
private readonly DockerActions $dockerActions,
private readonly CategoryFetcher $categoryFetcher,
private readonly IFactory $l10nFactory,
private readonly ExAppFetcher $exAppFetcher,
private readonly IL10N $l10n,
private readonly LoggerInterface $logger,
private readonly IAppManager $appManager,
private readonly ExAppService $exAppService,
) {
parent::__construct(Application::APP_ID, $request);

$this->initialStateService = $initialStateService;
$this->config = $config;
$this->service = $service;
$this->daemonConfigService = $daemonConfigService;
$this->dockerActions = $dockerActions;
$this->categoryFetcher = $categoryFetcher;
$this->l10nFactory = $l10nFactory;
$this->l10n = $l10n;
$this->exAppFetcher = $exAppFetcher;
$this->logger = $logger;
$this->appManager = $appManager;
}

#[NoCSRFRequired]
public function viewApps(): TemplateResponse {
$defaultDaemonConfigName = $this->config->getAppValue(Application::APP_ID, 'default_daemon_config');

$appInitialData = [
'appstoreEnabled' => $this->config->getSystemValueBool('appstoreenabled', true),
'updateCount' => count($this->getExAppsWithUpdates()),
];

if ($defaultDaemonConfigName !== '') {
$daemonConfig = $this->daemonConfigService->getDaemonConfigByName($defaultDaemonConfigName);
if ($daemonConfig !== null) {
$this->dockerActions->initGuzzleClient($daemonConfig);
$daemonConfigAccessible = $this->dockerActions->ping($this->dockerActions->buildDockerUrl($daemonConfig));
$appInitialData['daemon_config_accessible'] = $daemonConfigAccessible;
$appInitialData['default_daemon_config'] = $daemonConfig->jsonSerialize();
unset($appInitialData['default_daemon_config']['deploy_config']['haproxy_password']); // do not expose password
if (!$daemonConfigAccessible) {
$this->logger->error(sprintf('Deploy daemon "%s" is not accessible by Nextcloud. Please verify its configuration', $daemonConfig->getName()));
}
}
}

$this->initialStateService->provideInitialState('apps', $appInitialData);

$templateResponse = new TemplateResponse(Application::APP_ID, 'main');
$policy = new ContentSecurityPolicy();
$policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
$templateResponse->setContentSecurityPolicy($policy);

return $templateResponse;
}

private function getExAppsWithUpdates(): array {
$apps = $this->exAppFetcher->get();
$appsWithUpdates = array_filter($apps, function (array $app) {
$exApp = $this->exAppService->getExApp($app['id']);
$newestVersion = $app['releases'][0]['version'];
return $exApp !== null && isset($app['releases'][0]['version']) && version_compare($newestVersion, $exApp->getVersion(), '>');
});
return array_values($appsWithUpdates);
}

/**
Expand Down Expand Up @@ -195,6 +125,7 @@ private function getAppsForCategory(string $requestedCategory = ''): array {

$formattedApps[] = [
'id' => $app['id'],
'app_api' => true,
'installed' => $exApp !== null, // if ExApp registered then it's assumed that it was already deployed (installed)
'appstore' => true,
'name' => $app['translations'][$currentLanguage]['name'] ?? $app['translations']['en']['name'],
Expand Down Expand Up @@ -228,6 +159,7 @@ private function getAppsForCategory(string $requestedCategory = ''): array {
'removable' => $existsLocally,
'active' => $exApp !== null && $exApp->getEnabled() === 1,
'needsDownload' => !$existsLocally,
'groups' => [],
'fromAppStore' => true,
'appstoreData' => $app,
'daemon' => $daemon,
Expand All @@ -242,7 +174,7 @@ private function getAppsForCategory(string $requestedCategory = ''): array {
#[NoCSRFRequired]
public function listApps(): JSONResponse {
$apps = $this->getAppsForCategory('');
$appsWithUpdate = $this->getExAppsWithUpdates();
$appsWithUpdate = $this->exAppFetcher->getExAppsWithUpdates();

$exApps = $this->exAppService->getExAppsList('all');
$dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
Expand Down Expand Up @@ -325,12 +257,14 @@ private function buildLocalAppsList(array $apps, array $exApps): array {

$formattedLocalApps[] = [
'id' => $app['id'],
'app_api' => true,
'appstore' => false,
'installed' => true,
'name' => $exApp->getName(),
'description' => '',
'description' => $this->l10n->t('This app is not installed from the AppStore. No extra information available. Only enable/disable and remove actions are allowed.'),
'summary' => '',
'license' => '',
'licence' => '',
'author' => '',
'shipped' => false,
'version' => $exApp->getVersion(),
Expand All @@ -357,6 +291,7 @@ private function buildLocalAppsList(array $apps, array $exApps): array {
'removable' => true, // to allow "remove" command for manual-install
'active' => $exApp->getEnabled() === 1,
'needsDownload' => false,
'groups' => [],
'fromAppStore' => false,
'appstoreData' => $app,
'daemon' => $daemon,
Expand Down Expand Up @@ -391,7 +326,7 @@ public function enableApp(string $appId): JSONResponse {
return new JSONResponse([]);
}

$appsWithUpdate = $this->getExAppsWithUpdates();
$appsWithUpdate = $this->exAppFetcher->getExAppsWithUpdates();
$appIdsWithUpdate = array_map(function (array $appWithUpdate) {
return $appWithUpdate['id'];
}, $appsWithUpdate);
Expand Down Expand Up @@ -426,7 +361,7 @@ public function disableApp(string $appId): JSONResponse {
#[PasswordConfirmationRequired]
#[NoCSRFRequired]
public function updateApp(string $appId): JSONResponse {
$appsWithUpdate = $this->getExAppsWithUpdates();
$appsWithUpdate = $this->exAppFetcher->getExAppsWithUpdates();
$appIdsWithUpdate = array_map(function (array $appWithUpdate) {
return $appWithUpdate['id'];
}, $appsWithUpdate);
Expand Down
Loading
Loading