Skip to content

Commit

Permalink
Add well known handlers API
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
  • Loading branch information
ChristophWurst committed Dec 15, 2020
1 parent d37034f commit dd01db6
Show file tree
Hide file tree
Showing 21 changed files with 1,022 additions and 34 deletions.
2 changes: 0 additions & 2 deletions .htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L]
RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L]
RewriteRule ^\.well-known/webfinger /public.php?service=webfinger [QSA,L]
RewriteRule ^\.well-known/nodeinfo /public.php?service=nodeinfo [QSA,L]
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
Expand Down
8 changes: 4 additions & 4 deletions apps/settings/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,10 @@ window.addEventListener('DOMContentLoaded', function(){
// run setup checks then gather error messages
$.when(
OC.SetupChecks.checkWebDAV(),
OC.SetupChecks.checkWellKnownUrl('/.well-known/webfinger', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true && !!OC.appConfig.core.public_webfinger, [200, 404]),
OC.SetupChecks.checkWellKnownUrl('/.well-known/nodeinfo', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true && !!OC.appConfig.core.public_nodeinfo, [200, 404]),
OC.SetupChecks.checkWellKnownUrl('/.well-known/caldav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true),
OC.SetupChecks.checkWellKnownUrl('/.well-known/carddav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true),
OC.SetupChecks.checkWellKnownUrl('GET', '/.well-known/webfinger', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true, [200, 404], true),
OC.SetupChecks.checkWellKnownUrl('GET', '/.well-known/nodeinfo', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true, [200, 404], true),
OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true),
OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/carddav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true),
OC.SetupChecks.checkProviderUrl(OC.getRootPath() + '/ocm-provider/', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true),
OC.SetupChecks.checkProviderUrl(OC.getRootPath() + '/ocs-provider/', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true),
OC.SetupChecks.checkSetup(),
Expand Down
21 changes: 0 additions & 21 deletions apps/settings/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ public function boot(IBootContext $context): void {
$groupManager->listen('\OC\Group', 'postRemoveUser', [$this, 'removeUserFromGroup']);
$groupManager->listen('\OC\Group', 'postAddUser', [$this, 'addUserToGroup']);
});

Util::connectHook('\OCP\Config', 'js', $this, 'extendJsConfig');
}

public function addUserToGroup(IGroup $group, IUser $user): void {
Expand Down Expand Up @@ -209,23 +207,4 @@ public function onChangeInfo(array $parameters) {
$hooks = $this->getContainer()->query(Hooks::class);
$hooks->onChangeEmail($parameters['user'], $parameters['old_value']);
}

/**
* @param array $settings
*/
public function extendJsConfig(array $settings) {
$appConfig = json_decode($settings['array']['oc_appconfig'], true);

$publicWebFinger = \OC::$server->getConfig()->getAppValue('core', 'public_webfinger', '');
if (!empty($publicWebFinger)) {
$appConfig['core']['public_webfinger'] = $publicWebFinger;
}

$publicNodeInfo = \OC::$server->getConfig()->getAppValue('core', 'public_nodeinfo', '');
if (!empty($publicNodeInfo)) {
$appConfig['core']['public_nodeinfo'] = $publicNodeInfo;
}

$settings['array']['oc_appconfig'] = json_encode($appConfig);
}
}
67 changes: 67 additions & 0 deletions core/Controller/WellKnownController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

/*
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2020 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 OC\Core\Controller;

use OC\Http\WellKnown\RequestManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
use OCP\IRequest;

class WellKnownController extends Controller {

/** @var RequestManager */
private $requestManager;

public function __construct(IRequest $request,
RequestManager $wellKnownManager) {
parent::__construct('core', $request);
$this->requestManager = $wellKnownManager;
}

/**
* @PublicPage
* @NoCSRFRequired
*
* @return Response
*/
public function handle(string $service): Response {
$response = $this->requestManager->process(
$service,
$this->request
);

if ($response === null) {
$httpResponse = new JSONResponse(["message" => "$service not supported"], Http::STATUS_NOT_FOUND);
} else {
$httpResponse = $response->toHttpResponse();
}

// We add a custom header so that setup checks can detect if their requests are answered by this controller
return $httpResponse->addHeader('X-NEXTCLOUD-WELL-KNOWN', '1');
}
}
7 changes: 4 additions & 3 deletions core/js/setupchecks.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
* @param {int|int[]} expectedStatus the expected HTTP status to be returned by the URL, 207 by default
* @return $.Deferred object resolved with an array of error messages
*/
checkWellKnownUrl: function(url, placeholderUrl, runCheck, expectedStatus) {
checkWellKnownUrl: function(verb, url, placeholderUrl, runCheck, expectedStatus, checkCustomHeader) {
if (expectedStatus === undefined) {
expectedStatus = [207];
}
Expand All @@ -73,7 +73,8 @@
}
var afterCall = function(xhr) {
var messages = [];
if (expectedStatus.indexOf(xhr.status) === -1) {
var customWellKnown = xhr.getResponseHeader('X-NEXTCLOUD-WELL-KNOWN')
if (expectedStatus.indexOf(xhr.status) === -1 || (checkCustomHeader && !customWellKnown)) {
var docUrl = placeholderUrl.replace('PLACEHOLDER', 'admin-setup-well-known-URL');
messages.push({
msg: t('core', 'Your web server is not properly set up to resolve "{url}". Further information can be found in the <a target="_blank" rel="noreferrer noopener" href="{docLink}">documentation</a>.', { docLink: docUrl, url: url }),
Expand All @@ -84,7 +85,7 @@
};

$.ajax({
type: 'PROPFIND',
type: verb,
url: url,
complete: afterCall,
allowAuthErrors: true
Expand Down
8 changes: 4 additions & 4 deletions core/js/tests/specs/setupchecksSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('OC.SetupChecks tests', function() {

describe('checkWellKnownUrl', function() {
it('should fail with another response status code than the expected one', function(done) {
var async = OC.SetupChecks.checkWellKnownUrl('/.well-known/caldav', 'http://example.org/PLACEHOLDER', true, 207);
var async = OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', 'http://example.org/PLACEHOLDER', true, 207);

suite.server.requests[0].respond(200);

Expand All @@ -76,7 +76,7 @@ describe('OC.SetupChecks tests', function() {
});

it('should return no error with the expected response status code', function(done) {
var async = OC.SetupChecks.checkWellKnownUrl('/.well-known/caldav', 'http://example.org/PLACEHOLDER', true, 207);
var async = OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', 'http://example.org/PLACEHOLDER', true, 207);

suite.server.requests[0].respond(207);

Expand All @@ -87,7 +87,7 @@ describe('OC.SetupChecks tests', function() {
});

it('should return no error with the default expected response status code', function(done) {
var async = OC.SetupChecks.checkWellKnownUrl('/.well-known/caldav', 'http://example.org/PLACEHOLDER', true);
var async = OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', 'http://example.org/PLACEHOLDER', true);

suite.server.requests[0].respond(207);

Expand All @@ -98,7 +98,7 @@ describe('OC.SetupChecks tests', function() {
});

it('should return no error when no check should be run', function(done) {
var async = OC.SetupChecks.checkWellKnownUrl('/.well-known/caldav', 'http://example.org/PLACEHOLDER', false);
var async = OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', 'http://example.org/PLACEHOLDER', false);

async.done(function( data, s, x ){
expect(data).toEqual([]);
Expand Down
3 changes: 3 additions & 0 deletions core/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
// Logins for passwordless auth
['name' => 'WebAuthn#startAuthentication', 'url' => 'login/webauthn/start', 'verb' => 'POST'],
['name' => 'WebAuthn#finishAuthentication', 'url' => 'login/webauthn/finish', 'verb' => 'POST'],

// Well known requests https://tools.ietf.org/html/rfc5785
['name' => 'WellKnown#handle', 'url' => '.well-known/{service}'],
],
'ocs' => [
['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
Expand Down
7 changes: 7 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@
'OCP\\Http\\Client\\IClientService' => $baseDir . '/lib/public/Http/Client/IClientService.php',
'OCP\\Http\\Client\\IResponse' => $baseDir . '/lib/public/Http/Client/IResponse.php',
'OCP\\Http\\Client\\LocalServerException' => $baseDir . '/lib/public/Http/Client/LocalServerException.php',
'OCP\\Http\\WellKnown\\GenericResponse' => $baseDir . '/lib/public/Http/WellKnown/GenericResponse.php',
'OCP\\Http\\WellKnown\\IHandler' => $baseDir . '/lib/public/Http/WellKnown/IHandler.php',
'OCP\\Http\\WellKnown\\IRequestContext' => $baseDir . '/lib/public/Http/WellKnown/IRequestContext.php',
'OCP\\Http\\WellKnown\\IResponse' => $baseDir . '/lib/public/Http/WellKnown/IResponse.php',
'OCP\\Http\\WellKnown\\JrdResponse' => $baseDir . '/lib/public/Http/WellKnown/JrdResponse.php',
'OCP\\IAddressBook' => $baseDir . '/lib/public/IAddressBook.php',
'OCP\\IAppConfig' => $baseDir . '/lib/public/IAppConfig.php',
'OCP\\IAvatar' => $baseDir . '/lib/public/IAvatar.php',
Expand Down Expand Up @@ -892,6 +897,7 @@
'OC\\Core\\Controller\\UserController' => $baseDir . '/core/Controller/UserController.php',
'OC\\Core\\Controller\\WalledGardenController' => $baseDir . '/core/Controller/WalledGardenController.php',
'OC\\Core\\Controller\\WebAuthnController' => $baseDir . '/core/Controller/WebAuthnController.php',
'OC\\Core\\Controller\\WellKnownController' => $baseDir . '/core/Controller/WellKnownController.php',
'OC\\Core\\Controller\\WhatsNewController' => $baseDir . '/core/Controller/WhatsNewController.php',
'OC\\Core\\Controller\\WipeController' => $baseDir . '/core/Controller/WipeController.php',
'OC\\Core\\Data\\LoginFlowV2Credentials' => $baseDir . '/core/Data/LoginFlowV2Credentials.php',
Expand Down Expand Up @@ -1136,6 +1142,7 @@
'OC\\Http\\Client\\ClientService' => $baseDir . '/lib/private/Http/Client/ClientService.php',
'OC\\Http\\Client\\Response' => $baseDir . '/lib/private/Http/Client/Response.php',
'OC\\Http\\CookieHelper' => $baseDir . '/lib/private/Http/CookieHelper.php',
'OC\\Http\\WellKnown\\RequestManager' => $baseDir . '/lib/private/Http/WellKnown/RequestManager.php',
'OC\\InitialStateService' => $baseDir . '/lib/private/InitialStateService.php',
'OC\\Installer' => $baseDir . '/lib/private/Installer.php',
'OC\\IntegrityCheck\\Checker' => $baseDir . '/lib/private/IntegrityCheck/Checker.php',
Expand Down
7 changes: 7 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Http\\Client\\IClientService' => __DIR__ . '/../../..' . '/lib/public/Http/Client/IClientService.php',
'OCP\\Http\\Client\\IResponse' => __DIR__ . '/../../..' . '/lib/public/Http/Client/IResponse.php',
'OCP\\Http\\Client\\LocalServerException' => __DIR__ . '/../../..' . '/lib/public/Http/Client/LocalServerException.php',
'OCP\\Http\\WellKnown\\GenericResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/GenericResponse.php',
'OCP\\Http\\WellKnown\\IHandler' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/IHandler.php',
'OCP\\Http\\WellKnown\\IRequestContext' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/IRequestContext.php',
'OCP\\Http\\WellKnown\\IResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/IResponse.php',
'OCP\\Http\\WellKnown\\JrdResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/JrdResponse.php',
'OCP\\IAddressBook' => __DIR__ . '/../../..' . '/lib/public/IAddressBook.php',
'OCP\\IAppConfig' => __DIR__ . '/../../..' . '/lib/public/IAppConfig.php',
'OCP\\IAvatar' => __DIR__ . '/../../..' . '/lib/public/IAvatar.php',
Expand Down Expand Up @@ -921,6 +926,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Controller\\UserController' => __DIR__ . '/../../..' . '/core/Controller/UserController.php',
'OC\\Core\\Controller\\WalledGardenController' => __DIR__ . '/../../..' . '/core/Controller/WalledGardenController.php',
'OC\\Core\\Controller\\WebAuthnController' => __DIR__ . '/../../..' . '/core/Controller/WebAuthnController.php',
'OC\\Core\\Controller\\WellKnownController' => __DIR__ . '/../../..' . '/core/Controller/WellKnownController.php',
'OC\\Core\\Controller\\WhatsNewController' => __DIR__ . '/../../..' . '/core/Controller/WhatsNewController.php',
'OC\\Core\\Controller\\WipeController' => __DIR__ . '/../../..' . '/core/Controller/WipeController.php',
'OC\\Core\\Data\\LoginFlowV2Credentials' => __DIR__ . '/../../..' . '/core/Data/LoginFlowV2Credentials.php',
Expand Down Expand Up @@ -1165,6 +1171,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Http\\Client\\ClientService' => __DIR__ . '/../../..' . '/lib/private/Http/Client/ClientService.php',
'OC\\Http\\Client\\Response' => __DIR__ . '/../../..' . '/lib/private/Http/Client/Response.php',
'OC\\Http\\CookieHelper' => __DIR__ . '/../../..' . '/lib/private/Http/CookieHelper.php',
'OC\\Http\\WellKnown\\RequestManager' => __DIR__ . '/../../..' . '/lib/private/Http/WellKnown/RequestManager.php',
'OC\\InitialStateService' => __DIR__ . '/../../..' . '/lib/private/InitialStateService.php',
'OC\\Installer' => __DIR__ . '/../../..' . '/lib/private/Installer.php',
'OC\\IntegrityCheck\\Checker' => __DIR__ . '/../../..' . '/lib/private/IntegrityCheck/Checker.php',
Expand Down
24 changes: 24 additions & 0 deletions lib/private/AppFramework/Bootstrap/RegistrationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class RegistrationContext {
/** @var array[] */
private $initialStates = [];

/** @var array[] */
private $wellKnownHandlers = [];

/** @var ILogger */
private $logger;

Expand Down Expand Up @@ -174,6 +177,13 @@ public function registerInitialStateProvider(string $class): void {
$class
);
}

public function registerWellKnownHandler(string $class): void {
$this->context->registerWellKnown(
$this->appId,
$class
);
}
};
}

Expand Down Expand Up @@ -260,6 +270,13 @@ public function registerInitialState(string $appId, string $class): void {
];
}

public function registerWellKnown(string $appId, string $class): void {
$this->wellKnownHandlers[] = [
'appId' => $appId,
'class' => $class,
];
}

/**
* @param App[] $apps
*/
Expand Down Expand Up @@ -437,4 +454,11 @@ public function getAlternativeLogins(): array {
public function getInitialStates(): array {
return $this->initialStates;
}

/**
* @return array[]
*/
public function getWellKnownHandlers(): array {
return $this->wellKnownHandlers;
}
}
Loading

0 comments on commit dd01db6

Please sign in to comment.