Let ServerDatabases type hold undefined values (#6423)

* Let ServerDatabases type hold undefined values

* Avoid model.database
This commit is contained in:
Daniel Espino García
2022-06-22 23:51:28 +02:00
committed by GitHub
parent b5ff344b64
commit 844f2c0393
37 changed files with 136 additions and 108 deletions

View File

@@ -64,7 +64,7 @@ describe('switchToChannel', () => {
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl].operator;
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
spyNow = jest.spyOn(Date, 'now').mockImplementation(() => now);
});

View File

@@ -631,8 +631,13 @@ export async function markChannelAsRead(serverUrl: string, channelId: string) {
}
export async function switchToChannelByName(serverUrl: string, channelName: string, teamName: string, errorHandler: (intl: IntlShape) => void, intl: IntlShape) {
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
if (!database) {
let database;
let operator;
try {
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = result.database;
operator = result.operator;
} catch (e) {
return {error: `${serverUrl} database not found`};
}
@@ -737,7 +742,6 @@ export async function switchToChannelByName(serverUrl: string, channelName: stri
}
const modelPromises: Array<Promise<Model[]>> = [];
const {operator} = DatabaseManager.serverDatabases[serverUrl];
if (!(team instanceof Model)) {
modelPromises.push(...prepareMyTeams(operator, [team], [(myTeam as TeamMembership)]));
} else if (!(myTeam instanceof Model)) {

View File

@@ -24,8 +24,16 @@ export const fetchRolesIfNeeded = async (serverUrl: string, updatedRoles: string
return {error};
}
const database = DatabaseManager.serverDatabases[serverUrl].database;
const operator = DatabaseManager.serverDatabases[serverUrl].operator;
let database;
let operator;
try {
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = result.database;
operator = result.operator;
} catch (e) {
return {error: `${serverUrl} database not found`};
}
let newRoles;
if (force) {
newRoles = updatedRoles;

View File

@@ -288,11 +288,20 @@ export async function fetchStatusByIds(serverUrl: string, userIds: string[], fet
return {statuses: []};
}
let database;
let operator;
try {
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = result.database;
operator = result.operator;
} catch (e) {
return {error: `${serverUrl} database not found`};
}
try {
const statuses = await client.getStatusesByIds(userIds);
if (!fetchOnly && DatabaseManager.serverDatabases[serverUrl]) {
const {database, operator} = DatabaseManager.serverDatabases[serverUrl];
if (operator) {
const users = await queryUsersById(database, userIds).fetch();
const userStatuses = statuses.reduce((result: Record<string, UserStatus>, s) => {
@@ -792,9 +801,12 @@ export const buildProfileImageUrl = (serverUrl: string, userId: string, timestam
};
export const autoUpdateTimezone = async (serverUrl: string, {deviceTimezone, userId}: {deviceTimezone: string; userId: string}) => {
const database = DatabaseManager.serverDatabases[serverUrl].database;
if (!database) {
return {error: `No database present for ${serverUrl}`};
let database;
try {
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = result.database;
} catch (e) {
return {error: `${serverUrl} database not found`};
}
const currentUser = await getUserById(database, userId);
@@ -814,9 +826,12 @@ export const autoUpdateTimezone = async (serverUrl: string, {deviceTimezone, use
};
export const fetchTeamAndChannelMembership = async (serverUrl: string, userId: string, teamId: string, channelId?: string) => {
const operator = DatabaseManager.serverDatabases[serverUrl].operator;
if (!operator) {
return {error: `No database present for ${serverUrl}`};
let operator;
try {
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
operator = result.operator;
} catch (e) {
return {error: `${serverUrl} database not found`};
}
let client: Client;

View File

@@ -9,8 +9,13 @@ import {getPostById} from '@queries/servers/post';
import {deletePreferences, differsFromLocalNameFormat} from '@queries/servers/preference';
export async function handlePreferenceChangedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
const operator = DatabaseManager.serverDatabases[serverUrl].operator;
if (!operator) {
let database;
let operator;
try {
const result = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = result.database;
operator = result.operator;
} catch (e) {
return;
}
@@ -18,7 +23,7 @@ export async function handlePreferenceChangedEvent(serverUrl: string, msg: WebSo
const preference: PreferenceType = JSON.parse(msg.data.preference);
handleSavePostAdded(serverUrl, [preference]);
const hasDiffNameFormatPref = await differsFromLocalNameFormat(operator.database, [preference]);
const hasDiffNameFormatPref = await differsFromLocalNameFormat(database, [preference]);
if (operator) {
await operator.handlePreferences({

View File

@@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
import {markTeamThreadsAsRead, processReceivedThreads, updateThread} from '@actions/local/thread';
import DatabaseManager from '@database/manager';
export async function handleThreadUpdatedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
try {
@@ -18,23 +17,16 @@ export async function handleThreadUpdatedEvent(serverUrl: string, msg: WebSocket
}
export async function handleThreadReadChangedEvent(serverUrl: string, msg: WebSocketMessage<ThreadReadChangedData>): Promise<void> {
const operator = DatabaseManager.serverDatabases[serverUrl].operator;
if (!operator) {
return;
}
try {
if (operator) {
const {thread_id, timestamp, unread_mentions, unread_replies} = msg.data;
if (thread_id) {
await updateThread(serverUrl, thread_id, {
last_viewed_at: timestamp,
unread_mentions,
unread_replies,
});
} else {
await markTeamThreadsAsRead(serverUrl, msg.broadcast.team_id);
}
const {thread_id, timestamp, unread_mentions, unread_replies} = msg.data;
if (thread_id) {
await updateThread(serverUrl, thread_id, {
last_viewed_at: timestamp,
unread_mentions,
unread_replies,
});
} else {
await markTeamThreadsAsRead(serverUrl, msg.broadcast.team_id);
}
} catch (error) {
// Do nothing
@@ -42,23 +34,16 @@ export async function handleThreadReadChangedEvent(serverUrl: string, msg: WebSo
}
export async function handleThreadFollowChangedEvent(serverUrl: string, msg: WebSocketMessage): Promise<void> {
const operator = DatabaseManager.serverDatabases[serverUrl].operator;
if (!operator) {
return;
}
try {
if (operator) {
const {reply_count, state, thread_id} = msg.data as {
const {reply_count, state, thread_id} = msg.data as {
reply_count: number;
state: boolean;
thread_id: string;
};
await updateThread(serverUrl, thread_id, {
is_following: state,
reply_count,
});
}
await updateThread(serverUrl, thread_id, {
is_following: state,
reply_count,
});
} catch (error) {
// Do nothing
}

View File

@@ -42,9 +42,9 @@ const enhanced = withObservables([], ({database, channelId}: WithDatabaseArgs &
switchMap((c) => of$(Boolean(c?.isGroupConstrained))),
);
useChannelMentions = combineLatest([currentUser, currentChannel]).pipe(switchMap(([u, c]) => (u && c ? observePermissionForChannel(c, u, Permissions.USE_CHANNEL_MENTIONS, false) : of$(false))));
useChannelMentions = combineLatest([currentUser, currentChannel]).pipe(switchMap(([u, c]) => (u && c ? observePermissionForChannel(database, c, u, Permissions.USE_CHANNEL_MENTIONS, false) : of$(false))));
useGroupMentions = combineLatest([currentUser, currentChannel, hasLicense]).pipe(
switchMap(([u, c, lcs]) => (lcs && u && c ? observePermissionForChannel(c, u, Permissions.USE_GROUP_MENTIONS, false) : of$(false))),
switchMap(([u, c, lcs]) => (lcs && u && c ? observePermissionForChannel(database, c, u, Permissions.USE_GROUP_MENTIONS, false) : of$(false))),
);
} else {
useChannelMentions = of$(false);

View File

@@ -860,12 +860,15 @@ export class AppCommandParser {
constructor(serverUrl: string, intl: IntlShape, channelID: string, teamID = '', rootPostID = '', theme: Theme) {
this.serverUrl = serverUrl;
this.database = DatabaseManager.serverDatabases[serverUrl]?.database;
this.channelID = channelID;
this.rootPostID = rootPostID;
this.teamID = teamID;
this.intl = intl;
this.theme = theme;
// We are making the assumption the database is always present at this level.
// This assumption may not be correct. Please review.
this.database = DatabaseManager.serverDatabases[serverUrl]!.database;
}
// composeCommandSubmitCall creates the form submission call

View File

@@ -50,7 +50,7 @@ const enhanced = withObservables(['channelId', 'rootId', 'channelIsArchived'], (
switchMap((id) => observeChannel(database, id!)),
);
const canPost = combineLatest([channel, currentUser]).pipe(switchMap(([c, u]) => (c && u ? observePermissionForChannel(c, u, Permissions.CREATE_POST, true) : of$(true))));
const canPost = combineLatest([channel, currentUser]).pipe(switchMap(([c, u]) => (c && u ? observePermissionForChannel(database, c, u, Permissions.CREATE_POST, true) : of$(true))));
const channelIsArchived = channel.pipe(switchMap((c) => (ownProps.channelIsArchived ? of$(true) : of$(c?.deleteAt !== 0))));
const experimentalTownSquareIsReadOnly = observeConfigBooleanValue(database, 'ExperimentalTownSquareIsReadOnly');

View File

@@ -59,7 +59,7 @@ const enhanced = withObservables([], (ownProps: WithDatabaseArgs & OwnProps) =>
return of$(true);
}
return u ? observePermissionForChannel(c, u, Permissions.USE_CHANNEL_MENTIONS, false) : of$(false);
return u ? observePermissionForChannel(database, c, u, Permissions.USE_CHANNEL_MENTIONS, false) : of$(false);
}),
);

View File

@@ -28,7 +28,7 @@ const withCombinedPosts = withObservables(['postId'], ({database, postId}: WithD
const posts = queryPostsById(database, postIds).observe();
const post = posts.pipe(map((ps) => generateCombinedPost(postId, ps)));
const canDelete = combineLatest([posts, currentUser]).pipe(
switchMap(([ps, u]) => (u ? observePermissionForPost(ps[0], u, Permissions.DELETE_OTHERS_POSTS, false) : of$(false))),
switchMap(([ps, u]) => (u && ps.length ? observePermissionForPost(database, ps[0], u, Permissions.DELETE_OTHERS_POSTS, false) : of$(false))),
);
const usernamesById = post.pipe(

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import React, {useCallback, useRef} from 'react';
import {useIntl} from 'react-intl';
@@ -18,6 +19,7 @@ import {makeStyleSheetFromTheme, changeOpacity} from '@utils/theme';
import ButtonBindingText from './button_binding_text';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type PostModel from '@typings/database/models/servers/post';
@@ -125,9 +127,9 @@ const ButtonBinding = ({currentTeamId, binding, post, teamID, theme}: Props) =>
return null;
};
const withTeamId = withObservables(['post'], ({post}: {post: PostModel}) => ({
const withTeamId = withObservables(['post'], ({post, database}: {post: PostModel} & WithDatabaseArgs) => ({
teamID: post.channel.observe().pipe(map((channel: ChannelModel) => channel.teamId)),
currentTeamId: observeCurrentTeamId(post.database),
currentTeamId: observeCurrentTeamId(database),
}));
export default withTeamId(ButtonBinding);
export default withDatabase(withTeamId(ButtonBinding));

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import React, {useCallback, useState} from 'react';
import {useIntl} from 'react-intl';
@@ -11,6 +12,7 @@ import AutocompleteSelector from '@components/autocomplete_selector';
import {AppBindingLocations, AppCallResponseTypes} from '@constants/apps';
import {useServerUrl} from '@context/server';
import {observeCurrentTeamId} from '@queries/servers/system';
import {WithDatabaseArgs} from '@typings/database/database';
import {createCallContext} from '@utils/apps';
import type ChannelModel from '@typings/database/models/servers/channel';
@@ -94,9 +96,9 @@ const MenuBinding = ({binding, currentTeamId, post, teamID}: Props) => {
);
};
const withTeamId = withObservables(['post'], ({post}: {post: PostModel}) => ({
const withTeamId = withObservables(['post'], ({post, database}: {post: PostModel} & WithDatabaseArgs) => ({
teamID: post.channel.observe().pipe(map((channel: ChannelModel) => channel.teamId)),
currentTeamId: observeCurrentTeamId(post.database),
currentTeamId: observeCurrentTeamId(database),
}));
export default withTeamId(MenuBinding);
export default withDatabase(withTeamId(MenuBinding));

View File

@@ -33,8 +33,8 @@ const withReactions = withObservables(['post'], ({database, post}: WithReactions
map(([u, c, readOnly]) => ((c && c.deleteAt > 0) || (c?.name === General.DEFAULT_CHANNEL && !isSystemAdmin(u?.roles || '') && readOnly))),
);
const canAddReaction = currentUser.pipe(switchMap((u) => (u ? observePermissionForPost(post, u, Permissions.ADD_REACTION, true) : of$(true))));
const canRemoveReaction = currentUser.pipe(switchMap((u) => (u ? observePermissionForPost(post, u, Permissions.REMOVE_REACTION, true) : of$(true))));
const canAddReaction = currentUser.pipe(switchMap((u) => (u ? observePermissionForPost(database, post, u, Permissions.ADD_REACTION, true) : of$(true))));
const canRemoveReaction = currentUser.pipe(switchMap((u) => (u ? observePermissionForPost(database, post, u, Permissions.REMOVE_REACTION, true) : of$(true))));
return {
canAddReaction,

View File

@@ -20,6 +20,7 @@ import {areConsecutivePosts, isPostEphemeral} from '@utils/post';
import Post from './post';
import type {Database} from '@nozbe/watermelondb';
import type {WithDatabaseArgs} from '@typings/database/database';
import type CustomEmojiModel from '@typings/database/models/servers/custom_emoji';
import type PostModel from '@typings/database/models/servers/post';
@@ -35,8 +36,8 @@ type PropsInput = WithDatabaseArgs & {
previousPost: PostModel | undefined;
}
function observeShouldHighlightReplyBar(currentUser: UserModel, post: PostModel, postsInThread: PostsInThreadModel) {
const myPostsCount = queryPostsBetween(postsInThread.database, postsInThread.earliest, postsInThread.latest, null, currentUser.id, '', post.rootId || post.id).observeCount();
function observeShouldHighlightReplyBar(database: Database, currentUser: UserModel, post: PostModel, postsInThread: PostsInThreadModel) {
const myPostsCount = queryPostsBetween(database, postsInThread.earliest, postsInThread.latest, null, currentUser.id, '', post.rootId || post.id).observeCount();
const root = post.root.observe().pipe(switchMap((rl) => (rl.length ? rl[0].observe() : of$(undefined))));
return combineLatest([myPostsCount, root]).pipe(
@@ -101,7 +102,7 @@ const withPost = withObservables(
let isPostAddChannelMember = of$(false);
const isOwner = currentUser.id === post.userId;
const author = post.userId ? post.author.observe() : of$(null);
const canDelete = observePermissionForPost(post, currentUser, isOwner ? Permissions.DELETE_POST : Permissions.DELETE_OTHERS_POSTS, false);
const canDelete = observePermissionForPost(database, post, currentUser, isOwner ? Permissions.DELETE_POST : Permissions.DELETE_OTHERS_POSTS, false);
const isEphemeral = of$(isPostEphemeral(post));
const isSaved = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_SAVED_POST, post.id).
observeWithColumns(['value']).pipe(
@@ -109,13 +110,13 @@ const withPost = withObservables(
);
if (post.props?.add_channel_member && isPostEphemeral(post)) {
isPostAddChannelMember = observeCanManageChannelMembers(post, currentUser);
isPostAddChannelMember = observeCanManageChannelMembers(database, post, currentUser);
}
const highlightReplyBar = post.postsInThread.observe().pipe(
switchMap((postsInThreads: PostsInThreadModel[]) => {
if (postsInThreads.length) {
return observeShouldHighlightReplyBar(currentUser, post, postsInThreads[0]);
return observeShouldHighlightReplyBar(database, currentUser, post, postsInThreads[0]);
}
return of$(false);
}));
@@ -127,7 +128,7 @@ const withPost = withObservables(
}
if (post.message.length && !(/^\s{4}/).test(post.message)) {
isJumboEmoji = queryAllCustomEmojis(post.database).observe().pipe(
isJumboEmoji = queryAllCustomEmojis(database).observe().pipe(
// eslint-disable-next-line max-nested-callbacks
switchMap((customEmojis: CustomEmojiModel[]) => of$(hasJumboEmojiOnly(post.message, customEmojis.map((c) => c.name))),
),

View File

@@ -252,7 +252,7 @@ class DatabaseManager {
if (database) {
const server = await queryActiveServer(database);
if (server?.url) {
return this.serverDatabases[server.url].database;
return this.serverDatabases[server.url]!.database;
}
}

View File

@@ -58,7 +58,7 @@ describe('*** Database Manager tests ***', () => {
// as we haven't set an active server yet, so the first registered server should be the active one
expect(activeServerUrl).toBe(serverUrls[0]);
expect(serverA).toEqual(DatabaseManager.serverDatabases[serverUrls[0]].database);
expect(serverA).toEqual(DatabaseManager.serverDatabases[serverUrls[0]]!.database);
await DatabaseManager.setActiveServerDatabase('https://appv2.mattermost.com');
@@ -66,7 +66,7 @@ describe('*** Database Manager tests ***', () => {
activeServerUrl = await DatabaseManager.getActiveServerUrl();
const serverB = await DatabaseManager.getActiveServerDatabase();
expect(activeServerUrl).toBe(serverUrls[1]);
expect(serverB).toEqual(DatabaseManager.serverDatabases[serverUrls[1]].database);
expect(serverB).toEqual(DatabaseManager.serverDatabases[serverUrls[1]]!.database);
});
it('=> should delete appv1 server from the servers table of App database', async () => {

View File

@@ -14,7 +14,7 @@ describe('*** Operator: Category Handlers tests ***', () => {
let operator: ServerDataOperator;
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> handleCategories: should write to the CATEGORY table', async () => {

View File

@@ -20,7 +20,7 @@ describe('*** Operator: Channel Handlers tests ***', () => {
let operator: ServerDataOperator;
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleChannel: should write to the CHANNEL table', async () => {

View File

@@ -14,7 +14,7 @@ describe('*** Operator: Group Handlers tests ***', () => {
let operator: ServerDataOperator;
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> handleGroups: should write to the GROUP table', async () => {

View File

@@ -15,7 +15,7 @@ describe('*** DataOperator: Base Handlers tests ***', () => {
let operator: ServerDataOperator;
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleRole: should write to the ROLE table', async () => {

View File

@@ -19,7 +19,7 @@ describe('*** Operator: Post Handlers tests ***', () => {
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleDraft: should write to the the Draft table', async () => {

View File

@@ -9,7 +9,7 @@ describe('*** Operator: User Handlers tests ***', () => {
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleReactions: should write to Reactions table', async () => {

View File

@@ -20,7 +20,7 @@ describe('*** Operator: Team Handlers tests ***', () => {
let operator: ServerDataOperator;
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleTeam: should write to the TEAM table', async () => {

View File

@@ -23,7 +23,7 @@ describe('*** Operator: Thread Handlers tests ***', () => {
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleThreads: should write to the the Thread & ThreadParticipant & ThreadsInTeam tables', async () => {

View File

@@ -14,7 +14,7 @@ describe('*** Operator: User Handlers tests ***', () => {
beforeAll(async () => {
await DatabaseManager.init(['baseHandler.test.com']);
operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator;
operator = DatabaseManager.serverDatabases['baseHandler.test.com']!.operator;
});
it('=> HandleReactions: should write to Reactions table', async () => {

View File

@@ -69,7 +69,7 @@ describe('draft upload manager', () => {
beforeEach(async () => {
await DatabaseManager.init([url]);
operator = DatabaseManager.serverDatabases[url].operator;
operator = DatabaseManager.serverDatabases[url]!.operator;
AppState.currentState = 'active';
});

View File

@@ -37,8 +37,7 @@ export const queryRolesByNames = (database: Database, names: string[]) => {
return database.get<RoleModel>(ROLE).query(Q.where('name', Q.oneOf(names)));
};
export function observePermissionForChannel(channel: ChannelModel, user: UserModel, permission: string, defaultValue: boolean) {
const database = channel.database;
export function observePermissionForChannel(database: Database, channel: ChannelModel, user: UserModel, permission: string, defaultValue: boolean) {
const myChannel = observeMyChannel(database, channel.id);
const myTeam = channel.teamId ? observeMyTeam(database, channel.teamId) : of$(undefined);
@@ -56,8 +55,7 @@ export function observePermissionForChannel(channel: ChannelModel, user: UserMod
}));
}
export function observePermissionForTeam(team: TeamModel, user: UserModel, permission: string, defaultValue: boolean) {
const database = team.database;
export function observePermissionForTeam(database: Database, team: TeamModel, user: UserModel, permission: string, defaultValue: boolean) {
return observeMyTeam(database, team.id).pipe(
switchMap((myTeam) => {
const rolesArray = [...user.roles.split(' ')];
@@ -73,17 +71,17 @@ export function observePermissionForTeam(team: TeamModel, user: UserModel, permi
);
}
export function observePermissionForPost(post: PostModel, user: UserModel, permission: string, defaultValue: boolean) {
return observeChannel(post.database, post.channelId).pipe(switchMap((c) => (c ? observePermissionForChannel(c, user, permission, defaultValue) : of$(defaultValue))));
export function observePermissionForPost(database: Database, post: PostModel, user: UserModel, permission: string, defaultValue: boolean) {
return observeChannel(database, post.channelId).pipe(switchMap((c) => (c ? observePermissionForChannel(database, c, user, permission, defaultValue) : of$(defaultValue))));
}
export function observeCanManageChannelMembers(post: PostModel, user: UserModel) {
return observeChannel(post.database, post.channelId).pipe((switchMap((c) => {
export function observeCanManageChannelMembers(database: Database, post: PostModel, user: UserModel) {
return observeChannel(database, post.channelId).pipe((switchMap((c) => {
if (!c || c.deleteAt !== 0 || isDMorGM(c) || c.name === General.DEFAULT_CHANNEL) {
return of$(false);
}
const permission = c.type === General.OPEN_CHANNEL ? Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS : Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS;
return observePermissionForChannel(c, user, permission, true);
return observePermissionForChannel(database, c, user, permission, true);
})));
}

View File

@@ -47,10 +47,10 @@ const enhanced = withObservables(['channelId', 'type'], ({channelId, database, t
}
if (type === General.OPEN_CHANNEL) {
return observePermissionForChannel(ch, u, Permissions.DELETE_PUBLIC_CHANNEL, true);
return observePermissionForChannel(database, ch, u, Permissions.DELETE_PUBLIC_CHANNEL, true);
}
return observePermissionForChannel(ch, u, Permissions.DELETE_PRIVATE_CHANNEL, true);
return observePermissionForChannel(database, ch, u, Permissions.DELETE_PRIVATE_CHANNEL, true);
}),
);
@@ -64,7 +64,7 @@ const enhanced = withObservables(['channelId', 'type'], ({channelId, database, t
return of$(false);
}
return observePermissionForTeam(t, u, Permissions.MANAGE_TEAM, false);
return observePermissionForTeam(database, t, u, Permissions.MANAGE_TEAM, false);
}),
);

View File

@@ -29,7 +29,7 @@ const enhanced = withObservables(['channelId'], ({channelId, database}: Props) =
return of$(false);
}
return observePermissionForChannel(ch, u, Permissions.CONVERT_PUBLIC_CHANNEL_TO_PRIVATE, false);
return observePermissionForChannel(database, ch, u, Permissions.CONVERT_PUBLIC_CHANNEL_TO_PRIVATE, false);
}),
);

View File

@@ -21,15 +21,15 @@ const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
const currentUser = observeCurrentUser(database);
const canJoinChannels = combineLatest([currentUser, team]).pipe(
switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.JOIN_PUBLIC_CHANNELS, true) : of$(false))),
switchMap(([u, t]) => (t && u ? observePermissionForTeam(database, t, u, Permissions.JOIN_PUBLIC_CHANNELS, true) : of$(false))),
);
const canCreatePublicChannels = combineLatest([currentUser, team]).pipe(
switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.CREATE_PUBLIC_CHANNEL, true) : of$(false))),
switchMap(([u, t]) => (t && u ? observePermissionForTeam(database, t, u, Permissions.CREATE_PUBLIC_CHANNEL, true) : of$(false))),
);
const canCreatePrivateChannels = combineLatest([currentUser, team]).pipe(
switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.CREATE_PRIVATE_CHANNEL, false) : of$(false))),
switchMap(([u, t]) => (t && u ? observePermissionForTeam(database, t, u, Permissions.CREATE_PRIVATE_CHANNEL, false) : of$(false))),
);
const canCreateChannels = combineLatest([canCreatePublicChannels, canCreatePrivateChannels]).pipe(

View File

@@ -22,17 +22,17 @@ const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
const currentUser = observeCurrentUser(database);
const canJoinChannels = combineLatest([currentUser, team]).pipe(
switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.JOIN_PUBLIC_CHANNELS, true) : of$(false))),
switchMap(([u, t]) => (t && u ? observePermissionForTeam(database, t, u, Permissions.JOIN_PUBLIC_CHANNELS, true) : of$(false))),
distinctUntilChanged(),
);
const canCreatePublicChannels = combineLatest([currentUser, team]).pipe(
switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.CREATE_PUBLIC_CHANNEL, true) : of$(false))),
switchMap(([u, t]) => (t && u ? observePermissionForTeam(database, t, u, Permissions.CREATE_PUBLIC_CHANNEL, true) : of$(false))),
distinctUntilChanged(),
);
const canCreatePrivateChannels = combineLatest([currentUser, team]).pipe(
switchMap(([u, t]) => (t && u ? observePermissionForTeam(t, u, Permissions.CREATE_PRIVATE_CHANNEL, false) : of$(false))),
switchMap(([u, t]) => (t && u ? observePermissionForTeam(database, t, u, Permissions.CREATE_PRIVATE_CHANNEL, false) : of$(false))),
distinctUntilChanged(),
);

View File

@@ -466,7 +466,7 @@ const ServerItem = ({
{Boolean(database) && server.lastActiveAt > 0 &&
<WebSocket
database={database}
database={database!}
/>
}
{showTutorial &&

View File

@@ -143,6 +143,8 @@ const InAppNotification = ({componentId, serverName, serverUrl, notification}: I
// eslint-disable-next-line new-cap
const gesture = Gesture.Pan().activeOffsetY(-20).onStart(() => runOnJS(animateDismissOverlay)());
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
return (
<GestureHandlerRootView>
<GestureDetector gesture={gesture}>
@@ -156,14 +158,16 @@ const InAppNotification = ({componentId, serverName, serverUrl, notification}: I
onPress={notificationTapped}
activeOpacity={1}
>
{Boolean(database) &&
<Icon
database={DatabaseManager.serverDatabases[serverUrl].database}
database={database!}
fromWebhook={notification.payload?.from_webhook === 'true'}
overrideIconUrl={notification.payload?.override_icon_url}
senderId={notification.payload?.sender_id || ''}
serverUrl={serverUrl}
useUserIcon={notification.payload?.use_user_icon === 'true'}
/>
}
<View style={styles.titleContainer}>
<Title channelName={notification.payload?.channel_name || ''}/>
<View style={styles.flex}>

View File

@@ -20,6 +20,7 @@ import {isSystemAdmin} from '@utils/user';
import PostOptions from './post_options';
import type {Database} from '@nozbe/watermelondb';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type PostModel from '@typings/database/models/servers/post';
@@ -33,7 +34,7 @@ type EnhancedProps = WithDatabaseArgs & {
location: string;
}
const observeCanEditPost = (isOwner: boolean, post: PostModel, postEditTimeLimit: number, isLicensed: boolean, channel: ChannelModel, user: UserModel) => {
const observeCanEditPost = (database: Database, isOwner: boolean, post: PostModel, postEditTimeLimit: number, isLicensed: boolean, channel: ChannelModel, user: UserModel) => {
if (!post || isSystemMessage(post)) {
return of$(false);
}
@@ -45,11 +46,11 @@ const observeCanEditPost = (isOwner: boolean, post: PostModel, postEditTimeLimit
}
}
return observePermissionForChannel(channel, user, Permissions.EDIT_POST, false).pipe(switchMap((v) => {
return observePermissionForChannel(database, channel, user, Permissions.EDIT_POST, false).pipe(switchMap((v) => {
if (!v || isOwner) {
return of$(v);
}
return observePermissionForChannel(channel, user, Permissions.EDIT_OTHERS_POSTS, false);
return observePermissionForChannel(database, channel, user, Permissions.EDIT_OTHERS_POSTS, false);
}));
};
@@ -78,11 +79,11 @@ const enhanced = withObservables([], ({combinedPost, post, showAddReaction, loca
const serverVersion = config.pipe(switchMap((cfg) => of$(cfg?.Version || '')));
const postEditTimeLimit = config.pipe(switchMap((cfg) => of$(parseInt(cfg?.PostEditTimeLimit || '-1', 10))));
const canPostPermission = combineLatest([channel, currentUser]).pipe(switchMap(([c, u]) => ((c && u) ? observePermissionForChannel(c, u, Permissions.CREATE_POST, false) : of$(false))));
const hasAddReactionPermission = currentUser.pipe(switchMap((u) => (u ? observePermissionForPost(post, u, Permissions.ADD_REACTION, true) : of$(false))));
const canPostPermission = combineLatest([channel, currentUser]).pipe(switchMap(([c, u]) => ((c && u) ? observePermissionForChannel(database, c, u, Permissions.CREATE_POST, false) : of$(false))));
const hasAddReactionPermission = currentUser.pipe(switchMap((u) => (u ? observePermissionForPost(database, post, u, Permissions.ADD_REACTION, true) : of$(false))));
const canDeletePostPermission = currentUser.pipe(switchMap((u) => {
const isOwner = post.userId === u?.id;
return u ? observePermissionForPost(post, u, isOwner ? Permissions.DELETE_POST : Permissions.DELETE_OTHERS_POSTS, false) : of$(false);
return u ? observePermissionForPost(database, post, u, isOwner ? Permissions.DELETE_POST : Permissions.DELETE_OTHERS_POSTS, false) : of$(false);
}));
const experimentalTownSquareIsReadOnly = config.pipe(switchMap((value) => of$(value?.ExperimentalTownSquareIsReadOnly === 'true')));
@@ -117,7 +118,7 @@ const enhanced = withObservables([], ({combinedPost, post, showAddReaction, loca
const canEdit = combineLatest([postEditTimeLimit, isLicensed, channel, currentUser, channelIsArchived, channelIsReadOnly, canEditUntil, canPostPermission]).pipe(
switchMap(([lt, ls, c, u, isArchived, isReadOnly, until, canPost]) => {
const isOwner = u?.id === post.userId;
const canEditPostPermission = (c && u) ? observeCanEditPost(isOwner, post, lt, ls, c, u) : of$(false);
const canEditPostPermission = (c && u) ? observeCanEditPost(database, isOwner, post, lt, ls, c, u) : of$(false);
const timeNotReached = (until === -1) || (until > Date.now());
return canEditPostPermission.pipe(
// eslint-disable-next-line max-nested-callbacks

View File

@@ -54,7 +54,7 @@ class TestHelper {
setupServerDatabase = async () => {
const serverUrl = 'https://appv1.mattermost.com';
await DatabaseManager.init([serverUrl]);
const {database, operator} = DatabaseManager.serverDatabases[serverUrl];
const {database, operator} = DatabaseManager.serverDatabases[serverUrl]!;
this.initMockEntities();

View File

@@ -42,7 +42,7 @@ export type ServerDatabase = {
}
export type ServerDatabases = {
[x: string]: ServerDatabase;
[x: string]: ServerDatabase | undefined;
};
export type TransformerArgs = {