Use PostgreSQL instead of MongoDB (#4572)

* wip

* Update note.ts

* Update timeline.ts

* Update core.ts

* wip

* Update generate-visibility-query.ts

* wip

* wip

* wip

* wip

* wip

* Update global-timeline.ts

* wip

* wip

* wip

* Update vote.ts

* wip

* wip

* Update create.ts

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update files.ts

* wip

* wip

* Update CONTRIBUTING.md

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update read-notification.ts

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update cancel.ts

* wip

* wip

* wip

* Update show.ts

* wip

* wip

* Update gen-id.ts

* Update create.ts

* Update id.ts

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Docker: Update files about Docker (#4599)

* Docker: Use cache if files used by `yarn install` was not updated

This patch reduces the number of times to installing node_modules.
For example, `yarn install` step will be skipped when only ".config/default.yml" is updated.

* Docker: Migrate MongoDB to Postgresql

Misskey uses Postgresql as a database instead of Mongodb since version 11.

* Docker: Uncomment about data persistence

This patch will save a lot of databases.

* wip

* wip

* wip

* Update activitypub.ts

* wip

* wip

* wip

* Update logs.ts

* wip

* Update drive-file.ts

* Update register.ts

* wip

* wip

* Update mentions.ts

* wip

* wip

* wip

* Update recommendation.ts

* wip

* Update index.ts

* wip

* Update recommendation.ts

* Doc: Update docker.ja.md and docker.en.md (#1) (#4608)

Update how to set up misskey.

* wip

* ✌️

* wip

* Update note.ts

* Update postgre.ts

* wip

* wip

* wip

* wip

* Update add-file.ts

* wip

* wip

* wip

* Clean up

* Update logs.ts

* wip

* 🍕

* wip

* Ad notes

* wip

* Update api-visibility.ts

* Update note.ts

* Update add-file.ts

* tests

* tests

* Update postgre.ts

* Update utils.ts

* wip

* wip

* Refactor

* wip

* Refactor

* wip

* wip

* Update show-users.ts

* Update update-instance.ts

* wip

* Update feed.ts

* Update outbox.ts

* Update outbox.ts

* Update user.ts

* wip

* Update list.ts

* Update update-hashtag.ts

* wip

* Update update-hashtag.ts

* Refactor

* Update update.ts

* wip

* wip

* ✌️

* clean up

* docs

* Update push.ts

* wip

* Update api.ts

* wip

* ✌️

* Update make-pagination-query.ts

* ✌️

* Delete hashtags.ts

* Update instances.ts

* Update instances.ts

* Update create.ts

* Update search.ts

* Update reversi-game.ts

* Update signup.ts

* Update user.ts

* id

* Update example.yml

* 🎨

* objectid

* fix

* reversi

* reversi

* Fix bug of chart engine

* Add test of chart engine

* Improve test

* Better testing

* Improve chart engine

* Refactor

* Add test of chart engine

* Refactor

* Add chart test

* Fix bug

* コミットし忘れ

* Refactoring

* ✌️

* Add tests

* Add test

* Extarct note tests

* Refactor

* 存在しないユーザーにメンションできなくなっていた問題を修正

* Fix bug

* Update update-meta.ts

* Fix bug

* Update mention.vue

* Fix bug

* Update meta.ts

* Update CONTRIBUTING.md

* Fix bug

* Fix bug

* Fix bug

* Clean up

* Clean up

* Update notification.ts

* Clean up

* Add mute tests

* Add test

* Refactor

* Add test

* Fix test

* Refactor

* Refactor

* Add tests

* Update utils.ts

* Update utils.ts

* Fix test

* Update package.json

* Update update.ts

* Update manifest.ts

* Fix bug

* Fix bug

* Add test

* 🎨

* Update endpoint permissions

* Updaye permisison

* Update person.ts

#4299

* データベースと同期しないように

* Fix bug

* Fix bug

* Update reversi-game.ts

* Use a feature of Node v11.7.0 to extract a public key (#4644)

* wip

* wip

* ✌️

* Refactoring

#1540

* test

* test

* test

* test

* test

* test

* test

* Fix bug

* Fix test

* 🍣

* wip

* #4471

* Add test for #4335

* Refactor

* Fix test

* Add tests

* 🕓

* Fix bug

* Add test

* Add test

* rename

* Fix bug
This commit is contained in:
syuilo
2019-04-07 21:50:36 +09:00
committed by GitHub
parent 13caf37991
commit f0a29721c9
592 changed files with 13463 additions and 14147 deletions

View File

@ -0,0 +1,41 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['userId', 'reporterId'], { unique: true })
export class AbuseUserReport {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the AbuseUserReport.'
})
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column(id())
public reporterId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public reporter: User | null;
@Column('varchar', {
length: 512,
})
public comment: string;
}

View File

@ -0,0 +1,45 @@
import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn, RelationId } from 'typeorm';
import { User } from './user';
import { App } from './app';
import { id } from '../id';
@Entity()
export class AccessToken {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the AccessToken.'
})
public createdAt: Date;
@Index()
@Column('varchar', {
length: 128
})
public token: string;
@Index()
@Column('varchar', {
length: 128
})
public hash: string;
@RelationId((self: AccessToken) => self.user)
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column(id())
public appId: App['id'];
@ManyToOne(type => App, {
onDelete: 'CASCADE'
})
@JoinColumn()
public app: App | null;
}

