Chg: exactOptionalPropertyTypesをfalseに変更 / Chg(Security): トークンが不正な場合のエラーを全てtoken_invalidに変更 / New: channelテーブル・リポジトリ / Chg: configテーブルのvalueをstringに / Chg: configテーブルのlengthを4096に / New: messageテーブル / Chg: 安全のためuserテーブルのOptionalPropsにidを追加 / New: channel/createエンドポイント / New: channel/listエンドポイント / New: channel/editエンドポイント / Enhance: primary/signupエンドポイントの重複エラーの実装で末尾カンマなどの改善 / Chg: setup/initializationのdescriptionに最大文字数4096を制定 / Chg: serverInfoをdefault exportからexportに変更 / New: フロントエンドでmeを読み込み / New: フロントエンドでchannelを読み込み / New: client.tsでトークンがある場合はトークンを指定 / Chg: clientをrefに / Del: IndexedDBからserverテーブルを削除 / Fix: Dexieのclassに命名 / Feat: フロントエンドでのサインインページ / Fix: L.jsで任意のbodyがあるエンドポイントが定義できない問題を修正 / Del: L.jsのserver-infoでの不要なimportを削除 / Fix: L.jsでトークンのエラーを追加 / Fix: L.jsのUserSchemaにlastUsedAtを追加
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import generateUniqueId from "@/lib/id";
|
||||
import { Entity, EntityRepositoryType, Index, ManyToOne, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core";
|
||||
import { UserEntity } from "@/modules/entities/User";
|
||||
import { ChannelRepository } from "@/modules/repositories/Channel";
|
||||
|
||||
@Entity({
|
||||
tableName: "channel",
|
||||
repository: () => ChannelRepository,
|
||||
})
|
||||
export class ChannelEntity {
|
||||
[EntityRepositoryType]?: ChannelRepository;
|
||||
[OptionalProps]?: "id" | "createdAt";
|
||||
|
||||
@PrimaryKey({
|
||||
type: "string",
|
||||
length: 10,
|
||||
onCreate: () => generateUniqueId(),
|
||||
})
|
||||
id!: string;
|
||||
|
||||
@Property({
|
||||
type: "string",
|
||||
length: 20,
|
||||
unique: true,
|
||||
})
|
||||
@Index()
|
||||
name!: string;
|
||||
|
||||
@Property({
|
||||
type: "string",
|
||||
length: 4096,
|
||||
})
|
||||
description!: string;
|
||||
|
||||
@ManyToOne(() => UserEntity)
|
||||
createdBy!: UserEntity;
|
||||
|
||||
@Property({
|
||||
type: "datetime",
|
||||
onCreate: () => new Date(),
|
||||
})
|
||||
createdAt!: Date;
|
||||
}
|
||||
@@ -11,6 +11,9 @@ export class ConfigEntity {
|
||||
@PrimaryKey({ type: "string" })
|
||||
name!: string;
|
||||
|
||||
@Property({ type: "text" })
|
||||
@Property({
|
||||
type: "string",
|
||||
length: 4096,
|
||||
})
|
||||
value!: string;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import generateUniqueId from "@/lib/id";
|
||||
import { Entity, Index, ManyToOne, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core";
|
||||
import { UserEntity } from "@/modules/entities/User";
|
||||
import { ChannelEntity } from "@/modules/entities/Channel";
|
||||
|
||||
@Entity({
|
||||
tableName: "message",
|
||||
})
|
||||
export class MessageEntity {
|
||||
[OptionalProps]?: "id" | "createdAt";
|
||||
|
||||
@PrimaryKey({
|
||||
type: "string",
|
||||
length: 10,
|
||||
onCreate: () => generateUniqueId(),
|
||||
})
|
||||
id!: string;
|
||||
|
||||
@Property({
|
||||
type: "string",
|
||||
length: 4096,
|
||||
})
|
||||
message!: string;
|
||||
|
||||
@ManyToOne(() => ChannelEntity)
|
||||
channel!: ChannelEntity;
|
||||
|
||||
@ManyToOne(() => UserEntity)
|
||||
createdBy!: UserEntity;
|
||||
|
||||
@Property({
|
||||
type: "datetime",
|
||||
onCreate: () => new Date(),
|
||||
})
|
||||
createdAt!: Date;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import generateUniqueId from "@/lib/id";
|
||||
})
|
||||
export class UserEntity {
|
||||
[EntityRepositoryType]?: UserRepository;
|
||||
[OptionalProps]?: "profile" | "isSuspended" | "createdAt";
|
||||
[OptionalProps]?: "id" | "profile" | "isSuspended" | "createdAt";
|
||||
|
||||
@PrimaryKey({
|
||||
type: "string",
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||
import type { ChannelEntity } from "@/modules/entities/Channel";
|
||||
import { ErrorBase } from "@/errors";
|
||||
import z from "zod/v3";
|
||||
import { UserRepository } from "@/modules/repositories/User";
|
||||
|
||||
export class ChannelRepository extends EntityRepository<ChannelEntity> {
|
||||
public static schema = z.object({
|
||||
name: z.string().trim().min(1).max(20),
|
||||
description: z.string().trim().min(1).max(4096),
|
||||
userid: UserRepository.schema.shape.userid,
|
||||
});
|
||||
|
||||
async findChannel(limit: number = 20, sinceData?: string) {
|
||||
let since = sinceData ?? new Date();
|
||||
|
||||
if (
|
||||
sinceData &&
|
||||
!isNaN(new Date(sinceData).getTime())
|
||||
) {
|
||||
const itChannel = await this.findOne({ id: sinceData });
|
||||
|
||||
if (!itChannel) {
|
||||
return ErrorBase({
|
||||
bad: "client",
|
||||
code: "channel_not_found",
|
||||
message: "対象のチャンネルが見つかりませんでした。",
|
||||
});
|
||||
}
|
||||
|
||||
since = itChannel.createdAt;
|
||||
}
|
||||
|
||||
const findResult = await this.find({
|
||||
createdAt: {
|
||||
$lt: since,
|
||||
},
|
||||
}, {
|
||||
orderBy: {
|
||||
createdAt: "DESC",
|
||||
},
|
||||
limit: limit,
|
||||
});
|
||||
|
||||
return findResult ?? [];
|
||||
}
|
||||
|
||||
async createChannel(data: z.infer<typeof ChannelRepository.schema>) {
|
||||
const channel = this.create({
|
||||
...data,
|
||||
createdBy: data.userid,
|
||||
});
|
||||
|
||||
await this.em.persist(channel).flush();
|
||||
return channel.id;
|
||||
}
|
||||
|
||||
async editChannel(
|
||||
target: ChannelEntity,
|
||||
data: Partial<Omit<z.infer<typeof ChannelRepository.schema>, "userid">>
|
||||
) {
|
||||
await this.nativeUpdate(target, data);
|
||||
return target.id;
|
||||
}
|
||||
}
|
||||
@@ -52,9 +52,9 @@ export class TokenRepository extends EntityRepository<TokenEntity> {
|
||||
)
|
||||
return ErrorBase({
|
||||
bad: "client",
|
||||
code: "token_length_wrong",
|
||||
message: "トークンの文字数が不正です。",
|
||||
});
|
||||
code: "token_invalid",
|
||||
message: "トークンが不正です。",
|
||||
})
|
||||
|
||||
const token = await this.findOne({ name: tokenArr[0] }, { populate: ["user"] });
|
||||
if (!token)
|
||||
|
||||
Reference in New Issue
Block a user