Vmeda.Online/src/core/features/user/services/user.ts

1170 lines
39 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 { CoreNetwork } from '@services/network';
import { CoreFilepool } from '@services/filepool';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreUserOffline } from './user-offline';
import { CoreLogger } from '@singletons/logger';
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
import { makeSingleton, Translate } from '@singletons';
import { CoreEvents, CoreEventSiteData, CoreEventUserDeletedData, CoreEventUserSuspendedData } from '@singletons/events';
import { CoreStatusWithWarningsWSResponse, CoreWSExternalWarning } from '@services/ws';
import { CoreError } from '@classes/errors/error';
import { USERS_TABLE_NAME, CoreUserDBRecord } from './database/user';
import { CoreUserHelper } from './user-helper';
import { CoreUrlUtils } from '@services/utils/url';
const ROOT_CACHE_KEY = 'mmUser:';
declare module '@singletons/events' {
/**
* Augment CoreEventsData interface with events specific to this service.
*
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
*/
export interface CoreEventsData {
[USER_PROFILE_REFRESHED]: CoreUserProfileRefreshedData;
[USER_PROFILE_PICTURE_UPDATED]: CoreUserProfilePictureUpdatedData;
}
}
/**
* Profile picture updated event.
*/
export const USER_PROFILE_REFRESHED = 'CoreUserProfileRefreshed';
/**
* Profile picture updated event.
*/
export const USER_PROFILE_PICTURE_UPDATED = 'CoreUserProfilePictureUpdated';
/**
* Value set in timezone when using the server's timezone.
*/
export const USER_PROFILE_SERVER_TIMEZONE = '99';
/**
* Fake ID for a "no reply" user.
*/
export const USER_NOREPLY_USER = -10;
/**
* Service to provide user functionalities.
*/
@Injectable({ providedIn: 'root' })
export class CoreUserProvider {
static readonly PARTICIPANTS_LIST_LIMIT = 50; // Max of participants to retrieve in each WS call.
protected logger: CoreLogger;
constructor() {
this.logger = CoreLogger.getInstance('CoreUserProvider');
CoreEvents.on(CoreEvents.USER_DELETED, data => this.handleUserKickedOutEvent(data));
CoreEvents.on(CoreEvents.USER_SUSPENDED, data => this.handleUserKickedOutEvent(data));
CoreEvents.on(CoreEvents.USER_NO_LOGIN, data => this.handleUserKickedOutEvent(data));
}
/**
* Check if WS to search participants is available in site.
*
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved with boolean: whether it's available.
* @since 3.8
*/
async canSearchParticipants(siteId?: string): Promise<boolean> {
const site = await CoreSites.getSite(siteId);
return this.canSearchParticipantsInSite(site);
}
/**
* Check if WS to search participants is available in site.
*
* @param site Site. If not defined, current site.
* @returns Whether it's available.
* @since 3.8
*/
canSearchParticipantsInSite(site?: CoreSite): boolean {
site = site || CoreSites.getCurrentSite();
return !!site?.wsAvailable('core_enrol_search_users');
}
/**
* Check if WS to update profile picture is available in site.
*
* @returns Promise resolved with boolean: whether it's available.
* @deprecated since 4.0.
*/
async canUpdatePicture(): Promise<boolean> {
return true;
}
/**
* Check if WS to search participants is available in site.
*
* @returns Whether it's available.
* @deprecated since 4.0.
*/
canUpdatePictureInSite(): boolean {
return true;
}
/**
* Change the given user profile picture.
*
* @param draftItemId New picture draft item id.
* @param userId User ID.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolve with the new profileimageurl
*/
async changeProfilePicture(draftItemId: number, userId: number, siteId?: string): Promise<string> {
const site = await CoreSites.getSite(siteId);
const params: CoreUserUpdatePictureWSParams = {
draftitemid: draftItemId,
delete: false,
userid: userId,
};
const result = await site.write<CoreUserUpdatePictureWSResponse>('core_user_update_picture', params);
if (!result.success || !result.profileimageurl) {
return Promise.reject(null);
}
return result.profileimageurl;
}
/**
* Handle an event where a user was kicked out of the site.
*
* @param data Event data.
*/
async handleUserKickedOutEvent(
data: CoreEventSiteData & (CoreEventUserDeletedData | CoreEventUserSuspendedData),
): Promise<void> {
// Search for userid in params.
let userId = 0;
if (data.params.userid) {
userId = data.params.userid;
} else if (data.params.userids) {
userId = data.params.userids[0];
} else if (data.params.field === 'id' && data.params.values && data.params.values.length) {
userId = data.params.values[0];
} else if (data.params.userlist && data.params.userlist.length) {
userId = data.params.userlist[0].userid;
}
if (userId > 0) {
await this.deleteStoredUser(userId, data.siteId);
}
}
/**
* Store user basic information in local DB to be retrieved if the WS call fails.
*
* @param userId User ID.
* @param siteId ID of the site. If not defined, use current site.
* @returns Promise resolve when the user is deleted.
*/
async deleteStoredUser(userId: number, siteId?: string): Promise<void> {
if (isNaN(userId)) {
throw new CoreError('Invalid user ID.');
}
const site = await CoreSites.getSite(siteId);
await Promise.all([
this.invalidateUserCache(userId, site.getId()),
site.getDb().deleteRecords(USERS_TABLE_NAME, { id: userId }),
]);
}
/**
* Get participants for a certain course.
*
* @param courseId ID of the course.
* @param limitFrom Position of the first participant to get.
* @param limitNumber Number of participants to get.
* @param siteId Site Id. If not defined, use current site.
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
* @returns Promise resolved when the participants are retrieved.
*/
async getParticipants(
courseId: number,
limitFrom: number = 0,
limitNumber: number = CoreUserProvider.PARTICIPANTS_LIST_LIMIT,
siteId?: string,
ignoreCache?: boolean,
): Promise<{participants: CoreUserParticipant[]; canLoadMore: boolean}> {
const site = await CoreSites.getSite(siteId);
this.logger.debug(`Get participants for course '${courseId}' starting at '${limitFrom}'`);
const params: CoreEnrolGetEnrolledUsersWSParams = {
courseid: courseId,
options: [
{
name: 'limitfrom',
value: String(limitFrom),
},
{
name: 'limitnumber',
value: String(limitNumber),
},
{
name: 'sortby',
value: 'siteorder',
},
],
};
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getParticipantsListCacheKey(courseId),
updateFrequency: CoreSite.FREQUENCY_RARELY,
};
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
const users = await site.read<CoreEnrolGetEnrolledUsersWSResponse>('core_enrol_get_enrolled_users', params, preSets);
const canLoadMore = users.length >= limitNumber;
this.storeUsers(users, siteId);
return { participants: users, canLoadMore: canLoadMore };
}
/**
* Get cache key for participant list WS calls.
*
* @param courseId Course ID.
* @returns Cache key.
*/
protected getParticipantsListCacheKey(courseId: number): string {
return ROOT_CACHE_KEY + 'list:' + courseId;
}
/**
* Get user profile. The type of profile retrieved depends on the params.
*
* @param userId User's ID.
* @param courseId Course ID to get course profile, undefined or 0 to get site profile.
* @param forceLocal True to retrieve the user data from local DB, false to retrieve it from WS.
* @param siteId ID of the site. If not defined, use current site.
* @returns Promise resolved with the user data.
*/
async getProfile(
userId: number,
courseId?: number,
forceLocal: boolean = false,
siteId?: string,
): Promise<CoreUserProfile> {
siteId = siteId || CoreSites.getCurrentSiteId();
if (forceLocal) {
try {
return await this.getUserFromLocalDb(userId, siteId);
} catch {
return this.getUserFromWS(userId, courseId, siteId);
}
}
try {
return await this.getUserFromWS(userId, courseId, siteId);
} catch (error) {
try {
return await this.getUserFromLocalDb(userId, siteId);
} catch {
throw error;
}
}
}
/**
* Get cache key for a user WS call.
*
* @param userId User ID.
* @returns Cache key.
*/
protected getUserCacheKey(userId: number): string {
return ROOT_CACHE_KEY + 'data:' + userId;
}
/**
* Get user basic information from local DB.
*
* @param userId User ID.
* @param siteId ID of the site. If not defined, use current site.
* @returns Promise resolve when the user is retrieved.
*/
protected async getUserFromLocalDb(userId: number, siteId?: string): Promise<CoreUserDBRecord> {
const site = await CoreSites.getSite(siteId);
return site.getDb().getRecord(USERS_TABLE_NAME, { id: userId });
}
/**
* Get a user fullname, using a default text if user not found.
*
* @param userId User ID.
* @param courseId Course ID.
* @param siteId Site ID.
* @returns Promise resolved with user name.
*/
async getUserFullNameWithDefault(userId: number, courseId?: number, siteId?: string): Promise<string> {
try {
const user = await CoreUser.getProfile(userId, courseId, true, siteId);
return user.fullname;
} catch {
return Translate.instant('core.user.userwithid', { id: userId });
}
}
/**
* Get user profile from WS.
*
* @param userId User ID.
* @param courseId Course ID to get course profile, undefined or 0 to get site profile.
* @param siteId ID of the site. If not defined, use current site.
* @returns Promise resolve when the user is retrieved.
*/
protected async getUserFromWS(
userId: number,
courseId?: number,
siteId?: string,
): Promise<CoreUserCourseProfile | CoreUserData> {
const site = await CoreSites.getSite(siteId);
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getUserCacheKey(userId),
updateFrequency: CoreSite.FREQUENCY_RARELY,
};
let users: CoreUserData[] | CoreUserCourseProfile[] | undefined;
// Determine WS and data to use.
if (courseId && courseId != site.getSiteHomeId()) {
this.logger.debug(`Get participant with ID '${userId}' in course '${courseId}`);
const params: CoreUserGetCourseUserProfilesWSParams = {
userlist: [
{
userid: userId,
courseid: courseId,
},
],
};
users = await site.read<CoreUserGetCourseUserProfilesWSResponse>('core_user_get_course_user_profiles', params, preSets);
} else {
this.logger.debug(`Get user with ID '${userId}'`);
const params: CoreUserGetUsersByFieldWSParams = {
field: 'id',
values: [String(userId)],
};
users = await site.read<CoreUserGetUsersByFieldWSResponse>('core_user_get_users_by_field', params, preSets);
}
if (users.length == 0) {
// Shouldn't happen.
throw new CoreError('Cannot retrieve user info.');
}
const user: CoreUserData | CoreUserCourseProfile = users[0];
if (user.country) {
user.country = CoreUtils.getCountryName(user.country);
}
this.storeUser(user.id, user.fullname, user.profileimageurl);
return user;
}
/**
* Get a user preference (online or offline).
*
* @param name Name of the preference.
* @param siteId Site Id. If not defined, use current site.
* @returns Preference value or null if preference not set.
*/
async getUserPreference(name: string, siteId?: string): Promise<string | null> {
siteId = siteId || CoreSites.getCurrentSiteId();
const preference = await CoreUtils.ignoreErrors(CoreUserOffline.getPreference(name, siteId));
if (preference && !CoreNetwork.isOnline()) {
// Offline, return stored value.
return preference.value;
}
const wsValue = await this.getUserPreferenceOnline(name, siteId);
if (preference && preference.value != preference.onlinevalue && preference.onlinevalue == wsValue) {
// Sync is pending for this preference, return stored value.
return preference.value;
}
if (!wsValue) {
return null;
}
await CoreUserOffline.setPreference(name, wsValue, wsValue);
return wsValue;
}
/**
* Get cache key for a user preference WS call.
*
* @param name Preference name.
* @returns Cache key.
*/
protected getUserPreferenceCacheKey(name: string): string {
return ROOT_CACHE_KEY + 'preference:' + name;
}
/**
* Get a user preference online.
*
* @param name Name of the preference.
* @param siteId Site Id. If not defined, use current site.
* @returns Preference value or null if preference not set.
*/
async getUserPreferenceOnline(name: string, siteId?: string): Promise<string | null> {
const site = await CoreSites.getSite(siteId);
const params: CoreUserGetUserPreferencesWSParams = {
name,
};
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getUserPreferenceCacheKey(name),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
};
const result = await site.read<CoreUserGetUserPreferencesWSResponse>('core_user_get_user_preferences', params, preSets);
return result.preferences[0] ? result.preferences[0].value : null;
}
/**
* Invalidates user WS calls.
*
* @param userId User ID.
* @param siteId Site Id. If not defined, use current site.
* @returns Promise resolved when the data is invalidated.
*/
async invalidateUserCache(userId: number, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
await site.invalidateWsCacheForKey(this.getUserCacheKey(userId));
}
/**
* Invalidates participant list for a certain course.
*
* @param courseId Course ID.
* @param siteId Site Id. If not defined, use current site.
* @returns Promise resolved when the list is invalidated.
*/
async invalidateParticipantsList(courseId: number, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
await site.invalidateWsCacheForKey(this.getParticipantsListCacheKey(courseId));
}
/**
* Invalidate user preference.
*
* @param name Name of the preference.
* @param siteId Site Id. If not defined, use current site.
* @returns Promise resolved when the data is invalidated.
*/
async invalidateUserPreference(name: string, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
await site.invalidateWsCacheForKey(this.getUserPreferenceCacheKey(name));
}
/**
* Check if course participants is disabled in a certain site.
*
* @param siteId Site Id. If not defined, use current site.
* @returns Promise resolved with true if disabled, rejected or resolved with false otherwise.
*/
async isParticipantsDisabled(siteId?: string): Promise<boolean> {
const site = await CoreSites.getSite(siteId);
return this.isParticipantsDisabledInSite(site);
}
/**
* Check if course participants is disabled in a certain site.
*
* @param site Site. If not defined, use current site.
* @returns Whether it's disabled.
*/
isParticipantsDisabledInSite(site?: CoreSite): boolean {
site = site || CoreSites.getCurrentSite();
return !!site?.isFeatureDisabled('CoreCourseOptionsDelegate_CoreUserParticipants');
}
/**
* Returns whether or not participants is enabled for a certain course.
*
* @param courseId Course ID.
* @param siteId Site Id. If not defined, use current site.
* @returns Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise.
*/
isPluginEnabledForCourse(courseId: number, siteId?: string): Promise<boolean> {
if (!courseId) {
throw new CoreError('Invalid course ID.');
}
// Retrieving one participant will fail if browsing users is disabled by capabilities.
return CoreUtils.promiseWorks(this.getParticipants(courseId, 0, 1, siteId));
}
/**
* Check if update profile picture is disabled in a certain site.
*
* @param site Site. If not defined, use current site.
* @returns True if disabled, false otherwise.
*/
isUpdatePictureDisabledInSite(site?: CoreSite): boolean {
site = site || CoreSites.getCurrentSite();
return !!site?.isFeatureDisabled('CoreUserDelegate_picture');
}
/**
* Log User Profile View in Moodle.
*
* @param userId User ID.
* @param courseId Course ID.
* @returns Promise resolved when done.
*/
async logView(userId: number, courseId?: number, siteId?: string): Promise<CoreStatusWithWarningsWSResponse> {
const site = await CoreSites.getSite(siteId);
const params: CoreUserViewUserProfileWSParams = {
userid: userId,
};
if (courseId) {
params.courseid = courseId;
}
return site.write('core_user_view_user_profile', params);
}
/**
* Log Participants list view in Moodle.
*
* @param courseId Course ID.
* @returns Promise resolved when done.
*/
async logParticipantsView(courseId: number, siteId?: string): Promise<CoreStatusWithWarningsWSResponse> {
const site = await CoreSites.getSite(siteId);
const params: CoreUserViewUserListWSParams = {
courseid: courseId,
};
return site.write('core_user_view_user_list', params);
}
/**
* Prefetch user profiles and their images from a certain course. It prevents duplicates.
*
* @param userIds List of user IDs.
* @param courseId Course the users belong to.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when prefetched.
*/
async prefetchProfiles(userIds: number[], courseId?: number, siteId?: string): Promise<void> {
siteId = siteId || CoreSites.getCurrentSiteId();
if (!siteId) {
return;
}
const treated: Record<string, boolean> = {};
await Promise.all(userIds.map(async (userId) => {
if (userId === null || !siteId) {
return;
}
userId = Number(userId); // Make sure it's a number.
// Prevent repeats and errors.
if (isNaN(userId) || treated[userId] || userId <= 0) {
return;
}
treated[userId] = true;
try {
const profile = await this.getProfile(userId, courseId, false, siteId);
if (profile.profileimageurl) {
await CoreFilepool.addToQueueByUrl(siteId, profile.profileimageurl);
}
} catch (error) {
this.logger.warn(`Ignore error when prefetching user ${userId}`, error);
}
}));
}
/**
* Prefetch user avatars. It prevents duplicates.
*
* @param entries List of entries that have the images.
* @param propertyName The name of the property that contains the image.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when prefetched.
*/
async prefetchUserAvatars(entries: Record<string, unknown>[], propertyName: string, siteId?: string): Promise<void> {
siteId = siteId || CoreSites.getCurrentSiteId();
if (!siteId) {
return;
}
const treated: Record<string, boolean> = {};
const promises = entries.map(async (entry) => {
const imageUrl = <string> entry[propertyName];
if (!imageUrl || treated[imageUrl] || !siteId) {
// It doesn't have an image or it has already been treated.
return;
}
// Do not prefetch when initials are set and image is default.
if ('firstname' in entry || 'lastname' in entry) {
const initials = CoreUserHelper.getUserInitials(entry);
if (initials && imageUrl && CoreUrlUtils.isThemeImageUrl(imageUrl)) {
return;
}
}
treated[imageUrl] = true;
try {
await CoreFilepool.addToQueueByUrl(siteId, imageUrl);
} catch (ex) {
this.logger.warn(`Ignore error when prefetching user avatar ${imageUrl}`, entry, ex);
}
});
await Promise.all(promises);
}
/**
* Search participants in a certain course.
*
* @param courseId ID of the course.
* @param search The string to search.
* @param searchAnywhere Whether to find a match anywhere or only at the beginning.
* @param page Page to get.
* @param perPage Number of participants to get.
* @param siteId Site Id. If not defined, use current site.
* @returns Promise resolved when the participants are retrieved.
* @since 3.8
*/
async searchParticipants(
courseId: number,
search: string,
searchAnywhere: boolean = true,
page: number = 0,
perPage: number = CoreUserProvider.PARTICIPANTS_LIST_LIMIT,
siteId?: string,
): Promise<{participants: CoreUserData[]; canLoadMore: boolean}> {
const site = await CoreSites.getSite(siteId);
const params: CoreEnrolSearchUsersWSParams = {
courseid: courseId,
search: search,
searchanywhere: !!searchAnywhere,
page: page,
perpage: perPage,
};
const preSets: CoreSiteWSPreSets = {
getFromCache: false, // Always try to get updated data. If it fails, it will get it from cache.
};
const users = await site.read<CoreEnrolSearchUsersWSResponse>('core_enrol_search_users', params, preSets);
const canLoadMore = users.length >= perPage;
this.storeUsers(users, siteId);
return { participants: users, canLoadMore: canLoadMore };
}
/**
* Store user basic information in local DB to be retrieved if the WS call fails.
*
* @param userId User ID.
* @param fullname User full name.
* @param avatar User avatar URL.
* @param siteId ID of the site. If not defined, use current site.
* @returns Promise resolve when the user is stored.
*/
protected async storeUser(userId: number, fullname: string, avatar?: string, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
const userRecord: CoreUserDBRecord = {
id: userId,
fullname: fullname,
profileimageurl: avatar,
};
await site.getDb().insertRecord(USERS_TABLE_NAME, userRecord);
}
/**
* Store users basic information in local DB.
*
* @param users Users to store.
* @param siteId ID of the site. If not defined, use current site.
* @returns Promise resolve when the user is stored.
*/
async storeUsers(users: CoreUserBasicData[], siteId?: string): Promise<void> {
await Promise.all(users.map((user) => {
if (!user.id || isNaN(Number(user.id))) {
return;
}
return this.storeUser(Number(user.id), user.fullname, user.profileimageurl, siteId);
}));
}
/**
* Set a user preference (online or offline).
*
* @param name Name of the preference.
* @param value Value of the preference.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved on success.
*/
async setUserPreference(name: string, value: string, siteId?: string): Promise<void> {
siteId = siteId || CoreSites.getCurrentSiteId();
if (!CoreNetwork.isOnline()) {
// Offline, just update the preference.
return CoreUserOffline.setPreference(name, value);
}
try {
// Update the preference in the site.
const preferences = [
{ type: name, value },
];
await this.updateUserPreferences(preferences, undefined, undefined, siteId);
// Update preference and invalidate data.
await Promise.all([
CoreUserOffline.setPreference(name, value, value),
CoreUtils.ignoreErrors(this.invalidateUserPreference(name)),
]);
} catch (error) {
// Preference not saved online. Update the offline one.
await CoreUserOffline.setPreference(name, value);
}
}
/**
* Update a preference for a user.
*
* @param name Preference name.
* @param value Preference new value.
* @param userId User ID. If not defined, site's current user.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved if success.
*/
updateUserPreference(name: string, value: string | undefined, userId?: number, siteId?: string): Promise<void> {
const preferences = [
{
type: name,
value: value,
},
];
return this.updateUserPreferences(preferences, undefined, userId, siteId);
}
/**
* Update some preferences for a user.
*
* @param preferences List of preferences.
* @param disableNotifications Whether to disable all notifications. Undefined to not update this value.
* @param userId User ID. If not defined, site's current user.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved if success.
*/
async updateUserPreferences(
preferences: { type: string; value: string | undefined }[],
disableNotifications?: boolean,
userId?: number,
siteId?: string,
): Promise<void> {
const site = await CoreSites.getSite(siteId);
userId = userId || site.getUserId();
const params: CoreUserUpdateUserPreferencesWSParams = {
userid: userId,
preferences: preferences,
};
const preSets: CoreSiteWSPreSets = {
responseExpected: false,
};
if (disableNotifications !== undefined) {
params.emailstop = disableNotifications ? 1 : 0;
}
await site.write('core_user_update_user_preferences', params, preSets);
}
}
export const CoreUser = makeSingleton(CoreUserProvider);
/**
* Data passed to PROFILE_REFRESHED event.
*/
export type CoreUserProfileRefreshedData = {
courseId?: number; // Course the user profile belongs to.
userId: number; // User ID.
user?: CoreUserProfile; // User affected.
};
/**
* Data passed to PROFILE_PICTURE_UPDATED event.
*/
export type CoreUserProfilePictureUpdatedData = {
userId: number; // User ID.
picture: string | undefined; // New picture URL.
};
/**
* Basic data of a user.
*/
export type CoreUserBasicData = {
id: number; // ID of the user.
fullname: string; // The fullname of the user.
profileimageurl?: string; // User image profile URL - big version.
};
/**
* User preference.
*/
export type CoreUserPreference = {
name: string; // The name of the preference.
value: string; // The value of the preferenc.
};
/**
* User custom profile field.
*/
export type CoreUserProfileField = {
type: string; // The type of the custom field - text field, checkbox...
value: string; // The value of the custom field.
displayvalue?: string; // @since 4.2. Formatted value of the custom field.
name: string; // The name of the custom field.
shortname: string; // The shortname of the custom field - to be able to build the field class in the code.
};
/**
* User group.
*/
export type CoreUserGroup = {
id: number; // Group id.
name: string; // Group name.
description: string; // Group description.
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
};
/**
* User role.
*/
export type CoreUserRole = {
roleid: number; // Role id.
name: string; // Role name.
shortname: string; // Role shortname.
sortorder: number; // Role sortorder.
};
/**
* Basic data of a course the user is enrolled in.
*/
export type CoreUserEnrolledCourse = {
id: number; // Id of the course.
fullname: string; // Fullname of the course.
shortname: string; // Shortname of the course.
};
/**
* Common data returned by user_description function.
*/
export type CoreUserData = {
id: number; // ID of the user.
username?: string; // The username.
firstname?: string; // The first name(s) of the user.
lastname?: string; // The family name of the user.
fullname: string; // The fullname of the user.
email?: string; // An email address - allow email as root@localhost.
address?: string; // Postal address.
phone1?: string; // Phone 1.
phone2?: string; // Phone 2.
icq?: string; // Icq number.
skype?: string; // Skype id.
yahoo?: string; // Yahoo id.
aim?: string; // Aim id.
msn?: string; // Msn number.
department?: string; // Department.
institution?: string; // Institution.
idnumber?: string; // An arbitrary ID code number perhaps from the institution.
interests?: string; // User interests (separated by commas).
firstaccess?: number; // First access to the site (0 if never).
lastaccess?: number; // Last access to the site (0 if never).
auth?: string; // Auth plugins include manual, ldap, etc.
suspended?: boolean; // Suspend user account, either false to enable user login or true to disable it.
confirmed?: boolean; // Active user: 1 if confirmed, 0 otherwise.
lang?: string; // Language code such as "en", must exist on server.
calendartype?: string; // Calendar type such as "gregorian", must exist on server.
theme?: string; // Theme name such as "standard", must exist on server.
timezone?: string; // Timezone code such as Australia/Perth, or 99 for default.
mailformat?: number; // Mail format code is 0 for plain text, 1 for HTML etc.
description?: string; // User profile description.
descriptionformat?: number; // Int format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
city?: string; // Home city of the user.
url?: string; // URL of the user.
country?: string; // Home country code of the user, such as AU or CZ.
profileimageurlsmall: string; // User image profile URL - small version.
profileimageurl: string; // User image profile URL - big version.
customfields?: CoreUserProfileField[]; // User custom fields (also known as user profile fields).
preferences?: CoreUserPreference[]; // Users preferences.
};
/**
* Data returned by user_summary_exporter.
*/
export type CoreUserSummary = {
id: number; // Id.
email: string; // Email.
idnumber: string; // Idnumber.
phone1: string; // Phone1.
phone2: string; // Phone2.
department: string; // Department.
institution: string; // Institution.
fullname: string; // Fullname.
identity: string; // Identity.
profileurl: string; // Profileurl.
profileimageurl: string; // Profileimageurl.
profileimageurlsmall: string; // Profileimageurlsmall.
};
/**
* User data returned by core_enrol_get_enrolled_users WS.
*/
export type CoreUserParticipant = CoreUserBasicData & {
username?: string; // Username policy is defined in Moodle security config.
firstname?: string; // The first name(s) of the user.
lastname?: string; // The family name of the user.
email?: string; // An email address - allow email as root@localhost.
address?: string; // Postal address.
phone1?: string; // Phone 1.
phone2?: string; // Phone 2.
icq?: string; // Icq number.
skype?: string; // Skype id.
yahoo?: string; // Yahoo id.
aim?: string; // Aim id.
msn?: string; // Msn number.
department?: string; // Department.
institution?: string; // Institution.
idnumber?: string; // An arbitrary ID code number perhaps from the institution.
interests?: string; // User interests (separated by commas).
firstaccess?: number; // First access to the site (0 if never).
lastaccess?: number; // Last access to the site (0 if never).
lastcourseaccess?: number | null; // @since 3.7. Last access to the course (0 if never).
description?: string; // User profile description.
descriptionformat?: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
city?: string; // Home city of the user.
url?: string; // URL of the user.
country?: string; // Home country code of the user, such as AU or CZ.
profileimageurlsmall?: string; // User image profile URL - small version.
customfields?: CoreUserProfileField[]; // User custom fields (also known as user profil fields).
groups?: CoreUserGroup[]; // User groups.
roles?: CoreUserRole[]; // User roles.
preferences?: CoreUserPreference[]; // User preferences.
enrolledcourses?: CoreUserEnrolledCourse[]; // Courses where the user is enrolled.
};
/**
* User data returned by core_user_get_course_user_profiles WS.
*/
export type CoreUserCourseProfile = CoreUserData & {
groups?: CoreUserGroup[]; // User groups.
roles?: CoreUserRole[]; // User roles.
enrolledcourses?: CoreUserEnrolledCourse[]; // Courses where the user is enrolled.
};
/**
* User data returned by getProfile.
*/
export type CoreUserProfile = (CoreUserBasicData & Partial<CoreUserData>) | CoreUserCourseProfile;
/**
* Params of core_user_update_picture WS.
*/
type CoreUserUpdatePictureWSParams = {
draftitemid: number; // Id of the user draft file to use as image.
delete?: boolean; // If we should delete the user picture.
userid?: number; // Id of the user, 0 for current user.
};
/**
* Data returned by core_user_update_picture WS.
*/
type CoreUserUpdatePictureWSResponse = {
success: boolean; // True if the image was updated, false otherwise.
profileimageurl?: string; // New profile user image url.
warnings?: CoreWSExternalWarning[];
};
/**
* Params of core_enrol_get_enrolled_users WS.
*/
type CoreEnrolGetEnrolledUsersWSParams = {
courseid: number; // Course id.
options?: {
name: string; // Option name.
value: string; // Option value.
}[];
};
/**
* Data returned by core_enrol_get_enrolled_users WS.
*/
type CoreEnrolGetEnrolledUsersWSResponse = CoreUserParticipant[];
/**
* Params of core_user_get_course_user_profiles WS.
*/
type CoreUserGetCourseUserProfilesWSParams = {
userlist: {
userid: number; // Userid.
courseid: number; // Courseid.
}[];
};
/**
* Data returned by core_user_get_course_user_profiles WS.
*/
type CoreUserGetCourseUserProfilesWSResponse = CoreUserCourseProfile[];
/**
* Params of core_user_get_users_by_field WS.
*/
type CoreUserGetUsersByFieldWSParams = {
field: string; // The search field can be 'id' or 'idnumber' or 'username' or 'email'.
values: string[];
};
/**
* Data returned by core_user_get_users_by_field WS.
*/
type CoreUserGetUsersByFieldWSResponse = CoreUserData[];
/**
* Params of core_user_get_user_preferences WS.
*/
type CoreUserGetUserPreferencesWSParams = {
name?: string; // Preference name, empty for all.
userid?: number; // Id of the user, default to current user.
};
/**
* Data returned by core_user_get_user_preferences WS.
*/
type CoreUserGetUserPreferencesWSResponse = {
preferences: { // User custom fields (also known as user profile fields).
name: string; // The name of the preference.
value: string | null; // The value of the preference.
}[];
warnings?: CoreWSExternalWarning[];
};
/**
* Params of core_user_view_user_list WS.
*/
type CoreUserViewUserListWSParams = {
courseid: number; // Id of the course, 0 for site.
};
/**
* Params of core_user_view_user_profile WS.
*/
type CoreUserViewUserProfileWSParams = {
userid: number; // Id of the user, 0 for current user.
courseid?: number; // Id of the course, default site course.
};
/**
* Params of core_user_update_user_preferences WS.
*/
type CoreUserUpdateUserPreferencesWSParams = {
userid?: number; // Id of the user, default to current user.
emailstop?: number; // Enable or disable notifications for this user.
preferences?: { // User preferences.
type: string; // The name of the preference.
value?: string; // The value of the preference, do not set this field if you want to remove (unset) the current value.
}[];
};
/**
* Params of core_enrol_search_users WS.
*/
type CoreEnrolSearchUsersWSParams = {
courseid: number; // Course id.
search: string; // Query.
searchanywhere: boolean; // Find a match anywhere, or only at the beginning.
page: number; // Page number.
perpage: number; // Number per page.
};
/**
* Data returned by core_enrol_search_users WS.
*/
type CoreEnrolSearchUsersWSResponse = CoreUserData[];