View File

@ -0,0 +1,60 @@
import { Entity, PrimaryColumn, Column, Index, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class App {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the App.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The owner ID.'
})
public userId: User['id'] | null;
@ManyToOne(type => User, {
onDelete: 'SET NULL',
nullable: true,
})
public user: User | null;
@Index()
@Column('varchar', {
length: 64,
comment: 'The secret key of the App.'
})
public secret: string;
@Column('varchar', {
length: 128,
comment: 'The name of the App.'
})
public name: string;
@Column('varchar', {
length: 512,
comment: 'The description of the App.'
})
public description: string;
@Column('varchar', {
length: 64, array: true,
comment: 'The permission of the App.'
})
public permission: string[];
@Column('varchar', {
length: 256, nullable: true,
comment: 'The callbackUrl of the App.'
})
public callbackUrl: string | null;
}

View File

@ -0,0 +1,39 @@
import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm';
import { User } from './user';
import { App } from './app';
import { id } from '../id';
@Entity()
export class AuthSession {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the AuthSession.'
})
public createdAt: Date;
@Index()
@Column('varchar', {
length: 128
})
public token: string;
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column(id())
public appId: App['id'];
@ManyToOne(type => App, {
onDelete: 'CASCADE'
})
@JoinColumn()
public app: App | null;
}

View File

@ -0,0 +1,42 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['blockerId', 'blockeeId'], { unique: true })
export class Blocking {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the Blocking.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The blockee user ID.'
})
public blockeeId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public blockee: User | null;
@Index()
@Column({
...id(),
comment: 'The blocker user ID.'
})
public blockerId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public blocker: User | null;
}

View File

@ -0,0 +1,154 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { DriveFolder } from './drive-folder';
import { id } from '../id';
@Entity()
export class DriveFile {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the DriveFile.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The owner ID.'
})
public userId: User['id'] | null;
@ManyToOne(type => User, {
onDelete: 'SET NULL'
})
@JoinColumn()
public user: User | null;
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: 'The host of owner. It will be null if the user in local.'
})
public userHost: string | null;
@Index()
@Column('varchar', {
length: 32,
comment: 'The MD5 hash of the DriveFile.'
})
public md5: string;
@Column('varchar', {
length: 256,
comment: 'The file name of the DriveFile.'
})
public name: string;
@Index()
@Column('varchar', {
length: 128,
comment: 'The content type (MIME) of the DriveFile.'
})
public type: string;
@Column('integer', {
comment: 'The file size (bytes) of the DriveFile.'
})
public size: number;
@Column('varchar', {
length: 512, nullable: true,
comment: 'The comment of the DriveFile.'
})
public comment: string | null;
@Column('jsonb', {
default: {},
comment: 'The any properties of the DriveFile. For example, it includes image width/height.'
})
public properties: Record<string, any>;
@Column('boolean')
public storedInternal: boolean;
@Column('varchar', {
length: 512,
comment: 'The URL of the DriveFile.'
})
public url: string;
@Column('varchar', {
length: 512, nullable: true,
comment: 'The URL of the thumbnail of the DriveFile.'
})
public thumbnailUrl: string | null;
@Column('varchar', {
length: 512, nullable: true,
comment: 'The URL of the webpublic of the DriveFile.'
})
public webpublicUrl: string | null;
@Index({ unique: true })
@Column('varchar', {
length: 256,
})
public accessKey: string;
@Index({ unique: true })
@Column('varchar', {
length: 256, nullable: true,
})
public thumbnailAccessKey: string | null;
@Index({ unique: true })
@Column('varchar', {
length: 256, nullable: true,
})
public webpublicAccessKey: string | null;
@Index()
@Column('varchar', {
length: 512, nullable: true,
comment: 'The URI of the DriveFile. it will be null when the DriveFile is local.'
})
public uri: string | null;
@Column('varchar', {
length: 512, nullable: true,
})
public src: string | null;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The parent folder ID. If null, it means the DriveFile is located in root.'
})
public folderId: DriveFolder['id'] | null;
@ManyToOne(type => DriveFolder, {
onDelete: 'SET NULL'
})
@JoinColumn()
public folder: DriveFolder | null;
@Column('boolean', {
default: false,
comment: 'Whether the DriveFile is NSFW.'
})
public isSensitive: boolean;
/**
* 外部の(信頼されていない)URLへの直リンクか否か
*/
@Column('boolean', {
default: false,
comment: 'Whether the DriveFile is direct link to remote server.'
})
public isRemote: boolean;
}

View File

@ -0,0 +1,49 @@
import { JoinColumn, ManyToOne, Entity, PrimaryColumn, Index, Column } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class DriveFolder {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the DriveFolder.'
})
public createdAt: Date;
@Column('varchar', {
length: 128,
comment: 'The name of the DriveFolder.'
})
public name: string;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The owner ID.'
})
public userId: User['id'] | null;
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The parent folder ID. If null, it means the DriveFolder is located in root.'
})
public parentId: DriveFolder['id'] | null;
@ManyToOne(type => DriveFolder, {
onDelete: 'SET NULL'
})
@JoinColumn()
public parent: DriveFolder | null;
}

