* user_info websocket listening * add to edit profile * add tests * fix user_info test * improved types * add websocket tests * fix tests to adapt to the database * temp * fix test, remove unneeded file * Update app/actions/remote/custom_profile.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix test and storing fields and attributes * consistency * remove await from loop * remove db from component * simplify functions * address reviews * adress review comments * fix promises not being fulfilled before ordering * fix tests * address comments * address review comments * test_helper --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
144 lines
5.8 KiB
TypeScript
144 lines
5.8 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import {forceLogoutIfNecessary} from '@actions/remote/session';
|
|
import DatabaseManager from '@database/manager';
|
|
import NetworkManager from '@managers/network_manager';
|
|
import {customProfileAttributeId} from '@utils/custom_profile_attribute';
|
|
import {getFullErrorMessage} from '@utils/errors';
|
|
import {logDebug} from '@utils/log';
|
|
|
|
import type Model from '@nozbe/watermelondb/Model';
|
|
import type {CustomProfileField, CustomAttribute, CustomAttributeSet, CustomProfileAttribute, UserCustomProfileAttributeSimple} from '@typings/api/custom_profile_attributes';
|
|
|
|
/**
|
|
* Fetches custom profile attribute values for a user
|
|
* @param serverUrl - The server URL
|
|
* @param userId - The user ID
|
|
* @param filterEmpty - Whether to filter out empty values
|
|
* @returns Promise with the custom profile attributes or error
|
|
*/
|
|
export const fetchCustomProfileAttributes = async (serverUrl: string, userId: string, filterEmpty = false): Promise<{attributes: CustomAttributeSet; error: unknown}> => {
|
|
const attributes: Record<string, CustomAttribute> = {};
|
|
try {
|
|
const client = NetworkManager.getClient(serverUrl);
|
|
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
|
|
|
let fields: CustomProfileField[] = [];
|
|
let attrValues: Record<string, string> = {};
|
|
|
|
try {
|
|
[fields, attrValues] = await Promise.all([
|
|
client.getCustomProfileAttributeFields(),
|
|
client.getCustomProfileAttributeValues(userId),
|
|
]);
|
|
} catch (err) {
|
|
logDebug('error on fetchCustomProfileAttributes get fields and attr values', getFullErrorMessage(err));
|
|
return {attributes, error: err};
|
|
}
|
|
|
|
if (fields.length === 0) {
|
|
return {attributes, error: undefined};
|
|
}
|
|
|
|
try {
|
|
// Process each field to build attributes and collect promises
|
|
const attributeModelPromises: Array<Promise<Model[]>> = [];
|
|
const fieldModelPromises: Array<Promise<Model[]>> = [];
|
|
for (const field of fields) {
|
|
const value = attrValues[field.id] || '';
|
|
if (!filterEmpty || value) {
|
|
attributes[field.id] = {
|
|
id: field.id,
|
|
name: field.name,
|
|
value,
|
|
sort_order: field.attrs?.sort_order,
|
|
};
|
|
|
|
attributeModelPromises.push(operator.handleCustomProfileAttributes({
|
|
attributes: [{
|
|
id: customProfileAttributeId(field.id, userId),
|
|
field_id: field.id,
|
|
user_id: userId,
|
|
value,
|
|
}],
|
|
prepareRecordsOnly: true,
|
|
}));
|
|
fieldModelPromises.push(operator.handleCustomProfileFields({
|
|
fields: [field],
|
|
prepareRecordsOnly: true,
|
|
}));
|
|
}
|
|
}
|
|
|
|
const [fieldResults, attributeResults] = await Promise.all([
|
|
Promise.all(fieldModelPromises),
|
|
Promise.all(attributeModelPromises),
|
|
]);
|
|
const fieldBatch = fieldResults.flat();
|
|
const attributeBatch = attributeResults.flat();
|
|
|
|
if (fieldBatch.length > 0) {
|
|
await operator.batchRecords(fieldBatch, 'updateCustomProfileFields');
|
|
}
|
|
|
|
if (attributeBatch.length > 0) {
|
|
await operator.batchRecords(attributeBatch, 'updateCustomProfileAttributes');
|
|
}
|
|
|
|
} catch (err) {
|
|
logDebug('error on fetchCustomProfileAttributes field iteration', getFullErrorMessage(err));
|
|
return {attributes, error: err};
|
|
}
|
|
|
|
return {attributes, error: undefined};
|
|
} catch (error) {
|
|
logDebug('error on fetchCustomProfileAttributes', getFullErrorMessage(error));
|
|
forceLogoutIfNecessary(serverUrl, error);
|
|
return {attributes, error};
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Updates custom profile attributes for the current user
|
|
* @param serverUrl - The server URL
|
|
* @param userId - The user ID
|
|
* @param attributes - The attributes to update
|
|
* @returns Promise with success status or error
|
|
*/
|
|
export const updateCustomProfileAttributes = async (serverUrl: string, userId: string, attributes: CustomAttributeSet): Promise<{success: boolean; error: unknown}> => {
|
|
try {
|
|
const client = NetworkManager.getClient(serverUrl);
|
|
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
|
const attributeValues: UserCustomProfileAttributeSimple = {};
|
|
|
|
// Convert attributes to the format expected by the API
|
|
Object.entries(attributes).forEach(([id, attr]) => {
|
|
attributeValues[id] = attr.value;
|
|
});
|
|
|
|
// Update on the server
|
|
await client.updateCustomProfileAttributeValues(attributeValues);
|
|
|
|
// Store in the database
|
|
const attributesForDatabase: CustomProfileAttribute[] = Object.entries(attributes).map(([fieldId, attr]) => ({
|
|
id: customProfileAttributeId(fieldId, userId),
|
|
field_id: fieldId,
|
|
user_id: userId,
|
|
value: attr.value,
|
|
}));
|
|
|
|
if (attributesForDatabase.length > 0) {
|
|
await operator.handleCustomProfileAttributes({
|
|
attributes: attributesForDatabase,
|
|
prepareRecordsOnly: false,
|
|
});
|
|
}
|
|
|
|
return {success: true, error: undefined};
|
|
} catch (error) {
|
|
logDebug('error on updateCustomProfileAttributes', getFullErrorMessage(error));
|
|
forceLogoutIfNecessary(serverUrl, error);
|
|
return {success: false, error};
|
|
}
|
|
};
|