MM-42787 - Gekidou User DB field remote_id (#6094)

* added remote_id to user table schema

* update user model to accomodate for remote_id field

* transform - reaction - split into its own file

* update user transformer

* update isShared function

* Fix typescript

* make remote_id field optional

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Avinash Lingaloo
2022-03-29 21:54:09 +04:00
committed by GitHub
parent ec17aea41e
commit 7f8a55684d
10 changed files with 95 additions and 74 deletions

View File

@@ -14,6 +14,7 @@ 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';
import type TeamMembershipModel from '@typings/database/models/servers/team_membership';
import type UserModelInterface from '@typings/database/models/servers/user';
import type {UserMentionKey} from '@typings/global/markdown';
const {
@@ -31,7 +32,7 @@ const {
* The User model represents the 'USER' table and its relationship to other
* shareholders in the app.
*/
export default class UserModel extends Model {
export default class UserModel extends Model implements UserModelInterface {
/** table (name) : User */
static table = USER;
@@ -56,7 +57,7 @@ export default class UserModel extends Model {
/** USER has a 1:N relationship with TEAM_MEMBERSHIP. A user can join multiple teams */
[TEAM_MEMBERSHIP]: {type: 'has_many', foreignKey: 'user_id'},
/** USER has a 1:N relationship with THREAD_PARTICIPANT. A user can participante in multiple threads */
/** USER has a 1:N relationship with THREAD_PARTICIPANT. A user can participate in multiple threads */
[THREAD_PARTICIPANT]: {type: 'has_many', foreignKey: 'user_id'},
};
@@ -105,6 +106,9 @@ export default class UserModel extends Model {
/** username : The user's username */
@field('username') username!: string;
/** remote_id : The ID of the remote organization that this user belongs to */
@field('remote_id') remoteId!: string | null;
/** notify_props : Notification preferences/configurations */
@json('notify_props', safeParseJSON) notifyProps!: UserNotifyProps | null;

View File

@@ -3,7 +3,7 @@
import {MM_TABLES} from '@constants/database';
import DataOperatorException from '@database/exceptions/data_operator_exception';
import {transformReactionRecord} from '@database/operator/server_data_operator/transformers/user';
import {transformReactionRecord} from '@database/operator/server_data_operator/transformers/reaction';
import {sanitizeReactions} from '@database/operator/utils/reaction';
import type {HandleReactionsArgs} from '@typings/database/database';

View File

@@ -0,0 +1,35 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {transformReactionRecord} from '@database/operator/server_data_operator/transformers/reaction';
import {createTestConnection} from '@database/operator/utils/create_test_connection';
import {OperationType} from '@typings/database/enums';
describe('*** REACTION Prepare Records Test ***', () => {
it('=> transformReactionRecord: should return an array of type Reaction', async () => {
expect.assertions(3);
const database = await createTestConnection({databaseName: 'reaction_prepare_records', setActive: true});
expect(database).toBeTruthy();
const preparedRecords = await transformReactionRecord({
action: OperationType.CREATE,
database: database!,
value: {
record: undefined,
raw: {
id: 'ps81iqbddesfby8jayz7owg4yypoo',
user_id: 'q3mzxua9zjfczqakxdkowc6u6yy',
post_id: 'ps81iqbddesfby8jayz7owg4yypoo',
emoji_name: 'thumbsup',
create_at: 1596032651748,
update_at: 1608253011321,
delete_at: 0,
},
},
});
expect(preparedRecords).toBeTruthy();
expect(preparedRecords!.collection.modelClass.name).toBe('ReactionModel');
});
});

View File

@@ -0,0 +1,41 @@
// 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 ReactionModel from '@typings/database/models/servers/reaction';
const {REACTION} = MM_TABLES.SERVER;
/**
* transformReactionRecord: Prepares a record of the SERVER database 'Reaction' table for update or create actions.
* @param {TransformerArgs} operator
* @param {Database} operator.database
* @param {RecordPair} operator.value
* @returns {Promise<ReactionModel>}
*/
export const transformReactionRecord = ({action, database, value}: TransformerArgs): Promise<ReactionModel> => {
const raw = value.raw as Reaction;
const record = value.record as ReactionModel;
const isCreateAction = action === OperationType.CREATE;
// id of reaction comes from server response
const fieldsMapper = (reaction: ReactionModel) => {
reaction._raw.id = isCreateAction ? (raw?.id ?? reaction.id) : record.id;
reaction.userId = raw.user_id;
reaction.postId = raw.post_id;
reaction.emojiName = raw.emoji_name;
reaction.createAt = raw.create_at;
};
return prepareBaseRecord({
action,
database,
tableName: REACTION,
value,
fieldsMapper,
}) as Promise<ReactionModel>;
};

View File

@@ -1,11 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {
transformPreferenceRecord,
transformReactionRecord,
transformUserRecord,
} from '@database/operator/server_data_operator/transformers/user';
import {transformPreferenceRecord, transformUserRecord} from '@database/operator/server_data_operator/transformers/user';
import {createTestConnection} from '@database/operator/utils/create_test_connection';
import {OperationType} from '@typings/database/enums';
@@ -29,33 +25,6 @@ describe('*** USER Prepare Records Test ***', () => {
expect(preparedRecords!.collection.modelClass.name).toBe('PreferenceModel');
});
it('=> transformReactionRecord: should return an array of type Reaction', async () => {
expect.assertions(3);
const database = await createTestConnection({databaseName: 'user_prepare_records', setActive: true});
expect(database).toBeTruthy();
const preparedRecords = await transformReactionRecord({
action: OperationType.CREATE,
database: database!,
value: {
record: undefined,
raw: {
id: 'ps81iqbddesfby8jayz7owg4yypoo',
user_id: 'q3mzxua9zjfczqakxdkowc6u6yy',
post_id: 'ps81iqbddesfby8jayz7owg4yypoo',
emoji_name: 'thumbsup',
create_at: 1596032651748,
update_at: 1608253011321,
delete_at: 0,
},
},
});
expect(preparedRecords).toBeTruthy();
expect(preparedRecords!.collection.modelClass.name).toBe('ReactionModel');
});
it('=> transformUserRecord: should return an array of type User', async () => {
expect.assertions(3);

View File

@@ -7,44 +7,9 @@ import {OperationType} from '@typings/database/enums';
import type {TransformerArgs} from '@typings/database/database';
import type PreferenceModel from '@typings/database/models/servers/preference';
import type ReactionModel from '@typings/database/models/servers/reaction';
import type UserModel from '@typings/database/models/servers/user';
const {
PREFERENCE,
REACTION,
USER,
} = MM_TABLES.SERVER;
/**
* transformReactionRecord: Prepares a record of the SERVER database 'Reaction' table for update or create actions.
* @param {TransformerArgs} operator
* @param {Database} operator.database
* @param {RecordPair} operator.value
* @returns {Promise<ReactionModel>}
*/
export const transformReactionRecord = ({action, database, value}: TransformerArgs): Promise<ReactionModel> => {
const raw = value.raw as Reaction;
const record = value.record as ReactionModel;
const isCreateAction = action === OperationType.CREATE;
// id of reaction comes from server response
const fieldsMapper = (reaction: ReactionModel) => {
reaction._raw.id = isCreateAction ? (raw?.id ?? reaction.id) : record.id;
reaction.userId = raw.user_id;
reaction.postId = raw.post_id;
reaction.emojiName = raw.emoji_name;
reaction.createAt = raw.create_at;
};
return prepareBaseRecord({
action,
database,
tableName: REACTION,
value,
fieldsMapper,
}) as Promise<ReactionModel>;
};
const {PREFERENCE, USER} = MM_TABLES.SERVER;
/**
* transformUserRecord: Prepares a record of the SERVER database 'User' table for update or create actions.
@@ -78,6 +43,7 @@ export const transformUserRecord = ({action, database, value}: TransformerArgs):
user.props = raw.props || null;
user.timezone = raw.timezone || null;
user.isBot = raw.is_bot;
user.remoteId = raw?.remote_id ?? '';
if (raw.status) {
user.status = raw.status;
}

View File

@@ -28,5 +28,6 @@ export default tableSchema({
{name: 'status', type: 'string'},
{name: 'timezone', type: 'string'},
{name: 'username', type: 'string'},
{name: 'remote_id', type: 'string', isOptional: true},
],
});

View File

@@ -533,6 +533,7 @@ describe('*** Test schema for SERVER database ***', () => {
status: {name: 'status', type: 'string'},
timezone: {name: 'timezone', type: 'string'},
username: {name: 'username', type: 'string'},
remote_id: {name: 'remote_id', type: 'string', isOptional: true},
},
columnArray: [
{name: 'auth_service', type: 'string'},
@@ -553,6 +554,7 @@ describe('*** Test schema for SERVER database ***', () => {
{name: 'status', type: 'string'},
{name: 'timezone', type: 'string'},
{name: 'username', type: 'string'},
{name: 'remote_id', type: 'string', isOptional: true},
],
},
},

View File

@@ -6,10 +6,10 @@ import {Alert} from 'react-native';
import {General, Permissions, Preferences} from '@constants';
import {CustomStatusDuration} from '@constants/custom_status';
import {UserModel} from '@database/models/server';
import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n';
import {toTitleCase} from '@utils/helpers';
import type UserModel from '@typings/database/models/servers/user';
import type {IntlShape} from 'react-intl';
export function displayUsername(user?: UserProfile | UserModel, locale?: string, teammateDisplayNameSetting?: string, useFallbackUsername = true) {
@@ -51,7 +51,7 @@ export function getFullName(user: UserProfile | UserModel): string {
let firstName: string;
let lastName: string;
if (user instanceof UserModel) {
if ('lastName' in user) {
firstName = user.firstName;
lastName = user.lastName;
} else {
@@ -197,7 +197,7 @@ export function isBot(user: UserProfile | UserModel): boolean {
}
export function isShared(user: UserProfile | UserModel): boolean {
return 'remote_id' in user ? Boolean(user.remote_id) : Boolean(user.props?.remote_id);
return ('remoteId' in user) ? Boolean(user.remoteId) : Boolean(user.remote_id);
}
export function removeUserFromList(userId: string, originalList: UserProfile[]): UserProfile[] {

View File

@@ -68,6 +68,9 @@ export default class UserModel extends Model {
/** username : The user's username */
username: string;
/** remote_id : The ID of the remote organization that this user belongs to */
remoteId: string | null;
/** notify_props : Notification preferences/configurations */
notifyProps: UserNotifyProps | null;