MM_30476 [v2] Section 'User' of the server schema (#5073)

* MM_30476 : Added all isolated tables from the server schema

* MM_30476 : Updated 'test' script in package.json

* MM_30476 : Added USER section of the server schema

* MM_30476 : Added the models index back

* MM_30476 : Updated User entity as per previous comments

* MM_30476 : Added lazy query to channel membership

* MM_30476 : Adjusted PR as per suggestions

* MM_30476 : Update nick_name in user model

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>

* MM_30476 : Adjusted extra padding

* MM_30476 : Corrected ChannelMemberShipSchema to ChannelMembershipSchema

* MM_30476 : Updated types/database/index.ts to types/database/index.d.ts

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Avinash Lingaloo
2021-01-13 20:17:38 +04:00
committed by GitHub
parent 89d4cf235f
commit e471efa48f
19 changed files with 627 additions and 19 deletions

View File

@@ -0,0 +1,53 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q, Query, Relation} from '@nozbe/watermelondb';
import {field, immutableRelation, lazy} from '@nozbe/watermelondb/decorators';
import Model, {Associations} from '@nozbe/watermelondb/Model';
import {MM_TABLES} from '@constants/database';
import Channel from '@typings/database/channel';
import User from '@typings/database/user';
const {CHANNEL, CHANNEL_MEMBERSHIP, USER} = MM_TABLES.SERVER;
/**
* The ChannelMembership model represents the 'association table' where many channels have users and many users are on
* channels ( N:N relationship between model Users and model Channel)
*/
export default class ChannelMembership extends Model {
/** table (entity name) : ChannelMembership */
static table = CHANNEL_MEMBERSHIP;
/** associations : Describes every relationship to this entity. */
static associations: Associations = {
/** A CHANNEL can have multiple USER */
[CHANNEL]: {type: 'belongs_to', key: 'channel_id'},
/** A USER can belong to multiple CHANNEL */
[USER]: {type: 'belongs_to', key: 'user_id'},
};
/** channel_id : The foreign key to the related Channel record */
@field('channel_id') channelId!: string;
/* user_id: The foreign key to the related User record*/
@field('user_id') userId!: string;
/** memberChannel : The related channel this member belongs to */
@immutableRelation(CHANNEL, 'channel_id') channel!: Relation<Channel>;
/** memberUser : The related member belonging to the channel */
@immutableRelation(USER, 'user_id') user!: Relation<User>;
/**
* getAllChannelsForUser - Retrieves all the channels that the user is part of
*/
@lazy getAllChannelsForUser = this.collections.get(CHANNEL).query(Q.on(USER, 'id', this.userId)) as Query<Channel>
/**
* getAllUsersInChannel - Retrieves all the users who are part of this channel
*/
@lazy getAllUsersInChannel = this.collections.get(USER).query(Q.on(CHANNEL, 'id', this.channelId)) as Query<User>
}

View File

@@ -1,13 +1,17 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export {default as ChannelMembership} from './channel_membership';
export {default as CustomEmoji} from './custom_emoji';
export {default as MyTeam} from './my_team';
export {default as Preference} from './preference';
export {default as Reaction} from './reaction';
export {default as Role} from './role';
export {default as SlashCommand} from './slash_command';
export {default as System} from './system';
export {default as Team} from './team';
export {default as TeamChannelHistory} from './team_channel_history';
export {default as TeamMembership} from './team_membership';
export {default as TeamSearchHistory} from './team_search_history';
export {default as Team} from './team';
export {default as TermsOfService} from './terms_of_service';
export {default as User} from './user';

View File

@@ -0,0 +1,42 @@
// 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';
import {field, immutableRelation} from '@nozbe/watermelondb/decorators';
import {MM_TABLES} from '@constants/database';
import User from '@typings/database/user';
const {PREFERENCE, USER} = MM_TABLES.SERVER;
/**
* The Preference model hold information about the user's preference in the app.
* This includes settings about the account, the themes, etc.
*/
export default class Preference extends Model {
/** table (entity name) : Preference */
static table = PREFERENCE;
/** associations : Describes every relationship to this entity. */
static associations: Associations = {
/** A USER can have multiple PREFERENCE.(relationship is 1:N)*/
[USER]: {type: 'belongs_to', key: 'user_id'},
};
/** category : The preference category ( e.g. Themes, Account settings etc..) */
@field('category') category!: string;
/** name : The category name */
@field('name') name!: string;
/** user_id : The foreign key of the user's record in this model */
@field('user_id') userId!: string;
/** value : The preference's value */
@field('value') value!: string;
/** user : The related record to the parent User model */
@immutableRelation(USER, 'user_id') user!: Relation<User>;
}

