mirror of
https://github.com/nextcloud/server.git
synced 2026-04-24 23:59:27 -04:00
Merge pull request #57526 from nextcloud/refactor/loginflow-to-vue
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run
refactor(core): migrate login flow ui from jQuery to Vue
This commit is contained in:
commit
891d0fc481
43 changed files with 813 additions and 395 deletions
|
|
@ -16,6 +16,7 @@ module.exports = {
|
|||
files_fileinfo: path.join(__dirname, 'core/src', 'files/fileinfo.js'),
|
||||
install: path.join(__dirname, 'core/src', 'install.ts'),
|
||||
login: path.join(__dirname, 'core/src', 'login.js'),
|
||||
login_flow: path.join(__dirname, 'core/src', 'login-flow.ts'),
|
||||
main: path.join(__dirname, 'core/src', 'main.js'),
|
||||
maintenance: path.join(__dirname, 'core/src', 'maintenance.js'),
|
||||
'public-page-menu': path.resolve(__dirname, 'core/src', 'public-page-menu.ts'),
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use OCP\AppFramework\Http\ContentSecurityPolicy;
|
|||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Authentication\Exceptions\InvalidTokenException;
|
||||
use OCP\Authentication\Token\IToken;
|
||||
|
|
@ -35,11 +36,11 @@ use OCP\IL10N;
|
|||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Security\ICrypto;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OCP\Session\Exceptions\SessionNotAvailableException;
|
||||
use OCP\Util;
|
||||
|
||||
#[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
|
||||
class ClientFlowLoginController extends Controller {
|
||||
|
|
@ -61,6 +62,7 @@ class ClientFlowLoginController extends Controller {
|
|||
private IEventDispatcher $eventDispatcher,
|
||||
private ITimeFactory $timeFactory,
|
||||
private IConfig $config,
|
||||
private IInitialState $initialState,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
|
@ -135,24 +137,36 @@ class ClientFlowLoginController extends Controller {
|
|||
$csp->addAllowedFormActionDomain('nc://*');
|
||||
}
|
||||
|
||||
$this->initialState->provideInitialState('loginFlowState', 'auth');
|
||||
$this->initialState->provideInitialState('loginFlowAuth', [
|
||||
'client' => $clientName,
|
||||
'clientIdentifier' => $clientIdentifier,
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'stateToken' => $stateToken,
|
||||
'serverHost' => $this->getServerPath(),
|
||||
'oauthState' => $this->session->get('oauth.state'),
|
||||
'direct' => (bool)$direct,
|
||||
'providedRedirectUri' => $providedRedirectUri,
|
||||
'loginRedirectUrl' => $this->urlGenerator->linkToRoute(
|
||||
'core.ClientFlowLogin.grantPage',
|
||||
[
|
||||
'stateToken' => $stateToken,
|
||||
'clientIdentifier' => $clientIdentifier,
|
||||
'oauthState' => $this->session->get('oauth.state'),
|
||||
'user' => $user,
|
||||
'direct' => $direct,
|
||||
'providedRedirectUri' => $providedRedirectUri,
|
||||
]),
|
||||
'appTokenUrl' => $this->urlGenerator->linkToRouteAbsolute('core.ClientFlowLogin.apptokenRedirect'),
|
||||
]);
|
||||
|
||||
|
||||
Util::addScript('core', 'login_flow');
|
||||
$response = new StandaloneTemplateResponse(
|
||||
$this->appName,
|
||||
'loginflow/authpicker',
|
||||
[
|
||||
'client' => $clientName,
|
||||
'clientIdentifier' => $clientIdentifier,
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'stateToken' => $stateToken,
|
||||
'serverHost' => $this->getServerPath(),
|
||||
'oauthState' => $this->session->get('oauth.state'),
|
||||
'user' => $user,
|
||||
'direct' => $direct,
|
||||
'providedRedirectUri' => $providedRedirectUri,
|
||||
],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
|
||||
$response->setContentSecurityPolicy($csp);
|
||||
return $response;
|
||||
}
|
||||
|
|
@ -188,26 +202,31 @@ class ClientFlowLoginController extends Controller {
|
|||
$csp->addAllowedFormActionDomain('nc://*');
|
||||
}
|
||||
|
||||
/** @var IUser $user */
|
||||
$user = $this->userSession->getUser();
|
||||
\assert($user !== null);
|
||||
|
||||
$this->initialState->provideInitialState('loginFlowState', 'grant');
|
||||
$this->initialState->provideInitialState('loginFlowGrant', [
|
||||
'actionUrl' => $this->urlGenerator->linkToRouteAbsolute(
|
||||
'core.ClientFlowLogin.generateAppPassword',
|
||||
),
|
||||
'client' => $clientName,
|
||||
'clientIdentifier' => $clientIdentifier,
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'stateToken' => $stateToken,
|
||||
'serverHost' => $this->getServerPath(),
|
||||
'oauthState' => $this->session->get('oauth.state'),
|
||||
'direct' => $direct,
|
||||
'providedRedirectUri' => $providedRedirectUri,
|
||||
'userDisplayName' => $user->getDisplayName(),
|
||||
'userId' => $user->getUID(),
|
||||
]);
|
||||
|
||||
Util::addScript('core', 'login_flow');
|
||||
$response = new StandaloneTemplateResponse(
|
||||
$this->appName,
|
||||
'loginflow/grant',
|
||||
[
|
||||
'userId' => $user->getUID(),
|
||||
'userDisplayName' => $user->getDisplayName(),
|
||||
'client' => $clientName,
|
||||
'clientIdentifier' => $clientIdentifier,
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'stateToken' => $stateToken,
|
||||
'serverHost' => $this->getServerPath(),
|
||||
'oauthState' => $this->session->get('oauth.state'),
|
||||
'direct' => $direct,
|
||||
'providedRedirectUri' => $providedRedirectUri,
|
||||
],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
|
||||
$response->setContentSecurityPolicy($csp);
|
||||
|
|
|
|||
|
|
@ -26,16 +26,17 @@ use OCP\AppFramework\Http\JSONResponse;
|
|||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\Authentication\Exceptions\InvalidTokenException;
|
||||
use OCP\Defaults;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OCP\Server;
|
||||
use OCP\Util;
|
||||
|
||||
/**
|
||||
* @psalm-import-type CoreLoginFlowV2Credentials from ResponseDefinitions
|
||||
|
|
@ -58,6 +59,7 @@ class ClientFlowLoginV2Controller extends Controller {
|
|||
private Defaults $defaults,
|
||||
private ?string $userId,
|
||||
private IL10N $l10n,
|
||||
private IInitialState $initialState,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
|
@ -122,18 +124,21 @@ class ClientFlowLoginV2Controller extends Controller {
|
|||
);
|
||||
$this->session->set(self::STATE_NAME, $stateToken);
|
||||
|
||||
$this->initialState->provideInitialState('loginFlowState', 'auth');
|
||||
$this->initialState->provideInitialState('loginFlowAuth', [
|
||||
'client' => $flow->getClientName(),
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'stateToken' => $stateToken,
|
||||
'loginRedirectUrl' => $this->urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.grantPage', ['stateToken' => $stateToken, 'user' => $user, 'direct' => $direct]),
|
||||
'appTokenUrl' => $this->urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.apptokenRedirect'),
|
||||
]);
|
||||
|
||||
|
||||
Util::addScript('core', 'login_flow');
|
||||
return new StandaloneTemplateResponse(
|
||||
$this->appName,
|
||||
'loginflowv2/authpicker',
|
||||
[
|
||||
'client' => $flow->getClientName(),
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'stateToken' => $stateToken,
|
||||
'user' => $user,
|
||||
'direct' => $direct,
|
||||
],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -161,22 +166,26 @@ class ClientFlowLoginV2Controller extends Controller {
|
|||
return $this->loginTokenForbiddenClientResponse();
|
||||
}
|
||||
|
||||
/** @var IUser $user */
|
||||
$user = $this->userSession->getUser();
|
||||
\assert($user !== null);
|
||||
|
||||
$this->initialState->provideInitialState('loginFlowState', 'grant');
|
||||
$this->initialState->provideInitialState('loginFlowGrant', [
|
||||
'actionUrl' => $this->urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.generateAppPassword'),
|
||||
'userId' => $user->getUID(),
|
||||
'userDisplayName' => $user->getDisplayName(),
|
||||
'client' => $flow->getClientName(),
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'stateToken' => $stateToken,
|
||||
'direct' => $direct === 1,
|
||||
]);
|
||||
|
||||
|
||||
Util::addScript('core', 'login_flow');
|
||||
return new StandaloneTemplateResponse(
|
||||
$this->appName,
|
||||
'loginflowv2/grant',
|
||||
[
|
||||
'userId' => $user->getUID(),
|
||||
'userDisplayName' => $user->getDisplayName(),
|
||||
'client' => $flow->getClientName(),
|
||||
'instanceName' => $this->defaults->getName(),
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'stateToken' => $stateToken,
|
||||
'direct' => $direct,
|
||||
],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -260,11 +269,12 @@ class ClientFlowLoginV2Controller extends Controller {
|
|||
|
||||
private function handleFlowDone(bool $result): StandaloneTemplateResponse {
|
||||
if ($result) {
|
||||
Util::addScript('core', 'login_flow');
|
||||
$this->initialState->provideInitialState('loginFlowState', 'done');
|
||||
return new StandaloneTemplateResponse(
|
||||
$this->appName,
|
||||
'loginflowv2/done',
|
||||
[],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
jQuery(document).ready(function() {
|
||||
$('#app-token-login').click(function(e) {
|
||||
e.preventDefault()
|
||||
$(this).addClass('hidden')
|
||||
$('#redirect-link').addClass('hidden')
|
||||
$('#app-token-login-field').removeClass('hidden')
|
||||
})
|
||||
|
||||
document.getElementById('login-form').addEventListener('submit', function(e) {
|
||||
e.preventDefault()
|
||||
document.location.href = e.target.attributes.action.value
|
||||
})
|
||||
|
||||
$('#login-form input').removeAttr('disabled')
|
||||
})
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
const form = document.querySelector('form')
|
||||
form.addEventListener('submit', function(event) {
|
||||
const wrapper = document.getElementById('submit-wrapper')
|
||||
if (wrapper === null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
|
||||
// stop the event
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
// handle password confirmation
|
||||
OC.PasswordConfirmation.requirePasswordConfirmation(function() {
|
||||
// when password is confirmed we submit the form
|
||||
form.submit()
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Array.from(wrapper.getElementsByClassName('icon-confirm-white')).forEach(function(el) {
|
||||
el.classList.remove('icon-confirm-white')
|
||||
el.classList.add(OCA.Theming && OCA.Theming.inverted ? 'icon-loading-small' : 'icon-loading-small-dark')
|
||||
el.disabled = true
|
||||
})
|
||||
})
|
||||
49
core/src/components/LoginFlow/LoginFlowAuthAppToken.vue
Normal file
49
core/src/components/LoginFlow/LoginFlowAuthAppToken.vue
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getRequestToken } from '@nextcloud/auth'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import NcButton from '@nextcloud/vue/components/NcButton'
|
||||
import NcFormBox from '@nextcloud/vue/components/NcFormBox'
|
||||
import NcPasswordField from '@nextcloud/vue/components/NcPasswordField'
|
||||
import NcTextField from '@nextcloud/vue/components/NcTextField'
|
||||
|
||||
defineProps<{
|
||||
appTokenUrl: string
|
||||
direct: boolean
|
||||
stateToken: string
|
||||
}>()
|
||||
|
||||
const requestToken = getRequestToken()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form :action="appTokenUrl" :class="$style.loginFlowAuthAppToken" method="post">
|
||||
<NcFormBox>
|
||||
<NcTextField name="user" :label="t('core', 'Login')" />
|
||||
<NcPasswordField name="password" :label="t('core', 'App password')" />
|
||||
</NcFormBox>
|
||||
<input type="hidden" name="stateToken" :value="stateToken">
|
||||
<input type="hidden" name="requesttoken" :value="requestToken">
|
||||
<input
|
||||
v-if="direct"
|
||||
type="hidden"
|
||||
name="direct"
|
||||
value="1">
|
||||
|
||||
<NcButton type="submit" variant="primary" wide>
|
||||
{{ t('core', 'Grant access') }}
|
||||
</NcButton>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
.loginFlowAuthAppToken {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--default-grid-baseline);
|
||||
}
|
||||
</style>
|
||||
26
core/src/components/LoginFlow/LoginFlowContainer.vue
Normal file
26
core/src/components/LoginFlow/LoginFlowContainer.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import NcGuestContent from '@nextcloud/vue/components/NcGuestContent'
|
||||
|
||||
defineProps<{
|
||||
heading: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NcGuestContent class="picker-window" :class="$style.loginFlowContainer">
|
||||
<h2>{{ heading }}</h2>
|
||||
<slot />
|
||||
</NcGuestContent>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
.loginFlowContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
22
core/src/login-flow.ts
Normal file
22
core/src/login-flow.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import Vue, { defineAsyncComponent } from 'vue'
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
const LoginFlowAuth = defineAsyncComponent(() => import('./views/LoginFlowAuth.vue'))
|
||||
const LoginFlowGrant = defineAsyncComponent(() => import('./views/LoginFlowGrant.vue'))
|
||||
const LoginFlowDone = defineAsyncComponent(() => import('./views/LoginFlowDone.vue'))
|
||||
|
||||
const state = loadState<'auth' | 'grant' | 'done'>('core', 'loginFlowState')
|
||||
const app = new Vue({
|
||||
render: (h) => h(state === 'auth'
|
||||
? LoginFlowAuth
|
||||
: (state === 'grant' ? LoginFlowGrant : LoginFlowDone)),
|
||||
})
|
||||
app.$mount('#core-loginflow')
|
||||
73
core/src/views/LoginFlowAuth.vue
Normal file
73
core/src/views/LoginFlowAuth.vue
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { ref } from 'vue'
|
||||
import NcButton from '@nextcloud/vue/components/NcButton'
|
||||
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
|
||||
import LoginFlowAuthAppToken from '../components/LoginFlow/LoginFlowAuthAppToken.vue'
|
||||
import LoginFlowContainer from '../components/LoginFlow/LoginFlowContainer.vue'
|
||||
|
||||
const {
|
||||
client,
|
||||
direct,
|
||||
instanceName,
|
||||
loginRedirectUrl,
|
||||
appTokenUrl,
|
||||
stateToken,
|
||||
} = loadState<{
|
||||
client: string
|
||||
direct?: boolean
|
||||
instanceName: string
|
||||
loginRedirectUrl: string
|
||||
appTokenUrl: string
|
||||
stateToken: string
|
||||
}>('core', 'loginFlowAuth')
|
||||
|
||||
const useAppTokenLogin = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoginFlowContainer :heading="t('core', 'Connect to your account')">
|
||||
<NcNoteCard type="info">
|
||||
{{ t('core', 'Please log in before granting "{client}" access to your {instanceName} account.', { client, instanceName }) }}
|
||||
</NcNoteCard>
|
||||
|
||||
<NcNoteCard type="warning" :heading="t('core', 'Security warning')">
|
||||
{{ t('core', 'If you are not trying to set up a new device or app, someone is trying to trick you into granting them access to your data. In this case do not proceed and instead contact your system administrator.') }}
|
||||
</NcNoteCard>
|
||||
|
||||
<NcButton
|
||||
v-if="!useAppTokenLogin"
|
||||
:class="$style.loginFlowAuth__button"
|
||||
:href="loginRedirectUrl"
|
||||
variant="primary">
|
||||
{{ t('core', 'Log in') }}
|
||||
</NcButton>
|
||||
|
||||
<LoginFlowAuthAppToken
|
||||
v-else
|
||||
:app-token-url="appTokenUrl"
|
||||
:direct="direct ?? false"
|
||||
:state-token="stateToken" />
|
||||
|
||||
<NcButton
|
||||
:class="$style.loginFlowAuth__button"
|
||||
variant="tertiary"
|
||||
@click="useAppTokenLogin = !useAppTokenLogin">
|
||||
{{ useAppTokenLogin ? t('core', 'Log in using password') : t('core', 'Alternative log in using app password') }}
|
||||
</NcButton>
|
||||
</LoginFlowContainer>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
.loginFlowAuth__button {
|
||||
margin-top: 0.5rem;
|
||||
margin-inline: auto;
|
||||
min-width: 50% !important;
|
||||
}
|
||||
</style>
|
||||
20
core/src/views/LoginFlowDone.vue
Normal file
20
core/src/views/LoginFlowDone.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
|
||||
import LoginFlowContainer from '../components/LoginFlow/LoginFlowContainer.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoginFlowContainer :heading="t('core', 'Account connected')">
|
||||
<NcNoteCard type="info">
|
||||
{{ t('core', 'Your client should now be connected!') }}
|
||||
<br>
|
||||
{{ t('core', 'You can close this window.') }}
|
||||
</NcNoteCard>
|
||||
</LoginFlowContainer>
|
||||
</template>
|
||||
106
core/src/views/LoginFlowGrant.vue
Normal file
106
core/src/views/LoginFlowGrant.vue
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getRequestToken } from '@nextcloud/auth'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { confirmPassword, isPasswordConfirmationRequired, PwdConfirmationMode } from '@nextcloud/password-confirmation'
|
||||
import NcButton from '@nextcloud/vue/components/NcButton'
|
||||
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
|
||||
import LoginFlowContainer from '../components/LoginFlow/LoginFlowContainer.vue'
|
||||
|
||||
const {
|
||||
clientIdentifier,
|
||||
oauthState,
|
||||
providedRedirectUri,
|
||||
|
||||
actionUrl,
|
||||
client,
|
||||
direct,
|
||||
instanceName,
|
||||
stateToken,
|
||||
userDisplayName,
|
||||
userId,
|
||||
} = loadState<{
|
||||
clientIdentifier?: string
|
||||
oauthState?: string
|
||||
providedRedirectUri?: string
|
||||
|
||||
actionUrl: string
|
||||
client: string
|
||||
direct: boolean
|
||||
instanceName: string
|
||||
stateToken: string
|
||||
userId: string
|
||||
userDisplayName: string
|
||||
}>('core', 'loginFlowGrant')
|
||||
|
||||
const requestToken = getRequestToken()
|
||||
|
||||
/**
|
||||
* Handle submit event to confirm password if required
|
||||
*
|
||||
* @param event - The submit event
|
||||
*/
|
||||
async function onSubmit(event: SubmitEvent) {
|
||||
if (isPasswordConfirmationRequired(PwdConfirmationMode.Lax)) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
await confirmPassword()
|
||||
;(event.target as HTMLFormElement).submit()
|
||||
return false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoginFlowContainer :heading="t('core', 'Account access')">
|
||||
<NcNoteCard type="info">
|
||||
{{ t('core', 'Currently logged in as {userDisplayName} ({userId}).', { userDisplayName, userId }) }}
|
||||
<br>
|
||||
{{ t('core', 'You are about to grant "{client}" access to your {instanceName} account.', { client, instanceName }) }}
|
||||
</NcNoteCard>
|
||||
|
||||
<form method="POST" :action="actionUrl" @submit="onSubmit">
|
||||
<input type="hidden" name="requesttoken" :value="requestToken">
|
||||
<input type="hidden" name="stateToken" :value="stateToken">
|
||||
|
||||
<input
|
||||
v-if="direct"
|
||||
type="hidden"
|
||||
name="direct"
|
||||
value="1">
|
||||
<input
|
||||
v-if="clientIdentifier !== undefined"
|
||||
type="hidden"
|
||||
name="clientIdentifier"
|
||||
:value="clientIdentifier">
|
||||
<input
|
||||
v-if="oauthState !== undefined"
|
||||
type="hidden"
|
||||
name="oauthState"
|
||||
:value="oauthState">
|
||||
<input
|
||||
v-if="providedRedirectUri !== undefined"
|
||||
type="hidden"
|
||||
name="providedRedirectUri"
|
||||
:value="providedRedirectUri">
|
||||
|
||||
<NcButton :class="$style.loginFlowGrant__button" type="submit" variant="primary">
|
||||
{{ t('core', 'Grant access') }}
|
||||
</NcButton>
|
||||
</form>
|
||||
</LoginFlowContainer>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
.loginFlowGrant__button {
|
||||
margin-top: 0.5rem;
|
||||
margin-inline: auto;
|
||||
min-width: 50% !important;
|
||||
}
|
||||
</style>
|
||||
8
core/templates/loginflow.php
Normal file
8
core/templates/loginflow.php
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
?>
|
||||
|
||||
<div id="core-loginflow"></div>
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
\OCP\Util::addScript('core', 'login/authpicker', 'core');
|
||||
style('core', 'login/authpicker');
|
||||
|
||||
/** @var array $_ */
|
||||
/** @var \OCP\IURLGenerator $urlGenerator */
|
||||
$urlGenerator = $_['urlGenerator'];
|
||||
?>
|
||||
|
||||
<div class="picker-window">
|
||||
<h2><?php p($l->t('Connect to your account')) ?></h2>
|
||||
<p class="info">
|
||||
<?php print_unescaped($l->t('Please log in before granting %1$s access to your %2$s account.', [
|
||||
'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
|
||||
\OCP\Util::sanitizeHTML($_['instanceName'])
|
||||
])) ?>
|
||||
</p>
|
||||
|
||||
<div class="notecard warning">
|
||||
<h3><?php p($l->t('Security warning')) ?></h3>
|
||||
<p>
|
||||
<?php p($l->t('If you are not trying to set up a new device or app, someone is trying to trick you into granting them access to your data. In this case do not proceed and instead contact your system administrator.')) ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<p id="redirect-link">
|
||||
<form id="login-form" action="<?php p($urlGenerator->linkToRoute('core.ClientFlowLogin.grantPage', ['stateToken' => $_['stateToken'], 'clientIdentifier' => $_['clientIdentifier'], 'oauthState' => $_['oauthState'], 'user' => $_['user'], 'direct' => $_['direct'], 'providedRedirectUri' => $_['providedRedirectUri']])) ?>" method="get">
|
||||
<input type="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Log in')) ?>" disabled>
|
||||
</form>
|
||||
</p>
|
||||
|
||||
<form action="<?php p($urlGenerator->linkToRouteAbsolute('core.ClientFlowLogin.apptokenRedirect')); ?>" method="post" id="app-token-login-field" class="hidden">
|
||||
<p class="grouptop">
|
||||
<input type="text" name="user" id="user" placeholder="<?php p($l->t('Login')) ?>">
|
||||
<label for="user" class="infield"><?php p($l->t('Login')) ?></label>
|
||||
</p>
|
||||
<p class="groupbottom">
|
||||
<input type="password" name="password" id="password" placeholder="<?php p($l->t('App password')) ?>">
|
||||
<label for="password" class="infield"><?php p($l->t('Password')) ?></label>
|
||||
</p>
|
||||
<input type="hidden" name="stateToken" value="<?php p($_['stateToken']) ?>" />
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>">
|
||||
<?php if ($_['direct'] !== 0) { ?>
|
||||
<input type="hidden" name="direct" value="<?php p($_['direct']) ?>">
|
||||
<?php } ?>
|
||||
<input id="submit-app-token-login" type="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Grant access')) ?>">
|
||||
</form>
|
||||
|
||||
<?php if (empty($_['oauthState'])): ?>
|
||||
<a id="app-token-login" class="apptoken-link" href="#"><?php p($l->t('Alternative log in using app password')) ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
\OCP\Util::addScript('core', 'login/grant', 'core');
|
||||
style('core', 'login/authpicker');
|
||||
|
||||
/** @var array $_ */
|
||||
/** @var \OCP\IURLGenerator $urlGenerator */
|
||||
$urlGenerator = $_['urlGenerator'];
|
||||
?>
|
||||
|
||||
<div class="picker-window small">
|
||||
<h2><?php p($l->t('Account access')) ?></h2>
|
||||
<p class="info">
|
||||
<?php p($l->t('Currently logged in as %1$s (%2$s).', [
|
||||
$_['userDisplayName'],
|
||||
$_['userId'],
|
||||
])) ?>
|
||||
</p>
|
||||
<p class="info">
|
||||
<?php print_unescaped($l->t('You are about to grant %1$s access to your %2$s account.', [
|
||||
'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
|
||||
\OCP\Util::sanitizeHTML($_['instanceName'])
|
||||
])) ?>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
|
||||
<p id="redirect-link">
|
||||
<form method="POST" action="<?php p($urlGenerator->linkToRouteAbsolute('core.ClientFlowLogin.generateAppPassword')) ?>">
|
||||
<input type="hidden" name="clientIdentifier" value="<?php p($_['clientIdentifier']) ?>" />
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" />
|
||||
<input type="hidden" name="stateToken" value="<?php p($_['stateToken']) ?>" />
|
||||
<input type="hidden" name="oauthState" value="<?php p($_['oauthState']) ?>" />
|
||||
<input type="hidden" name="providedRedirectUri" value="<?php p($_['providedRedirectUri']) ?>">
|
||||
<?php if ($_['direct']) { ?>
|
||||
<input type="hidden" name="direct" value="1" />
|
||||
<?php } ?>
|
||||
<div id="submit-wrapper">
|
||||
<input type="submit" class="login primary icon-confirm-white" title="" value="<?php p($l->t('Grant access')); ?>" />
|
||||
</div>
|
||||
</form>
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
style('core', 'login/authpicker');
|
||||
\OCP\Util::addScript('core', 'login/authpicker', 'core');
|
||||
|
||||
/** @var array $_ */
|
||||
/** @var \OCP\IURLGenerator $urlGenerator */
|
||||
$urlGenerator = $_['urlGenerator'];
|
||||
?>
|
||||
|
||||
<div class="picker-window">
|
||||
<h2><?php p($l->t('Connect to your account')) ?></h2>
|
||||
<p class="info">
|
||||
<?php print_unescaped($l->t('Please log in before granting %1$s access to your %2$s account.', [
|
||||
'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
|
||||
\OCP\Util::sanitizeHTML($_['instanceName'])
|
||||
])) ?>
|
||||
</p>
|
||||
|
||||
<div class="notecard warning">
|
||||
<h3><?php p($l->t('Security warning')) ?></h3>
|
||||
<p>
|
||||
<?php p($l->t('If you are not trying to set up a new device or app, someone is trying to trick you into granting them access to your data. In this case do not proceed and instead contact your system administrator.')) ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<p id="redirect-link">
|
||||
<form id="login-form" action="<?php p($urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.grantPage', ['stateToken' => $_['stateToken'], 'user' => $_['user'], 'direct' => $_['direct'] ?? 0])) ?>" method="get">
|
||||
<input type="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Log in')) ?>" disabled>
|
||||
</form>
|
||||
</p>
|
||||
|
||||
<form action="<?php p($urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.apptokenRedirect')); ?>" method="post" id="app-token-login-field" class="hidden">
|
||||
<p class="grouptop">
|
||||
<input type="text" name="user" id="user" placeholder="<?php p($l->t('Login')) ?>">
|
||||
<label for="user" class="infield"><?php p($l->t('Login')) ?></label>
|
||||
</p>
|
||||
<p class="groupbottom">
|
||||
<input type="password" name="password" id="password" placeholder="<?php p($l->t('App password')) ?>">
|
||||
<label for="password" class="infield"><?php p($l->t('Password')) ?></label>
|
||||
</p>
|
||||
<input type="hidden" name="stateToken" value="<?php p($_['stateToken']) ?>" />
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>">
|
||||
<input id="submit-app-token-login" type="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Grant access')) ?>">
|
||||
</form>
|
||||
|
||||
<?php if (empty($_['oauthState'])): ?>
|
||||
<a id="app-token-login" class="apptoken-link" href="#"><?php p($l->t('Alternative log in using app password')) ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
style('core', 'login/authpicker');
|
||||
|
||||
/** @var array $_ */
|
||||
?>
|
||||
|
||||
<div class="picker-window">
|
||||
<h2><?php p($l->t('Account connected')) ?></h2>
|
||||
<p class="info">
|
||||
<?php p($l->t('Your client should now be connected!')) ?><br/>
|
||||
<?php p($l->t('You can close this window.')) ?>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
\OCP\Util::addScript('core', 'login/grant', 'core');
|
||||
style('core', 'login/authpicker');
|
||||
|
||||
/** @var array $_ */
|
||||
/** @var \OCP\IURLGenerator $urlGenerator */
|
||||
$urlGenerator = $_['urlGenerator'];
|
||||
?>
|
||||
|
||||
<div class="picker-window small">
|
||||
<h2><?php p($l->t('Account access')) ?></h2>
|
||||
<p class="info">
|
||||
<?php p($l->t('Currently logged in as %1$s (%2$s).', [
|
||||
$_['userDisplayName'],
|
||||
$_['userId'],
|
||||
])) ?>
|
||||
</p>
|
||||
<p class="info">
|
||||
<?php print_unescaped($l->t('You are about to grant %1$s access to your %2$s account.', [
|
||||
'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
|
||||
\OCP\Util::sanitizeHTML($_['instanceName'])
|
||||
])) ?>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
|
||||
<p id="redirect-link">
|
||||
<form method="POST" action="<?php p($urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.generateAppPassword')) ?>">
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" />
|
||||
<input type="hidden" name="stateToken" value="<?php p($_['stateToken']) ?>" />
|
||||
<?php if ($_['direct']) { ?>
|
||||
<input type="hidden" name="direct" value="1" />
|
||||
<?php } ?>
|
||||
<div id="submit-wrapper">
|
||||
<input type="submit" class="login primary icon-confirm-white" title="" value="<?php p($l->t('Grant access')); ?>" />
|
||||
</div>
|
||||
</form>
|
||||
</p>
|
||||
</div>
|
||||
2
dist/2426-2426.js
vendored
Normal file
2
dist/2426-2426.js
vendored
Normal file
File diff suppressed because one or more lines are too long
136
dist/2426-2426.js.license
vendored
Normal file
136
dist/2426-2426.js.license
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: ISC
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: debounce developers
|
||||
SPDX-FileCopyrightText: atomiks
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
SPDX-FileCopyrightText: Guillaume Chau
|
||||
SPDX-FileCopyrightText: GitHub Inc.
|
||||
SPDX-FileCopyrightText: Feross Aboukhadijeh
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Eduardo San Martin Morote
|
||||
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
|
||||
SPDX-FileCopyrightText: David Clark
|
||||
SPDX-FileCopyrightText: Christoph Wurst
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @floating-ui/core
|
||||
- version: 1.7.3
|
||||
- license: MIT
|
||||
- @floating-ui/utils
|
||||
- version: 0.2.10
|
||||
- license: MIT
|
||||
- @nextcloud/auth
|
||||
- version: 2.5.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/axios
|
||||
- version: 2.5.2
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/browser-storage
|
||||
- version: 0.5.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/capabilities
|
||||
- version: 1.2.1
|
||||
- license: GPL-3.0-or-later
|
||||
- semver
|
||||
- version: 7.7.2
|
||||
- license: ISC
|
||||
- @nextcloud/event-bus
|
||||
- version: 3.3.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/initial-state
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/l10n
|
||||
- version: 3.4.1
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/logger
|
||||
- version: 3.0.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/vue
|
||||
- version: 9.2.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- @vue/reactivity
|
||||
- version: 3.5.24
|
||||
- license: MIT
|
||||
- @vue/runtime-core
|
||||
- version: 3.5.24
|
||||
- license: MIT
|
||||
- @vue/runtime-dom
|
||||
- version: 3.5.24
|
||||
- license: MIT
|
||||
- @vue/shared
|
||||
- version: 3.5.24
|
||||
- license: MIT
|
||||
- vue-router
|
||||
- version: 4.6.3
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 3.5.24
|
||||
- license: MIT
|
||||
- @nextcloud/password-confirmation
|
||||
- version: 6.0.2
|
||||
- license: MIT
|
||||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/vue
|
||||
- version: 8.35.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- @vue/devtools-api
|
||||
- version: 6.6.4
|
||||
- license: MIT
|
||||
- axios
|
||||
- version: 1.12.2
|
||||
- license: MIT
|
||||
- base64-js
|
||||
- version: 1.5.1
|
||||
- license: MIT
|
||||
- css-loader
|
||||
- version: 7.1.2
|
||||
- license: MIT
|
||||
- debounce
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- dompurify
|
||||
- version: 3.3.1
|
||||
- license: (MPL-2.0 OR Apache-2.0)
|
||||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- focus-trap
|
||||
- version: 7.6.6
|
||||
- license: MIT
|
||||
- ieee754
|
||||
- version: 1.2.1
|
||||
- license: BSD-3-Clause
|
||||
- buffer
|
||||
- version: 6.0.3
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
- style-loader
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- tabbable
|
||||
- version: 6.3.0
|
||||
- license: MIT
|
||||
- vue-loader
|
||||
- version: 15.11.1
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
- nextcloud
|
||||
- version: 1.0.0
|
||||
- license: AGPL-3.0-or-later
|
||||
1
dist/2426-2426.js.map
vendored
Normal file
1
dist/2426-2426.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/2426-2426.js.map.license
vendored
Symbolic link
1
dist/2426-2426.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
2426-2426.js.license
|
||||
2
dist/7867-7867.js
vendored
Normal file
2
dist/7867-7867.js
vendored
Normal file
File diff suppressed because one or more lines are too long
104
dist/7867-7867.js.license
vendored
Normal file
104
dist/7867-7867.js.license
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: ISC
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: debounce developers
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
SPDX-FileCopyrightText: GitHub Inc.
|
||||
SPDX-FileCopyrightText: Feross Aboukhadijeh
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
|
||||
SPDX-FileCopyrightText: Christoph Wurst
|
||||
SPDX-FileCopyrightText: Anthony Fu <https://github.com/antfu>
|
||||
SPDX-FileCopyrightText: Anthony Fu <anthonyfu117@hotmail.com>
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @nextcloud/auth
|
||||
- version: 2.5.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/axios
|
||||
- version: 2.5.2
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/browser-storage
|
||||
- version: 0.5.0
|
||||
- license: GPL-3.0-or-later
|
||||
- semver
|
||||
- version: 7.7.2
|
||||
- license: ISC
|
||||
- @nextcloud/event-bus
|
||||
- version: 3.3.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/initial-state
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/l10n
|
||||
- version: 3.4.1
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/logger
|
||||
- version: 3.0.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/initial-state
|
||||
- version: 2.2.0
|
||||
- license: GPL-3.0-or-later
|
||||
- debounce
|
||||
- version: 2.2.0
|
||||
- license: MIT
|
||||
- @nextcloud/vue
|
||||
- version: 8.35.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- @vueuse/core
|
||||
- version: 11.3.0
|
||||
- license: MIT
|
||||
- @vueuse/shared
|
||||
- version: 11.3.0
|
||||
- license: MIT
|
||||
- axios
|
||||
- version: 1.12.2
|
||||
- license: MIT
|
||||
- base64-js
|
||||
- version: 1.5.1
|
||||
- license: MIT
|
||||
- css-loader
|
||||
- version: 7.1.2
|
||||
- license: MIT
|
||||
- dompurify
|
||||
- version: 3.3.1
|
||||
- license: (MPL-2.0 OR Apache-2.0)
|
||||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- ieee754
|
||||
- version: 1.2.1
|
||||
- license: BSD-3-Clause
|
||||
- buffer
|
||||
- version: 6.0.3
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
- style-loader
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- vue-demi
|
||||
- version: 0.14.10
|
||||
- license: MIT
|
||||
- vue-loader
|
||||
- version: 15.11.1
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
- nextcloud
|
||||
- version: 1.0.0
|
||||
- license: AGPL-3.0-or-later
|
||||
1
dist/7867-7867.js.map
vendored
Normal file
1
dist/7867-7867.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/7867-7867.js.map.license
vendored
Symbolic link
1
dist/7867-7867.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
7867-7867.js.license
|
||||
2
dist/9811-9811.js
vendored
Normal file
2
dist/9811-9811.js
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
"use strict";(globalThis.webpackChunknextcloud_ui_legacy=globalThis.webpackChunknextcloud_ui_legacy||[]).push([[9811],{3357(n,t,e){e.d(t,{A:()=>c});var o=e(71354),l=e.n(o),s=e(76314),i=e.n(s)()(l());i.push([n.id,"\n._loginFlowContainer_OSz1H {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n","",{version:3,sources:["webpack://./core/src/components/LoginFlow/LoginFlowContainer.vue"],names:[],mappings:";AAqBA;CACA,aAAA;CACA,sBAAA;AACA",sourcesContent:['\x3c!--\n - SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n--\x3e\n\n<script setup lang="ts">\nimport NcGuestContent from \'@nextcloud/vue/components/NcGuestContent\'\n\ndefineProps<{\n\theading: string\n}>()\n<\/script>\n\n<template>\n\t<NcGuestContent class="picker-window" :class="$style.loginFlowContainer">\n\t\t<h2>{{ heading }}</h2>\n\t\t<slot />\n\t</NcGuestContent>\n</template>\n\n<style module>\n.loginFlowContainer {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n</style>\n'],sourceRoot:""}]),i.locals={loginFlowContainer:"_loginFlowContainer_OSz1H"};const c=i},7579(n,t,e){e.d(t,{A:()=>x});var o=e(85471),l=e(66768);const s=(0,o.pM)({__name:"LoginFlowContainer",props:{heading:null},setup:n=>({__sfc:!0,NcGuestContent:l.A})});var i=e(85072),c=e.n(i),r=e(97825),a=e.n(r),u=e(77659),d=e.n(u),p=e(55056),_=e.n(p),A=e(10540),C=e.n(A),g=e(41113),w=e.n(g),h=e(3357),f={};f.styleTagTransform=w(),f.setAttributes=_(),f.insert=d().bind(null,"head"),f.domAPI=a(),f.insertStyleElement=C(),c()(h.A,f);const m=h.A&&h.A.locals?h.A.locals:void 0,x=(0,e(14486).A)(s,function(){var n=this,t=n._self._c;return t(n._self._setupProxy.NcGuestContent,{staticClass:"picker-window",class:n.$style.loginFlowContainer},[t("h2",[n._v(n._s(n.heading))]),n._v(" "),n._t("default")],2)},[],!1,function(n){this.$style=m.locals||m},null,null).exports},59811(n,t,e){e.r(t),e.d(t,{default:()=>r});var o=e(85471),l=e(53334),s=e(371),i=e(7579);const c=(0,o.pM)({__name:"LoginFlowDone",setup:n=>({__sfc:!0,t:l.t,NcNoteCard:s.A,LoginFlowContainer:i.A})}),r=(0,e(14486).A)(c,function(){var n=this,t=n._self._c,e=n._self._setupProxy;return t(e.LoginFlowContainer,{attrs:{heading:e.t("core","Account connected")}},[t(e.NcNoteCard,{attrs:{type:"info"}},[n._v("\n\t\t"+n._s(e.t("core","Your client should now be connected!"))+"\n\t\t"),t("br"),n._v("\n\t\t"+n._s(e.t("core","You can close this window."))+"\n\t")])],1)},[],!1,null,null,null).exports}}]);
|
||||
//# sourceMappingURL=9811-9811.js.map?v=975f353a252dd0095921
|
||||
42
dist/9811-9811.js.license
vendored
Normal file
42
dist/9811-9811.js.license
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @nextcloud/l10n
|
||||
- version: 3.4.1
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/vue
|
||||
- version: 8.35.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- css-loader
|
||||
- version: 7.1.2
|
||||
- license: MIT
|
||||
- dompurify
|
||||
- version: 3.3.1
|
||||
- license: (MPL-2.0 OR Apache-2.0)
|
||||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- style-loader
|
||||
- version: 4.0.0
|
||||
- license: MIT
|
||||
- vue-loader
|
||||
- version: 15.11.1
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
- nextcloud
|
||||
- version: 1.0.0
|
||||
- license: AGPL-3.0-or-later
|
||||
1
dist/9811-9811.js.map
vendored
Normal file
1
dist/9811-9811.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/9811-9811.js.map.license
vendored
Symbolic link
1
dist/9811-9811.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
9811-9811.js.license
|
||||
4
dist/core-common.js
vendored
4
dist/core-common.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-common.js.map
vendored
2
dist/core-common.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/core-login_flow.js
vendored
Normal file
2
dist/core-login_flow.js
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(()=>{"use strict";var e,r,t,o={43925(e,r,t){var o=t(21777),a=t(81222),n=t(85471);t.nc=(0,o.aV)();const l=(0,n.$V)(()=>Promise.all([t.e(4208),t.e(7867)]).then(t.bind(t,50412))),i=(0,n.$V)(()=>Promise.all([t.e(4208),t.e(2426)]).then(t.bind(t,32426))),c=(0,n.$V)(()=>Promise.all([t.e(4208),t.e(9811)]).then(t.bind(t,59811))),d=(0,a.C)("core","loginFlowState");new n.Ay({render:e=>e("auth"===d?l:"grant"===d?i:c)}).$mount("#core-loginflow")}},a={};function n(e){var r=a[e];if(void 0!==r)return r.exports;var t=a[e]={id:e,loaded:!1,exports:{}};return o[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}n.m=o,e=[],n.O=(r,t,o,a)=>{if(!t){var l=1/0;for(u=0;u<e.length;u++){for(var[t,o,a]=e[u],i=!0,c=0;c<t.length;c++)(!1&a||l>=a)&&Object.keys(n.O).every(e=>n.O[e](t[c]))?t.splice(c--,1):(i=!1,a<l&&(l=a));if(i){e.splice(u--,1);var d=o();void 0!==d&&(r=d)}}return r}a=a||0;for(var u=e.length;u>0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[t,o,a]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce((r,t)=>(n.f[t](e,r),r),[])),n.u=e=>e+"-"+e+".js?v="+{2426:"7593fca92590d7569251",7867:"fe18f7f990988eb27475",9811:"975f353a252dd0095921"}[e],n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="nextcloud-ui-legacy:",n.l=(e,o,a,l)=>{if(r[e])r[e].push(o);else{var i,c;if(void 0!==a)for(var d=document.getElementsByTagName("script"),u=0;u<d.length;u++){var s=d[u];if(s.getAttribute("src")==e||s.getAttribute("data-webpack")==t+a){i=s;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",n.nc&&i.setAttribute("nonce",n.nc),i.setAttribute("data-webpack",t+a),i.src=e),r[e]=[o];var p=(t,o)=>{i.onerror=i.onload=null,clearTimeout(f);var a=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),a&&a.forEach(e=>e(o)),t)return t(o)},f=setTimeout(p.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=p.bind(null,i.onerror),i.onload=p.bind(null,i.onload),c&&document.head.appendChild(i)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),n.j=3181,(()=>{var e;globalThis.importScripts&&(e=globalThis.location+"");var r=globalThis.document;if(!e&&r&&(r.currentScript&&"SCRIPT"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var o=t.length-1;o>-1&&(!e||!/^http(s?):/.test(e));)e=t[o--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),n.p=e})(),(()=>{n.b="undefined"!=typeof document&&document.baseURI||self.location.href;var e={3181:0};n.f.j=(r,t)=>{var o=n.o(e,r)?e[r]:void 0;if(0!==o)if(o)t.push(o[2]);else{var a=new Promise((t,a)=>o=e[r]=[t,a]);t.push(o[2]=a);var l=n.p+n.u(r),i=new Error;n.l(l,t=>{if(n.o(e,r)&&(0!==(o=e[r])&&(e[r]=void 0),o)){var a=t&&("load"===t.type?"missing":t.type),l=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+a+": "+l+")",i.name="ChunkLoadError",i.type=a,i.request=l,o[1](i)}},"chunk-"+r,r)}},n.O.j=r=>0===e[r];var r=(r,t)=>{var o,a,[l,i,c]=t,d=0;if(l.some(r=>0!==e[r])){for(o in i)n.o(i,o)&&(n.m[o]=i[o]);if(c)var u=c(n)}for(r&&r(t);d<l.length;d++)a=l[d],n.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return n.O(u)},t=globalThis.webpackChunknextcloud_ui_legacy=globalThis.webpackChunknextcloud_ui_legacy||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),n.nc=void 0;var l=n.O(void 0,[4208],()=>n(43925));l=n.O(l)})();
|
||||
//# sourceMappingURL=core-login_flow.js.map?v=96b339a389e0e8f30783
|
||||
40
dist/core-login_flow.js.license
vendored
Normal file
40
dist/core-login_flow.js.license
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: ISC
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: GitHub Inc.
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Christoph Wurst
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @nextcloud/auth
|
||||
- version: 2.5.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/browser-storage
|
||||
- version: 0.5.0
|
||||
- license: GPL-3.0-or-later
|
||||
- semver
|
||||
- version: 7.7.2
|
||||
- license: ISC
|
||||
- @nextcloud/event-bus
|
||||
- version: 3.3.3
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/initial-state
|
||||
- version: 3.0.0
|
||||
- license: GPL-3.0-or-later
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
- webpack
|
||||
- version: 5.104.1
|
||||
- license: MIT
|
||||
- nextcloud
|
||||
- version: 1.0.0
|
||||
- license: AGPL-3.0-or-later
|
||||
1
dist/core-login_flow.js.map
vendored
Normal file
1
dist/core-login_flow.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/core-login_flow.js.map.license
vendored
Symbolic link
1
dist/core-login_flow.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
core-login_flow.js.license
|
||||
4
dist/files-main.js
vendored
4
dist/files-main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files-main.js.map
vendored
2
dist/files-main.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/settings-users-3239.js
vendored
4
dist/settings-users-3239.js
vendored
File diff suppressed because one or more lines are too long
2
dist/settings-users-3239.js.map
vendored
2
dist/settings-users-3239.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -22,6 +22,7 @@ use OCP\AppFramework\Http\ContentSecurityPolicy;
|
|||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Defaults;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
|
@ -53,6 +54,7 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
private IEventDispatcher&MockObject $eventDispatcher;
|
||||
private ITimeFactory&MockObject $timeFactory;
|
||||
private IConfig&MockObject $config;
|
||||
private IInitialState&MockObject $initialState;
|
||||
|
||||
private ClientFlowLoginController $clientFlowLoginController;
|
||||
|
||||
|
|
@ -79,6 +81,7 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
|
||||
$this->timeFactory = $this->createMock(ITimeFactory::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->initialState = $this->createMock(IInitialState::class);
|
||||
|
||||
$this->clientFlowLoginController = new ClientFlowLoginController(
|
||||
'core',
|
||||
|
|
@ -96,6 +99,7 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
$this->eventDispatcher,
|
||||
$this->timeFactory,
|
||||
$this->config,
|
||||
$this->initialState,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +142,7 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
->method('set')
|
||||
->with('client.flow.state.token', 'StateToken');
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with('oauth.state')
|
||||
->willReturn('OauthStateToken');
|
||||
|
|
@ -154,27 +158,39 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
->method('getServerProtocol')
|
||||
->willReturn('https');
|
||||
|
||||
$initialState = [];
|
||||
$this->initialState->expects($this->exactly(2))
|
||||
->method('provideInitialState')
|
||||
->willReturnCallback(function () use (&$initialState) {
|
||||
$initialState[] = func_get_args();
|
||||
});
|
||||
|
||||
$expected = new StandaloneTemplateResponse(
|
||||
'core',
|
||||
'loginflow/authpicker',
|
||||
[
|
||||
'client' => 'Mac OS X Sync Client',
|
||||
'clientIdentifier' => '',
|
||||
'instanceName' => 'ExampleCloud',
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'stateToken' => 'StateToken',
|
||||
'serverHost' => 'https://example.com',
|
||||
'oauthState' => 'OauthStateToken',
|
||||
'user' => '',
|
||||
'direct' => 0,
|
||||
'providedRedirectUri' => '',
|
||||
],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
$csp = new ContentSecurityPolicy();
|
||||
$csp->addAllowedFormActionDomain('nc://*');
|
||||
$expected->setContentSecurityPolicy($csp);
|
||||
$this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage());
|
||||
self::assertEquals([
|
||||
['loginFlowState', 'auth'],
|
||||
[
|
||||
'loginFlowAuth', [
|
||||
'client' => 'Mac OS X Sync Client',
|
||||
'clientIdentifier' => '',
|
||||
'instanceName' => 'ExampleCloud',
|
||||
'stateToken' => 'StateToken',
|
||||
'serverHost' => 'https://example.com',
|
||||
'oauthState' => 'OauthStateToken',
|
||||
'direct' => false,
|
||||
'providedRedirectUri' => '',
|
||||
'appTokenUrl' => '',
|
||||
'loginRedirectUrl' => '',
|
||||
],
|
||||
],
|
||||
], $initialState);
|
||||
}
|
||||
|
||||
public function testShowAuthPickerPageWithOauth(): void {
|
||||
|
|
@ -205,7 +221,7 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
->method('set')
|
||||
->with('client.flow.state.token', 'StateToken');
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with('oauth.state')
|
||||
->willReturn('OauthStateToken');
|
||||
|
|
@ -221,27 +237,39 @@ class ClientFlowLoginControllerTest extends TestCase {
|
|||
->method('getServerProtocol')
|
||||
->willReturn('https');
|
||||
|
||||
$initialState = [];
|
||||
$this->initialState->expects($this->exactly(2))
|
||||
->method('provideInitialState')
|
||||
->willReturnCallback(function () use (&$initialState) {
|
||||
$initialState[] = func_get_args();
|
||||
});
|
||||
|
||||
$expected = new StandaloneTemplateResponse(
|
||||
'core',
|
||||
'loginflow/authpicker',
|
||||
[
|
||||
'client' => 'My external service',
|
||||
'clientIdentifier' => 'MyClientIdentifier',
|
||||
'instanceName' => 'ExampleCloud',
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'stateToken' => 'StateToken',
|
||||
'serverHost' => 'https://example.com',
|
||||
'oauthState' => 'OauthStateToken',
|
||||
'user' => '',
|
||||
'direct' => 0,
|
||||
'providedRedirectUri' => '',
|
||||
],
|
||||
'guest'
|
||||
'loginflow',
|
||||
renderAs: 'guest'
|
||||
);
|
||||
$csp = new ContentSecurityPolicy();
|
||||
$csp->addAllowedFormActionDomain('https://example.com/redirect.php');
|
||||
$expected->setContentSecurityPolicy($csp);
|
||||
$this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage('MyClientIdentifier'));
|
||||
self::assertEquals([
|
||||
['loginFlowState', 'auth'],
|
||||
[
|
||||
'loginFlowAuth', [
|
||||
'client' => 'My external service',
|
||||
'clientIdentifier' => 'MyClientIdentifier',
|
||||
'instanceName' => 'ExampleCloud',
|
||||
'stateToken' => 'StateToken',
|
||||
'serverHost' => 'https://example.com',
|
||||
'oauthState' => 'OauthStateToken',
|
||||
'direct' => false,
|
||||
'providedRedirectUri' => '',
|
||||
'appTokenUrl' => '',
|
||||
'loginRedirectUrl' => '',
|
||||
],
|
||||
],
|
||||
], $initialState);
|
||||
}
|
||||
|
||||
public function testGenerateAppPasswordWithInvalidToken(): void {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use OC\Core\Service\LoginFlowV2Service;
|
|||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\StandaloneTemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\Defaults;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
|
|
@ -29,22 +30,15 @@ use PHPUnit\Framework\MockObject\MockObject;
|
|||
use Test\TestCase;
|
||||
|
||||
class ClientFlowLoginV2ControllerTest extends TestCase {
|
||||
/** @var IRequest|MockObject */
|
||||
private $request;
|
||||
/** @var LoginFlowV2Service|MockObject */
|
||||
private $loginFlowV2Service;
|
||||
/** @var IURLGenerator|MockObject */
|
||||
private $urlGenerator;
|
||||
/** @var ISession|MockObject */
|
||||
private $session;
|
||||
/** @var IUserSession|MockObject */
|
||||
private $userSession;
|
||||
/** @var ISecureRandom|MockObject */
|
||||
private $random;
|
||||
/** @var Defaults|MockObject */
|
||||
private $defaults;
|
||||
/** @var IL10N|MockObject */
|
||||
private $l;
|
||||
private IRequest&MockObject $request;
|
||||
private LoginFlowV2Service&MockObject $loginFlowV2Service;
|
||||
private IURLGenerator&MockObject $urlGenerator;
|
||||
private ISession&MockObject $session;
|
||||
private IUserSession&MockObject $userSession;
|
||||
private ISecureRandom&MockObject $random;
|
||||
private Defaults&MockObject $defaults;
|
||||
private IInitialState&MockObject $initialState;
|
||||
private IL10N&MockObject $l;
|
||||
/** @var ClientFlowLoginV2Controller */
|
||||
private $controller;
|
||||
|
||||
|
|
@ -58,6 +52,7 @@ class ClientFlowLoginV2ControllerTest extends TestCase {
|
|||
$this->userSession = $this->createMock(IUserSession::class);
|
||||
$this->random = $this->createMock(ISecureRandom::class);
|
||||
$this->defaults = $this->createMock(Defaults::class);
|
||||
$this->initialState = $this->createMock(IInitialState::class);
|
||||
$this->l = $this->createMock(IL10N::class);
|
||||
$this->l
|
||||
->expects($this->any())
|
||||
|
|
@ -75,7 +70,8 @@ class ClientFlowLoginV2ControllerTest extends TestCase {
|
|||
$this->random,
|
||||
$this->defaults,
|
||||
'user',
|
||||
$this->l
|
||||
$this->l,
|
||||
$this->initialState,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue