diff --git a/app/actions/remote/entry/common.ts b/app/actions/remote/entry/common.ts index 8cf9ec22dc..c04d0b576f 100644 --- a/app/actions/remote/entry/common.ts +++ b/app/actions/remote/entry/common.ts @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import {fetchChannelStats, fetchMissingSidebarInfo, fetchMyChannelsForTeam, markChannelAsRead, MyChannelsRequest} from '@actions/remote/channel'; -import {fetchGroupsForTeam} from '@actions/remote/group'; import {fetchPostsForChannel, fetchPostsForUnreadChannels} from '@actions/remote/post'; import {MyPreferencesRequest, fetchMyPreferences} from '@actions/remote/preference'; import {fetchConfigAndLicense} from '@actions/remote/systems'; @@ -183,11 +182,6 @@ export const deferredAppEntryActions = async ( fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, initialChannelId); } - // defer groups for team - if (initialTeamId) { - fetchGroupsForTeam(serverUrl, initialTeamId, since); - } - // defer fetch channels and unread posts for other teams if (teamData.teams?.length && teamData.memberships?.length) { await fetchTeamsChannelsAndUnreadPosts(serverUrl, since, teamData.teams, teamData.memberships, initialTeamId); diff --git a/app/actions/remote/group.ts b/app/actions/remote/group.ts deleted file mode 100644 index 6b0436d7d5..0000000000 --- a/app/actions/remote/group.ts +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Model} from '@nozbe/watermelondb'; - -import DatabaseManager from '@database/manager'; -import NetworkManager from '@init/network_manager'; -import {queryCommonSystemValues} from '@queries/servers/system'; -import {queryTeamById} from '@queries/servers/team'; - -import {forceLogoutIfNecessary} from './session'; - -export const fetchGroupsForTeam = async (serverUrl: string, teamId: string, since: number) => { - const database = DatabaseManager.serverDatabases[serverUrl]?.database; - if (!database) { - return {error: `${serverUrl} database not found`}; - } - - let client; - try { - client = NetworkManager.getClient(serverUrl); - } catch (error) { - return {error}; - } - - try { - const system = await queryCommonSystemValues(database); - const team = await queryTeamById(database, teamId); - const hasLicense = system.license.IsLicensed === 'true' && system.license.LDAPGroups === 'true'; - - if (hasLicense && team) { - const groups: Group[] = []; - const groupsChannels: GroupChannelRelation[] = []; - const groupsTeams: GroupTeamRelation[] = []; - const groupMemberships: GroupMembership[] = []; - if (team.isGroupConstrained) { - const [groupsAssociatedToChannelsInTeam, groupsAssociatedToTeam]: [{groups: Record}, {groups: Group[]; total_group_count: number}] = await Promise.all([ - client.getAllGroupsAssociatedToChannelsInTeam(teamId, true), - client.getAllGroupsAssociatedToTeam(teamId, true), - ]); - - if (groupsAssociatedToChannelsInTeam.groups) { - const keys = Object.keys(groupsAssociatedToChannelsInTeam.groups); - for (const key of keys) { - for (const group of groupsAssociatedToChannelsInTeam.groups[key]) { - groups.push(group); - groupsChannels.push({ - channel_id: key, - group_id: group.id, - }); - } - } - } - - if (groupsAssociatedToTeam.groups) { - for (const group of groupsAssociatedToTeam.groups) { - groups.push(group); - groupsTeams.push({group_id: group.id, team_id: teamId}); - } - } - } else { - const [groupsAssociatedToChannelsInTeam, allGroups]: [{groups: Record}, Group[]] = await Promise.all([ - client.getAllGroupsAssociatedToChannelsInTeam(teamId, true), - client.getGroups(true, 0, 0, since), - ]); - - if (groupsAssociatedToChannelsInTeam.groups) { - const keys = Object.keys(groupsAssociatedToChannelsInTeam.groups); - for (const key of keys) { - for (const group of groupsAssociatedToChannelsInTeam.groups[key]) { - groups.push(group); - groupsChannels.push({ - channel_id: key, - group_id: group.id, - }); - } - } - } - - if (allGroups?.length) { - groups.push(...allGroups); - } - } - - const userGroups = await client.getGroupsByUserId(system.currentUserId); - if (userGroups) { - for (const mg of userGroups) { - groupMemberships.push({group_id: mg.id, user_id: system.currentUserId}); - groups.push(mg); - } - } - - const models: Model[] = []; - const {operator} = DatabaseManager.serverDatabases[serverUrl]; - if (groups.length) { - const gModels = await operator.handleGroup({groups, prepareRecordsOnly: true}); - if (gModels.length) { - models.push(...gModels); - } - } - - if (groupsChannels.length) { - const gcModels = await operator.handleGroupsChannel({groupsChannels, prepareRecordsOnly: true}); - if (gcModels.length) { - models.push(...gcModels); - } - } - - if (groupsTeams.length) { - const gtModels = await operator.handleGroupsTeam({groupsTeams, prepareRecordsOnly: true}); - if (gtModels.length) { - models.push(...gtModels); - } - } - - if (groupMemberships.length) { - const gmModels = await operator.handleGroupMembership({groupMemberships, prepareRecordsOnly: true}); - if (gmModels.length) { - models.push(...gmModels); - } - } - - if (models.length) { - await operator.batchRecords(models.flat()); - } - } - return null; - } catch (error) { - forceLogoutIfNecessary(serverUrl, error as ClientErrorProps); - return {error}; - } -}; diff --git a/app/actions/websocket/index.ts b/app/actions/websocket/index.ts index 89453922f6..aa203346d5 100644 --- a/app/actions/websocket/index.ts +++ b/app/actions/websocket/index.ts @@ -3,7 +3,6 @@ import {fetchMissingSidebarInfo, switchToChannelById} from '@actions/remote/channel'; import {AppEntryData, AppEntryError, fetchAppEntryData} from '@actions/remote/entry/common'; -import {fetchGroupsForTeam} from '@actions/remote/group'; import {fetchPostsForUnreadChannels, fetchPostsSince} from '@actions/remote/post'; import {fetchRoles} from '@actions/remote/role'; import {fetchConfigAndLicense} from '@actions/remote/systems'; @@ -179,10 +178,6 @@ async function doReconnect(serverUrl: string) { } } - if (initialTeamId) { - fetchGroupsForTeam(serverUrl, initialTeamId, lastDisconnectedAt); - } - // defer fetch channels and unread posts for other teams if (teamData.teams?.length && teamData.memberships?.length) { await fetchTeamsChannelsAndUnreadPosts(serverUrl, lastDisconnectedAt, teamData.teams, teamData.memberships, initialTeamId); @@ -335,11 +330,6 @@ export async function handleEvent(serverUrl: string, msg: WebSocketMessage) { case WebsocketEvents.OPEN_DIALOG: break; - // return dispatch(handleOpenDialogEvent(msg)); - case WebsocketEvents.RECEIVED_GROUP: - break; - - // return dispatch(handleGroupUpdatedEvent(msg)); case WebsocketEvents.THREAD_UPDATED: break; diff --git a/app/components/markdown/at_mention/index.tsx b/app/components/markdown/at_mention/index.tsx index 2e955f06ec..c18c15e91d 100644 --- a/app/components/markdown/at_mention/index.tsx +++ b/app/components/markdown/at_mention/index.tsx @@ -20,11 +20,9 @@ import {useTheme} from '@context/theme'; import UserModel from '@database/models/server/user'; import {getTeammateNameDisplaySetting} from '@helpers/api/preference'; import {bottomSheet, dismissBottomSheet, showModal} from '@screens/navigation'; -import {displayUsername, getUserMentionKeys, getUsersByUsername} from '@utils/user'; +import {displayUsername, getUsersByUsername} from '@utils/user'; import type {WithDatabaseArgs} from '@typings/database/database'; -import type GroupModel from '@typings/database/models/servers/group'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; import type PreferenceModel from '@typings/database/models/servers/preference'; import type SystemModel from '@typings/database/models/servers/system'; import type UserModelType from '@typings/database/models/servers/user'; @@ -33,19 +31,17 @@ type AtMentionProps = { currentUserId: string; database: Database; disableAtChannelMentionHighlight?: boolean; - groups: GroupModel[]; isSearchResult?: boolean; mentionKeys?: Array<{key: string }>; mentionName: string; mentionStyle: TextStyle; - myGroups: GroupMembershipModel[]; onPostPress?: (e: GestureResponderEvent) => void; teammateNameDisplay: string; textStyle?: StyleProp; users: UserModelType[]; } -const {SERVER: {GROUP, GROUP_MEMBERSHIP, PREFERENCE, SYSTEM, USER}} = MM_TABLES; +const {SERVER: {PREFERENCE, SYSTEM, USER}} = MM_TABLES; const style = StyleSheet.create({ bottomSheet: { @@ -57,12 +53,10 @@ const AtMention = ({ currentUserId, database, disableAtChannelMentionHighlight, - groups, isSearchResult, mentionName, mentionKeys, mentionStyle, - myGroups, onPostPress, teammateNameDisplay, textStyle, @@ -99,13 +93,9 @@ const AtMention = ({ if (user.id !== currentUserId) { return []; } - return getUserMentionKeys(user, groups, myGroups); - }, [currentUserId, groups, mentionKeys, myGroups, user]); - const getGroupFromMentionName = () => { - const mentionNameTrimmed = mentionName.toLowerCase().replace(/[._-]*$/, ''); - return groups.find((g) => g.name === mentionNameTrimmed); - }; + return user.mentionKeys; + }, [currentUserId, mentionKeys, user]); const goToUserProfile = useCallback(() => { const screen = 'UserProfile'; @@ -199,24 +189,16 @@ const AtMention = ({ isMention = true; canPress = true; } else { - const group = getGroupFromMentionName(); - if (group?.allowReference) { - highlighted = userMentionKeys.some((item) => item.key === `@${group.name}`); - isMention = true; - mention = group.name; - suffix = mentionName.substring(group.name.length); - } else { - const pattern = new RegExp(/\b(all|channel|here)(?:\.\B|_\b|\b)/, 'i'); - const mentionMatch = pattern.exec(mentionName); + const pattern = new RegExp(/\b(all|channel|here)(?:\.\B|_\b|\b)/, 'i'); + const mentionMatch = pattern.exec(mentionName); - if (mentionMatch && !disableAtChannelMentionHighlight) { - mention = mentionMatch.length > 1 ? mentionMatch[1] : mentionMatch[0]; - suffix = mentionName.replace(mention, ''); - isMention = true; - highlighted = true; - } else { - mention = mentionName; - } + if (mentionMatch && !disableAtChannelMentionHighlight) { + mention = mentionMatch.length > 1 ? mentionMatch[1] : mentionMatch[0]; + suffix = mentionName.replace(mention, ''); + isMention = true; + highlighted = true; + } else { + mention = mentionName; } } @@ -276,8 +258,6 @@ const withAtMention = withObservables(['mentionName'], ({database, mentionName}: return { currentUserId, - groups: database.get(GROUP).query(Q.where('delete_at', Q.eq(0))).observe(), - myGroups: database.get(GROUP_MEMBERSHIP).query().observe(), teammateNameDisplay, users: database.get(USER).query( Q.where('username', Q.like( diff --git a/app/components/post_draft/send_handler/index.ts b/app/components/post_draft/send_handler/index.ts index cf06913b5b..4ccaeb2eae 100644 --- a/app/components/post_draft/send_handler/index.ts +++ b/app/components/post_draft/send_handler/index.ts @@ -1,7 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {Q} from '@nozbe/watermelondb'; import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; import {combineLatest, of as of$, from as from$} from 'rxjs'; @@ -18,11 +17,10 @@ import type {WithDatabaseArgs} from '@typings/database/database'; import type ChannelModel from '@typings/database/models/servers/channel'; import type ChannelInfoModel from '@typings/database/models/servers/channel_info'; import type CustomEmojiModel from '@typings/database/models/servers/custom_emoji'; -import type GroupModel from '@typings/database/models/servers/group'; import type SystemModel from '@typings/database/models/servers/system'; import type UserModel from '@typings/database/models/servers/user'; -const {SERVER: {SYSTEM, USER, CHANNEL, GROUP, GROUPS_TEAM, GROUPS_CHANNEL, CUSTOM_EMOJI}} = MM_TABLES; +const {SERVER: {SYSTEM, USER, CHANNEL, CUSTOM_EMOJI}} = MM_TABLES; type OwnProps = { rootId: string; @@ -75,27 +73,6 @@ const enhanced = withObservables([], (ownProps: WithDatabaseArgs & OwnProps) => }), ); - const license = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe( - switchMap(({value}) => of$(value as ClientLicense)), - ); - - const useGroupMentions = combineLatest([channel, currentUser, license]).pipe( - switchMap(([c, u, l]) => { - if (!c || l?.IsLicensed !== 'true') { - return of$(false); - } - - return from$(hasPermissionForChannel(c, u, Permissions.USE_GROUP_MENTIONS, true)); - }), - ); - - const groupsWithAllowReference = channel.pipe(switchMap( - (c) => database.get(GROUP).query( - Q.experimentalJoinTables([GROUPS_TEAM, GROUPS_CHANNEL]), - Q.or(Q.on(GROUPS_TEAM, 'team_id', c.teamId), Q.on(GROUPS_CHANNEL, 'channel_id', c.id)), - ).observeWithColumns(['name'])), - ); - const channelInfo = channel.pipe(switchMap((c) => c.info.observe())); const membersCount = channelInfo.pipe( switchMap((i: ChannelInfoModel) => of$(i.memberCount)), @@ -111,8 +88,6 @@ const enhanced = withObservables([], (ownProps: WithDatabaseArgs & OwnProps) => membersCount, userIsOutOfOffice, useChannelMentions, - useGroupMentions, - groupsWithAllowReference, customEmojis, }; }); diff --git a/app/components/post_draft/send_handler/send_handler.tsx b/app/components/post_draft/send_handler/send_handler.tsx index 18fa362f9d..51af3aab3b 100644 --- a/app/components/post_draft/send_handler/send_handler.tsx +++ b/app/components/post_draft/send_handler/send_handler.tsx @@ -5,7 +5,7 @@ import React, {useCallback, useEffect, useState} from 'react'; import {useIntl} from 'react-intl'; import {DeviceEventEmitter} from 'react-native'; -import {getChannelMemberCountsByGroup, getChannelTimezones} from '@actions/remote/channel'; +import {getChannelTimezones} from '@actions/remote/channel'; import {executeCommand, handleGotoLocation} from '@actions/remote/command'; import {createPost} from '@actions/remote/post'; import {handleReactionToLatestPost} from '@actions/remote/reactions'; @@ -22,7 +22,6 @@ import {confirmOutOfOfficeDisabled} from '@utils/user'; import DraftInput from '../draft_input'; import type CustomEmojiModel from '@typings/database/models/servers/custom_emoji'; -import type GroupModel from '@typings/database/models/servers/group'; type Props = { testID?: string; @@ -38,8 +37,6 @@ type Props = { membersCount?: number; useChannelMentions: boolean; userIsOutOfOffice: boolean; - useGroupMentions: boolean; - groupsWithAllowReference: GroupModel[]; customEmojis: CustomEmojiModel[]; // DRAFT Handler @@ -68,8 +65,6 @@ export default function SendHandler({ userIsOutOfOffice, customEmojis, value, - useGroupMentions, - groupsWithAllowReference, clearDraft, updateValue, addFiles, @@ -82,7 +77,6 @@ export default function SendHandler({ const [channelTimezoneCount, setChannelTimezoneCount] = useState(0); const [sendingMessage, setSendingMessage] = useState(false); - const [channelMemberCountsByGroup, setChannelMemberCountsByGroup] = useState([]); const canSend = useCallback(() => { if (sendingMessage) { @@ -134,15 +128,6 @@ export default function SendHandler({ DraftUtils.alertChannelWideMention(intl, notifyAllMessage, doSubmitMessage, cancel); }, [intl, isTimezoneEnabled, channelTimezoneCount, doSubmitMessage]); - const showSendToGroupsAlert = useCallback((groupMentions: string[], memberNotifyCount: number, calculatedChannelTimezoneCount: number) => { - const notifyAllMessage = DraftUtils.buildGroupMentionsMessage(intl, groupMentions, memberNotifyCount, calculatedChannelTimezoneCount); - const cancel = () => { - setSendingMessage(false); - }; - - DraftUtils.alertSendToGroups(intl, notifyAllMessage, doSubmitMessage, cancel); - }, [intl, doSubmitMessage]); - const sendCommand = useCallback(async () => { const status = DraftUtils.getStatusFromSlashCommand(value); if (userIsOutOfOffice && status) { @@ -182,40 +167,23 @@ export default function SendHandler({ const sendMessage = useCallback(() => { const notificationsToChannel = enableConfirmNotificationsToChannel && useChannelMentions; - const notificationsToGroups = enableConfirmNotificationsToChannel && useGroupMentions; const toAllOrChannel = DraftUtils.textContainsAtAllAtChannel(value); const toHere = DraftUtils.textContainsAtHere(value); - const groupMentions = (!toAllOrChannel && !toHere && notificationsToGroups) ? DraftUtils.groupsMentionedInText(groupsWithAllowReference, value) : []; if (value.indexOf('/') === 0) { sendCommand(); } else if (notificationsToChannel && membersCount > NOTIFY_ALL_MEMBERS && (toAllOrChannel || toHere)) { showSendToAllOrChannelOrHereAlert(membersCount, toHere && !toAllOrChannel); - } else if (groupMentions.length > 0) { - const { - groupMentionsSet, - memberNotifyCount, - channelTimezoneCount: calculatedChannelTimezoneCount, - } = DraftUtils.mapGroupMentions(channelMemberCountsByGroup, groupMentions); - if (memberNotifyCount > 0) { - showSendToGroupsAlert(Array.from(groupMentionsSet), memberNotifyCount, calculatedChannelTimezoneCount); - } else { - doSubmitMessage(); - } } else { doSubmitMessage(); } }, [ enableConfirmNotificationsToChannel, useChannelMentions, - useGroupMentions, value, - groupsWithAllowReference, channelTimezoneCount, - channelMemberCountsByGroup, sendCommand, showSendToAllOrChannelOrHereAlert, - showSendToGroupsAlert, doSubmitMessage, ]); @@ -248,21 +216,6 @@ export default function SendHandler({ } }), [canSend, value, handleReaction, files, sendMessage, customEmojis]); - useEffect(() => { - if (useGroupMentions) { - getChannelMemberCountsByGroup(serverUrl, channelId, isTimezoneEnabled).then((resp) => { - if (resp.error) { - return; - } - - const received = resp.channelMemberCountsByGroup || []; - if (received.length || channelMemberCountsByGroup.length) { - setChannelMemberCountsByGroup(received); - } - }); - } - }, [useGroupMentions, channelId, isTimezoneEnabled, channelMemberCountsByGroup.length]); - useEffect(() => { getChannelTimezones(serverUrl, channelId).then(({channelTimezones}) => { setChannelTimezoneCount(channelTimezones?.length || 0); diff --git a/app/components/post_list/post/body/message/index.ts b/app/components/post_list/post/body/message/index.ts index e498abb2cc..5cc21eda69 100644 --- a/app/components/post_list/post/body/message/index.ts +++ b/app/components/post_list/post/body/message/index.ts @@ -3,34 +3,24 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; -import {from as from$} from 'rxjs'; import {switchMap} from 'rxjs/operators'; import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; -import {queryGroupForPosts} from '@helpers/database/groups'; import Message from './message'; import type {WithDatabaseArgs} from '@typings/database/database'; -import type PostModel from '@typings/database/models/servers/post'; import type SystemModel from '@typings/database/models/servers/system'; import type UserModel from '@typings/database/models/servers/user'; const {SERVER: {SYSTEM, USER}} = MM_TABLES; -type MessageInputArgs = { - post: PostModel; -} - -const withMessageInput = withObservables(['post'], ({database, post}: WithDatabaseArgs & MessageInputArgs) => { +const withMessageInput = withObservables([], ({database}: WithDatabaseArgs) => { const currentUser = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe( switchMap(({value}) => database.get(USER).findAndObserve(value)), ); - const groupsForPosts = from$(queryGroupForPosts(post)); - return { currentUser, - groupsForPosts, }; }); diff --git a/app/components/post_list/post/body/message/message.tsx b/app/components/post_list/post/body/message/message.tsx index 014ae67db6..1afa78ff05 100644 --- a/app/components/post_list/post/body/message/message.tsx +++ b/app/components/post_list/post/body/message/message.tsx @@ -9,18 +9,15 @@ import Markdown from '@components/markdown'; import {SEARCH} from '@constants/screens'; import {useShowMoreAnimatedStyle} from '@hooks/show_more'; import {getMarkdownTextStyles, getMarkdownBlockStyles} from '@utils/markdown'; -import {getMentionKeysForPost} from '@utils/post'; import {makeStyleSheetFromTheme} from '@utils/theme'; import ShowMoreButton from './show_more_button'; -import type GroupModel from '@typings/database/models/servers/group'; import type PostModel from '@typings/database/models/servers/post'; import type UserModel from '@typings/database/models/servers/user'; type MessageProps = { currentUser: UserModel; - groupsForPosts: GroupModel[]; highlight: boolean; isEdited: boolean; isPendingOrFailed: boolean; @@ -52,7 +49,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -const Message = ({currentUser, groupsForPosts, highlight, isEdited, isPendingOrFailed, isReplyPost, location, post, theme}: MessageProps) => { +const Message = ({currentUser, highlight, isEdited, isPendingOrFailed, isReplyPost, location, post, theme}: MessageProps) => { const [open, setOpen] = useState(false); const [height, setHeight] = useState(); const dimensions = useWindowDimensions(); @@ -61,9 +58,10 @@ const Message = ({currentUser, groupsForPosts, highlight, isEdited, isPendingOrF const style = getStyleSheet(theme); const blockStyles = getMarkdownBlockStyles(theme); const textStyles = getMarkdownTextStyles(theme); + const mentionKeys = useMemo(() => { - return getMentionKeysForPost(currentUser, post, groupsForPosts); - }, [currentUser, post.message, groupsForPosts]); + return currentUser.mentionKeys; + }, [currentUser]); const onLayout = useCallback((event: LayoutChangeEvent) => setHeight(event.nativeEvent.layout.height), []); const onPress = () => setOpen(!open); diff --git a/app/constants/database.ts b/app/constants/database.ts index 07e867f87e..8a818a9c82 100644 --- a/app/constants/database.ts +++ b/app/constants/database.ts @@ -18,10 +18,6 @@ export const MM_TABLES = { CUSTOM_EMOJI: 'CustomEmoji', DRAFT: 'Draft', FILE: 'File', - GROUP: 'Group', - GROUPS_CHANNEL: 'GroupsChannel', - GROUPS_TEAM: 'GroupsTeam', - GROUP_MEMBERSHIP: 'GroupMembership', MY_CHANNEL: 'MyChannel', MY_CHANNEL_SETTINGS: 'MyChannelSettings', MY_TEAM: 'MyTeam', diff --git a/app/constants/websocket.ts b/app/constants/websocket.ts index b7191e345b..46dd09887a 100644 --- a/app/constants/websocket.ts +++ b/app/constants/websocket.ts @@ -44,7 +44,6 @@ const WebsocketEvents = { OPEN_DIALOG: 'open_dialog', INCREASE_POST_VISIBILITY_BY_ONE: 'increase_post_visibility_by_one', MEMBERROLE_UPDATED: 'memberrole_updated', - RECEIVED_GROUP: 'received_group', THREAD_UPDATED: 'thread_updated', THREAD_FOLLOW_CHANGED: 'thread_follow_changed', THREAD_READ_CHANGED: 'thread_read_changed', diff --git a/app/database/manager/__mocks__/index.ts b/app/database/manager/__mocks__/index.ts index 3af7e380ff..8fe94f81ae 100644 --- a/app/database/manager/__mocks__/index.ts +++ b/app/database/manager/__mocks__/index.ts @@ -12,7 +12,7 @@ import AppDatabaseMigrations from '@database/migration/app'; import ServerDatabaseMigrations from '@database/migration/server'; import {InfoModel, GlobalModel, ServersModel} from '@database/models/app'; import {CategoryModel, CategoryChannelModel, ChannelModel, ChannelInfoModel, ChannelMembershipModel, CustomEmojiModel, DraftModel, FileModel, - GroupModel, GroupMembershipModel, GroupsChannelModel, GroupsTeamModel, MyChannelModel, MyChannelSettingsModel, MyTeamModel, + MyChannelModel, MyChannelSettingsModel, MyTeamModel, PostModel, PostsInChannelModel, PostsInThreadModel, PreferenceModel, ReactionModel, RoleModel, SlashCommandModel, SystemModel, TeamModel, TeamChannelHistoryModel, TeamMembershipModel, TeamSearchHistoryModel, TermsOfServiceModel, UserModel, @@ -48,7 +48,7 @@ class DatabaseManager { this.appModels = [InfoModel, GlobalModel, ServersModel]; this.serverModels = [ CategoryModel, CategoryChannelModel, ChannelModel, ChannelInfoModel, ChannelMembershipModel, CustomEmojiModel, DraftModel, FileModel, - GroupModel, GroupMembershipModel, GroupsChannelModel, GroupsTeamModel, MyChannelModel, MyChannelSettingsModel, MyTeamModel, + MyChannelModel, MyChannelSettingsModel, MyTeamModel, PostModel, PostsInChannelModel, PostsInThreadModel, PreferenceModel, ReactionModel, RoleModel, SlashCommandModel, SystemModel, TeamModel, TeamChannelHistoryModel, TeamMembershipModel, TeamSearchHistoryModel, TermsOfServiceModel, UserModel, diff --git a/app/database/manager/index.ts b/app/database/manager/index.ts index 6dd5a6281c..c04a44fb5f 100644 --- a/app/database/manager/index.ts +++ b/app/database/manager/index.ts @@ -13,7 +13,7 @@ import AppDatabaseMigrations from '@database/migration/app'; import ServerDatabaseMigrations from '@database/migration/server'; import {InfoModel, GlobalModel, ServersModel} from '@database/models/app'; import {CategoryModel, CategoryChannelModel, ChannelModel, ChannelInfoModel, ChannelMembershipModel, CustomEmojiModel, DraftModel, FileModel, - GroupModel, GroupMembershipModel, GroupsChannelModel, GroupsTeamModel, MyChannelModel, MyChannelSettingsModel, MyTeamModel, + MyChannelModel, MyChannelSettingsModel, MyTeamModel, PostModel, PostsInChannelModel, PostsInThreadModel, PreferenceModel, ReactionModel, RoleModel, SlashCommandModel, SystemModel, TeamModel, TeamChannelHistoryModel, TeamMembershipModel, TeamSearchHistoryModel, TermsOfServiceModel, UserModel, @@ -43,7 +43,7 @@ class DatabaseManager { this.appModels = [InfoModel, GlobalModel, ServersModel]; this.serverModels = [ CategoryModel, CategoryChannelModel, ChannelModel, ChannelInfoModel, ChannelMembershipModel, CustomEmojiModel, DraftModel, FileModel, - GroupModel, GroupMembershipModel, GroupsChannelModel, GroupsTeamModel, MyChannelModel, MyChannelSettingsModel, MyTeamModel, + MyChannelModel, MyChannelSettingsModel, MyTeamModel, PostModel, PostsInChannelModel, PostsInThreadModel, PreferenceModel, ReactionModel, RoleModel, SlashCommandModel, SystemModel, TeamModel, TeamChannelHistoryModel, TeamMembershipModel, TeamSearchHistoryModel, TermsOfServiceModel, UserModel, diff --git a/app/database/models/server/channel.ts b/app/database/models/server/channel.ts index 7394e83a45..b47b129726 100644 --- a/app/database/models/server/channel.ts +++ b/app/database/models/server/channel.ts @@ -10,7 +10,6 @@ import {MM_TABLES} from '@constants/database'; import type ChannelInfoModel from '@typings/database/models/servers/channel_info'; import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership'; import type DraftModel from '@typings/database/models/servers/draft'; -import type GroupsChannelModel from '@typings/database/models/servers/groups_channel'; import type MyChannelModel from '@typings/database/models/servers/my_channel'; import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings'; import type PostModel from '@typings/database/models/servers/post'; @@ -24,7 +23,6 @@ const { CHANNEL_INFO, CHANNEL_MEMBERSHIP, DRAFT, - GROUPS_CHANNEL, MY_CHANNEL, MY_CHANNEL_SETTINGS, POSTS_IN_CHANNEL, @@ -52,9 +50,6 @@ export default class ChannelModel extends Model { /** A CHANNEL can be associated with multiple DRAFT (relationship is 1:N) */ [DRAFT]: {type: 'has_many', foreignKey: 'channel_id'}, - /** A CHANNEL can be associated with multiple GROUPS_CHANNEL (relationship is 1:N) */ - [GROUPS_CHANNEL]: {type: 'has_many', foreignKey: 'channel_id'}, - /** A CHANNEL can be associated with multiple POSTS_IN_CHANNEL (relationship is 1:N) */ [POSTS_IN_CHANNEL]: {type: 'has_many', foreignKey: 'channel_id'}, @@ -110,9 +105,6 @@ export default class ChannelModel extends Model { /** drafts : All drafts for this channel */ @children(DRAFT) drafts!: DraftModel[]; - /** groupsChannel : Every group contained in this channel */ - @children(GROUPS_CHANNEL) groupsChannel!: GroupsChannelModel[]; - /** posts : All posts made in that channel */ @children(POST) posts!: PostModel[]; diff --git a/app/database/models/server/group.ts b/app/database/models/server/group.ts deleted file mode 100644 index 1e32f1f390..0000000000 --- a/app/database/models/server/group.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {children, field} from '@nozbe/watermelondb/decorators'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -import {MM_TABLES} from '@constants/database'; - -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; -import type GroupsChannelModel from '@typings/database/models/servers/groups_channel'; -import type GroupsTeamModel from '@typings/database/models/servers/groups_team'; - -const {GROUP, GROUPS_CHANNEL, GROUPS_TEAM, GROUP_MEMBERSHIP} = MM_TABLES.SERVER; - -/** - * The Group model unifies/assembles users, teams and channels based on a common ground. For example, a group can be - * all users who are in the mobile team. If one needs to send that group a message, then s/he can mention the group's - * name in the message. (e.g @mobile_team) - */ -export default class GroupModel extends Model { - /** table (name) : Group */ - static table = GROUP; - - /** associations : Describes every relationship to this table. */ - static associations: Associations = { - - /** A GROUP has a 1:N relationship with GROUPS_CHANNEL */ - [GROUPS_CHANNEL]: {type: 'has_many', foreignKey: 'group_id'}, - - /** A GROUP has a 1:N relationship with GROUPS_TEAM */ - [GROUPS_TEAM]: {type: 'has_many', foreignKey: 'group_id'}, - - /** A GROUP has a 1:N relationship with GROUP_MEMBERSHIP */ - [GROUP_MEMBERSHIP]: {type: 'has_many', foreignKey: 'group_id'}, - }; - - /** allow_reference : Determins if the group can be referenced in mentions */ - @field('allow_reference') allowReference!: boolean; - - /** delete_at : When the group was deleted */ - @field('delete_at') deleteAt!: number; - - /** display_name : The display name for the group */ - @field('display_name') displayName!: string; - - /** name : The name of the group */ - @field('name') name!: string; - - /** groupsChannel : All the related children records from GroupsChannel */ - @children(GROUPS_CHANNEL) groupsChannel!: GroupsChannelModel[]; - - /** groupsTeam : All the related children records from GroupsTeam */ - @children(GROUPS_TEAM) groupsTeam!: GroupsTeamModel[]; - - /** groupMemberships : All the related children records from GroupMembership */ - @children(GROUP_MEMBERSHIP) groupMemberships!: GroupMembershipModel[]; -} diff --git a/app/database/models/server/group_membership.ts b/app/database/models/server/group_membership.ts deleted file mode 100644 index 47054b76c8..0000000000 --- a/app/database/models/server/group_membership.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Relation} from '@nozbe/watermelondb'; -import {field, immutableRelation} from '@nozbe/watermelondb/decorators'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -import {MM_TABLES} from '@constants/database'; - -import type GroupModel from '@typings/database/models/servers/group'; -import type UserModel from '@typings/database/models/servers/user'; - -const {GROUP, GROUP_MEMBERSHIP, USER} = MM_TABLES.SERVER; - -/** - * The GroupMembership model represents the 'association table' where many groups have users and many users are in - * groups (relationship type N:N) - */ -export default class GroupMembershipModel extends Model { - /** table (name) : GroupMembership */ - static table = GROUP_MEMBERSHIP; - - /** associations : Describes every relationship to this table */ - static associations: Associations = { - - /** A GROUP can have multiple users in it */ - [GROUP]: {type: 'belongs_to', key: 'group_id'}, - - /** A USER can be part of multiple groups */ - [USER]: {type: 'belongs_to', key: 'user_id'}, - }; - - /* group_id: The foreign key to the related Group record*/ - @field('group_id') groupId!: string; - - /* user_id: The foreign key to the related User record*/ - @field('user_id') userId!: string; - - /** group : The related group this user belongs to */ - @immutableRelation(GROUP, 'group_id') group!: Relation; - - /** user : The related user in the group */ - @immutableRelation(USER, 'user_id') user!: Relation; -} diff --git a/app/database/models/server/groups_channel.ts b/app/database/models/server/groups_channel.ts deleted file mode 100644 index dbed805d22..0000000000 --- a/app/database/models/server/groups_channel.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Relation} from '@nozbe/watermelondb'; -import {field, immutableRelation} from '@nozbe/watermelondb/decorators'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -import {MM_TABLES} from '@constants/database'; - -import type ChannelModel from '@typings/database/models/servers/channel'; -import type GroupModel from '@typings/database/models/servers/group'; - -const {GROUP, GROUPS_CHANNEL, CHANNEL} = MM_TABLES.SERVER; - -/** - * The GroupsChannel links the Channel model with the Group model - */ -export default class GroupsChannelModel extends Model { - /** table (name) : GroupsChannel */ - static table = GROUPS_CHANNEL; - - /** associations : Describes every relationship to this table. */ - static associations: Associations = { - - /** A GROUP can be associated with multiple GROUPS_CHANNEL (relationship is 1:N) */ - [GROUP]: {type: 'belongs_to', key: 'group_id'}, - - /** A CHANNEL can be associated with multiple GROUPS_CHANNEL (relationship is 1:N) */ - [CHANNEL]: {type: 'belongs_to', key: 'channel_id'}, - }; - - /** channel_id : The foreign key of the related CHANNEL model */ - @field('channel_id') channelId!: string; - - /** group_id : The foreign key of the related GROUP model */ - @field('group_id') groupId!: string; - - /** channel : The related record to the parent Channel model */ - @immutableRelation(CHANNEL, 'channel_id') channel!: Relation; - - /** group : The related record to the parent Group model */ - @immutableRelation(GROUP, 'group_id') group!: Relation; -} diff --git a/app/database/models/server/groups_team.ts b/app/database/models/server/groups_team.ts deleted file mode 100644 index 5416e2b6b9..0000000000 --- a/app/database/models/server/groups_team.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Relation} from '@nozbe/watermelondb'; -import {field, immutableRelation} from '@nozbe/watermelondb/decorators'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -import {MM_TABLES} from '@constants/database'; - -import type GroupModel from '@typings/database/models/servers/group'; -import type TeamModel from '@typings/database/models/servers/team'; - -const {GROUP, GROUPS_TEAM, TEAM} = MM_TABLES.SERVER; - -/** - * The GroupsTeam links the Team model with the Group model - */ -export default class GroupsTeamModel extends Model { - /** table (name) : GroupsTeam */ - static table = GROUPS_TEAM; - - /** associations : Describes every relationship to this table. */ - static associations: Associations = { - - /** GroupsTeam can belong to only one Group */ - [GROUP]: {type: 'belongs_to', key: 'group_id'}, - - /** GroupsTeam can belong to only one Team */ - [TEAM]: {type: 'belongs_to', key: 'team_id'}, - }; - - /** group_id : The foreign key to the related Group record */ - @field('group_id') groupId!: string; - - /** team_id : The foreign key to the related Team record */ - @field('team_id') teamId!: string; - - /** team : The related record to the parent Team model */ - @immutableRelation(TEAM, 'team_id') team!: Relation; - - /** group : The related record to the parent Team model */ - @immutableRelation(GROUP, 'group_id') group!: Relation; -} diff --git a/app/database/models/server/index.ts b/app/database/models/server/index.ts index 44e9d21088..ef6b0296b6 100644 --- a/app/database/models/server/index.ts +++ b/app/database/models/server/index.ts @@ -9,10 +9,6 @@ export {default as ChannelModel} from './channel'; export {default as CustomEmojiModel} from './custom_emoji'; export {default as DraftModel} from './draft'; export {default as FileModel} from './file'; -export {default as GroupMembershipModel} from './group_membership'; -export {default as GroupModel} from './group'; -export {default as GroupsChannelModel} from './groups_channel'; -export {default as GroupsTeamModel} from './groups_team'; export {default as MyChannelModel} from './my_channel'; export {default as MyChannelSettingsModel} from './my_channel_settings'; export {default as MyTeamModel} from './my_team'; diff --git a/app/database/models/server/team.ts b/app/database/models/server/team.ts index 3ce934a3f2..2c13bf64bd 100644 --- a/app/database/models/server/team.ts +++ b/app/database/models/server/team.ts @@ -8,7 +8,6 @@ import Model, {Associations} from '@nozbe/watermelondb/Model'; import {MM_TABLES} from '@constants/database'; import type ChannelModel from '@typings/database/models/servers/channel'; -import type GroupsTeamModel from '@typings/database/models/servers/groups_team'; import type MyTeamModel from '@typings/database/models/servers/my_team'; import type SlashCommandModel from '@typings/database/models/servers/slash_command'; import type TeamChannelHistoryModel from '@typings/database/models/servers/team_channel_history'; @@ -17,7 +16,6 @@ import type TeamSearchHistoryModel from '@typings/database/models/servers/team_s const { CHANNEL, - GROUPS_TEAM, TEAM, MY_TEAM, SLASH_COMMAND, @@ -39,9 +37,6 @@ export default class TeamModel extends Model { /** A TEAM has a 1:N relationship with CHANNEL. A TEAM can possess multiple channels */ [CHANNEL]: {type: 'has_many', foreignKey: 'team_id'}, - /** A TEAM has a 1:N relationship with GROUPS_TEAM. A TEAM can possess multiple groups */ - [GROUPS_TEAM]: {type: 'has_many', foreignKey: 'team_id'}, - /** A TEAM can be associated to one MY_TEAM (relationship is 1:1) */ [MY_TEAM]: {type: 'has_many', foreignKey: 'id'}, @@ -85,9 +80,6 @@ export default class TeamModel extends Model { /** channels : All the channels associated with this team */ @children(CHANNEL) channels!: ChannelModel[]; - /** groupsTeam : All the groups associated with this team */ - @children(GROUPS_TEAM) groupsTeam!: GroupsTeamModel[]; - /** myTeam : Retrieves additional information about the team that this user is possibly part of. */ @immutableRelation(MY_TEAM, 'id') myTeam!: Relation; diff --git a/app/database/models/server/user.ts b/app/database/models/server/user.ts index d27f3d53f0..b4bf642515 100644 --- a/app/database/models/server/user.ts +++ b/app/database/models/server/user.ts @@ -9,7 +9,6 @@ import {safeParseJSON} from '@utils/helpers'; import type ChannelModel from '@typings/database/models/servers/channel'; import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; import type PostModel from '@typings/database/models/servers/post'; import type PreferenceModel from '@typings/database/models/servers/preference'; import type ReactionModel from '@typings/database/models/servers/reaction'; @@ -19,7 +18,6 @@ import type {UserMentionKey} from '@typings/global/markdown'; const { CHANNEL, CHANNEL_MEMBERSHIP, - GROUP_MEMBERSHIP, POST, PREFERENCE, REACTION, @@ -44,9 +42,6 @@ export default class UserModel extends Model { /** USER has a 1:N relationship with CHANNEL_MEMBERSHIP. A user can be part of multiple channels */ [CHANNEL_MEMBERSHIP]: {type: 'has_many', foreignKey: 'user_id'}, - /** USER has a 1:N relationship with GROUP_MEMBERSHIP. A user can be part of multiple groups */ - [GROUP_MEMBERSHIP]: {type: 'has_many', foreignKey: 'user_id'}, - /** USER has a 1:N relationship with POST. A user can author multiple posts */ [POST]: {type: 'has_many', foreignKey: 'user_id'}, @@ -122,9 +117,6 @@ export default class UserModel extends Model { /** channels : All the channels that this user is part of */ @children(CHANNEL_MEMBERSHIP) channels!: ChannelMembershipModel[]; - /** groups : All the groups that this user is part of */ - @children(GROUP_MEMBERSHIP) groups!: GroupMembershipModel[]; - /** posts : All the posts that this user has written*/ @children(POST) posts!: PostModel[]; diff --git a/app/database/operator/server_data_operator/comparators/index.ts b/app/database/operator/server_data_operator/comparators/index.ts index 1962f0035c..1f49eff5b7 100644 --- a/app/database/operator/server_data_operator/comparators/index.ts +++ b/app/database/operator/server_data_operator/comparators/index.ts @@ -9,10 +9,6 @@ import type ChannelMembershipModel from '@typings/database/models/servers/channe import type CustomEmojiModel from '@typings/database/models/servers/custom_emoji'; import type DraftModel from '@typings/database/models/servers/draft'; import type FileModel from '@typings/database/models/servers/file'; -import type GroupModel from '@typings/database/models/servers/group'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; -import type GroupsChannelModel from '@typings/database/models/servers/groups_channel'; -import type GroupsTeamModel from '@typings/database/models/servers/groups_team'; import type MyChannelModel from '@typings/database/models/servers/my_channel'; import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings'; import type MyTeamModel from '@typings/database/models/servers/my_team'; @@ -83,26 +79,10 @@ export const isRecordCustomEmojiEqualToRaw = (record: CustomEmojiModel, raw: Cus return raw.id === record.id; }; -export const isRecordGroupMembershipEqualToRaw = (record: GroupMembershipModel, raw: GroupMembership) => { - return raw.user_id === record.userId && raw.group_id === record.groupId; -}; - export const isRecordChannelMembershipEqualToRaw = (record: ChannelMembershipModel, raw: Pick) => { return raw.user_id === record.userId && raw.channel_id === record.channelId; }; -export const isRecordGroupEqualToRaw = (record: GroupModel, raw: Group) => { - return raw.id === record.id; -}; - -export const isRecordGroupsTeamEqualToRaw = (record: GroupsTeamModel, raw: GroupTeam) => { - return raw.team_id === record.teamId && raw.group_id === record.groupId; -}; - -export const isRecordGroupsChannelEqualToRaw = (record: GroupsChannelModel, raw: GroupChannel) => { - return raw.channel_id === record.channelId && raw.group_id === record.groupId; -}; - export const isRecordTeamEqualToRaw = (record: TeamModel, raw: Team) => { return raw.id === record.id; }; diff --git a/app/database/operator/server_data_operator/handlers/group.test.ts b/app/database/operator/server_data_operator/handlers/group.test.ts deleted file mode 100644 index 64471723d3..0000000000 --- a/app/database/operator/server_data_operator/handlers/group.test.ts +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import DatabaseManager from '@database/manager'; -import { - isRecordGroupEqualToRaw, - isRecordGroupMembershipEqualToRaw, - isRecordGroupsChannelEqualToRaw, - isRecordGroupsTeamEqualToRaw, -} from '@database/operator/server_data_operator/comparators'; -import { - transformGroupMembershipRecord, - transformGroupRecord, - transformGroupsChannelRecord, - transformGroupsTeamRecord, -} from '@database/operator/server_data_operator/transformers/group'; - -import ServerDataOperator from '..'; - -describe('*** Operator: Group Handlers tests ***', () => { - let operator: ServerDataOperator; - beforeAll(async () => { - await DatabaseManager.init(['baseHandler.test.com']); - operator = DatabaseManager.serverDatabases['baseHandler.test.com'].operator; - }); - - it('=> HandleGroup: should write to the GROUP table', async () => { - expect.assertions(2); - - const spyOnHandleRecords = jest.spyOn(operator, 'handleRecords'); - const groups: Group[] = [ - { - id: 'id_groupdfjdlfkjdkfdsf', - name: 'mobile_team', - display_name: 'mobile team', - description: '', - remote_id: '', - create_at: 0, - update_at: 0, - delete_at: 0, - has_syncables: true, - type: '', - member_count: 1, - allow_reference: true, - }, - ]; - - await operator.handleGroup({ - groups, - prepareRecordsOnly: false, - }); - - expect(spyOnHandleRecords).toHaveBeenCalledTimes(1); - expect(spyOnHandleRecords).toHaveBeenCalledWith({ - fieldName: 'id', - createOrUpdateRawValues: groups, - tableName: 'Group', - prepareRecordsOnly: false, - findMatchingRecordBy: isRecordGroupEqualToRaw, - transformer: transformGroupRecord, - }); - }); - - it('=> HandleGroupsTeam: should write to the GROUPS_TEAM table', async () => { - expect.assertions(2); - - const spyOnHandleRecords = jest.spyOn(operator, 'handleRecords'); - const groupsTeams = [ - { - team_id: 'team_899', - team_display_name: '', - team_type: '', - group_id: 'group_id89', - auto_add: true, - create_at: 0, - delete_at: 0, - update_at: 0, - }, - ]; - - await operator.handleGroupsTeam({ - groupsTeams, - prepareRecordsOnly: false, - }); - - expect(spyOnHandleRecords).toHaveBeenCalledTimes(1); - expect(spyOnHandleRecords).toHaveBeenCalledWith({ - fieldName: 'group_id', - createOrUpdateRawValues: groupsTeams, - tableName: 'GroupsTeam', - prepareRecordsOnly: false, - findMatchingRecordBy: isRecordGroupsTeamEqualToRaw, - transformer: transformGroupsTeamRecord, - }); - }); - - it('=> HandleGroupsChannel: should write to the GROUPS_CHANNEL table', async () => { - expect.assertions(2); - - const spyOnHandleRecords = jest.spyOn(operator, 'handleRecords'); - const groupsChannels = [ - { - auto_add: true, - channel_display_name: '', - channel_id: 'channelid', - channel_type: '', - create_at: 0, - delete_at: 0, - group_id: 'groupId', - team_display_name: '', - team_id: '', - team_type: '', - update_at: 0, - }, - ]; - - await operator.handleGroupsChannel({ - groupsChannels, - prepareRecordsOnly: false, - }); - - expect(spyOnHandleRecords).toHaveBeenCalledTimes(1); - expect(spyOnHandleRecords).toHaveBeenCalledWith({ - fieldName: 'group_id', - createOrUpdateRawValues: groupsChannels, - tableName: 'GroupsChannel', - prepareRecordsOnly: false, - findMatchingRecordBy: isRecordGroupsChannelEqualToRaw, - transformer: transformGroupsChannelRecord, - }); - }); - - it('=> HandleGroupMembership: should write to the GROUP_MEMBERSHIP table', async () => { - expect.assertions(2); - - const spyOnHandleRecords = jest.spyOn(operator, 'handleRecords'); - const groupMemberships = [ - { - user_id: 'u4cprpki7ri81mbx8efixcsb8jo', - group_id: 'g4cprpki7ri81mbx8efixcsb8jo', - }, - ]; - - await operator.handleGroupMembership({ - groupMemberships, - prepareRecordsOnly: false, - }); - - expect(spyOnHandleRecords).toHaveBeenCalledTimes(1); - expect(spyOnHandleRecords).toHaveBeenCalledWith({ - fieldName: 'group_id', - createOrUpdateRawValues: groupMemberships, - tableName: 'GroupMembership', - prepareRecordsOnly: false, - findMatchingRecordBy: isRecordGroupMembershipEqualToRaw, - transformer: transformGroupMembershipRecord, - }); - }); -}); diff --git a/app/database/operator/server_data_operator/handlers/group.ts b/app/database/operator/server_data_operator/handlers/group.ts deleted file mode 100644 index 9b60f89a43..0000000000 --- a/app/database/operator/server_data_operator/handlers/group.ts +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {MM_TABLES} from '@constants/database'; -import DataOperatorException from '@database/exceptions/data_operator_exception'; -import { - isRecordGroupEqualToRaw, - isRecordGroupMembershipEqualToRaw, - isRecordGroupsChannelEqualToRaw, - isRecordGroupsTeamEqualToRaw, -} from '@database/operator/server_data_operator/comparators'; -import { - transformGroupMembershipRecord, - transformGroupRecord, - transformGroupsChannelRecord, - transformGroupsTeamRecord, -} from '@database/operator/server_data_operator/transformers/group'; -import {getUniqueRawsBy} from '@database/operator/utils/general'; - -import type {HandleGroupArgs, HandleGroupMembershipArgs, HandleGroupsChannelArgs, HandleGroupsTeamArgs} from '@typings/database/database'; -import type GroupModel from '@typings/database/models/servers/group'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; -import type GroupsChannelModel from '@typings/database/models/servers/groups_channel'; -import type GroupsTeamModel from '@typings/database/models/servers/groups_team'; - -const { - GROUP, - GROUPS_CHANNEL, - GROUPS_TEAM, - GROUP_MEMBERSHIP, -} = MM_TABLES.SERVER; - -export interface GroupHandlerMix { - handleGroupMembership: ({groupMemberships, prepareRecordsOnly}: HandleGroupMembershipArgs) => Promise; - handleGroup: ({groups, prepareRecordsOnly}: HandleGroupArgs) => Promise; - handleGroupsTeam: ({groupsTeams, prepareRecordsOnly}: HandleGroupsTeamArgs) => Promise; - handleGroupsChannel: ({groupsChannels, prepareRecordsOnly}: HandleGroupsChannelArgs) => Promise; -} - -const GroupHandler = (superclass: any) => class extends superclass { - /** - * handleGroupMembership: Handler responsible for the Create/Update operations occurring on the GROUP_MEMBERSHIP table from the 'Server' schema - * @param {HandleGroupMembershipArgs} groupMembershipsArgs - * @param {RawGroupMembership[]} groupMembershipsArgs.groupMemberships - * @param {boolean} groupMembershipsArgs.prepareRecordsOnly - * @throws DataOperatorException - * @returns {Promise} - */ - handleGroupMembership = ({groupMemberships, prepareRecordsOnly = true}: HandleGroupMembershipArgs): Promise => { - if (!groupMemberships.length) { - throw new DataOperatorException( - 'An empty "groupMemberships" array has been passed to the handleGroupMembership method', - ); - } - - const createOrUpdateRawValues = getUniqueRawsBy({raws: groupMemberships, key: 'group_id'}); - - return this.handleRecords({ - fieldName: 'group_id', - findMatchingRecordBy: isRecordGroupMembershipEqualToRaw, - transformer: transformGroupMembershipRecord, - prepareRecordsOnly, - createOrUpdateRawValues, - tableName: GROUP_MEMBERSHIP, - }); - }; - - /** - * handleGroup: Handler responsible for the Create/Update operations occurring on the GROUP table from the 'Server' schema - * @param {HandleGroupArgs} groupsArgs - * @param {RawGroup[]} groupsArgs.groups - * @param {boolean} groupsArgs.prepareRecordsOnly - * @throws DataOperatorException - * @returns {Promise} - */ - handleGroup = ({groups, prepareRecordsOnly = true}: HandleGroupArgs): Promise => { - if (!groups.length) { - throw new DataOperatorException( - 'An empty "groups" array has been passed to the handleGroup method', - ); - } - - const createOrUpdateRawValues = getUniqueRawsBy({raws: groups, key: 'id'}); - - return this.handleRecords({ - fieldName: 'id', - findMatchingRecordBy: isRecordGroupEqualToRaw, - transformer: transformGroupRecord, - prepareRecordsOnly, - createOrUpdateRawValues, - tableName: GROUP, - }); - }; - - /** - * handleGroupsTeam: Handler responsible for the Create/Update operations occurring on the GROUPS_TEAM table from the 'Server' schema - * @param {HandleGroupsTeamArgs} groupsTeamsArgs - * @param {GroupsTeam[]} groupsTeamsArgs.groupsTeams - * @param {boolean} groupsTeamsArgs.prepareRecordsOnly - * @throws DataOperatorException - * @returns {Promise} - */ - handleGroupsTeam = ({groupsTeams, prepareRecordsOnly = true}: HandleGroupsTeamArgs): Promise => { - if (!groupsTeams.length) { - throw new DataOperatorException( - 'An empty "groups" array has been passed to the handleGroupsTeam method', - ); - } - - const createOrUpdateRawValues = groupsTeams.filter((gt, index, self) => ( - index === self.findIndex((item) => item.team_id === gt.team_id && item.group_id === gt.group_id))); - - return this.handleRecords({ - fieldName: 'group_id', - findMatchingRecordBy: isRecordGroupsTeamEqualToRaw, - transformer: transformGroupsTeamRecord, - prepareRecordsOnly, - createOrUpdateRawValues, - tableName: GROUPS_TEAM, - }); - }; - - /** - * handleGroupsChannel: Handler responsible for the Create/Update operations occurring on the GROUPS_CHANNEL table from the 'Server' schema - * @param {HandleGroupsChannelArgs} groupsChannelsArgs - * @param {GroupsChannel[]} groupsChannelsArgs.groupsChannels - * @param {boolean} groupsChannelsArgs.prepareRecordsOnly - * @throws DataOperatorException - * @returns {Promise} - */ - handleGroupsChannel = ({groupsChannels, prepareRecordsOnly = true}: HandleGroupsChannelArgs): Promise => { - if (!groupsChannels.length) { - throw new DataOperatorException( - 'An empty "groups" array has been passed to the handleGroupsTeam method', - ); - } - - const createOrUpdateRawValues = groupsChannels.filter((gc, index, self) => ( - index === self.findIndex((item) => item.channel_id === gc.channel_id && item.group_id === gc.group_id))); - - return this.handleRecords({ - fieldName: 'group_id', - findMatchingRecordBy: isRecordGroupsChannelEqualToRaw, - transformer: transformGroupsChannelRecord, - prepareRecordsOnly, - createOrUpdateRawValues, - tableName: GROUPS_CHANNEL, - }); - }; -}; - -export default GroupHandler; diff --git a/app/database/operator/server_data_operator/index.ts b/app/database/operator/server_data_operator/index.ts index b7dff4120c..12c47d0a6d 100644 --- a/app/database/operator/server_data_operator/index.ts +++ b/app/database/operator/server_data_operator/index.ts @@ -4,7 +4,6 @@ import ServerDataOperatorBase from '@database/operator/server_data_operator/handlers'; import CategoryHandler, {CategoryHandlerMix} from '@database/operator/server_data_operator/handlers/category'; import ChannelHandler, {ChannelHandlerMix} from '@database/operator/server_data_operator/handlers/channel'; -import GroupHandler, {GroupHandlerMix} from '@database/operator/server_data_operator/handlers/group'; import PostHandler, {PostHandlerMix} from '@database/operator/server_data_operator/handlers/post'; import PostsInChannelHandler, {PostsInChannelHandlerMix} from '@database/operator/server_data_operator/handlers/posts_in_channel'; import PostsInThreadHandler, {PostsInThreadHandlerMix} from '@database/operator/server_data_operator/handlers/posts_in_thread'; @@ -15,12 +14,11 @@ import mix from '@utils/mix'; import type {Database} from '@nozbe/watermelondb'; interface ServerDataOperator extends ServerDataOperatorBase, PostHandlerMix, PostsInChannelHandlerMix, - PostsInThreadHandlerMix, UserHandlerMix, GroupHandlerMix, ChannelHandlerMix, CategoryHandlerMix, TeamHandlerMix {} + PostsInThreadHandlerMix, UserHandlerMix, ChannelHandlerMix, CategoryHandlerMix, TeamHandlerMix {} class ServerDataOperator extends mix(ServerDataOperatorBase).with( CategoryHandler, ChannelHandler, - GroupHandler, PostHandler, PostsInChannelHandler, PostsInThreadHandler, diff --git a/app/database/operator/server_data_operator/transformers/group.test.ts b/app/database/operator/server_data_operator/transformers/group.test.ts deleted file mode 100644 index 9acd697180..0000000000 --- a/app/database/operator/server_data_operator/transformers/group.test.ts +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import { - transformGroupMembershipRecord, - transformGroupRecord, - transformGroupsChannelRecord, - transformGroupsTeamRecord, -} from '@database/operator/server_data_operator/transformers/group'; -import {createTestConnection} from '@database/operator/utils/create_test_connection'; -import {OperationType} from '@typings/database/enums'; - -describe('*** GROUP Prepare Records Test ***', () => { - it('=> transformGroupRecord: should return an array of type Group', async () => { - expect.assertions(3); - - const database = await createTestConnection({databaseName: 'group_prepare_records', setActive: true}); - expect(database).toBeTruthy(); - - const preparedRecords = await transformGroupRecord({ - action: OperationType.CREATE, - database: database!, - value: { - record: undefined, - raw: { - id: 'id_groupdfjdlfkjdkfdsf', - name: 'mobile_team', - display_name: 'mobile team', - description: '', - type: '', - remote_id: '', - create_at: 0, - update_at: 0, - delete_at: 0, - has_syncables: true, - member_count: 0, - allow_reference: false, - }, - }, - }); - - expect(preparedRecords).toBeTruthy(); - expect(preparedRecords!.collection.modelClass.name).toBe('GroupModel'); - }); - - it('=> transformGroupsTeamRecord: should return an array of type GroupsTeam', async () => { - expect.assertions(3); - - const database = await createTestConnection({databaseName: 'group_prepare_records', setActive: true}); - expect(database).toBeTruthy(); - - const preparedRecords = await transformGroupsTeamRecord({ - action: OperationType.CREATE, - database: database!, - value: { - record: undefined, - raw: { - team_id: 'team_89', - team_display_name: '', - team_type: '', - group_id: 'group_id89', - auto_add: true, - create_at: 0, - delete_at: 0, - update_at: 0, - }, - }, - }); - - expect(preparedRecords).toBeTruthy(); - expect(preparedRecords!.collection.modelClass.name).toBe('GroupsTeamModel'); - }); - - it('=> transformGroupsChannelRecord: should return an array of type GroupsChannel', async () => { - expect.assertions(3); - - const database = await createTestConnection({databaseName: 'group_prepare_records', setActive: true}); - expect(database).toBeTruthy(); - - const preparedRecords = await transformGroupsChannelRecord({ - action: OperationType.CREATE, - database: database!, - value: { - record: undefined, - raw: { - auto_add: true, - channel_display_name: '', - channel_id: 'channelid', - channel_type: '', - create_at: 0, - delete_at: 0, - group_id: 'groupId', - team_display_name: '', - team_id: '', - team_type: '', - update_at: 0, - }, - }, - }); - - expect(preparedRecords).toBeTruthy(); - expect(preparedRecords!.collection.modelClass.name).toBe('GroupsChannelModel'); - }); - - it('=> transformGroupMembershipRecord: should return an array of type GroupMembership', async () => { - expect.assertions(3); - - const database = await createTestConnection({databaseName: 'group_prepare_records', setActive: true}); - expect(database).toBeTruthy(); - - const preparedRecords = await transformGroupMembershipRecord({ - action: OperationType.CREATE, - database: database!, - value: { - record: undefined, - raw: { - user_id: 'u4cprpki7ri81mbx8efixcsb8jo', - group_id: 'g4cprpki7ri81mbx8efixcsb8jo', - }, - }, - }); - - expect(preparedRecords).toBeTruthy(); - expect(preparedRecords!.collection.modelClass.name).toBe('GroupMembershipModel'); - }); -}); diff --git a/app/database/operator/server_data_operator/transformers/group.ts b/app/database/operator/server_data_operator/transformers/group.ts deleted file mode 100644 index 98b2790a6b..0000000000 --- a/app/database/operator/server_data_operator/transformers/group.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {MM_TABLES} from '@constants/database'; -import {prepareBaseRecord} from '@database/operator/server_data_operator/transformers/index'; -import {OperationType} from '@typings/database/enums'; - -import type {TransformerArgs} from '@typings/database/database'; -import type GroupModel from '@typings/database/models/servers/group'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; -import type GroupsChannelModel from '@typings/database/models/servers/groups_channel'; -import type GroupsTeamModel from '@typings/database/models/servers/groups_team'; - -const { - GROUP, - GROUPS_CHANNEL, - GROUPS_TEAM, - GROUP_MEMBERSHIP, -} = MM_TABLES.SERVER; - -/** - * transformGroupMembershipRecord: Prepares a record of the SERVER database 'GroupMembership' table for update or create actions. - * @param {TransformerArgs} operator - * @param {Database} operator.database - * @param {RecordPair} operator.value - * @returns {Promise} - */ -export const transformGroupMembershipRecord = ({action, database, value}: TransformerArgs): Promise => { - const raw = value.raw as GroupMembership; - const record = value.record as GroupMembershipModel; - const isCreateAction = action === OperationType.CREATE; - - // If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database - const fieldsMapper = (groupMember: GroupMembershipModel) => { - groupMember._raw.id = isCreateAction ? (raw?.id ?? groupMember.id) : record.id; - groupMember.groupId = raw.group_id; - groupMember.userId = raw.user_id; - }; - - return prepareBaseRecord({ - action, - database, - tableName: GROUP_MEMBERSHIP, - value, - fieldsMapper, - }) as Promise; -}; - -/** - * transformGroupRecord: Prepares a record of the SERVER database 'Group' table for update or create actions. - * @param {DataFactory} operator - * @param {Database} operator.database - * @param {RecordPair} operator.value - * @returns {Promise} - */ -export const transformGroupRecord = ({action, database, value}: TransformerArgs): Promise => { - const raw = value.raw as Group; - const record = value.record as GroupModel; - const isCreateAction = action === OperationType.CREATE; - - // If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database - const fieldsMapper = (group: GroupModel) => { - group._raw.id = isCreateAction ? (raw?.id ?? group.id) : record.id; - group.allowReference = raw.allow_reference; - group.deleteAt = raw.delete_at; - group.name = raw.name; - group.displayName = raw.display_name; - }; - - return prepareBaseRecord({ - action, - database, - tableName: GROUP, - value, - fieldsMapper, - }) as Promise; -}; - -/** - * transformGroupsTeamRecord: Prepares a record of the SERVER database 'GroupsTeam' table for update or create actions. - * @param {DataFactory} operator - * @param {Database} operator.database - * @param {RecordPair} operator.value - * @returns {Promise} - */ -export const transformGroupsTeamRecord = ({action, database, value}: TransformerArgs): Promise => { - const raw = value.raw as GroupTeam; - const record = value.record as GroupsTeamModel; - const isCreateAction = action === OperationType.CREATE; - - const fieldsMapper = (groupsTeam: GroupsTeamModel) => { - groupsTeam._raw.id = isCreateAction ? groupsTeam.id : record.id; - groupsTeam.teamId = raw.team_id; - groupsTeam.groupId = raw.group_id; - }; - - return prepareBaseRecord({ - action, - database, - tableName: GROUPS_TEAM, - value, - fieldsMapper, - }) as Promise; -}; - -/** - * transformGroupsChannelRecord: Prepares a record of the SERVER database 'GroupsChannel' table for update or create actions. - * @param {DataFactory} operator - * @param {Database} operator.database - * @param {RecordPair} operator.value - * @returns {Promise} - */ -export const transformGroupsChannelRecord = ({action, database, value}: TransformerArgs): Promise => { - const raw = value.raw as GroupChannelRelation; - const record = value.record as GroupsChannelModel; - const isCreateAction = action === OperationType.CREATE; - - const fieldsMapper = (groupsChannel: GroupsChannelModel) => { - groupsChannel._raw.id = isCreateAction ? groupsChannel.id : record.id; - groupsChannel.channelId = raw.channel_id; - groupsChannel.groupId = raw.group_id; - }; - - return prepareBaseRecord({ - action, - database, - tableName: GROUPS_CHANNEL, - value, - fieldsMapper, - }) as Promise; -}; diff --git a/app/database/schema/server/index.ts b/app/database/schema/server/index.ts index 76f10c33ed..5ec4e669b8 100644 --- a/app/database/schema/server/index.ts +++ b/app/database/schema/server/index.ts @@ -12,10 +12,6 @@ import { CustomEmojiSchema, DraftSchema, FileSchema, - GroupMembershipSchema, - GroupSchema, - GroupsChannelSchema, - GroupsTeamSchema, MyChannelSchema, MyChannelSettingsSchema, MyTeamSchema, @@ -46,10 +42,6 @@ export const serverSchema: AppSchema = appSchema({ CustomEmojiSchema, DraftSchema, FileSchema, - GroupMembershipSchema, - GroupSchema, - GroupsChannelSchema, - GroupsTeamSchema, MyChannelSchema, MyChannelSettingsSchema, MyTeamSchema, diff --git a/app/database/schema/server/table_schemas/group.ts b/app/database/schema/server/table_schemas/group.ts deleted file mode 100644 index baadfb6c00..0000000000 --- a/app/database/schema/server/table_schemas/group.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {tableSchema} from '@nozbe/watermelondb'; - -import {MM_TABLES} from '@constants/database'; - -const {GROUP} = MM_TABLES.SERVER; - -export default tableSchema({ - name: GROUP, - columns: [ - {name: 'allow_reference', type: 'boolean'}, - {name: 'delete_at', type: 'number'}, - {name: 'display_name', type: 'string'}, - {name: 'name', type: 'string'}, - ], -}); diff --git a/app/database/schema/server/table_schemas/group_membership.ts b/app/database/schema/server/table_schemas/group_membership.ts deleted file mode 100644 index 389d3ebbfb..0000000000 --- a/app/database/schema/server/table_schemas/group_membership.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {tableSchema} from '@nozbe/watermelondb'; - -import {MM_TABLES} from '@constants/database'; - -const {GROUP_MEMBERSHIP} = MM_TABLES.SERVER; - -export default tableSchema({ - name: GROUP_MEMBERSHIP, - columns: [ - {name: 'group_id', type: 'string', isIndexed: true}, - {name: 'user_id', type: 'string', isIndexed: true}, - ], -}); diff --git a/app/database/schema/server/table_schemas/groups_channel.ts b/app/database/schema/server/table_schemas/groups_channel.ts deleted file mode 100644 index 5d7f5ff880..0000000000 --- a/app/database/schema/server/table_schemas/groups_channel.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {tableSchema} from '@nozbe/watermelondb'; - -import {MM_TABLES} from '@constants/database'; - -const {GROUPS_CHANNEL} = MM_TABLES.SERVER; - -export default tableSchema({ - name: GROUPS_CHANNEL, - columns: [ - {name: 'channel_id', type: 'string', isIndexed: true}, - {name: 'group_id', type: 'string', isIndexed: true}, - {name: 'member_count', type: 'number'}, - {name: 'timezone_count', type: 'number'}, - ], -}); diff --git a/app/database/schema/server/table_schemas/groups_team.ts b/app/database/schema/server/table_schemas/groups_team.ts deleted file mode 100644 index 9041b402c2..0000000000 --- a/app/database/schema/server/table_schemas/groups_team.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {tableSchema} from '@nozbe/watermelondb'; - -import {MM_TABLES} from '@constants/database'; - -const {GROUPS_TEAM} = MM_TABLES.SERVER; - -export default tableSchema({ - name: GROUPS_TEAM, - columns: [ - {name: 'group_id', type: 'string', isIndexed: true}, - {name: 'team_id', type: 'string', isIndexed: true}, - ], -}); diff --git a/app/database/schema/server/table_schemas/index.ts b/app/database/schema/server/table_schemas/index.ts index c38d1d3e3d..ce131eddd4 100644 --- a/app/database/schema/server/table_schemas/index.ts +++ b/app/database/schema/server/table_schemas/index.ts @@ -9,10 +9,6 @@ export {default as ChannelSchema} from './channel'; export {default as CustomEmojiSchema} from './custom_emoji'; export {default as DraftSchema} from './draft'; export {default as FileSchema} from './file'; -export {default as GroupMembershipSchema} from './group_membership'; -export {default as GroupSchema} from './group'; -export {default as GroupsChannelSchema} from './groups_channel'; -export {default as GroupsTeamSchema} from './groups_team'; export {default as MyChannelSchema} from './my_channel'; export {default as MyChannelSettingsSchema} from './my_channel_settings'; export {default as MyTeamSchema} from './my_team'; diff --git a/app/database/schema/server/test.ts b/app/database/schema/server/test.ts index f78e881fd1..5a19719ae4 100644 --- a/app/database/schema/server/test.ts +++ b/app/database/schema/server/test.ts @@ -16,10 +16,6 @@ const { CUSTOM_EMOJI, DRAFT, FILE, - GROUP, - GROUPS_CHANNEL, - GROUPS_TEAM, - GROUP_MEMBERSHIP, MY_CHANNEL, MY_CHANNEL_SETTINGS, MY_TEAM, @@ -292,62 +288,6 @@ describe('*** Test schema for SERVER database ***', () => { {name: 'user_id', type: 'string', isIndexed: true}, ], }, - [GROUP]: { - name: GROUP, - unsafeSql: undefined, - columns: { - allow_reference: {name: 'allow_reference', type: 'boolean'}, - delete_at: {name: 'delete_at', type: 'number'}, - display_name: {name: 'display_name', type: 'string'}, - name: {name: 'name', type: 'string'}, - }, - columnArray: [ - {name: 'allow_reference', type: 'boolean'}, - {name: 'delete_at', type: 'number'}, - {name: 'display_name', type: 'string'}, - {name: 'name', type: 'string'}, - ], - }, - [GROUPS_CHANNEL]: { - name: GROUPS_CHANNEL, - unsafeSql: undefined, - columns: { - channel_id: {name: 'channel_id', type: 'string', isIndexed: true}, - group_id: {name: 'group_id', type: 'string', isIndexed: true}, - member_count: {name: 'member_count', type: 'number'}, - timezone_count: {name: 'timezone_count', type: 'number'}, - }, - columnArray: [ - {name: 'channel_id', type: 'string', isIndexed: true}, - {name: 'group_id', type: 'string', isIndexed: true}, - {name: 'member_count', type: 'number'}, - {name: 'timezone_count', type: 'number'}, - ], - }, - [GROUPS_TEAM]: { - name: GROUPS_TEAM, - unsafeSql: undefined, - columns: { - group_id: {name: 'group_id', type: 'string', isIndexed: true}, - team_id: {name: 'team_id', type: 'string', isIndexed: true}, - }, - columnArray: [ - {name: 'group_id', type: 'string', isIndexed: true}, - {name: 'team_id', type: 'string', isIndexed: true}, - ], - }, - [GROUP_MEMBERSHIP]: { - name: GROUP_MEMBERSHIP, - unsafeSql: undefined, - columns: { - group_id: {name: 'group_id', type: 'string', isIndexed: true}, - user_id: {name: 'user_id', type: 'string', isIndexed: true}, - }, - columnArray: [ - {name: 'group_id', type: 'string', isIndexed: true}, - {name: 'user_id', type: 'string', isIndexed: true}, - ], - }, [PREFERENCE]: { name: PREFERENCE, unsafeSql: undefined, diff --git a/app/helpers/database/groups.ts b/app/helpers/database/groups.ts deleted file mode 100644 index 965f1b6754..0000000000 --- a/app/helpers/database/groups.ts +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {MM_TABLES} from '@constants/database'; - -import type ChannelModel from '@typings/database/models/servers/channel'; -import type GroupModel from '@typings/database/models/servers/group'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; -import type GroupsChannelModel from '@typings/database/models/servers/groups_channel'; -import type GroupsTeamModel from '@typings/database/models/servers/groups_team'; -import type PostModel from '@typings/database/models/servers/post'; -import type TeamModel from '@typings/database/models/servers/team'; - -export const queryGroupsAssociatedToChannelForReference = async (channel: ChannelModel) => { - const groupChannels = await channel.groupsChannel.fetch() as GroupsChannelModel[]; - const groupChannelPromises = groupChannels.map((g) => g.group.fetch()); - const groups = await Promise.all(groupChannelPromises) as GroupModel[]; - return groups.filter((g) => g.deleteAt === 0); -}; - -export const queryGroupsAssociatedToTeamForReference = async (team: TeamModel) => { - const groupTeams = await team.groupsTeam.fetch() as GroupsTeamModel[]; - const teamGroupPromises = groupTeams.map((g) => g.group.fetch()); - const groups = await Promise.all(teamGroupPromises) as GroupModel[]; - return groups.filter((g) => g.deleteAt === 0); -}; - -export const queryGroupForPosts = async (post: PostModel) => { - try { - if (post.id === post.pendingPostId) { - return null; - } - - const channel = await post.channel.fetch() as ChannelModel; - const team = await channel?.team.fetch() as TeamModel | undefined; - let groupsForReference: GroupModel[] | null = null; - - if (team?.isGroupConstrained && channel.isGroupConstrained) { - const groupsFromChannel = await queryGroupsAssociatedToChannelForReference(channel); - const groupsFromTeam = await queryGroupsAssociatedToTeamForReference(team); - groupsForReference = groupsFromChannel.concat(groupsFromTeam.filter((item) => groupsFromChannel.indexOf(item) < 0)); - } else if (team?.isGroupConstrained) { - groupsForReference = await queryGroupsAssociatedToTeamForReference(team); - } else if (channel.isGroupConstrained) { - groupsForReference = await queryGroupsAssociatedToChannelForReference(channel); - } else { - const myGroups = await post.collections.get(MM_TABLES.SERVER.GROUP_MEMBERSHIP).query().fetch() as GroupMembershipModel[]; - const myGroupsPromises = myGroups.map((g) => g.group.fetch()); - groupsForReference = await Promise.all(myGroupsPromises) as GroupModel[]; - } - - return groupsForReference; - } catch { - return null; - } -}; diff --git a/app/queries/servers/channel.ts b/app/queries/servers/channel.ts index 57b1452d7c..6f29effe62 100644 --- a/app/queries/servers/channel.ts +++ b/app/queries/servers/channel.ts @@ -111,7 +111,6 @@ export const prepareDeleteChannel = async (channel: ChannelModel): Promise> = [ channel.members, channel.drafts, - channel.groupsChannel, channel.postsInChannel, ]; for await (const children of associatedChildren) { diff --git a/app/queries/servers/team.ts b/app/queries/servers/team.ts index 04ef31d364..3d7dac1d1f 100644 --- a/app/queries/servers/team.ts +++ b/app/queries/servers/team.ts @@ -221,7 +221,6 @@ export const prepareDeleteTeam = async (team: TeamModel): Promise => { const associatedChildren: Array> = [ team.members, - team.groupsTeam, team.slashCommands, team.teamSearchHistories, ]; diff --git a/app/utils/draft/index.ts b/app/utils/draft/index.ts index b0aceacc5f..ff95beee1f 100644 --- a/app/utils/draft/index.ts +++ b/app/utils/draft/index.ts @@ -5,11 +5,9 @@ import {MessageDescriptor} from '@formatjs/intl/src/types'; import {Alert, AlertButton} from 'react-native'; import {General} from '@constants'; -import {AT_MENTION_REGEX_GLOBAL, CODE_REGEX} from '@constants/autocomplete'; -import {NOTIFY_ALL_MEMBERS} from '@constants/post_draft'; +import {CODE_REGEX} from '@constants/autocomplete'; import {t} from '@i18n'; -import type GroupModel from '@typings/database/models/servers/group'; import type {IntlShape} from 'react-intl'; type AlertCallback = (value?: string) => void; @@ -79,106 +77,6 @@ export const textContainsAtHere = (text: string) => { return (/(?:\B|\b_+)@(here)(?!(\.|-|_)*[^\W_])/i).test(textWithoutCode); }; -export const groupsMentionedInText = (groupsWithAllowReference: GroupModel[], text: string) => { - if (!groupsWithAllowReference.length) { - return []; - } - const textWithoutCode = text.replace(CODE_REGEX, ''); - const mentions = textWithoutCode.match(AT_MENTION_REGEX_GLOBAL) || []; - return groupsWithAllowReference.filter((g) => mentions.includes(g.id)); -}; - -// mapGroupMentions remove duplicates from the groupMentions, and if any of the -// groups has more members than the NOTIFY_ALL_MEMBERS, return the highest -// number of notifications and the timezones of that group. -export const mapGroupMentions = (channelMemberCountsByGroup: ChannelMemberCountByGroup[], groupMentions: GroupModel[]) => { - let memberNotifyCount = 0; - let channelTimezoneCount = 0; - const groupMentionsSet = new Set(); - const mappedChannelMemberCountsByGroup: ChannelMemberCountsByGroup = {}; - channelMemberCountsByGroup.forEach((group) => { - mappedChannelMemberCountsByGroup[group.group_id] = group; - }); - groupMentions. - forEach((group) => { - const mappedValue = mappedChannelMemberCountsByGroup[group.id]; - if (mappedValue?.channel_member_count > NOTIFY_ALL_MEMBERS && mappedValue?.channel_member_count > memberNotifyCount) { - memberNotifyCount = mappedValue.channel_member_count; - channelTimezoneCount = mappedValue.channel_member_timezones_count; - } - if (group.name) { - groupMentionsSet.add(`@${group.name}`); - } - }); - return {groupMentionsSet, memberNotifyCount, channelTimezoneCount}; -}; - -export function buildGroupMentionsMessage(intl: IntlShape, groupMentions: string[], memberNotifyCount: number, channelTimezoneCount: number) { - let notifyAllMessage = ''; - - if (groupMentions.length === 1) { - if (channelTimezoneCount > 0) { - notifyAllMessage = ( - intl.formatMessage( - { - id: 'mobile.post_textbox.one_group.message.with_timezones', - defaultMessage: 'By using {mention} you are about to send notifications to {totalMembers} people in {timezones, number} {timezones, plural, one {timezone} other {timezones}}. Are you sure you want to do this?', - }, - { - mention: groupMentions[0], - totalMembers: memberNotifyCount, - timezones: channelTimezoneCount, - }, - ) - ); - } else { - notifyAllMessage = ( - intl.formatMessage( - { - id: 'mobile.post_textbox.one_group.message.without_timezones', - defaultMessage: 'By using {mention} you are about to send notifications to {totalMembers} people. Are you sure you want to do this?', - }, - { - mention: groupMentions[0], - totalMembers: memberNotifyCount, - }, - ) - ); - } - } else if (channelTimezoneCount > 0) { - notifyAllMessage = ( - intl.formatMessage( - { - id: 'mobile.post_textbox.multi_group.message.with_timezones', - defaultMessage: 'By using {mentions} and {finalMention} you are about to send notifications to at least {totalMembers} people in {timezones, number} {timezones, plural, one {timezone} other {timezones}}. Are you sure you want to do this?', - }, - { - mentions: groupMentions.slice(0, -1).join(', '), - finalMention: groupMentions[groupMentions.length - 1], - totalMembers: memberNotifyCount, - timezones: channelTimezoneCount, - }, - ) - ); - } else { - notifyAllMessage = ( - intl.formatMessage( - { - id: 'mobile.post_textbox.multi_group.message.without_timezones', - defaultMessage: 'By using {mentions} and {finalMention} you are about to send notifications to at least {totalMembers} people. Are you sure you want to do this?', - }, - { - mentions: groupMentions.slice(0, -1).join(', '), - finalMention: groupMentions[groupMentions.length - 1], - totalMembers: memberNotifyCount, - }, - ) - ); - } - - return notifyAllMessage; -} - export function buildChannelWideMentionMessage(intl: IntlShape, membersCount: number, isTimezoneEnabled: boolean, channelTimezoneCount: number, atHere: boolean) { let notifyAllMessage = ''; if (isTimezoneEnabled && channelTimezoneCount) { diff --git a/app/utils/post/index.ts b/app/utils/post/index.ts index 7c11a13ab8..78e2082f58 100644 --- a/app/utils/post/index.ts +++ b/app/utils/post/index.ts @@ -5,10 +5,8 @@ import {Post} from '@constants'; import {DEFAULT_LOCALE} from '@i18n'; import {displayUsername} from '@utils/user'; -import type GroupModel from '@typings/database/models/servers/group'; import type PostModel from '@typings/database/models/servers/post'; import type UserModel from '@typings/database/models/servers/user'; -import type {UserMentionKey} from '@typings/global/markdown'; export function areConsecutivePosts(post: PostModel, previousPost: PostModel) { let consecutive = false; @@ -60,20 +58,6 @@ export function postUserDisplayName(post: PostModel, author?: UserModel, teammat return displayUsername(author, author?.locale || DEFAULT_LOCALE, teammateNameDisplay, true); } -export const getMentionKeysForPost = (user: UserModel, post: PostModel, groups: GroupModel[] | null) => { - const keys: UserMentionKey[] = user.mentionKeys; - - if (groups?.length) { - for (const group of groups) { - if (group.name && group.name.trim()) { - keys.push({key: `@${group.name}`}); - } - } - } - - return keys; -}; - export function shouldIgnorePost(post: Post): boolean { return Post.IGNORE_POST_TYPES.includes(post.type); } diff --git a/app/utils/user/index.ts b/app/utils/user/index.ts index f417dba05d..c66524b48e 100644 --- a/app/utils/user/index.ts +++ b/app/utils/user/index.ts @@ -10,8 +10,6 @@ import {UserModel} from '@database/models/server'; import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n'; import {toTitleCase} from '@utils/helpers'; -import type GroupModel from '@typings/database/models/servers/group'; -import type GroupMembershipModel from '@typings/database/models/servers/group_membership'; import type {IntlShape} from 'react-intl'; export function displayUsername(user?: UserProfile | UserModel, locale?: string, teammateDisplayNameSetting?: string, useFallbackUsername = true) { @@ -103,24 +101,6 @@ export const getUsersByUsername = (users: UserModel[]) => { return usersByUsername; }; -export const getUserMentionKeys = (user: UserModel, groups: GroupModel[], userGroups: GroupMembershipModel[]) => { - const keys = user.mentionKeys; - - if (groups.length && userGroups.length) { - const groupMentions = userGroups.reduce((result: Array<{key: string}>, ug: GroupMembershipModel) => { - const group = groups.find((g) => ug.groupId === g.id); - if (group) { - result.push({key: `@${group.name}`}); - } - return result; - }, []); - - keys.push(...groupMentions); - } - - return keys; -}; - export const getUserTimezone = (user: UserModel) => { return getTimezone(user.timezone); }; diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index dc4950d332..684309710b 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -286,10 +286,6 @@ "mobile.post_textbox.entire_channel.message.with_timezones": "By using @all or @channel you are about to send notifications to {totalMembers, number} {totalMembers, plural, one {person} other {people}} in {timezones, number} {timezones, plural, one {timezone} other {timezones}}. Are you sure you want to do this?", "mobile.post_textbox.entire_channel.title": "Confirm sending notifications to entire channel", "mobile.post_textbox.groups.title": "Confirm sending notifications to groups", - "mobile.post_textbox.multi_group.message.with_timezones": "By using {mentions} and {finalMention} you are about to send notifications to at least {totalMembers} people in {timezones, number} {timezones, plural, one {timezone} other {timezones}}. Are you sure you want to do this?", - "mobile.post_textbox.multi_group.message.without_timezones": "By using {mentions} and {finalMention} you are about to send notifications to at least {totalMembers} people. Are you sure you want to do this?", - "mobile.post_textbox.one_group.message.with_timezones": "By using {mention} you are about to send notifications to {totalMembers} people in {timezones, number} {timezones, plural, one {timezone} other {timezones}}. Are you sure you want to do this?", - "mobile.post_textbox.one_group.message.without_timezones": "By using {mention} you are about to send notifications to {totalMembers} people. Are you sure you want to do this?", "mobile.post_textbox.uploadFailedDesc": "Some attachments failed to upload to the server. Are you sure you want to post the message?", "mobile.post_textbox.uploadFailedTitle": "Attachment failure", "mobile.post.cancel": "Cancel", diff --git a/types/database/database.d.ts b/types/database/database.d.ts index 5cb85ae931..d2be557a12 100644 --- a/types/database/database.d.ts +++ b/types/database/database.d.ts @@ -219,26 +219,10 @@ export type HandleTeamArgs = PrepareOnly & { teams: Team[]; }; -export type HandleGroupsChannelArgs = PrepareOnly & { - groupsChannels: GroupChannelRelation[]; -}; - -export type HandleGroupsTeamArgs = PrepareOnly &{ - groupsTeams: GroupTeamRelation[]; -}; - -export type HandleGroupArgs = PrepareOnly & { - groups: Group[]; -}; - export type HandleChannelMembershipArgs = PrepareOnly & { channelMemberships: Array>; }; -export type HandleGroupMembershipArgs = PrepareOnly & { - groupMemberships: GroupMembership[]; -}; - export type HandleTeamMembershipArgs = PrepareOnly & { teamMemberships: TeamMembership[]; }; diff --git a/types/database/models/servers/channel.d.ts b/types/database/models/servers/channel.d.ts index 4ce5ea9fd1..45d3a4e8e7 100644 --- a/types/database/models/servers/channel.d.ts +++ b/types/database/models/servers/channel.d.ts @@ -50,9 +50,6 @@ export default class ChannelModel extends Model { /** drafts : All drafts for this channel */ drafts: Query; - /** groupsChannel : Every group contained in this channel */ - groupsChannel: Query; - /** posts : All posts made in the channel */ posts: Query; diff --git a/types/database/models/servers/group.d.ts b/types/database/models/servers/group.d.ts deleted file mode 100644 index f67014f3c2..0000000000 --- a/types/database/models/servers/group.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -/** - * The Group model unifies/assembles users, teams and channels based on a common ground. For example, a group can be - * all users who are in the mobile team. If one needs to send that group a message, then s/he can mention the group's - * name in the message. (e.g @mobile_team) - */ -export default class GroupModel extends Model { - /** table (name) : Group */ - static table: string; - - /** associations : Describes every relationship to this table. */ - static associations: Associations; - - /** allow_reference : Determins if the group can be referenced in mentions */ - allowReference: boolean; - - /** delete_at : When the group was deleted */ - deleteAt: number; - - /** display_name : The display name for the group */ - displayName: string; - - /** name : The name of the group */ - name: string; - - /** groupsChannel : All the related children records from GroupsChannel */ - groupsChannel: Query; - - /** groupsTeam : All the related children records from GroupsTeam */ - groupsTeam: Query; - - /** groupMemberships : All the related children records from GroupMembership */ - groupMemberships: Query; -} diff --git a/types/database/models/servers/group_membership.d.ts b/types/database/models/servers/group_membership.d.ts deleted file mode 100644 index dd6c1e8f3a..0000000000 --- a/types/database/models/servers/group_membership.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Relation} from '@nozbe/watermelondb'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -/** - * The GroupMembership model represents the 'association table' where many groups have users and many users are in - * groups (relationship type N:N) - */ -export default class GroupMembershipModel extends Model { - /** table (name) : GroupMembership */ - static table: string; - - /** associations : Describes every relationship to this table */ - static associations: Associations; - groupId: string; - userId: string; - - /** group : The related group this user belongs to */ - group: Relation; - - /** user : The related user in the group */ - user: Relation; -} diff --git a/types/database/models/servers/groups_channel.d.ts b/types/database/models/servers/groups_channel.d.ts deleted file mode 100644 index 0b501f5db9..0000000000 --- a/types/database/models/servers/groups_channel.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Relation} from '@nozbe/watermelondb'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -/** - * The GroupsChannel links the Channel model with the Group model - */ -export default class GroupsChannelModel extends Model { - /** table (name) : GroupsChannel */ - static table: string; - - /** associations : Describes every relationship to this table. */ - static associations: Associations; - - /** channel_id : The foreign key of the related CHANNEL model */ - channelId: string; - - /** group_id : The foreign key of the related GROUP model */ - groupId: string; - - /** channel : The related record to the parent Channel model */ - channel: Relation; - - /** group : The related record to the parent Group model */ - group: Relation; -} diff --git a/types/database/models/servers/groups_team.d.ts b/types/database/models/servers/groups_team.d.ts deleted file mode 100644 index fee932f3a1..0000000000 --- a/types/database/models/servers/groups_team.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Relation} from '@nozbe/watermelondb'; -import Model, {Associations} from '@nozbe/watermelondb/Model'; - -/** - * The GroupsTeam links the Team model with the Group model - */ -export default class GroupsTeamModel extends Model { - /** table (name) : GroupsTeam */ - static table: string; - - /** associations : Describes every relationship to this table. */ - static associations: Associations; - - /** group_id : The foreign key to the related Group record */ - groupId: string; - - /** member_count : The number of users in the group */ - memberCount: number; - - /** team_id : The foreign key to the related Team record */ - teamId: string; - - /** timezone_count : The number of timezones */ - timezoneCount: number; - - /** team : The related record to the parent Team model */ - team: Relation; - - /** group : The related record to the parent Team model */ - group: Relation; -} diff --git a/types/database/models/servers/team.d.ts b/types/database/models/servers/team.d.ts index 6d60bbbde2..5036c68255 100644 --- a/types/database/models/servers/team.d.ts +++ b/types/database/models/servers/team.d.ts @@ -44,9 +44,6 @@ export default class TeamModel extends Model { /** channels : All the channels associated with this team */ channels: Query; - /** groupsTeam : All the groups associated with this team */ - groupsTeam: Query; - /** myTeam : Retrieves additional information about the team that this user is possibly part of. This query might yield no result if the user isn't part of a team. */ myTeam: Relation; diff --git a/types/database/models/servers/user.d.ts b/types/database/models/servers/user.d.ts index 2f181cdd0c..21c95180dc 100644 --- a/types/database/models/servers/user.d.ts +++ b/types/database/models/servers/user.d.ts @@ -76,9 +76,6 @@ export default class UserModel extends Model { /** channels : All the channels that this user is part of */ channels: Query; - /** groups : All the groups that this user is part of */ - groups: Query; - /** posts : All the posts that this user has written*/ posts: Query; diff --git a/types/database/raw_values.d.ts b/types/database/raw_values.d.ts index b4f27a58a3..d30de0589a 100644 --- a/types/database/raw_values.d.ts +++ b/types/database/raw_values.d.ts @@ -23,22 +23,6 @@ type Draft = { root_id: string; }; -type GroupMembership = { - id?: string; - user_id: string; - group_id: string; -}; - -type GroupChannelRelation = { - channel_id: string; - group_id: string; -} - -type GroupTeamRelation = { - group_id: string; - team_id: string; -} - type MyTeam = { id: string; roles: string; @@ -104,10 +88,6 @@ type RawValue = | CustomEmoji | Draft | FileInfo - | Group - | GroupMembership - | GroupChannel - | GroupTeam | IdValue | Metadata | MyTeam