View File

@@ -0,0 +1,48 @@
// 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';
import {field, immutableRelation} from '@nozbe/watermelondb/decorators';
import {MM_TABLES} from '@constants/database';
import User from '@typings/database/user';
import Post from '@typings/database/post';
const {POST, REACTION, USER} = MM_TABLES.SERVER;
/**
* The Reaction Model is used to present the reactions a user had on a particular post
*/
export default class Reaction extends Model {
/** table (entity name) : Reaction */
static table = REACTION;
/** associations : Describes every relationship to this entity. */
static associations: Associations = {
/** A POST can have multiple REACTION. (relationship is 1:N) */
[POST]: {type: 'belongs_to', key: 'post_id'},
/** A USER can have multiple REACTION. (relationship is 1:N) */
[USER]: {type: 'belongs_to', key: 'user_id'},
};
/** createAt : Creation timestamp used for sorting reactions amongst users on a particular post */
@field('create_at') createAt!: number;
/** emoji_name : The emoticon used to express the reaction */
@field('emoji_name') emojiName!: string;
/** post_id : The related Post's foreign key on which this reaction was expressed */
@field('post_id') postId!: string;
/** user_id : The related User's foreign key by which this reaction was expressed */
@field('user_id') userId!: string;
/** reactionUser : The related record to the User model */
@immutableRelation(USER, 'user_id') user!: Relation<User>;
/** reactionPost : The related record to the Post model */
@immutableRelation(POST, 'post_id') post!: Relation<Post>;
}

View File

@@ -0,0 +1,133 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {children, field, json} from '@nozbe/watermelondb/decorators';
import {MM_TABLES} from '@constants/database';
import Channel from '@typings/database/channel';
import ChannelMembership from '@typings/database/channel_membership';
import GroupMembership from '@typings/database/group_membership';
import Model, {Associations} from '@nozbe/watermelondb/Model';
import Post from '@typings/database/post';
import Preference from '@typings/database/preference';
import Reaction from '@typings/database/reaction';
import TeamMembership from '@typings/database/team_membership';
const {
CHANNEL,
CHANNEL_MEMBERSHIP,
GROUP_MEMBERSHIP,
POST,
PREFERENCE,
REACTION,
TEAM_MEMBERSHIP,
USER,
} = MM_TABLES.SERVER;
/**
* The User model represents the 'USER' entity and its relationship to other
* shareholders in the app.
*/
export default class User extends Model {
/** table (entity name) : User */
static table = USER;
/** associations : Describes every relationship to this entity. */
static associations: Associations = {
/** USER has a 1:N relationship with CHANNEL. A user can create multiple channels */
[CHANNEL]: {type: 'has_many', foreignKey: 'creator_id'},
/** 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'},
/** USER has a 1:N relationship with PREFERENCE. A user can have multiple preferences */
[PREFERENCE]: {type: 'has_many', foreignKey: 'user_id'},
/** USER has a 1:N relationship with REACTION. A user can react to multiple posts */
[REACTION]: {type: 'has_many', foreignKey: 'user_id'},
/** USER has a 1:N relationship with TEAM_MEMBERSHIP. A user can join multiple teams */
[TEAM_MEMBERSHIP]: {type: 'has_many', foreignKey: 'user_id'},
};
/** auth_service : The type of authentication service registered to that user */
@field('auth_service') authService!: string;
/** delete_at : The timestamp at which this user account has been archived/deleted */
@field('delete_at') deleteAt!: number;
/** email : The email address for that user */
@field('email') email!: string;
/** first_name : The user's first name */
@field('first_name') firstName!: string;
/** is_bot : Boolean flag indicating if the user is a bot */
@field('is_bot') isBot!: boolean;
/** is_guest : Boolean flag indicating if the user is a guest */
@field('is_guest') isGuest!: boolean;
/** last_name : The user's last name */
@field('last_name') lastName!: string;
/** last_picture_update : The timestamp of the last time the profile picture has been updated */
@field('last_picture_update') lastPictureUpdate!: number;
/** locale : The user's locale */
@field('locale') locale!: string;
/** nickname : The user's nickname */
@field('nickname') nickname!: string;
/** position : The user's position in the company */
@field('position') position!: string;
/** roles : The associated roles that this user has */
@field('roles') roles!: string;
/** status : The presence status for the user */
@field('status') status!: string;
/** username : The user's username */
@field('username') username!: string;
/** notify_props : Notification preferences/configurations */
@json('notify_props', (rawJson) => rawJson) notifyProps!: NotifyProps;
/** props : Custom objects ( e.g. custom status) can be stored in there. Its type definition is known as
* 'excess property check' in Typescript land. We keep using it till we build up the final shape of this object.
*/
@json('props', (rawJson) => rawJson) props!: UserProps;
/** timezone : The timezone for this user */
@json('timezone', (rawJson) => rawJson) timezone!: Timezone;
/** channelsCreated : All the channels that this user created */
@children(CHANNEL) channelsCreated!: Channel[];
/** channels : All the channels that this user is part of */
@children(CHANNEL_MEMBERSHIP) channels!: ChannelMembership[];
/** groups : All the groups that this user is part of */
@children(GROUP_MEMBERSHIP) groups!: GroupMembership[];
/** posts : All the posts that this user has written*/
@children(POST) posts!: Post[];
/** preferences : All user preferences */
@children(PREFERENCE) preferences!: Preference[];
/** reactions : All the reactions to posts that this user had */
@children(REACTION) reactions!: Reaction[];
/** teams : All the team that this user is part of */
@children(TEAM_MEMBERSHIP) teams!: TeamMembership[];
}

