diff --git a/src/addons/enrol/guest/services/enrol-handler.ts b/src/addons/enrol/guest/services/enrol-handler.ts index d8b6f5ef0c0..0a0b174c4af 100644 --- a/src/addons/enrol/guest/services/enrol-handler.ts +++ b/src/addons/enrol/guest/services/enrol-handler.ts @@ -13,7 +13,12 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreEnrolAction, CoreEnrolGuestHandler, CoreEnrolInfoIcon } from '@features/enrol/services/enrol-delegate'; +import { + CoreEnrolAction, + CoreEnrolCanAccessData, + CoreEnrolGuestHandler, + CoreEnrolInfoIcon, +} from '@features/enrol/services/enrol-delegate'; import { makeSingleton } from '@singletons'; import { AddonEnrolGuest } from './guest'; import { CorePasswordModalResponse } from '@components/password-modal/password-modal'; @@ -66,10 +71,13 @@ export class AddonEnrolGuestHandlerService implements CoreEnrolGuestHandler { /** * @inheritdoc */ - async canAccess(method: CoreEnrolEnrolmentMethod): Promise { + async canAccess(method: CoreEnrolEnrolmentMethod): Promise { const info = await AddonEnrolGuest.getGuestEnrolmentInfo(method.id); - return info.status && (!info.passwordrequired || AddonEnrolGuest.isValidateGuestAccessPasswordAvailable()); + return { + canAccess: info.status && (!info.passwordrequired || AddonEnrolGuest.isValidateGuestAccessPasswordAvailable()), + requiresUserInput: info.passwordrequired, + }; } /** diff --git a/src/core/features/course/pages/course-summary/course-summary.page.ts b/src/core/features/course/pages/course-summary/course-summary.page.ts index e354df78ec2..d3c5700dca9 100644 --- a/src/core/features/course/pages/course-summary/course-summary.page.ts +++ b/src/core/features/course/pages/course-summary/course-summary.page.ts @@ -231,7 +231,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { if (!this.canAccessCourse) { // The user is not an admin/manager. Check if we can provide guest access to the course. const promises = this.guestEnrolInstances.map(async (method) => { - const canAccess = await CoreEnrolDelegate.canAccess(method); + const { canAccess } = await CoreEnrolDelegate.canAccess(method); if (canAccess) { this.canAccessCourse = true; } diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index 74eaa9f5488..283d3e6d2e5 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -74,8 +74,8 @@ import { CoreCourseWithImageAndColor } from '@features/courses/services/courses- import { CoreCourseSummaryPage } from '../pages/course-summary/course-summary.page'; import { CoreRemindersPushNotificationData } from '@features/reminders/services/reminders'; import { CoreLocalNotifications } from '@services/local-notifications'; -import { AddonEnrolGuest } from '@addons/enrol/guest/services/guest'; import { CoreEnrol } from '@features/enrol/services/enrol'; +import { CoreEnrolAction, CoreEnrolDelegate } from '@features/enrol/services/enrol-delegate'; /** * Prefetch info of a module. @@ -594,22 +594,26 @@ export class CoreCourseHelperProvider { } /** - * Check whether a course is accessed using guest access and if it requires password to enter. + * Check whether a course is accessed using guest access and if it requires user input to enter. * * @param courseId Course ID. * @param siteId Site ID. If not defined, current site. - * @returns Promise resolved with guestAccess and passwordRequired booleans. + * @returns Data about guest access info. */ async courseUsesGuestAccessInfo( courseId: number, siteId?: string, - ): Promise<{guestAccess: boolean; passwordRequired?: boolean}> { + ): Promise { + const accessData: CoreCourseGuestAccessInfo = { + guestAccess: false, + }; + try { try { // Check if user is enrolled. If enrolled, no guest access. await CoreCourses.getUserCourse(courseId, false, siteId); - return { guestAccess: false }; + return accessData; } catch { // Ignore errors. } @@ -618,26 +622,35 @@ export class CoreCourseHelperProvider { // The user is not enrolled in the course. Use getCourses to see if it's an admin/manager and can see the course. await CoreCourses.getCourse(courseId, siteId); - return { guestAccess: false }; + return accessData; } catch { // Ignore errors. } // Check if guest access is enabled. - const enrolmentMethods = await CoreEnrol.getSupportedCourseEnrolmentMethods(courseId, { type: 'guest', siteId }); + const enrolmentMethods = await CoreEnrol.getSupportedCourseEnrolmentMethods(courseId, { + action: CoreEnrolAction.GUEST, + siteId, + }); + if (!enrolmentMethods) { - return { guestAccess: false }; + return accessData; } - const info = await AddonEnrolGuest.getGuestEnrolmentInfo(enrolmentMethods[0].id); + const results = await Promise.all(enrolmentMethods.map(method => CoreEnrolDelegate.canAccess(method))); - // Don't allow guest access if it requires a password and it's available. - return { - guestAccess: info.status && (!info.passwordrequired || AddonEnrolGuest.isValidateGuestAccessPasswordAvailable()), - passwordRequired: info.passwordrequired, - }; + results.forEach(result => { + accessData.guestAccess = accessData.guestAccess || result.canAccess; + if (accessData.requiresUserInput !== false && result.canAccess) { + accessData.requiresUserInput = result.requiresUserInput ?? accessData.requiresUserInput; + } + }); + + accessData.passwordRequired = accessData.requiresUserInput; // For backwards compatibility. + + return accessData; } catch { - return { guestAccess: false }; + return accessData; } } @@ -2192,3 +2205,15 @@ export type CoreCourseOpenModuleOptions = { sectionId?: number; // Section the module belongs to. modNavOptions?: CoreNavigationOptions; // Navigation options to open the module, including params to pass to the module. }; + +/** + * Result of courseUsesGuestAccessInfo. + */ +export type CoreCourseGuestAccessInfo = { + guestAccess: boolean; // Whether guest access is enabled for a course. + requiresUserInput?: boolean; // Whether the first guest access enrolment method requires user input. + /** + * @deprecated since 4.3. Use requiresUserInput instead. + */ + passwordRequired?: boolean; +}; diff --git a/src/core/features/courses/services/handlers/course-link.ts b/src/core/features/courses/services/handlers/course-link.ts index 4c60c16b6fe..d29db57e62b 100644 --- a/src/core/features/courses/services/handlers/course-link.ts +++ b/src/core/features/courses/services/handlers/course-link.ts @@ -132,7 +132,7 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler const guestInfo = await CoreCourseHelper.courseUsesGuestAccessInfo(courseId); pageParams.isGuest = guestInfo.guestAccess; - if (hasAccess && !guestInfo.guestAccess && !guestInfo.passwordRequired) { + if (hasAccess && !guestInfo.guestAccess && !guestInfo.requiresUserInput) { // Direct access. const course = await CoreUtils.ignoreErrors(CoreCourses.getUserCourse(courseId), { id: courseId }); diff --git a/src/core/features/enrol/services/enrol-delegate.ts b/src/core/features/enrol/services/enrol-delegate.ts index a728ef96e6f..3ef216fda9e 100644 --- a/src/core/features/enrol/services/enrol-delegate.ts +++ b/src/core/features/enrol/services/enrol-delegate.ts @@ -89,9 +89,9 @@ export interface CoreEnrolGuestHandler extends CoreEnrolHandler { * Check if the user can access to the course. * * @param method Course enrolment method. - * @returns Whether the user can access. + * @returns Access info. */ - canAccess(method: CoreEnrolEnrolmentMethod): Promise; + canAccess(method: CoreEnrolEnrolmentMethod): Promise; /** * Validates the access to a course @@ -100,7 +100,6 @@ export interface CoreEnrolGuestHandler extends CoreEnrolHandler { * @returns Whether the user has validated the access to the course. */ validateAccess(method: CoreEnrolEnrolmentMethod): Promise; - } /** @@ -112,6 +111,14 @@ export interface CoreEnrolInfoIcon { className?: string; } +/** + * Data about course access using a GUEST enrolment method. + */ +export interface CoreEnrolCanAccessData { + canAccess: boolean; // Whether the user can access the course using this enrolment method. + requiresUserInput?: boolean; // Whether the user needs to input some data to access the course using this enrolment method. +} + /** * Delegate to register enrol handlers. */ @@ -193,16 +200,16 @@ export class CoreEnrolDelegateService extends CoreDelegate { * Check if the user can access to the course. * * @param method Course enrolment method. - * @returns Whether the user can access. + * @returns Access data. */ - async canAccess(method: CoreEnrolEnrolmentMethod): Promise { - const canAccess = await this.executeFunctionOnEnabled( + async canAccess(method: CoreEnrolEnrolmentMethod): Promise { + const canAccess = await this.executeFunctionOnEnabled( method.type, 'canAccess', [method], ); - return !!canAccess; + return canAccess ?? { canAccess: false }; } /** diff --git a/src/core/features/siteplugins/classes/handlers/enrol-handler.ts b/src/core/features/siteplugins/classes/handlers/enrol-handler.ts index f387804bb2b..188e63e8506 100644 --- a/src/core/features/siteplugins/classes/handlers/enrol-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/enrol-handler.ts @@ -14,7 +14,12 @@ import { CoreLogger } from '@singletons/logger'; import { CoreSitePluginsBaseHandler } from './base-handler'; -import { CoreEnrolAction, CoreEnrolHandler, CoreEnrolInfoIcon } from '@features/enrol/services/enrol-delegate'; +import { + CoreEnrolAction, + CoreEnrolCanAccessData, + CoreEnrolHandler, + CoreEnrolInfoIcon, +} from '@features/enrol/services/enrol-delegate'; import { CoreSitePluginsContent, CoreSitePluginsEnrolHandlerData } from '@features/siteplugins/services/siteplugins'; /** @@ -61,9 +66,9 @@ export class CoreSitePluginsEnrolHandler extends CoreSitePluginsBaseHandler impl /** * @inheritdoc */ - async canAccess(): Promise { + async canAccess(): Promise { // To be overridden. - return false; + return { canAccess: false }; } /**