forked from CIT/Vmeda.Online
335 lines
11 KiB
TypeScript
335 lines
11 KiB
TypeScript
// (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 { Injectable } from '@angular/core';
|
|
import { CoreError } from '@classes/errors/error';
|
|
import { CoreWSError } from '@classes/errors/wserror';
|
|
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
|
import { CoreNavigator } from '@services/navigator';
|
|
import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
|
|
import { CoreWSExternalWarning } from '@services/ws';
|
|
import { makeSingleton } from '@singletons';
|
|
import { POLICY_PAGE_NAME, SITE_POLICY_PAGE_NAME } from '../constants';
|
|
import { CoreSite } from '@classes/sites/site';
|
|
|
|
/**
|
|
* Service that provides some common features regarding policies.
|
|
*/
|
|
@Injectable({ providedIn: 'root' })
|
|
export class CorePolicyService {
|
|
|
|
protected static readonly ROOT_CACHE_KEY = 'CorePolicy:';
|
|
|
|
/**
|
|
* Accept all mandatory site policies.
|
|
*
|
|
* @param siteId Site ID. If not defined, current site.
|
|
* @returns Promise resolved if success, rejected if failure.
|
|
*/
|
|
async acceptMandatorySitePolicies(siteId?: string): Promise<void> {
|
|
const site = await CoreSites.getSite(siteId);
|
|
|
|
const result = await site.write<CorePolicyAgreeSitePolicyResult>('core_user_agree_site_policy', {});
|
|
|
|
if (result.status) {
|
|
return;
|
|
}
|
|
|
|
if (!result.warnings?.length) {
|
|
throw new CoreError('Cannot agree site policy');
|
|
}
|
|
|
|
// Check if there is a warning 'alreadyagreed'.
|
|
const found = result.warnings.some((warning) => warning.warningcode === 'alreadyagreed');
|
|
if (found) {
|
|
// Policy already agreed, treat it as a success.
|
|
return;
|
|
}
|
|
|
|
// Another warning, reject.
|
|
throw new CoreWSError(result.warnings[0]);
|
|
}
|
|
|
|
/**
|
|
* Get the URL to view the site policy (or all the site policies in a single page if there's more than one).
|
|
*
|
|
* @param siteId Site ID. If not defined, current site.
|
|
* @returns Promise resolved with the site policy.
|
|
*/
|
|
async getSitePoliciesURL(siteId?: string): Promise<string> {
|
|
const site = await CoreSites.getSite(siteId);
|
|
|
|
let sitePolicy: string | undefined;
|
|
|
|
try {
|
|
// Try to get the latest config, maybe the site policy was just added or has changed.
|
|
sitePolicy = await site.getConfig('sitepolicy', true);
|
|
} catch (error) {
|
|
// Cannot get config, try to get the site policy using signup settings.
|
|
const settings = await CoreLoginHelper.getEmailSignupSettings(site.getURL());
|
|
|
|
sitePolicy = settings.sitepolicy;
|
|
}
|
|
|
|
if (!sitePolicy) {
|
|
throw new CoreError('Cannot retrieve site policy');
|
|
}
|
|
|
|
return sitePolicy;
|
|
}
|
|
|
|
/**
|
|
* Get the next policies to accept.
|
|
*
|
|
* @param options Options
|
|
* @returns Next pending policies
|
|
*/
|
|
async getNextPendingPolicies(options: CoreSitesCommonWSOptions = {}): Promise<CorePolicySitePolicy[]> {
|
|
const policies = await this.getUserAcceptances(options);
|
|
|
|
const pendingPolicies: CorePolicySitePolicy[] = [];
|
|
|
|
for (const i in policies) {
|
|
const policy = policies[i];
|
|
const hasAccepted = policy.acceptance?.status === 1;
|
|
const hasDeclined = policy.acceptance?.status === 0;
|
|
|
|
if (hasAccepted || (hasDeclined && policy.optional === 1)) {
|
|
// Policy already answered, ignore.
|
|
continue;
|
|
}
|
|
|
|
if (policy.agreementstyle === CorePolicyAgreementStyle.OwnPage) {
|
|
// Policy needs to be accepted on its own page, it's the next policy to accept.
|
|
return [policy];
|
|
}
|
|
|
|
pendingPolicies.push(policy);
|
|
}
|
|
|
|
return pendingPolicies;
|
|
}
|
|
|
|
/**
|
|
* Get user acceptances.
|
|
*
|
|
* @param options Options
|
|
* @returns List of policies with their acceptances.
|
|
*/
|
|
async getUserAcceptances(options: CorePolicyGetAcceptancesOptions = {}): Promise<CorePolicySitePolicy[]> {
|
|
const site = await CoreSites.getSite(options.siteId);
|
|
|
|
const userId = options.userId || site.getUserId();
|
|
const data: CorePolicyGetUserAcceptancesWSParams = {
|
|
userid: userId,
|
|
};
|
|
const preSets = {
|
|
cacheKey: this.getUserAcceptancesCacheKey(userId),
|
|
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
|
...CoreSites.getReadingStrategyPreSets(options.readingStrategy),
|
|
};
|
|
|
|
const response = await site.read<CorePolicyGetUserAcceptancesWSResponse>('tool_policy_get_user_acceptances', data, preSets);
|
|
if (response.warnings?.length) {
|
|
throw new CoreWSError(response.warnings[0]);
|
|
}
|
|
|
|
return response.policies;
|
|
}
|
|
|
|
/**
|
|
* Get the cache key for the get user acceptances call.
|
|
*
|
|
* @param userId ID of the user to get the badges from.
|
|
* @returns Cache key.
|
|
*/
|
|
protected getUserAcceptancesCacheKey(userId: number): string {
|
|
return CorePolicyService.ROOT_CACHE_KEY + 'userAcceptances:' + userId;
|
|
}
|
|
|
|
/**
|
|
* Open page to accept site policies.
|
|
*
|
|
* @param siteId Site ID. If not defined, current site.
|
|
*/
|
|
goToAcceptSitePolicies(siteId?: string): void {
|
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
|
if (!siteId || siteId != CoreSites.getCurrentSiteId()) {
|
|
// Only current site allowed.
|
|
return;
|
|
}
|
|
|
|
const routePath = `/${POLICY_PAGE_NAME}/${SITE_POLICY_PAGE_NAME}`;
|
|
|
|
// If current page is already site policy, stop.
|
|
if (CoreNavigator.isCurrent(routePath)) {
|
|
return;
|
|
}
|
|
|
|
CoreNavigator.navigate(routePath, { params: { siteId }, reset: true });
|
|
}
|
|
|
|
/**
|
|
* Invalidate acceptances WS call.
|
|
*
|
|
* @param options Options.
|
|
* @returns Promise resolved when data is invalidated.
|
|
*/
|
|
async invalidateAcceptances(options: {userId?: number; siteId?: string} = {}): Promise<void> {
|
|
const site = await CoreSites.getSite(options.siteId);
|
|
|
|
await site.invalidateWsCacheForKey(this.getUserAcceptancesCacheKey(options.userId || site.getUserId()));
|
|
}
|
|
|
|
/**
|
|
* Check whether a site allows getting and setting acceptances.
|
|
*
|
|
* @param siteId Site Id.
|
|
* @returns Whether the site allows getting and setting acceptances.
|
|
*/
|
|
async isManageAcceptancesAvailable(siteId?: string): Promise<boolean> {
|
|
const site = await CoreSites.getSite(siteId);
|
|
|
|
return site.wsAvailable('tool_policy_get_user_acceptances') && site.wsAvailable('tool_policy_set_acceptances_status');
|
|
}
|
|
|
|
/**
|
|
* Set user acceptances.
|
|
*
|
|
* @param policies Policies to accept or decline. Keys are policy version id, value is whether to accept or decline.
|
|
* @param siteId Site ID. If not defined, current site.
|
|
* @returns New value for policyagreed.
|
|
*/
|
|
async setUserAcceptances(policies: Record<number, number>, siteId?: string): Promise<number> {
|
|
const site = await CoreSites.getSite(siteId);
|
|
|
|
const data: CorePolicySetAcceptancesWSParams = {
|
|
userid: site.getUserId(),
|
|
policies: Object.keys(policies).map((versionId) => ({
|
|
versionid: Number(versionId),
|
|
status: policies[versionId],
|
|
})),
|
|
};
|
|
|
|
const response = await site.write<CorePolicySetAcceptancesWSResponse>('tool_policy_set_acceptances_status', data);
|
|
if (response.warnings?.length) {
|
|
throw new CoreWSError(response.warnings[0]);
|
|
}
|
|
|
|
return response.policyagreed;
|
|
}
|
|
|
|
}
|
|
|
|
export const CorePolicy = makeSingleton(CorePolicyService);
|
|
|
|
/**
|
|
* Options for get policy acceptances.
|
|
*/
|
|
type CorePolicyGetAcceptancesOptions = CoreSitesCommonWSOptions & {
|
|
userId?: number; // User ID. If not defined, current user.
|
|
};
|
|
|
|
/**
|
|
* Result of WS core_user_agree_site_policy.
|
|
*/
|
|
type CorePolicyAgreeSitePolicyResult = {
|
|
status: boolean; // Status: true only if we set the policyagreed to 1 for the user.
|
|
warnings?: CoreWSExternalWarning[];
|
|
};
|
|
|
|
/**
|
|
* Params of tool_policy_get_user_acceptances WS.
|
|
*/
|
|
type CorePolicyGetUserAcceptancesWSParams = {
|
|
userid?: number; // The user id we want to retrieve the acceptances.
|
|
};
|
|
|
|
/**
|
|
* Data returned by tool_policy_get_user_acceptances WS.
|
|
*/
|
|
type CorePolicyGetUserAcceptancesWSResponse = {
|
|
policies: CorePolicySitePolicy[];
|
|
warnings?: CoreWSExternalWarning[];
|
|
};
|
|
|
|
/**
|
|
* Policy data returned by tool_policy_get_user_acceptances WS.
|
|
*/
|
|
export type CorePolicySitePolicy = {
|
|
policyid: number; // The policy id.
|
|
versionid: number; // The policy version id.
|
|
agreementstyle: number; // The policy agreement style. 0: consent page, 1: own page.
|
|
optional: number; // Whether the policy is optional. 0: compulsory, 1: optional.
|
|
revision: string; // The policy revision.
|
|
status: number; // The policy status. 0: draft, 1: active, 2: archived.
|
|
name: string; // The policy name.
|
|
summary?: string; // The policy summary.
|
|
summaryformat: number; // Summary format (1 = HTML, 0 = MOODLE, 2 = PLAIN, or 4 = MARKDOWN).
|
|
content?: string; // The policy content.
|
|
contentformat: number; // Content format (1 = HTML, 0 = MOODLE, 2 = PLAIN, or 4 = MARKDOWN).
|
|
acceptance?: CorePolicySitePolicyAcceptance; // Acceptance status for the given user.
|
|
canaccept: boolean; // Whether the policy can be accepted.
|
|
candecline: boolean; // Whether the policy can be declined.
|
|
canrevoke: boolean; // Whether the policy can be revoked.
|
|
};
|
|
|
|
/**
|
|
* Policy acceptance data returned by tool_policy_get_user_acceptances WS.
|
|
*/
|
|
export type CorePolicySitePolicyAcceptance = {
|
|
status: number; // The acceptance status. 0: declined, 1: accepted.
|
|
lang: string; // The policy lang.
|
|
timemodified: number; // The time the acceptance was set.
|
|
usermodified: number; // The user who accepted.
|
|
note?: string; // The policy note/remarks.
|
|
modfullname?: string; // The fullname who accepted on behalf.
|
|
};
|
|
|
|
/**
|
|
* Params of tool_policy_set_acceptances_status WS.
|
|
*/
|
|
type CorePolicySetAcceptancesWSParams = {
|
|
policies: {
|
|
versionid: number; // The policy version id.
|
|
status: number; // The policy acceptance status. 0: decline, 1: accept.
|
|
}[]; // Policies acceptances for the given user.
|
|
userid?: number; // The user id we want to set the acceptances. Default is the current user.
|
|
};
|
|
|
|
/**
|
|
* Data returned by tool_policy_set_acceptances_status WS.
|
|
*/
|
|
type CorePolicySetAcceptancesWSResponse = {
|
|
policyagreed: number; // Whether the user has provided acceptance to all current site policies. 1 if yes, 0 if not.
|
|
warnings?: CoreWSExternalWarning[];
|
|
};
|
|
|
|
/**
|
|
* Agreement style.
|
|
*/
|
|
export enum CorePolicyAgreementStyle {
|
|
ConsentPage = 0, // Policy to be accepted together with others on the consent page.
|
|
OwnPage = 1, // Policy to be accepted on its own page before reaching the consent page.
|
|
}
|
|
|
|
/**
|
|
* Status of a policy.
|
|
*/
|
|
export enum CorePolicyStatus {
|
|
Draft = 0,
|
|
Active = 1,
|
|
Archived = 2,
|
|
}
|