View File

@ -0,0 +1,46 @@
import { PrimaryColumn, Entity, Index, Column } from 'typeorm';
import { id } from '../id';
@Entity()
@Index(['name', 'host'], { unique: true })
export class Emoji {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
nullable: true
})
public updatedAt: Date | null;
@Index()
@Column('varchar', {
length: 128
})
public name: string;
@Index()
@Column('varchar', {
length: 128, nullable: true
})
public host: string | null;
@Column('varchar', {
length: 256,
})
public url: string;
@Column('varchar', {
length: 256, nullable: true
})
public uri: string | null;
@Column('varchar', {
length: 64, nullable: true
})
public type: string | null;
@Column('varchar', {
array: true, length: 128, default: '{}'
})
public aliases: string[];
}

View File

@ -0,0 +1,85 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['followerId', 'followeeId'], { unique: true })
export class FollowRequest {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the FollowRequest.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The followee user ID.'
})
public followeeId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public followee: User | null;
@Index()
@Column({
...id(),
comment: 'The follower user ID.'
})
public followerId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public follower: User | null;
@Column('varchar', {
length: 128, nullable: true,
comment: 'id of Follow Activity.'
})
public requestId: string | null;
//#region Denormalized fields
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public followerHost: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followerInbox: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followerSharedInbox: string | null;
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public followeeHost: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followeeInbox: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followeeSharedInbox: string | null;
//#endregion
}

View File

@ -0,0 +1,80 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['followerId', 'followeeId'], { unique: true })
export class Following {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the Following.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The followee user ID.'
})
public followeeId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public followee: User | null;
@Index()
@Column({
...id(),
comment: 'The follower user ID.'
})
public followerId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public follower: User | null;
//#region Denormalized fields
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public followerHost: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followerInbox: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followerSharedInbox: string | null;
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public followeeHost: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followeeInbox: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: '[Denormalized]'
})
public followeeSharedInbox: string | null;
//#endregion
}

View File

@ -0,0 +1,133 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from '../../user';
import { id } from '../../../id';
@Entity()
export class ReversiGame {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the ReversiGame.'
})
public createdAt: Date;
@Column('timestamp with time zone', {
nullable: true,
comment: 'The started date of the ReversiGame.'
})
public startedAt: Date | null;
@Column(id())
public user1Id: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user1: User | null;
@Column(id())
public user2Id: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user2: User | null;
@Column('boolean', {
default: false,
})
public user1Accepted: boolean;
@Column('boolean', {
default: false,
})
public user2Accepted: boolean;
/**
* どちらのプレイヤーが先行(黒)か
* 1 ... user1
* 2 ... user2
*/
@Column('integer', {
nullable: true,
})
public black: number | null;
@Column('boolean', {
default: false,
})
public isStarted: boolean;
@Column('boolean', {
default: false,
})
public isEnded: boolean;
@Column({
...id(),
nullable: true
})
public winnerId: User['id'] | null;
@Column({
...id(),
nullable: true
})
public surrendered: User['id'] | null;
@Column('jsonb', {
default: [],
})
public logs: {
at: Date;
color: boolean;
pos: number;
}[];
@Column('varchar', {
array: true, length: 64,
})
public map: string[];
@Column('varchar', {
length: 32
})
public bw: string;
@Column('boolean', {
default: false,
})
public isLlotheo: boolean;
@Column('boolean', {
default: false,
})
public canPutEverywhere: boolean;
@Column('boolean', {
default: false,
})
public loopedBoard: boolean;
@Column('jsonb', {
nullable: true, default: null,
})
public form1: any | null;
@Column('jsonb', {
nullable: true, default: null,
})
public form2: any | null;
/**
* ログのposを文字列としてすべて連結したもののCRC32値
*/
@Column('varchar', {
length: 32, nullable: true
})
public crc32: string | null;
}

View File

@ -0,0 +1,35 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from '../../user';
import { id } from '../../../id';
@Entity()
export class ReversiMatching {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the ReversiMatching.'
})
public createdAt: Date;
@Index()
@Column(id())
public parentId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public parent: User | null;
@Index()
@Column(id())
public childId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public child: User | null;
}

View File

@ -0,0 +1,87 @@
import { Entity, PrimaryColumn, Index, Column } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class Hashtag {
@PrimaryColumn(id())
public id: string;
@Index({ unique: true })
@Column('varchar', {
length: 128
})
public name: string;
@Column({
...id(),
array: true,
})
public mentionedUserIds: User['id'][];
@Index()
@Column('integer', {
default: 0
})
public mentionedUsersCount: number;
@Column({
...id(),
array: true,
})
public mentionedLocalUserIds: User['id'][];
@Index()
@Column('integer', {
default: 0
})
public mentionedLocalUsersCount: number;
@Column({
...id(),
array: true,
})
public mentionedRemoteUserIds: User['id'][];
@Index()
@Column('integer', {
default: 0
})
public mentionedRemoteUsersCount: number;
@Column({
...id(),
array: true,
})
public attachedUserIds: User['id'][];
@Index()
@Column('integer', {
default: 0
})
public attachedUsersCount: number;
@Column({
...id(),
array: true,
})
public attachedLocalUserIds: User['id'][];
@Index()
@Column('integer', {
default: 0
})
public attachedLocalUsersCount: number;
@Column({
...id(),
array: true,
})
public attachedRemoteUserIds: User['id'][];
@Index()
@Column('integer', {
default: 0
})
public attachedRemoteUsersCount: number;
}

