Skip to content

Commit

Permalink
MOBILE-4323 enrol: Check all methods in courseUsesGuestAccessInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
dpalou authored and crazyserver committed Aug 23, 2023
1 parent b019e15 commit 3ece458
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 31 deletions.
14 changes: 11 additions & 3 deletions src/addons/enrol/guest/services/enrol-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -66,10 +71,13 @@ export class AddonEnrolGuestHandlerService implements CoreEnrolGuestHandler {
/**
* @inheritdoc
*/
async canAccess(method: CoreEnrolEnrolmentMethod): Promise<boolean> {
async canAccess(method: CoreEnrolEnrolmentMethod): Promise<CoreEnrolCanAccessData> {
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,
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ 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);
if (canAccess) {
const result = await CoreEnrolDelegate.canAccess(method);
if (result.canAccess) {
this.canAccessCourse = true;
}
});
Expand Down
55 changes: 40 additions & 15 deletions src/core/features/course/services/course-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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<CoreCourseGuestAccessInfo> {
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.
}
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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;
};
2 changes: 1 addition & 1 deletion src/core/features/courses/services/handlers/course-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });

Expand Down
21 changes: 14 additions & 7 deletions src/core/features/enrol/services/enrol-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean>;
canAccess(method: CoreEnrolEnrolmentMethod): Promise<CoreEnrolCanAccessData>;

/**
* Validates the access to a course
Expand All @@ -100,7 +100,6 @@ export interface CoreEnrolGuestHandler extends CoreEnrolHandler {
* @returns Whether the user has validated the access to the course.
*/
validateAccess(method: CoreEnrolEnrolmentMethod): Promise<boolean>;

}

/**
Expand All @@ -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.
*/
Expand Down Expand Up @@ -193,16 +200,16 @@ export class CoreEnrolDelegateService extends CoreDelegate<CoreEnrolHandler> {
* 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<boolean> {
const canAccess = await this.executeFunctionOnEnabled<boolean>(
async canAccess(method: CoreEnrolEnrolmentMethod): Promise<CoreEnrolCanAccessData> {
const canAccess = await this.executeFunctionOnEnabled<CoreEnrolCanAccessData>(
method.type,
'canAccess',
[method],
);

return !!canAccess;
return canAccess ?? { canAccess: false };
}

/**
Expand Down
11 changes: 8 additions & 3 deletions src/core/features/siteplugins/classes/handlers/enrol-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand Down Expand Up @@ -61,9 +66,9 @@ export class CoreSitePluginsEnrolHandler extends CoreSitePluginsBaseHandler impl
/**
* @inheritdoc
*/
async canAccess(): Promise<boolean> {
async canAccess(): Promise<CoreEnrolCanAccessData> {
// To be overridden.
return false;
return { canAccess: false };
}

/**
Expand Down

0 comments on commit 3ece458

Please sign in to comment.