Rocket.Chat.ReactNative/app/lib/methods/getPermissions.ts

199 lines
5.5 KiB
TypeScript

import { Q } from '@nozbe/watermelondb';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import orderBy from 'lodash/orderBy';
import { setPermissions as setPermissionsAction } from '../../actions/permissions';
import { IPermission, TPermissionModel } from '../../definitions';
import log from './helpers/log';
import { store as reduxStore } from '../store/auxStore';
import database from '../database';
import sdk from '../services/sdk';
import protectedFunction from './helpers/protectedFunction';
import { compareServerVersion } from './helpers';
export const SUPPORTED_PERMISSIONS = [
'add-user-to-any-c-room',
'add-user-to-any-p-room',
'add-user-to-joined-room',
'add-team-channel',
'archive-room',
'auto-translate',
'create-invite-links',
'create-c',
'create-p',
'create-d',
'start-discussion',
'start-discussion-other-user',
'create-team',
'delete-c',
'delete-message',
'delete-p',
'delete-team',
'edit-message',
'edit-room',
'edit-team-member',
'edit-team-channel',
'force-delete-message',
'mute-user',
'pin-message',
'post-readonly',
'remove-user',
'remove-team-channel',
'set-leader',
'set-moderator',
'set-owner',
'set-react-when-readonly',
'set-readonly',
'toggle-room-e2e-encryption',
'transfer-livechat-guest',
'unarchive-room',
'view-broadcast-member-list',
'view-privileged-setting',
'view-room-administration',
'view-statistics',
'view-user-administration',
'view-all-teams',
'view-all-team-channels',
'convert-team',
'edit-omnichannel-contact',
'edit-livechat-room-customfields',
'view-canned-responses',
'mobile-upload-file',
'delete-own-message',
'call-management',
'test-push-notifications'
] as const;
export async function setPermissions(): Promise<void> {
const db = database.active;
const permissionsCollection = db.get('permissions');
const allPermissions = await permissionsCollection
.query(Q.where('id', Q.oneOf(SUPPORTED_PERMISSIONS as unknown as string[])))
.fetch();
const parsed = allPermissions.reduce((acc, item) => ({ ...acc, [item.id]: item.roles }), {});
reduxStore.dispatch(setPermissionsAction(parsed));
}
const getUpdatedSince = (allRecords: TPermissionModel[]) => {
try {
if (!allRecords.length) {
return null;
}
const ordered = orderBy(
allRecords.filter(item => item._updatedAt !== null),
['_updatedAt'],
['desc']
);
return new Date(ordered[0]._updatedAt).toISOString();
} catch (e) {
log(e);
}
return null;
};
const updatePermissions = async ({
update = [],
remove = [],
allRecords
}: {
update?: IPermission[];
remove?: IPermission[];
allRecords: TPermissionModel[];
}) => {
if (!((update && update.length) || (remove && remove.length))) {
return;
}
const db = database.active;
const permissionsCollection = db.get('permissions');
const batch: TPermissionModel[] = [];
// Delete
if (remove?.length) {
const filteredPermissionsToDelete = allRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
const permissionsToDelete = filteredPermissionsToDelete.map(permission => permission.prepareDestroyPermanently());
batch.push(...permissionsToDelete);
}
// Create or update
if (update?.length) {
const filteredPermissionsToCreate = update.filter(i1 => !allRecords.find(i2 => i1._id === i2.id));
const filteredPermissionsToUpdate = allRecords.filter(i1 => update.find(i2 => i1.id === i2._id));
const permissionsToCreate = filteredPermissionsToCreate.map(permission =>
permissionsCollection.prepareCreate(
protectedFunction((p: TPermissionModel) => {
p._raw = sanitizedRaw({ id: permission._id }, permissionsCollection.schema);
Object.assign(p, permission);
})
)
);
const permissionsToUpdate = filteredPermissionsToUpdate.map(permission => {
const newPermission = update.find(p => p._id === permission.id);
return permission.prepareUpdate(
protectedFunction((p: TPermissionModel) => {
Object.assign(p, newPermission);
})
);
});
batch.push(...permissionsToCreate, ...permissionsToUpdate);
}
try {
await db.write(async () => {
await db.batch(...batch);
});
return true;
} catch (e) {
log(e);
}
};
export function getPermissions(): Promise<void> {
return new Promise(async resolve => {
try {
const serverVersion: string | null = reduxStore.getState().server.version;
const db = database.active;
const permissionsCollection = db.get('permissions');
const allRecords = await permissionsCollection.query().fetch();
sdk.subscribe('stream-notify-logged', 'permissions-changed');
// if server version is lower than 0.73.0, fetches from old api
if (serverVersion && compareServerVersion(serverVersion, 'lowerThan', '0.73.0')) {
// RC 0.66.0
// @ts-ignore
const result: any = await sdk.get('permissions.list');
if (!result.success) {
return resolve();
}
const changePermissions = await updatePermissions({ update: result.permissions, allRecords });
if (changePermissions) {
setPermissions();
}
return resolve();
}
const params: { updatedSince?: string } = {};
const updatedSince = getUpdatedSince(allRecords);
if (updatedSince) {
params.updatedSince = updatedSince;
}
// RC 0.73.0
const result = await sdk.get('permissions.listAll', params);
if (!result.success) {
return resolve();
}
const changePermissions = await updatePermissions({ update: result.update, remove: result.remove, allRecords });
if (changePermissions) {
setPermissions();
}
return resolve();
} catch (e) {
log(e);
return resolve();
}
});
}