View File

@ -0,0 +1,132 @@
import { Entity, PrimaryColumn, Index, Column } from 'typeorm';
import { id } from '../id';
@Entity()
export class Instance {
@PrimaryColumn(id())
public id: string;
/**
* このインスタンスを捕捉した日時
*/
@Index()
@Column('timestamp with time zone', {
comment: 'The caught date of the Instance.'
})
public caughtAt: Date;
/**
* ホスト
*/
@Index({ unique: true })
@Column('varchar', {
length: 128,
comment: 'The host of the Instance.'
})
public host: string;
/**
* インスタンスのシステム (MastodonとかMisskeyとかPleromaとか)
*/
@Column('varchar', {
length: 64, nullable: true,
comment: 'The system of the Instance.'
})
public system: string | null;
/**
* インスタンスのユーザー数
*/
@Column('integer', {
default: 0,
comment: 'The count of the users of the Instance.'
})
public usersCount: number;
/**
* インスタンスの投稿数
*/
@Column('integer', {
default: 0,
comment: 'The count of the notes of the Instance.'
})
public notesCount: number;
/**
* このインスタンスのユーザーからフォローされている、自インスタンスのユーザーの数
*/
@Column('integer', {
default: 0,
})
public followingCount: number;
/**
* このインスタンスのユーザーをフォローしている、自インスタンスのユーザーの数
*/
@Column('integer', {
default: 0,
})
public followersCount: number;
/**
* ドライブ使用量
*/
@Column('integer', {
default: 0,
})
public driveUsage: number;
/**
* ドライブのファイル数
*/
@Column('integer', {
default: 0,
})
public driveFiles: number;
/**
* 直近のリクエスト送信日時
*/
@Column('timestamp with time zone', {
nullable: true,
})
public latestRequestSentAt: Date | null;
/**
* 直近のリクエスト送信時のHTTPステータスコード
*/
@Column('integer', {
nullable: true,
})
public latestStatus: number | null;
/**
* 直近のリクエスト受信日時
*/
@Column('timestamp with time zone', {
nullable: true,
})
public latestRequestReceivedAt: Date | null;
/**
* このインスタンスと最後にやり取りした日時
*/
@Column('timestamp with time zone')
public lastCommunicatedAt: Date;
/**
* このインスタンスと不通かどうか
*/
@Column('boolean', {
default: false
})
public isNotResponding: boolean;
/**
* このインスタンスが閉鎖済みとしてマークされているか
*/
@Column('boolean', {
default: false
})
public isMarkedAsClosed: boolean;
}

View File

@ -0,0 +1,46 @@
import { Entity, PrimaryColumn, Index, Column } from 'typeorm';
import { id } from '../id';
@Entity()
export class Log {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the Log.'
})
public createdAt: Date;
@Index()
@Column('varchar', {
length: 64, array: true, default: '{}'
})
public domain: string[];
@Index()
@Column('enum', {
enum: ['error', 'warning', 'info', 'success', 'debug']
})
public level: string;
@Column('varchar', {
length: 8
})
public worker: string;
@Column('varchar', {
length: 128
})
public machine: string;
@Column('varchar', {
length: 1024
})
public message: string;
@Column('jsonb', {
default: {}
})
public data: Record<string, any>;
}

View File

@ -0,0 +1,64 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { DriveFile } from './drive-file';
import { id } from '../id';
@Entity()
export class MessagingMessage {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the MessagingMessage.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The sender user ID.'
})
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column({
...id(),
comment: 'The recipient user ID.'
})
public recipientId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public recipient: User | null;
@Column('varchar', {
length: 4096, nullable: true
})
public text: string | null;
@Column('boolean', {
default: false,
})
public isRead: boolean;
@Column({
...id(),
nullable: true,
})
public fileId: DriveFile['id'] | null;
@ManyToOne(type => DriveFile, {
onDelete: 'CASCADE'
})
@JoinColumn()
public file: DriveFile | null;
}

264
src/models/entities/meta.ts Normal file
View File

