commit
988a5b6b39
|
@ -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;
|
||||
|
@ -268,7 +269,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
*
|
||||
* @param component Component name.
|
||||
* @param componentId Component id.
|
||||
* @returns Promise resolved when the entries are deleted.
|
||||
*/
|
||||
async deleteComponentFromCache(component: string, componentId?: number): Promise<void> {
|
||||
if (!component) {
|
||||
|
@ -284,7 +284,7 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
await this.cacheTable.delete(params);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Uploads a file using Cordova File API.
|
||||
*
|
||||
* @param filePath File path.
|
||||
|
@ -366,13 +366,17 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
* @param url The url to be fixed.
|
||||
* @returns Promise resolved with the fixed URL.
|
||||
*/
|
||||
checkAndFixPluginfileURL(url: string): Promise<string> {
|
||||
return this.checkTokenPluginFile(url).then(() => this.fixPluginfileURL(url));
|
||||
async checkAndFixPluginfileURL(url: string): Promise<string> {
|
||||
// Resolve the checking promise to make sure it's finished.
|
||||
await this.checkTokenPluginFile(url);
|
||||
|
||||
// The previous promise (tokenPluginFileWorks) result will be used here.
|
||||
return this.fixPluginfileURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic function for adding the wstoken to Moodle urls and for pointing to the correct script.
|
||||
* Uses CoreUtilsProvider.fixPluginfileURL, passing site's token.
|
||||
* Uses CoreUrl.fixPluginfileURL, passing site's token.
|
||||
*
|
||||
* @param url The url to be fixed.
|
||||
* @returns Fixed URL.
|
||||
|
@ -386,8 +390,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
|
||||
/**
|
||||
* Deletes site's DB.
|
||||
*
|
||||
* @returns Promise to be resolved when the DB is deleted.
|
||||
*/
|
||||
async deleteDB(): Promise<void> {
|
||||
await CoreDB.deleteDB('Site-' + this.id);
|
||||
|
@ -395,8 +397,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
|
||||
/**
|
||||
* Deletes site's folder.
|
||||
*
|
||||
* @returns Promise to be resolved when the DB is deleted.
|
||||
*/
|
||||
async deleteFolder(): Promise<void> {
|
||||
if (!CoreFile.isAvailable() || !this.id) {
|
||||
|
@ -466,7 +466,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
* @param url The URL to open.
|
||||
* @param alertMessage If defined, an alert will be shown before opening the browser.
|
||||
* @param options Other options.
|
||||
* @returns Promise resolved when done, rejected otherwise.
|
||||
*/
|
||||
async openInBrowserWithAutoLogin(
|
||||
url: string,
|
||||
|
@ -598,8 +597,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
|
||||
/**
|
||||
* Invalidates config WS call.
|
||||
*
|
||||
* @returns Promise resolved when the data is invalidated.
|
||||
*/
|
||||
async invalidateConfig(): Promise<void> {
|
||||
await this.invalidateWsCacheForKey(this.getConfigCacheKey());
|
||||
|
@ -728,7 +725,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
* Deletes a site setting.
|
||||
*
|
||||
* @param name The config name.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async deleteSiteConfig(name: string): Promise<void> {
|
||||
await this.configTable.deleteByPrimaryKey({ name });
|
||||
|
@ -760,13 +756,12 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
*
|
||||
* @param name The config name.
|
||||
* @param value The config value. Can only store number or strings.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async setLocalSiteConfig(name: string, value: number | string): Promise<void> {
|
||||
await this.configTable.insert({ name, value });
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check if tokenpluginfile script works in the site.
|
||||
*
|
||||
* @param url URL to check.
|
||||
|
@ -802,7 +797,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
* Deletes last viewed records based on some conditions.
|
||||
*
|
||||
* @param conditions Conditions.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async deleteLastViewed(conditions?: Partial<CoreSiteLastViewedDBRecord>): Promise<void> {
|
||||
await this.lastViewedTable.delete(conditions);
|
||||
|
@ -853,7 +847,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
* @param id ID.
|
||||
* @param value Last viewed item value.
|
||||
* @param options Options.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async storeLastViewed(
|
||||
component: string,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -151,7 +151,6 @@ export class CoreLoginHelperProvider {
|
|||
* @param service The service to use. If not defined, core service will be used.
|
||||
* @param launchUrl The URL to open for SSO. If not defined, default tool mobile launch URL will be used.
|
||||
* @param redirectData Data of the path/url to open once authenticated. If not defined, site initial page.
|
||||
* @returns Promise resolved when done or if user cancelled.
|
||||
* @deprecated since 4.3. Use openBrowserForSSOLogin instead.
|
||||
*/
|
||||
async confirmAndOpenBrowserForSSOLogin(
|
||||
|
@ -393,7 +392,7 @@ export class CoreLoginHelperProvider {
|
|||
siteConfig.identityproviders.forEach((provider) => {
|
||||
const urlParams = CoreUrl.extractUrlParams(provider.url);
|
||||
|
||||
if (provider.url && (provider.url.indexOf(httpsUrl) != -1 || provider.url.indexOf(httpUrl) != -1) &&
|
||||
if (provider.url && (provider.url.indexOf(httpsUrl) !== -1 || provider.url.indexOf(httpUrl) !== -1) &&
|
||||
!site.isFeatureDisabled(IDENTITY_PROVIDER_FEATURE_NAME_PREFIX + urlParams.id)) {
|
||||
validProviders.push(provider);
|
||||
}
|
||||
|
@ -403,13 +402,27 @@ 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.
|
||||
*
|
||||
* @param setRoot True to set the new page as root, false to add it to the stack.
|
||||
* @param showKeyboard Whether to show keyboard in the new page. Only if no fixed URL set.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async goToAddSite(setRoot = false, showKeyboard = false): Promise<void> {
|
||||
if (CoreSites.isLoggedIn()) {
|
||||
|
@ -462,6 +475,7 @@ export class CoreLoginHelperProvider {
|
|||
* @param privateToken User's private token.
|
||||
* @param oauthId OAuth ID. Only if the authentication was using an OAuth method.
|
||||
* @returns Promise resolved when the user is authenticated with the token.
|
||||
* @deprecated since 5.0. This is now handled by CoreCustomURLSchemes.
|
||||
*/
|
||||
handleSSOLoginAuthentication(siteUrl: string, token: string, privateToken?: string, oauthId?: number): Promise<string> {
|
||||
// Always create a new site to prevent overriding data if another user credentials were introduced.
|
||||
|
@ -682,7 +696,6 @@ export class CoreLoginHelperProvider {
|
|||
*
|
||||
* @param siteUrl Site URL to construct change password URL.
|
||||
* @param error Error message.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async openChangePassword(siteUrl: string, error: string): Promise<void> {
|
||||
const alert = await CoreDomUtils.showAlert(Translate.instant('core.notice'), error, undefined, 3000);
|
||||
|
@ -708,7 +721,6 @@ export class CoreLoginHelperProvider {
|
|||
* @param path The relative path of the URL to open.
|
||||
* @param alertMessage The key of the message to display before opening the in app browser.
|
||||
* @param invalidateCache Whether to invalidate site's cache (e.g. when the user is forced to change password).
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async openInAppForEdit(siteId: string, path: string, alertMessage?: string, invalidateCache?: boolean): Promise<void> {
|
||||
if (!siteId || siteId !== CoreSites.getCurrentSiteId()) {
|
||||
|
@ -840,7 +852,6 @@ export class CoreLoginHelperProvider {
|
|||
* Function that should be called when the session expires. Reserved for core use.
|
||||
*
|
||||
* @param data Data received by the SESSION_EXPIRED event.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async sessionExpired(data: CoreEventSessionExpiredData & CoreEventSiteData): Promise<void> {
|
||||
const siteId = data?.siteId;
|
||||
|
@ -1214,8 +1225,6 @@ export class CoreLoginHelperProvider {
|
|||
|
||||
/**
|
||||
* Start waiting when opening a browser/IAB.
|
||||
*
|
||||
* @returns Promise resolved when the app is resumed.
|
||||
*/
|
||||
async waitForBrowser(): Promise<void> {
|
||||
if (!this.waitingForBrowser) {
|
||||
|
@ -1268,8 +1277,6 @@ export class CoreLoginHelperProvider {
|
|||
|
||||
/**
|
||||
* Show instructions to scan QR code.
|
||||
*
|
||||
* @returns Promise resolved if the user accepts to scan QR.
|
||||
*/
|
||||
async showScanQRInstructions(): Promise<void> {
|
||||
const dontShowWarning = await CoreConfig.get(FAQ_QRCODE_INFO_DONE, 0);
|
||||
|
@ -1303,8 +1310,6 @@ export class CoreLoginHelperProvider {
|
|||
|
||||
/**
|
||||
* Scan a QR code and tries to authenticate the user using custom URL scheme.
|
||||
*
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
async scanQR(): Promise<void> {
|
||||
// Scan for a QR code.
|
||||
|
@ -1375,7 +1380,6 @@ export class CoreLoginHelperProvider {
|
|||
*
|
||||
* @param accountsList Account list.
|
||||
* @param site Site to be deleted.
|
||||
* @returns Resolved when done.
|
||||
*/
|
||||
async deleteAccountFromList(accountsList: CoreAccountsList, site: CoreSiteBasicInfo): Promise<void> {
|
||||
await CoreSites.deleteSite(site.id);
|
||||
|
|
|
@ -1611,7 +1611,6 @@ export class CoreSitesProvider {
|
|||
* @param siteId Site Id.
|
||||
* @param token User's new token.
|
||||
* @param privateToken User's private token.
|
||||
* @returns A promise resolved when the site is updated.
|
||||
*/
|
||||
async updateSiteTokenBySiteId(siteId: string, token: string, privateToken: string = ''): Promise<void> {
|
||||
const site = await this.getSite(siteId);
|
||||
|
@ -1633,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.
|
||||
*
|
||||
|
|
|
@ -82,7 +82,6 @@ export class CoreOpener {
|
|||
*
|
||||
* @param path The local path of the file to be open.
|
||||
* @param options Options.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
static async openFile(path: string, options: CoreOpenerOpenFileOptions = {}): Promise<void> {
|
||||
// Convert the path to a native path if needed.
|
||||
|
|
|
@ -49,7 +49,6 @@ export class CoreWindow {
|
|||
*
|
||||
* @param url URL to open.
|
||||
* @param name Name of the browsing context into which to load the URL.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
static async open(url: string, name?: string): Promise<void> {
|
||||
if (CoreUrl.isLocalFileUrl(url)) {
|
||||
|
|
Loading…
Reference in New Issue