View File

@@ -4,8 +4,11 @@
import {AppSchema, appSchema} from '@nozbe/watermelondb';
import {
ChannelMembershipSchema,
CustomEmojiSchema,
MyTeamSchema,
PreferenceSchema,
ReactionSchema,
RoleSchema,
SlashCommandSchema,
SystemSchema,
@@ -14,13 +17,17 @@ import {
TeamSchema,
TeamSearchHistorySchema,
TermsOfServiceSchema,
UserSchema,
} from './table_schemas';
export const serverSchema: AppSchema = appSchema({
version: 1,
tables: [
ChannelMembershipSchema,
CustomEmojiSchema,
MyTeamSchema,
PreferenceSchema,
ReactionSchema,
RoleSchema,
SlashCommandSchema,
SystemSchema,
@@ -29,5 +36,6 @@ export const serverSchema: AppSchema = appSchema({
TeamSchema,
TeamSearchHistorySchema,
TermsOfServiceSchema,
UserSchema,
],
});

View File

@@ -0,0 +1,16 @@
// 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 {CHANNEL_MEMBERSHIP} = MM_TABLES.SERVER;
export default tableSchema({
name: CHANNEL_MEMBERSHIP,
columns: [
{name: 'channel_id', type: 'string', isIndexed: true},
{name: 'user_id', type: 'string', isIndexed: true},
],
});

View File

@@ -1,8 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export {default as ChannelMembershipSchema} from './channel_membership';
export {default as CustomEmojiSchema} from './custom_emoji';
export {default as MyTeamSchema} from './my_team';
export {default as PreferenceSchema} from './preference';
export {default as ReactionSchema} from './reaction';
export {default as RoleSchema} from './role';
export {default as SlashCommandSchema} from './slash_command';
export {default as SystemSchema} from './system';
@@ -11,3 +14,4 @@ export {default as TeamMembershipSchema} from './team_membership';
export {default as TeamSchema} from './team';
export {default as TeamSearchHistorySchema} from './team_search_history';
export {default as TermsOfServiceSchema} from './terms_of_service';
export {default as UserSchema} from './user';

View File

@@ -0,0 +1,18 @@
// 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 {PREFERENCE} = MM_TABLES.SERVER;
export default tableSchema({
name: PREFERENCE,
columns: [
{name: 'category', type: 'string', isIndexed: true},
{name: 'name', type: 'string'},
{name: 'user_id', type: 'string', isIndexed: true},
{name: 'value', type: 'string'},
],
});

View File

@@ -0,0 +1,18 @@
// 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 {REACTION} = MM_TABLES.SERVER;
export default tableSchema({
name: REACTION,
columns: [
{name: 'create_at', type: 'number'},
{name: 'emoji_name', type: 'string'},
{name: 'post_id', type: 'string', isIndexed: true},
{name: 'user_id', type: 'string', isIndexed: true},
],
});

View File

@@ -0,0 +1,32 @@
// 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 {USER} = MM_TABLES.SERVER;
export default tableSchema({
name: USER,
columns: [
{name: 'auth_service', type: 'string'},
{name: 'delete_at', type: 'number'},
{name: 'email', type: 'string'},
{name: 'first_name', type: 'string'},
{name: 'is_bot', type: 'boolean'},
{name: 'is_guest', type: 'boolean'},
{name: 'last_name', type: 'string'},
{name: 'last_picture_update', type: 'number'},
{name: 'locale', type: 'string'},
{name: 'nickname', type: 'string'},
{name: 'notify_props', type: 'string'},
{name: 'position', type: 'string'},
{name: 'props', type: 'string'},
{name: 'roles', type: 'string'},
{name: 'status', type: 'string'},
{name: 'timezone', type: 'string'},
{name: 'user_id', type: 'string'},
{name: 'username', type: 'string'},
],
});

View File

@@ -6,16 +6,20 @@ import {MM_TABLES} from '@constants/database';
import {serverSchema} from './index';
const {
CHANNEL_MEMBERSHIP,
CUSTOM_EMOJI,
MY_TEAM,
PREFERENCE,
REACTION,
ROLE,
SLASH_COMMAND,
SYSTEM,
TERMS_OF_SERVICE,
TEAM,
TEAM_CHANNEL_HISTORY,
TEAM_MEMBERSHIP,
TEAM_SEARCH_HISTORY,
TERMS_OF_SERVICE,
USER,
} = MM_TABLES.SERVER;
describe('*** Test schema for SERVER database ***', () => {
@@ -23,6 +27,17 @@ describe('*** Test schema for SERVER database ***', () => {
expect(serverSchema).toEqual({
version: 1,
tables: {
[CHANNEL_MEMBERSHIP]: {
name: CHANNEL_MEMBERSHIP,
columns: {
channel_id: {name: 'channel_id', type: 'string', isIndexed: true},
user_id: {name: 'user_id', type: 'string', isIndexed: true},
},
columnArray: [
{name: 'channel_id', type: 'string', isIndexed: true},
{name: 'user_id', type: 'string', isIndexed: true},
],
},
[CUSTOM_EMOJI]: {
name: CUSTOM_EMOJI,
columns: {
@@ -32,6 +47,36 @@ describe('*** Test schema for SERVER database ***', () => {
{name: 'name', type: 'string'},
],
},
[PREFERENCE]: {
name: PREFERENCE,
columns: {
category: {name: 'category', type: 'string', isIndexed: true},
name: {name: 'name', type: 'string'},
user_id: {name: 'user_id', type: 'string', isIndexed: true},
value: {name: 'value', type: 'string'},
},
columnArray: [
{name: 'category', type: 'string', isIndexed: true},
{name: 'name', type: 'string'},
{name: 'user_id', type: 'string', isIndexed: true},
{name: 'value', type: 'string'},
],
},
[REACTION]: {
name: REACTION,
columns: {
create_at: {name: 'create_at', type: 'number'},
emoji_name: {name: 'emoji_name', type: 'string'},
post_id: {name: 'post_id', type: 'string', isIndexed: true},
user_id: {name: 'user_id', type: 'string', isIndexed: true},
},
columnArray: [
{name: 'create_at', type: 'number'},
{name: 'emoji_name', type: 'string'},
{name: 'post_id', type: 'string', isIndexed: true},
{name: 'user_id', type: 'string', isIndexed: true},
],
},
[MY_TEAM]: {
name: MY_TEAM,
columns: {
@@ -162,6 +207,49 @@ describe('*** Test schema for SERVER database ***', () => {
{name: 'accepted_at', type: 'number'},
],
},
[USER]: {
name: USER,
columns: {
auth_service: {name: 'auth_service', type: 'string'},
delete_at: {name: 'delete_at', type: 'number'},
email: {name: 'email', type: 'string'},
first_name: {name: 'first_name', type: 'string'},
is_bot: {name: 'is_bot', type: 'boolean'},
is_guest: {name: 'is_guest', type: 'boolean'},
last_name: {name: 'last_name', type: 'string'},
last_picture_update: {name: 'last_picture_update', type: 'number'},
locale: {name: 'locale', type: 'string'},
nickname: {name: 'nickname', type: 'string'},
notify_props: {name: 'notify_props', type: 'string'},
position: {name: 'position', type: 'string'},
props: {name: 'props', type: 'string'},
roles: {name: 'roles', type: 'string'},
status: {name: 'status', type: 'string'},
timezone: {name: 'timezone', type: 'string'},
user_id: {name: 'user_id', type: 'string'},
username: {name: 'username', type: 'string'},
},
columnArray: [
{name: 'auth_service', type: 'string'},
{name: 'delete_at', type: 'number'},
{name: 'email', type: 'string'},
{name: 'first_name', type: 'string'},
{name: 'is_bot', type: 'boolean'},
{name: 'is_guest', type: 'boolean'},
{name: 'last_name', type: 'string'},
{name: 'last_picture_update', type: 'number'},
{name: 'locale', type: 'string'},
{name: 'nickname', type: 'string'},
{name: 'notify_props', type: 'string'},
{name: 'position', type: 'string'},
{name: 'props', type: 'string'},
{name: 'roles', type: 'string'},
{name: 'status', type: 'string'},
{name: 'timezone', type: 'string'},
{name: 'user_id', type: 'string'},
{name: 'username', type: 'string'},
],
},
},
});
});