@ -0,0 +1,264 @@
import { Entity, Column, PrimaryColumn } from 'typeorm';
import { id } from '../id';
@Entity()
export class Meta {
@PrimaryColumn(id())
public id: string;
@Column('varchar', {
length: 128, nullable: true
})
public name: string | null;
@Column('varchar', {
length: 1024, nullable: true
})
public description: string | null;
/**
* メンテナの名前
*/
@Column('varchar', {
length: 128, nullable: true
})
public maintainerName: string | null;
/**
* メンテナの連絡先
*/
@Column('varchar', {
length: 128, nullable: true
})
public maintainerEmail: string | null;
@Column('jsonb', {
default: [],
})
public announcements: Record<string, any>[];
@Column('boolean', {
default: false,
})
public disableRegistration: boolean;
@Column('boolean', {
default: false,
})
public disableLocalTimeline: boolean;
@Column('boolean', {
default: false,
})
public disableGlobalTimeline: boolean;
@Column('boolean', {
default: true,
})
public enableEmojiReaction: boolean;
@Column('boolean', {
default: false,
})
public useStarForReactionFallback: boolean;
@Column('varchar', {
length: 64, array: true, default: '{}'
})
public langs: string[];
@Column('varchar', {
length: 256, array: true, default: '{}'
})
public hiddenTags: string[];
@Column('varchar', {
length: 256, array: true, default: '{}'
})
public blockedHosts: string[];
@Column('varchar', {
length: 256,
nullable: true,
default: '/assets/ai.png'
})
public mascotImageUrl: string | null;
@Column('varchar', {
length: 256,
nullable: true
})
public bannerUrl: string | null;
@Column('varchar', {
length: 256,
nullable: true,
default: 'https://ai.misskey.xyz/aiart/yubitun.png'
})
public errorImageUrl: string | null;
@Column('varchar', {
length: 256,
nullable: true
})
public iconUrl: string | null;
@Column('boolean', {
default: true,
})
public cacheRemoteFiles: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public proxyAccount: string | null;
@Column('boolean', {
default: false,
})
public enableRecaptcha: boolean;
@Column('varchar', {
length: 64,
nullable: true
})
public recaptchaSiteKey: string | null;
@Column('varchar', {
length: 64,
nullable: true
})
public recaptchaSecretKey: string | null;
@Column('integer', {
default: 1024,
comment: 'Drive capacity of a local user (MB)'
})
public localDriveCapacityMb: number;
@Column('integer', {
default: 32,
comment: 'Drive capacity of a remote user (MB)'
})
public remoteDriveCapacityMb: number;
@Column('integer', {
default: 500,
comment: 'Max allowed note text length in characters'
})
public maxNoteTextLength: number;
@Column('varchar', {
length: 128,
nullable: true
})
public summalyProxy: string | null;
@Column('boolean', {
default: false,
})
public enableEmail: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public email: string | null;
@Column('boolean', {
default: false,
})
public smtpSecure: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public smtpHost: string | null;
@Column('integer', {
nullable: true
})
public smtpPort: number | null;
@Column('varchar', {
length: 128,
nullable: true
})
public smtpUser: string | null;
@Column('varchar', {
length: 128,
nullable: true
})
public smtpPass: string | null;
@Column('boolean', {
default: false,
})
public enableServiceWorker: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public swPublicKey: string | null;
@Column('varchar', {
length: 128,
nullable: true
})
public swPrivateKey: string | null;
@Column('boolean', {
default: false,
})
public enableTwitterIntegration: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public twitterConsumerKey: string | null;
@Column('varchar', {
length: 128,
nullable: true
})
public twitterConsumerSecret: string | null;
@Column('boolean', {
default: false,
})
public enableGithubIntegration: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public githubClientId: string | null;
@Column('varchar', {
length: 128,
nullable: true
})
public githubClientSecret: string | null;
@Column('boolean', {
default: false,
})
public enableDiscordIntegration: boolean;
@Column('varchar', {
length: 128,
nullable: true
})
public discordClientId: string | null;
@Column('varchar', {
length: 128,
nullable: true
})
public discordClientSecret: string | null;
}

View File

@ -0,0 +1,42 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['muterId', 'muteeId'], { unique: true })
export class Muting {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the Muting.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The mutee user ID.'
})
public muteeId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public mutee: User | null;
@Index()
@Column({
...id(),
comment: 'The muter user ID.'
})
public muterId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public muter: User | null;
}

View File

@ -0,0 +1,35 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { Note } from './note';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['userId', 'noteId'], { unique: true })
export class NoteFavorite {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the NoteFavorite.'
})
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column(id())
public noteId: Note['id'];
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
}

View File

@ -0,0 +1,42 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { Note } from './note';
import { id } from '../id';
@Entity()
@Index(['userId', 'noteId'], { unique: true })
export class NoteReaction {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the NoteReaction.'
})
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column(id())
public noteId: Note['id'];
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
@Column('varchar', {
length: 32
})
public reaction: string;
}

View File

@ -0,0 +1,43 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { Note } from './note';
import { id } from '../id';
@Entity()
@Index(['userId', 'noteId'], { unique: true })
export class NoteUnread {
@PrimaryColumn(id())
public id: string;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column(id())
public noteId: Note['id'];
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
@Column({
...id(),
comment: '[Denormalized]'
})
public noteUserId: User['id'];
/**
* ダイレクト投稿か
*/
@Column('boolean')
public isSpecified: boolean;
}

View File

@ -0,0 +1,52 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { Note } from './note';
import { id } from '../id';
@Entity()
@Index(['userId', 'noteId'], { unique: true })
export class NoteWatching {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the NoteWatching.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The watcher ID.'
})
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column({
...id(),
comment: 'The target Note ID.'
})
public noteId: Note['id'];
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
//#region Denormalized fields
@Index()
@Column({
...id(),
comment: '[Denormalized]'
})
public noteUserId: Note['userId'];
//#endregion
}

236
src/models/entities/note.ts Normal file
View File

