Chore: Migrate getPermissions to Typescript (#3720)
* Migrating... * Fix IPermission * Playing with types * Remove `as const` * Fix lint * Fix test * Apply sdk * Fix lint and autocomplete
This commit is contained in:
parent
86cc8a7d16
commit
a58b27e4f1
|
@ -1,26 +1,26 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IPermissions } from '../reducers/permissions';
|
||||
import { IPermissionsState, TSupportedPermissions } from '../reducers/permissions';
|
||||
import { PERMISSIONS } from './actionsTypes';
|
||||
|
||||
interface ISetPermissions extends Action {
|
||||
permissions: IPermissions;
|
||||
permissions: IPermissionsState;
|
||||
}
|
||||
|
||||
interface IUpdatePermissions extends Action {
|
||||
payload: { id: string; roles: string };
|
||||
payload: { id: TSupportedPermissions; roles: string[] };
|
||||
}
|
||||
|
||||
export type TActionPermissions = ISetPermissions & IUpdatePermissions;
|
||||
|
||||
export function setPermissions(permissions: IPermissions): ISetPermissions {
|
||||
export function setPermissions(permissions: IPermissionsState): ISetPermissions {
|
||||
return {
|
||||
type: PERMISSIONS.SET,
|
||||
permissions
|
||||
};
|
||||
}
|
||||
|
||||
export function updatePermission(id: string, roles: string): IUpdatePermissions {
|
||||
export function updatePermission(id: TSupportedPermissions, roles: string[]): IUpdatePermissions {
|
||||
return {
|
||||
type: PERMISSIONS.UPDATE,
|
||||
payload: { id, roles }
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
export interface IPermission {
|
||||
id: string;
|
||||
_id: string;
|
||||
roles: string[];
|
||||
_updatedAt: Date;
|
||||
_updatedAt: Date | string;
|
||||
}
|
||||
|
||||
export type TPermissionModel = IPermission & Model;
|
||||
|
|
|
@ -13,6 +13,8 @@ import { IActionSettings } from '../../actions/settings';
|
|||
import { TActionsShare } from '../../actions/share';
|
||||
import { TActionSortPreferences } from '../../actions/sortPreferences';
|
||||
import { TActionUserTyping } from '../../actions/usersTyping';
|
||||
import { TActionPermissions } from '../../actions/permissions';
|
||||
import { TActionEnterpriseModules } from '../../actions/enterpriseModules';
|
||||
// REDUCERS
|
||||
import { IActiveUsers } from '../../reducers/activeUsers';
|
||||
import { IApp } from '../../reducers/app';
|
||||
|
@ -26,8 +28,8 @@ import { ISelectedUsers } from '../../reducers/selectedUsers';
|
|||
import { IServer } from '../../reducers/server';
|
||||
import { ISettings } from '../../reducers/settings';
|
||||
import { IShare } from '../../reducers/share';
|
||||
import { IPermissionsState } from '../../reducers/permissions';
|
||||
import { IEnterpriseModules } from '../../reducers/enterpriseModules';
|
||||
import { TActionEnterpriseModules } from '../../actions/enterpriseModules';
|
||||
|
||||
export interface IApplicationState {
|
||||
settings: ISettings;
|
||||
|
@ -49,7 +51,7 @@ export interface IApplicationState {
|
|||
inquiry: any;
|
||||
enterpriseModules: IEnterpriseModules;
|
||||
encryption: IEncryption;
|
||||
permissions: any;
|
||||
permissions: IPermissionsState;
|
||||
roles: IRoles;
|
||||
}
|
||||
|
||||
|
@ -67,4 +69,5 @@ export type TApplicationActions = TActionActiveUsers &
|
|||
TActionsShare &
|
||||
TActionServer &
|
||||
TActionApp &
|
||||
TActionPermissions &
|
||||
TActionEnterpriseModules;
|
||||
|
|
|
@ -7,10 +7,12 @@ import database from '../database';
|
|||
import log from '../../utils/log';
|
||||
import { store as reduxStore } from '../auxStore';
|
||||
import RocketChat from '../rocketchat';
|
||||
import sdk from '../rocketchat/services/sdk';
|
||||
import { setPermissions as setPermissionsAction } from '../../actions/permissions';
|
||||
import protectedFunction from './helpers/protectedFunction';
|
||||
import { TPermissionModel, IPermission } from '../../definitions';
|
||||
|
||||
const PERMISSIONS = [
|
||||
export const SUPPORTED_PERMISSIONS = [
|
||||
'add-user-to-any-c-room',
|
||||
'add-user-to-any-p-room',
|
||||
'add-user-to-joined-room',
|
||||
|
@ -57,18 +59,20 @@ const PERMISSIONS = [
|
|||
'edit-livechat-room-customfields',
|
||||
'view-canned-responses',
|
||||
'mobile-upload-file'
|
||||
];
|
||||
] as const;
|
||||
|
||||
export async function setPermissions() {
|
||||
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(PERMISSIONS))).fetch();
|
||||
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 => {
|
||||
const getUpdatedSince = (allRecords: TPermissionModel[]) => {
|
||||
try {
|
||||
if (!allRecords.length) {
|
||||
return null;
|
||||
|
@ -78,57 +82,63 @@ const getUpdatedSince = allRecords => {
|
|||
['_updatedAt'],
|
||||
['desc']
|
||||
);
|
||||
return ordered && ordered[0]._updatedAt.toISOString();
|
||||
return new Date(ordered[0]._updatedAt).toISOString();
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const updatePermissions = async ({ update = [], remove = [], allRecords }) => {
|
||||
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');
|
||||
|
||||
// filter permissions
|
||||
let permissionsToCreate = [];
|
||||
let permissionsToUpdate = [];
|
||||
let permissionsToDelete = [];
|
||||
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 && update.length) {
|
||||
permissionsToCreate = update.filter(i1 => !allRecords.find(i2 => i1._id === i2.id));
|
||||
permissionsToUpdate = allRecords.filter(i1 => update.find(i2 => i1.id === i2._id));
|
||||
permissionsToCreate = permissionsToCreate.map(permission =>
|
||||
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 => {
|
||||
protectedFunction((p: TPermissionModel) => {
|
||||
p._raw = sanitizedRaw({ id: permission._id }, permissionsCollection.schema);
|
||||
Object.assign(p, permission);
|
||||
})
|
||||
)
|
||||
);
|
||||
permissionsToUpdate = permissionsToUpdate.map(permission => {
|
||||
const permissionsToUpdate = filteredPermissionsToUpdate.map(permission => {
|
||||
const newPermission = update.find(p => p._id === permission.id);
|
||||
return permission.prepareUpdate(
|
||||
protectedFunction(p => {
|
||||
protectedFunction((p: TPermissionModel) => {
|
||||
Object.assign(p, newPermission);
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Delete
|
||||
if (remove && remove.length) {
|
||||
permissionsToDelete = allRecords.filter(i1 => remove.find(i2 => i1.id === i2._id));
|
||||
permissionsToDelete = permissionsToDelete.map(permission => permission.prepareDestroyPermanently());
|
||||
batch.push(...permissionsToCreate, ...permissionsToUpdate);
|
||||
}
|
||||
|
||||
const batch = [...permissionsToCreate, ...permissionsToUpdate, ...permissionsToDelete];
|
||||
|
||||
try {
|
||||
await db.action(async () => {
|
||||
await db.write(async () => {
|
||||
await db.batch(...batch);
|
||||
});
|
||||
return true;
|
||||
|
@ -137,18 +147,19 @@ const updatePermissions = async ({ update = [], remove = [], allRecords }) => {
|
|||
}
|
||||
};
|
||||
|
||||
export function getPermissions() {
|
||||
export function getPermissions(): Promise<void> {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
const serverVersion = reduxStore.getState().server.version;
|
||||
const serverVersion: string | null = reduxStore.getState().server.version;
|
||||
const db = database.active;
|
||||
const permissionsCollection = db.get('permissions');
|
||||
const allRecords = await permissionsCollection.query().fetch();
|
||||
RocketChat.subscribe('stream-notify-logged', 'permissions-changed');
|
||||
// if server version is lower than 0.73.0, fetches from old api
|
||||
if (compareServerVersion(serverVersion, 'lowerThan', '0.73.0')) {
|
||||
if (serverVersion && compareServerVersion(serverVersion, 'lowerThan', '0.73.0')) {
|
||||
// RC 0.66.0
|
||||
const result = await this.sdk.get('permissions.list');
|
||||
// @ts-ignore
|
||||
const result: any = await sdk.get('permissions.list');
|
||||
if (!result.success) {
|
||||
return resolve();
|
||||
}
|
||||
|
@ -157,25 +168,25 @@ export function getPermissions() {
|
|||
setPermissions();
|
||||
}
|
||||
return resolve();
|
||||
} else {
|
||||
const params = {};
|
||||
const updatedSince = getUpdatedSince(allRecords);
|
||||
if (updatedSince) {
|
||||
params.updatedSince = updatedSince;
|
||||
}
|
||||
// RC 0.73.0
|
||||
const result = await this.sdk.get('permissions.listAll', params);
|
||||
}
|
||||
|
||||
if (!result.success) {
|
||||
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);
|
||||
|
||||
const changePermissions = await updatePermissions({ update: result.update, remove: result.delete, allRecords });
|
||||
if (changePermissions) {
|
||||
setPermissions();
|
||||
}
|
||||
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();
|
|
@ -1,6 +1,6 @@
|
|||
import { setPermissions, updatePermission } from '../actions/permissions';
|
||||
import { mockedStore } from './mockedStore';
|
||||
import { initialState } from './permissions';
|
||||
import { initialState, IPermissionsState } from './permissions';
|
||||
|
||||
describe('test permissions reducer', () => {
|
||||
it('should return initial state', () => {
|
||||
|
@ -9,15 +9,15 @@ describe('test permissions reducer', () => {
|
|||
});
|
||||
|
||||
it('should return modified store after setPermissions', () => {
|
||||
const permissions = { hasEditPermission: 'enabled', hasForceDeletePermission: 'enabled' };
|
||||
const permissions: IPermissionsState = { 'add-user-to-any-c-room': ['admin'], 'add-team-channel': ['user'] };
|
||||
mockedStore.dispatch(setPermissions(permissions));
|
||||
const state = mockedStore.getState().permissions;
|
||||
expect(state).toEqual(permissions);
|
||||
});
|
||||
|
||||
it('should return empty store after remove user', () => {
|
||||
mockedStore.dispatch(updatePermission('hasEditPermission', 'disabled'));
|
||||
mockedStore.dispatch(updatePermission('add-team-channel', ['owner']));
|
||||
const state = mockedStore.getState().permissions;
|
||||
expect(state.hasEditPermission).toEqual('disabled');
|
||||
expect(state['add-team-channel']).toEqual(['owner']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import { PERMISSIONS } from '../actions/actionsTypes';
|
||||
import { TActionPermissions } from '../actions/permissions';
|
||||
import { SUPPORTED_PERMISSIONS } from '../lib/methods/getPermissions';
|
||||
|
||||
export type IPermissions = Record<string, string>;
|
||||
export type TSupportedPermissions = typeof SUPPORTED_PERMISSIONS[number];
|
||||
|
||||
export const initialState: IPermissions = {};
|
||||
export type IPermissionsState = {
|
||||
[K in TSupportedPermissions]?: string[];
|
||||
};
|
||||
|
||||
export default function permissions(state = initialState, action: TActionPermissions): IPermissions {
|
||||
export const initialState: IPermissionsState = {};
|
||||
|
||||
export default function permissions(state = initialState, action: TActionPermissions): IPermissionsState {
|
||||
switch (action.type) {
|
||||
case PERMISSIONS.SET:
|
||||
return action.permissions;
|
||||
|
|
|
@ -96,8 +96,8 @@ interface ICreateChannelViewProps extends IBaseScreen<ChatsStackParamList, 'Crea
|
|||
roles: string[];
|
||||
};
|
||||
teamId: string;
|
||||
createPublicChannelPermission: string[];
|
||||
createPrivateChannelPermission: string[];
|
||||
createPublicChannelPermission: string[] | undefined;
|
||||
createPrivateChannelPermission: string[] | undefined;
|
||||
}
|
||||
|
||||
interface ISwitch extends SwitchProps {
|
||||
|
|
|
@ -87,8 +87,8 @@ interface ILivechatEditViewProps {
|
|||
navigation: StackNavigationProp<ChatsStackParamList, 'LivechatEditView'>;
|
||||
route: RouteProp<ChatsStackParamList, 'LivechatEditView'>;
|
||||
theme: string;
|
||||
editOmnichannelContact: string[];
|
||||
editLivechatRoomCustomfields: string[];
|
||||
editOmnichannelContact: string[] | undefined;
|
||||
editLivechatRoomCustomfields: string[] | undefined;
|
||||
}
|
||||
|
||||
const Title = ({ title, theme }: ITitle) =>
|
||||
|
|
|
@ -77,11 +77,11 @@ interface INewMessageViewProps extends IBaseScreen<any, 'NewMessageView'> {
|
|||
maxUsers: number;
|
||||
isMasterDetail: boolean;
|
||||
serverVersion: string;
|
||||
createTeamPermission: string[];
|
||||
createDirectMessagePermission: string[];
|
||||
createPublicChannelPermission: string[];
|
||||
createPrivateChannelPermission: string[];
|
||||
createDiscussionPermission: string[];
|
||||
createTeamPermission: string[] | undefined;
|
||||
createDirectMessagePermission: string[] | undefined;
|
||||
createPublicChannelPermission: string[] | undefined;
|
||||
createPrivateChannelPermission: string[] | undefined;
|
||||
createDiscussionPermission: string[] | undefined;
|
||||
}
|
||||
|
||||
class NewMessageView extends React.Component<INewMessageViewProps, INewMessageViewState> {
|
||||
|
|
Loading…
Reference in New Issue