forked from EVOgeek/Vmeda.Online
		
	MOBILE-4680 login: Show the current oauth method to the top on reconnect
This commit is contained in:
		
							parent
							
								
									ae1c719f19
								
							
						
					
					
						commit
						6c132bd736
					
				@ -2168,6 +2168,7 @@
 | 
			
		||||
  "core.login.missingfirstname": "moodle",
 | 
			
		||||
  "core.login.missinglastname": "moodle",
 | 
			
		||||
  "core.login.mobileservicesnotenabled": "local_moodlemobileapp",
 | 
			
		||||
  "core.login.morewaystologin": "local_moodlemobileapp",
 | 
			
		||||
  "core.login.mustconfirm": "moodle",
 | 
			
		||||
  "core.login.newaccount": "moodle",
 | 
			
		||||
  "core.login.notloggedin": "local_moodlemobileapp",
 | 
			
		||||
 | 
			
		||||
@ -195,6 +195,7 @@ export class CoreSite extends CoreAuthenticatedSite {
 | 
			
		||||
     * Check if the user authenticated in the site using an OAuth method.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns Whether the user authenticated in the site using an OAuth method.
 | 
			
		||||
     * @deprecated since 5.0. Use getOAuthId instead.
 | 
			
		||||
     */
 | 
			
		||||
    isOAuth(): boolean {
 | 
			
		||||
        return this.oauthId != null && this.oauthId !== undefined;
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ import { NgModule } from '@angular/core';
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreLoginMethodsComponent } from './login-methods/login-methods';
 | 
			
		||||
import { CoreLoginExceededAttemptsComponent } from '@features/login/components/exceeded-attempts/exceeded-attempts';
 | 
			
		||||
import { CoreLoginIdentityProviderComponent } from './identity-provider/identity-provider';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
@ -24,6 +25,7 @@ import { CoreLoginExceededAttemptsComponent } from '@features/login/components/e
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
        CoreLoginIdentityProviderComponent,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [
 | 
			
		||||
        CoreLoginExceededAttemptsComponent,
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<ion-button class="ion-text-wrap ion-margin core-oauth-provider" (click)="openOAuth()" [ariaLabel]="provider.name" expand="block"
 | 
			
		||||
    fill="outline">
 | 
			
		||||
    @if (provider.iconurl) {
 | 
			
		||||
    <img [src]="provider.iconurl" alt="" width="32" height="32" slot="start" aria-hidden="true" (error)="provider.iconurl = ''" />
 | 
			
		||||
    }
 | 
			
		||||
    <ion-label>{{ provider.name }}</ion-label>
 | 
			
		||||
</ion-button>
 | 
			
		||||
@ -0,0 +1,53 @@
 | 
			
		||||
// (C) Copyright 2015 Moodle Pty Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Component, Input } from '@angular/core';
 | 
			
		||||
import { CoreSiteIdentityProvider } from '@classes/sites/unauthenticated-site';
 | 
			
		||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreRedirectPayload } from '@services/navigator';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-identity-provider',
 | 
			
		||||
    templateUrl: 'identity-provider.html',
 | 
			
		||||
    standalone: true,
 | 
			
		||||
    imports: [
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreLoginIdentityProviderComponent {
 | 
			
		||||
 | 
			
		||||
    @Input({ required: true }) provider!: CoreSiteIdentityProvider;
 | 
			
		||||
    @Input() launchurl = '';
 | 
			
		||||
    @Input() siteUrl = '';
 | 
			
		||||
    @Input() redirectData?: CoreRedirectPayload;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The button has been clicked.
 | 
			
		||||
     */
 | 
			
		||||
    async openOAuth(): Promise<void> {
 | 
			
		||||
        const result = await CoreLoginHelper.openBrowserForOAuthLogin(
 | 
			
		||||
            this.siteUrl,
 | 
			
		||||
            this.provider,
 | 
			
		||||
            this.launchurl,
 | 
			
		||||
            this.redirectData,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (!result) {
 | 
			
		||||
            CoreDomUtils.showErrorModal('Invalid data.');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -21,9 +21,6 @@
 | 
			
		||||
<!-- Identity providers. -->
 | 
			
		||||
<ion-list *ngIf="identityProviders.length" class="core-login-identity-providers">
 | 
			
		||||
    <h2 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h2>
 | 
			
		||||
    <ion-button [fill]="'outline'" *ngFor="let provider of identityProviders" class="ion-text-wrap ion-margin core-oauth-provider"
 | 
			
		||||
        (click)="oauthClicked(provider)" [ariaLabel]="provider.name" expand="block">
 | 
			
		||||
        <img *ngIf="provider.iconurl" [src]="provider.iconurl" alt="" width="32" height="32" slot="start" aria-hidden="true">
 | 
			
		||||
        <ion-label>{{ provider.name }}</ion-label>
 | 
			
		||||
    </ion-button>
 | 
			
		||||
    <core-identity-provider *ngFor="let provider of identityProviders" [provider]="provider" [launchurl]="siteConfig?.launchurl"
 | 
			
		||||
        [redirectData]="redirectData" [siteUrl]="siteUrl" />
 | 
			
		||||
</ion-list>
 | 
			
		||||
 | 
			
		||||
@ -12,14 +12,13 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { toBoolean } from '@/core/transforms/boolean';
 | 
			
		||||
import { Component, Input, OnInit } from '@angular/core';
 | 
			
		||||
import { CorePromisedValue } from '@classes/promised-value';
 | 
			
		||||
import { CoreSite } from '@classes/sites/site';
 | 
			
		||||
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site';
 | 
			
		||||
import { CoreLoginHelper, CoreLoginMethod } from '@features/login/services/login-helper';
 | 
			
		||||
import { CoreRedirectPayload } from '@services/navigator';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreSitesFactory } from '@services/sites-factory';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-login-methods',
 | 
			
		||||
@ -28,10 +27,10 @@ import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
})
 | 
			
		||||
export class CoreLoginMethodsComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    @Input({ transform: toBoolean }) reconnect = false;
 | 
			
		||||
    @Input() siteUrl = '';
 | 
			
		||||
    @Input() siteConfig?: CoreSitePublicConfigResponse;
 | 
			
		||||
    @Input() redirectData?: CoreRedirectPayload;
 | 
			
		||||
    @Input() site?: CoreSite; // Defined when the user is reconnecting.
 | 
			
		||||
    @Input() showLoginForm = true;
 | 
			
		||||
 | 
			
		||||
    isBrowserSSO  = false;
 | 
			
		||||
@ -39,16 +38,20 @@ export class CoreLoginMethodsComponent implements OnInit {
 | 
			
		||||
    loginMethods: CoreLoginMethod[] = [];
 | 
			
		||||
    identityProviders: CoreSiteIdentityProvider[] = [];
 | 
			
		||||
 | 
			
		||||
    protected currentLoginProvider?: CoreSiteIdentityProvider;
 | 
			
		||||
    protected isReady = new CorePromisedValue<void>();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        if (this.reconnect) {
 | 
			
		||||
        if (this.site) {
 | 
			
		||||
            this.siteUrl = this.site.getURL();
 | 
			
		||||
 | 
			
		||||
            this.loginMethods = await CoreLoginHelper.getLoginMethods();
 | 
			
		||||
 | 
			
		||||
            const currentSite = CoreSites.getCurrentSite();
 | 
			
		||||
            const defaultMethod = await CoreLoginHelper.getDefaultLoginMethod();
 | 
			
		||||
            if (currentSite?.isLoggedOut() && defaultMethod) {
 | 
			
		||||
            if (this.site.isLoggedOut() && defaultMethod) {
 | 
			
		||||
                await defaultMethod.action();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -59,25 +62,29 @@ export class CoreLoginMethodsComponent implements OnInit {
 | 
			
		||||
            // Identity providers won't be shown if login on browser.
 | 
			
		||||
            if (!this.isBrowserSSO) {
 | 
			
		||||
                this.identityProviders = await CoreLoginHelper.getValidIdentityProvidersForSite(
 | 
			
		||||
                    CoreSitesFactory.makeUnauthenticatedSite(this.siteUrl, this.siteConfig),
 | 
			
		||||
                    this.site ?? CoreSitesFactory.makeUnauthenticatedSite(this.siteUrl, this.siteConfig),
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.reconnect) {
 | 
			
		||||
            if (this.site) {
 | 
			
		||||
                this.showScanQR = CoreLoginHelper.displayQRInSiteScreen();
 | 
			
		||||
 | 
			
		||||
                // The identity provider set in the site will be shown at the top.
 | 
			
		||||
                const oAuthId = this.site.getOAuthId();
 | 
			
		||||
                this.currentLoginProvider = CoreLoginHelper.findIdentityProvider(this.identityProviders, oAuthId);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // If still false or credentials screen.
 | 
			
		||||
            if (!this.reconnect || !this.showScanQR) {
 | 
			
		||||
            if (!this.site || !this.showScanQR) {
 | 
			
		||||
                this.showScanQR = await CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.isReady.resolve();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Show instructions and scan QR code.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    async showInstructionsAndScanQR(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
@ -90,21 +97,33 @@ export class CoreLoginMethodsComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * An OAuth button was clicked.
 | 
			
		||||
     * Get the current login, removing the identity provider from the list.
 | 
			
		||||
     *
 | 
			
		||||
     * @param provider The provider that was clicked.
 | 
			
		||||
     * @returns Current login.
 | 
			
		||||
     */
 | 
			
		||||
    async oauthClicked(provider: CoreSiteIdentityProvider): Promise<void> {
 | 
			
		||||
        const result = await CoreLoginHelper.openBrowserForOAuthLogin(
 | 
			
		||||
            this.siteUrl,
 | 
			
		||||
            provider,
 | 
			
		||||
            this.siteConfig?.launchurl,
 | 
			
		||||
            this.redirectData,
 | 
			
		||||
        );
 | 
			
		||||
    async extractCurrentLogin(): Promise<CoreLoginMethodsCurrentLogin | undefined> {
 | 
			
		||||
        await this.isReady;
 | 
			
		||||
 | 
			
		||||
        if (!result) {
 | 
			
		||||
            CoreDomUtils.showErrorModal('Invalid data.');
 | 
			
		||||
        if (!this.currentLoginProvider) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Remove the identity provider from the array.
 | 
			
		||||
        this.identityProviders = this.identityProviders.filter((provider) =>
 | 
			
		||||
            provider.url !== this.currentLoginProvider?.url);
 | 
			
		||||
 | 
			
		||||
        const showOther = !!(this.showLoginForm || this.isBrowserSSO) &&
 | 
			
		||||
            !!(this.loginMethods.length || this.identityProviders.length || this.showScanQR);
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            provider: this.currentLoginProvider,
 | 
			
		||||
            showOther,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type CoreLoginMethodsCurrentLogin = {
 | 
			
		||||
    provider: CoreSiteIdentityProvider;
 | 
			
		||||
    showOther: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -71,6 +71,7 @@
 | 
			
		||||
    "missingfirstname": "Missing given name",
 | 
			
		||||
    "missinglastname": "Missing last name",
 | 
			
		||||
    "mobileservicesnotenabled": "Mobile services are not enabled on the site.",
 | 
			
		||||
    "morewaystologin": "More ways to log in",
 | 
			
		||||
    "mustconfirm": "You need to confirm your account",
 | 
			
		||||
    "newaccount": "New account",
 | 
			
		||||
    "notloggedin": "You need to be logged in.",
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreLoginComponentsModule } from '@features/login/components/components.module';
 | 
			
		||||
import { CoreLoginReconnectPage } from '@features/login/pages/reconnect/reconnect';
 | 
			
		||||
import { CoreSiteLogoComponent } from '@/core/components/site-logo/site-logo';
 | 
			
		||||
import { CoreLoginIdentityProviderComponent } from './components/identity-provider/identity-provider';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
@ -33,6 +34,7 @@ const routes: Routes = [
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
        CoreLoginComponentsModule,
 | 
			
		||||
        CoreSiteLogoComponent,
 | 
			
		||||
        CoreLoginIdentityProviderComponent,
 | 
			
		||||
    ],
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreLoginReconnectPage,
 | 
			
		||||
 | 
			
		||||
@ -51,41 +51,62 @@
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="core-login-methods">
 | 
			
		||||
                <form *ngIf="showLoginForm && !isBrowserSSO" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form"
 | 
			
		||||
                    #reconnectForm>
 | 
			
		||||
                    <ion-item class="ion-margin-bottom" lines="inset">
 | 
			
		||||
                        <ion-input class="core-ioninput-password" name="password" type="password"
 | 
			
		||||
                            placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
 | 
			
		||||
                            autocomplete="current-password" enterkeyhint="go" required="true"
 | 
			
		||||
                            [attr.aria-label]="'core.login.password' | translate">
 | 
			
		||||
                            <ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
 | 
			
		||||
                        </ion-input>
 | 
			
		||||
                    </ion-item>
 | 
			
		||||
                    <ion-button type="submit" expand="block" [disabled]="!credForm.valid"
 | 
			
		||||
                        class="ion-margin core-login-login-button ion-text-wrap">
 | 
			
		||||
                        {{ 'core.login.loginbutton' | translate }}
 | 
			
		||||
                    </ion-button>
 | 
			
		||||
                @if (currentLogin && currentLogin.provider) {
 | 
			
		||||
                <core-identity-provider [provider]="currentLogin.provider" [launchurl]="siteConfig?.launchurl" [redirectData]="redirectData"
 | 
			
		||||
                    [siteUrl]="site.siteUrl" />
 | 
			
		||||
                @if (currentLogin.showOther) {
 | 
			
		||||
                <ion-accordion-group>
 | 
			
		||||
                    <ion-accordion toggleIconSlot="start">
 | 
			
		||||
                        <ion-item class="ion-text-wrap" slot="header">
 | 
			
		||||
                            <ion-label>
 | 
			
		||||
                                <p class="item-heading">{{ 'core.login.morewaystologin' | translate }}</p>
 | 
			
		||||
                            </ion-label>
 | 
			
		||||
                        </ion-item>
 | 
			
		||||
 | 
			
		||||
                    <!-- Forgotten password option. -->
 | 
			
		||||
                    <ion-button *ngIf="showForgottenPassword" expand="block" fill="clear"
 | 
			
		||||
                        class="core-login-forgotten-password core-button-as-link ion-text-wrap" (click)="forgottenPassword()">
 | 
			
		||||
                        {{ 'core.login.forgotaccount' | translate }}
 | 
			
		||||
                    </ion-button>
 | 
			
		||||
                </form>
 | 
			
		||||
 | 
			
		||||
                <ng-container *ngIf="isBrowserSSO">
 | 
			
		||||
                    <ion-button expand="block" (click)="openBrowserSSO()"
 | 
			
		||||
                        class="ion-margin core-login-login-inbrowser-button ion-text-wrap">
 | 
			
		||||
                        {{ 'core.login.loginbutton' | translate }}
 | 
			
		||||
                        <ion-icon name="fas-up-right-from-square" slot="end" aria-hidden="true" />
 | 
			
		||||
                    </ion-button>
 | 
			
		||||
                    <p class="text-center core-login-inbrowser">{{ 'core.openinbrowserdescription' | translate }}</p>
 | 
			
		||||
                </ng-container>
 | 
			
		||||
 | 
			
		||||
                <!-- Additional Login methods -->
 | 
			
		||||
                <core-login-methods *ngIf="siteConfig" [siteConfig]="siteConfig" [reconnect]="true" [siteUrl]="site.siteUrl"
 | 
			
		||||
                    [redirectData]="redirectData" [showLoginForm]="showLoginForm" />
 | 
			
		||||
                        <div slot="content">
 | 
			
		||||
                            <ng-template *ngTemplateOutlet="loginMethods" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ion-accordion>
 | 
			
		||||
                </ion-accordion-group>
 | 
			
		||||
                }
 | 
			
		||||
                } @else {
 | 
			
		||||
                <ng-template *ngTemplateOutlet="loginMethods" />
 | 
			
		||||
                }
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<ng-template #loginMethods>
 | 
			
		||||
    <form *ngIf="showLoginForm && !isBrowserSSO" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
 | 
			
		||||
        <ion-item class="ion-margin-bottom" lines="inset">
 | 
			
		||||
            <ion-input class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.login.password' | translate }}"
 | 
			
		||||
                formControlName="password" [clearOnEdit]="false" autocomplete="current-password" enterkeyhint="go" required="true"
 | 
			
		||||
                [attr.aria-label]="'core.login.password' | translate">
 | 
			
		||||
                <ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
 | 
			
		||||
            </ion-input>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <ion-button type="submit" expand="block" [disabled]="!credForm.valid" class="ion-margin core-login-login-button ion-text-wrap">
 | 
			
		||||
            {{ 'core.login.loginbutton' | translate }}
 | 
			
		||||
        </ion-button>
 | 
			
		||||
 | 
			
		||||
        <!-- Forgotten password option. -->
 | 
			
		||||
        <ion-button *ngIf="showForgottenPassword" expand="block" fill="clear"
 | 
			
		||||
            class="core-login-forgotten-password core-button-as-link ion-text-wrap" (click)="forgottenPassword()">
 | 
			
		||||
            {{ 'core.login.forgotaccount' | translate }}
 | 
			
		||||
        </ion-button>
 | 
			
		||||
    </form>
 | 
			
		||||
 | 
			
		||||
    <ng-container *ngIf="isBrowserSSO">
 | 
			
		||||
        <ion-button expand="block" (click)="openBrowserSSO()" class="ion-margin core-login-login-inbrowser-button ion-text-wrap">
 | 
			
		||||
            {{ 'core.login.loginbutton' | translate }}
 | 
			
		||||
            <ion-icon name="fas-up-right-from-square" slot="end" aria-hidden="true" />
 | 
			
		||||
        </ion-button>
 | 
			
		||||
        <p class="text-center core-login-inbrowser">{{ 'core.openinbrowserdescription' | translate }}</p>
 | 
			
		||||
    </ng-container>
 | 
			
		||||
 | 
			
		||||
    <!-- Additional Login methods -->
 | 
			
		||||
    <core-login-methods *ngIf="siteConfig" [site]="site" [siteConfig]="siteConfig" [siteUrl]="site.siteUrl" [redirectData]="redirectData"
 | 
			
		||||
        [showLoginForm]="showLoginForm" />
 | 
			
		||||
</ng-template>
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@ import { CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-sit
 | 
			
		||||
import { ALWAYS_SHOW_LOGIN_FORM_CHANGED, FORGOTTEN_PASSWORD_FEATURE_NAME } from '@features/login/constants';
 | 
			
		||||
import { CoreKeyboard } from '@singletons/keyboard';
 | 
			
		||||
import { CoreLoadings } from '@services/loadings';
 | 
			
		||||
import { CoreLoginMethodsComponent, CoreLoginMethodsCurrentLogin } from '@features/login/components/login-methods/login-methods';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page to enter the user password to reconnect to a site.
 | 
			
		||||
@ -46,6 +47,17 @@ import { CoreLoadings } from '@services/loadings';
 | 
			
		||||
export class CoreLoginReconnectPage implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    @ViewChild('reconnectForm') formElement?: ElementRef;
 | 
			
		||||
    @ViewChild(CoreLoginMethodsComponent) set loginMethods(loginMethods: CoreLoginMethodsComponent) {
 | 
			
		||||
        if (loginMethods && !this.currentLogin) {
 | 
			
		||||
            loginMethods.extractCurrentLogin().then(login => {
 | 
			
		||||
                this.currentLogin = login;
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }).catch(() => {
 | 
			
		||||
                // Ignore errors.
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    credForm: FormGroup;
 | 
			
		||||
    site!: CoreSite;
 | 
			
		||||
@ -53,6 +65,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
 | 
			
		||||
    showForgottenPassword = true;
 | 
			
		||||
    showUserAvatar = false;
 | 
			
		||||
    isBrowserSSO = false;
 | 
			
		||||
    currentLogin?: CoreLoginMethodsCurrentLogin;
 | 
			
		||||
    isLoggedOut: boolean;
 | 
			
		||||
    siteId!: string;
 | 
			
		||||
    siteInfo?: CoreSiteBasicInfo;
 | 
			
		||||
@ -252,16 +265,21 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
        const modal = await CoreLoadings.show();
 | 
			
		||||
 | 
			
		||||
        const url = this.site.getURL();
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // Start the authentication process.
 | 
			
		||||
            const data = await CoreSites.getUserToken(this.site.getURL(), this.username, password);
 | 
			
		||||
            const data = await CoreSites.getUserToken(url, this.username, password);
 | 
			
		||||
 | 
			
		||||
            await CoreSites.updateSiteToken(this.site.getURL(), this.username, data.token, data.privateToken);
 | 
			
		||||
            await CoreSites.updateSiteToken(url, this.username, data.token, data.privateToken);
 | 
			
		||||
 | 
			
		||||
            CoreForms.triggerFormSubmittedEvent(this.formElement, true);
 | 
			
		||||
 | 
			
		||||
            // Unset oAuthID if it's set.
 | 
			
		||||
            await CoreSites.removeSiteOauthId(this.siteId);
 | 
			
		||||
 | 
			
		||||
            // Update site info too.
 | 
			
		||||
            await CoreSites.updateSiteInfoByUrl(this.site.getURL(), this.username);
 | 
			
		||||
            await CoreSites.updateSiteInfoByUrl(url, this.username);
 | 
			
		||||
 | 
			
		||||
            // Reset fields so the data is not in the view anymore.
 | 
			
		||||
            this.credForm.controls['password'].reset();
 | 
			
		||||
@ -271,7 +289,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
 | 
			
		||||
                params: this.redirectData,
 | 
			
		||||
            });
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreLoginHelper.treatUserTokenError(this.site.getURL(), error, this.username, password);
 | 
			
		||||
            CoreLoginHelper.treatUserTokenError(url, error, this.username, password);
 | 
			
		||||
 | 
			
		||||
            if (error.loggedout) {
 | 
			
		||||
                this.cancel();
 | 
			
		||||
 | 
			
		||||
@ -402,6 +402,21 @@ export class CoreLoginHelperProvider {
 | 
			
		||||
        return validProviders;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds an identity provider from a list of providers based on the given OAuth ID.
 | 
			
		||||
     *
 | 
			
		||||
     * @param providers Array of identity providers.
 | 
			
		||||
     * @param oauthId The OAuth ID to match against the providers' URLs.
 | 
			
		||||
     * @returns The identity provider that matches the given OAuth ID, or undefined if no match is found.
 | 
			
		||||
     */
 | 
			
		||||
    findIdentityProvider(providers: CoreSiteIdentityProvider[], oauthId?: number): CoreSiteIdentityProvider | undefined {
 | 
			
		||||
        if (!oauthId) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return providers.find(provider => Number(CoreUrl.extractUrlParams(provider.url).id) === oauthId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Go to the page to add a new site.
 | 
			
		||||
     * If a fixed URL is configured, go to credentials instead.
 | 
			
		||||
 | 
			
		||||
@ -1632,6 +1632,23 @@ export class CoreSitesProvider {
 | 
			
		||||
        await Promise.all(promises);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes the OAuth ID for a given site.
 | 
			
		||||
     *
 | 
			
		||||
     * @param siteId The ID of the site to update.
 | 
			
		||||
     */
 | 
			
		||||
    async removeSiteOauthId(siteId: string): Promise<void> {
 | 
			
		||||
        const site = await this.getSite(siteId);
 | 
			
		||||
 | 
			
		||||
        site.setOAuthId(undefined);
 | 
			
		||||
 | 
			
		||||
        const newData: Partial<SiteDBEntry> = {
 | 
			
		||||
            oauthId: null,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        await this.sitesTable.update(newData, { id: siteId });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates a site's info.
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user