@ -0,0 +1,236 @@
import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm';
import { User } from './user';
import { App } from './app';
import { DriveFile } from './drive-file';
import { id } from '../id';
@Entity()
export class Note {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the Note.'
})
public createdAt: Date;
@Index()
@Column('timestamp with time zone', {
nullable: true,
comment: 'The updated date of the Note.'
})
public updatedAt: Date | null;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The ID of reply target.'
})
public replyId: Note['id'] | null;
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public reply: Note | null;
@Index()
@Column({
...id(),
nullable: true,
comment: 'The ID of renote target.'
})
public renoteId: Note['id'] | null;
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public renote: Note | null;
@Column({
type: 'text', nullable: true
})
public text: string | null;
@Column('varchar', {
length: 256, nullable: true
})
public name: string | null;
@Column('varchar', {
length: 512, nullable: true
})
public cw: string | null;
@Column({
...id(),
nullable: true
})
public appId: App['id'] | null;
@ManyToOne(type => App, {
onDelete: 'SET NULL'
})
@JoinColumn()
public app: App | null;
@Index()
@Column({
...id(),
comment: 'The ID of author.'
})
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column('boolean', {
default: false
})
public viaMobile: boolean;
@Column('boolean', {
default: false
})
public localOnly: boolean;
@Column('integer', {
default: 0
})
public renoteCount: number;
@Column('integer', {
default: 0
})
public repliesCount: number;
@Column('jsonb', {
default: {}
})
public reactions: Record<string, number>;
/**
* public ... 公開
* home ... ホームタイムライン(ユーザーページのタイムライン含む)のみに流す
* followers ... フォロワーのみ
* specified ... visibleUserIds で指定したユーザーのみ
*/
@Column('enum', { enum: ['public', 'home', 'followers', 'specified'] })
public visibility: 'public' | 'home' | 'followers' | 'specified';
@Index({ unique: true })
@Column('varchar', {
length: 256, nullable: true,
comment: 'The URI of a note. it will be null when the note is local.'
})
public uri: string | null;
@Column('integer', {
default: 0
})
public score: number;
@Column({
...id(),
array: true, default: '{}'
})
public fileIds: DriveFile['id'][];
@Column('varchar', {
length: 256, array: true, default: '{}'
})
public attachedFileTypes: string[];
@Index()
@Column({
...id(),
array: true, default: '{}'
})
public visibleUserIds: User['id'][];
@Index()
@Column({
...id(),
array: true, default: '{}'
})
public mentions: User['id'][];
@Column('text', {
default: '[]'
})
public mentionedRemoteUsers: string;
@Column('varchar', {
length: 128, array: true, default: '{}'
})
public emojis: string[];
@Index()
@Column('varchar', {
length: 128, array: true, default: '{}'
})
public tags: string[];
@Column('boolean', {
default: false
})
public hasPoll: boolean;
@Column('jsonb', {
nullable: true, default: {}
})
public geo: any | null;
//#region Denormalized fields
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public userHost: string | null;
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public userInbox: string | null;
@Column({
...id(),
nullable: true,
comment: '[Denormalized]'
})
public replyUserId: User['id'] | null;
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public replyUserHost: string | null;
@Column({
...id(),
nullable: true,
comment: '[Denormalized]'
})
public renoteUserId: User['id'] | null;
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public renoteUserHost: string | null;
//#endregion
}
export type IMentionedRemoteUsers = {
uri: string;
username: string;
host: string;
}[];

View File

@ -0,0 +1,94 @@
import { Entity, Index, JoinColumn, ManyToOne, Column, PrimaryColumn } from 'typeorm';
import { User } from './user';
import { id } from '../id';
import { Note } from './note';
@Entity()
export class Notification {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the Notification.'
})
public createdAt: Date;
/**
* 通知の受信者
*/
@Index()
@Column({
...id(),
comment: 'The ID of recipient user of the Notification.'
})
public notifieeId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public notifiee: User | null;
/**
* 通知の送信者(initiator)
*/
@Column({
...id(),
comment: 'The ID of sender user of the Notification.'
})
public notifierId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public notifier: User | null;
/**
* 通知の種類。
* follow - フォローされた
* mention - 投稿で自分が言及された
* reply - (自分または自分がWatchしている)投稿が返信された
* renote - (自分または自分がWatchしている)投稿がRenoteされた
* quote - (自分または自分がWatchしている)投稿が引用Renoteされた
* reaction - (自分または自分がWatchしている)投稿にリアクションされた
* pollVote - (自分または自分がWatchしている)投稿の投票に投票された
*/
@Column('varchar', {
length: 32,
comment: 'The type of the Notification.'
})
public type: string;
/**
* 通知が読まれたかどうか
*/
@Column('boolean', {
default: false,
comment: 'Whether the Notification is read.'
})
public isRead: boolean;
@Column({
...id(),
nullable: true
})
public noteId: Note['id'] | null;
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
@Column('varchar', {
length: 128, nullable: true
})
public reaction: string;
@Column('integer', {
nullable: true
})
public choice: number;
}

View File

@ -0,0 +1,40 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { Note } from './note';
import { id } from '../id';
@Entity()
@Index(['userId', 'noteId', 'choice'], { unique: true })
export class PollVote {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the PollVote.'
})
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column(id())
public noteId: Note['id'];
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
@Column('integer')
public choice: number;
}

View File

@ -0,0 +1,67 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm';
import { id } from '../id';
import { Note } from './note';
import { User } from './user';
@Entity()
export class Poll {
@PrimaryColumn(id())
public id: string;
@Index({ unique: true })
@Column(id())
public noteId: Note['id'];
@OneToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
@Column('timestamp with time zone', {
nullable: true
})
public expiresAt: Date | null;
@Column('boolean')
public multiple: boolean;
@Column('varchar', {
length: 128, array: true, default: '{}'
})
public choices: string[];
@Column('integer', {
array: true,
})
public votes: number[];
//#region Denormalized fields
@Column('enum', {
enum: ['public', 'home', 'followers', 'specified'],
comment: '[Denormalized]'
})
public noteVisibility: 'public' | 'home' | 'followers' | 'specified';
@Index()
@Column({
...id(),
comment: '[Denormalized]'
})
public userId: User['id'];
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public userHost: string | null;
//#endregion
}
export type IPoll = {
choices: string[];
votes?: number[];
multiple: boolean;
expiresAt: Date;
};

View File

@ -0,0 +1,17 @@
import { PrimaryColumn, Entity, Index, Column } from 'typeorm';
import { id } from '../id';
@Entity()
export class RegistrationTicket {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone')
public createdAt: Date;
@Index({ unique: true })
@Column('varchar', {
length: 64,
})
public code: string;
}

View File

@ -0,0 +1,35 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class Signin {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the Signin.'
})
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column('varchar', {
length: 128,
})
public ip: string;
@Column('jsonb')
public headers: Record<string, any>;
@Column('boolean')
public success: boolean;
}

View File

@ -0,0 +1,37 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class SwSubscription {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone')
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column('varchar', {
length: 256,
})
public endpoint: string;
@Column('varchar', {
length: 256,
})
public auth: string;
@Column('varchar', {
length: 128,
})
public publickey: string;
}

View File

@ -0,0 +1,24 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class UserKeypair {
@PrimaryColumn(id())
public id: string;
@Index({ unique: true })
@Column(id())
public userId: User['id'];
@OneToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column('varchar', {
length: 4096,
})
public keyPem: string;
}

View File

@ -0,0 +1,41 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { UserList } from './user-list';
import { id } from '../id';
@Entity()
export class UserListJoining {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the UserListJoining.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The user ID.'
})
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index()
@Column({
...id(),
comment: 'The list ID.'
})
public userListId: UserList['id'];
@ManyToOne(type => UserList, {
onDelete: 'CASCADE'
})
@JoinColumn()
public userList: UserList | null;
}

View File

@ -0,0 +1,33 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class UserList {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the UserList.'
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: 'The owner ID.'
})
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column('varchar', {
length: 128,
comment: 'The name of the UserList.'
})
public name: string;
}

View File

@ -0,0 +1,35 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
import { Note } from './note';
import { User } from './user';
import { id } from '../id';
@Entity()
@Index(['userId', 'noteId'], { unique: true })
export class UserNotePining {
@PrimaryColumn(id())
public id: string;
@Column('timestamp with time zone', {
comment: 'The created date of the UserNotePinings.'
})
public createdAt: Date;
@Index()
@Column(id())
public userId: User['id'];
@ManyToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column(id())
public noteId: Note['id'];
@ManyToOne(type => Note, {
onDelete: 'CASCADE'
})
@JoinColumn()
public note: Note | null;
}

View File

@ -0,0 +1,30 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class UserPublickey {
@PrimaryColumn(id())
public id: string;
@Index({ unique: true })
@Column(id())
public userId: User['id'];
@OneToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Index({ unique: true })
@Column('varchar', {
length: 256,
})
public keyId: string;
@Column('varchar', {
length: 4096,
})
public keyPem: string;
}

View File

@ -0,0 +1,108 @@
import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm';
import { User } from './user';
import { id } from '../id';
@Entity()
export class UserServiceLinking {
@PrimaryColumn(id())
public id: string;
@Index({ unique: true })
@Column(id())
public userId: User['id'];
@OneToOne(type => User, {
onDelete: 'CASCADE'
})
@JoinColumn()
public user: User | null;
@Column('boolean', {
default: false,
})
public twitter: boolean;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public twitterAccessToken: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public twitterAccessTokenSecret: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public twitterUserId: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public twitterScreenName: string | null;
@Column('boolean', {
default: false,
})
public github: boolean;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public githubAccessToken: string | null;
@Column('integer', {
nullable: true, default: null,
})
public githubId: number | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public githubLogin: string | null;
@Column('boolean', {
default: false,
})
public discord: boolean;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public discordAccessToken: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public discordRefreshToken: string | null;
@Column('integer', {
nullable: true, default: null,
})
public discordExpiresDate: number | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public discordId: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public discordUsername: string | null;
@Column('varchar', {
length: 64, nullable: true, default: null,
})
public discordDiscriminator: string | null;
//#region Denormalized fields
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]'
})
public userHost: string | null;
//#endregion
}

297
src/models/entities/user.ts Normal file
View File

@ -0,0 +1,297 @@
import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
import { DriveFile } from './drive-file';
import { id } from '../id';
@Entity()
@Index(['usernameLower', 'host'], { unique: true })
export class User {
@PrimaryColumn(id())
public id: string;
@Index()
@Column('timestamp with time zone', {
comment: 'The created date of the User.'
})
public createdAt: Date;
@Index()
@Column('timestamp with time zone', {
nullable: true,
comment: 'The updated date of the User.'
})
public updatedAt: Date | null;
@Column('timestamp with time zone', {
nullable: true
})
public lastFetchedAt: Date | null;
@Column('varchar', {
length: 128,
comment: 'The username of the User.'
})
public username: string;
@Index()
@Column('varchar', {
length: 128, select: false,
comment: 'The username (lowercased) of the User.'
})
public usernameLower: string;
@Column('varchar', {
length: 128, nullable: true,
comment: 'The name of the User.'
})
public name: string | null;
@Column('varchar', {
length: 128, nullable: true,
comment: 'The location of the User.'
})
public location: string | null;
@Column('char', {
length: 10, nullable: true,
comment: 'The birthday (YYYY-MM-DD) of the User.'
})
public birthday: string | null;
@Column('integer', {
default: 0,
comment: 'The count of followers.'
})
public followersCount: number;
@Column('integer', {
default: 0,
comment: 'The count of following.'
})
public followingCount: number;
@Column('integer', {
default: 0,
comment: 'The count of notes.'
})
public notesCount: number;
@Column({
...id(),
nullable: true,
comment: 'The ID of avatar DriveFile.'
})
public avatarId: DriveFile['id'] | null;
@OneToOne(type => DriveFile, {
onDelete: 'SET NULL'
})
@JoinColumn()
public avatar: DriveFile | null;
@Column({
...id(),
nullable: true,
comment: 'The ID of banner DriveFile.'
})
public bannerId: DriveFile['id'] | null;
@OneToOne(type => DriveFile, {
onDelete: 'SET NULL'
})
@JoinColumn()
public banner: DriveFile | null;
@Column('varchar', {
length: 1024, nullable: true,
comment: 'The description (bio) of the User.'
})
public description: string | null;
@Index()
@Column('varchar', {
length: 128, array: true, default: '{}'
})
public tags: string[];
@Column('varchar', {
length: 128, nullable: true,
comment: 'The email address of the User.'
})
public email: string | null;
@Column('varchar', {
length: 128, nullable: true,
})
public emailVerifyCode: string | null;
@Column('boolean', {
default: false,
})
public emailVerified: boolean;
@Column('varchar', {
length: 128, nullable: true,
})
public twoFactorTempSecret: string | null;
@Column('varchar', {
length: 128, nullable: true,
})
public twoFactorSecret: string | null;
@Column('varchar', {
length: 256, nullable: true,
})
public avatarUrl: string | null;
@Column('varchar', {
length: 256, nullable: true,
})
public bannerUrl: string | null;
@Column('varchar', {
length: 32, nullable: true,
})
public avatarColor: string | null;
@Column('varchar', {
length: 32, nullable: true,
})
public bannerColor: string | null;
@Column('boolean', {
default: false,
comment: 'Whether the User is suspended.'
})
public isSuspended: boolean;
@Column('boolean', {
default: false,
comment: 'Whether the User is silenced.'
})
public isSilenced: boolean;
@Column('boolean', {
default: false,
comment: 'Whether the User is locked.'
})
public isLocked: boolean;
@Column('boolean', {
default: false,
comment: 'Whether the User is a bot.'
})
public isBot: boolean;
@Column('boolean', {
default: false,
comment: 'Whether the User is a cat.'
})
public isCat: boolean;
@Column('boolean', {
default: false,
comment: 'Whether the User is the admin.'
})
public isAdmin: boolean;
@Column('boolean', {
default: false,
comment: 'Whether the User is a moderator.'
})
public isModerator: boolean;
@Column('boolean', {
default: false,
})
public isVerified: boolean;
@Column('boolean', {
default: false,
})
public twoFactorEnabled: boolean;
@Column('varchar', {
length: 128, array: true, default: '{}'
})
public emojis: string[];
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: 'The host of the User. It will be null if the origin of the user is local.'
})
public host: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: 'The inbox of the User. It will be null if the origin of the user is local.'
})
public inbox: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: 'The sharedInbox of the User. It will be null if the origin of the user is local.'
})
public sharedInbox: string | null;
@Column('varchar', {
length: 256, nullable: true,
comment: 'The featured of the User. It will be null if the origin of the user is local.'
})
public featured: string | null;
@Index()
@Column('varchar', {
length: 256, nullable: true,
comment: 'The URI of the User. It will be null if the origin of the user is local.'
})
public uri: string | null;
@Column('varchar', {
length: 128, nullable: true,
comment: 'The password hash of the User. It will be null if the origin of the user is local.'
})
public password: string | null;
@Index({ unique: true })
@Column('varchar', {
length: 32, nullable: true, unique: true,
comment: 'The native access token of the User. It will be null if the origin of the user is local.'
})
public token: string | null;
@Column('jsonb', {
default: {},
comment: 'The client-specific data of the User.'
})
public clientData: Record<string, any>;
@Column('boolean', {
default: false,
})
public autoWatch: boolean;
@Column('boolean', {
default: false,
})
public autoAcceptFollowed: boolean;
@Column('boolean', {
default: false,
})
public alwaysMarkNsfw: boolean;
@Column('boolean', {
default: false,
})
public carefulBot: boolean;
}
export interface ILocalUser extends User {
host: null;
}
export interface IRemoteUser extends User {
host: string;
}