Skip to content

Commit

Permalink
feat: add migration supports for attachment (#21)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/kind feature

#### What this PR does / why we need it:

增加 1.x 版本附件的迁移功能。

关于云存储支持:
Halo 2.x 云存储需要插件 s3 的支持,详见 https://github.com/halo-sigs/plugin-s3
**注意:目前只支持 阿里云、腾讯云、百度云、七牛云 等支持 s3 规范的云存储迁移。**

#### Which issue(s) this PR fixes:

#### Special notes for your reviewer:

1. 从 Halo 1.x 版本中导出 json 数据文件
2. 将 1.x 工作目录下的 `upload` 目录里的所有文件夹(不包括 upload 目录本身)移动到 2.0 工作目录下的 `attachments\migrate-from-1.x` 文件夹
3. 安装可运行插件 [plugin-migrate-1.1.0-SNAPSHOT.jar.zip](https://github.com/halo-sigs/plugin-migrate/files/11229003/plugin-migrate-1.1.0-SNAPSHOT.jar.zip)
4. 安装 [plugin-s3](https://github.com/halo-sigs/plugin-s3) 插件
5. 点击“选择附件存储策略”,选择 1.x 各附件存储位置所对应的存储策略。
6. 点击“开始导入”,导入完成后,前往“附件“菜单查看是否导入成功

#### Does this PR introduce a user-facing change?

```release-note
增加 Halo 1.x 中附件的迁移功能
```
  • Loading branch information
LIlGG authored Apr 21, 2023
1 parent 3cd451f commit 10b4534
Show file tree
Hide file tree
Showing 5 changed files with 379 additions and 10 deletions.
148 changes: 147 additions & 1 deletion console/src/composables/use-migrate-from-halo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Ref } from "vue";
import { apiClient } from "@/utils/api-client";
import type { User } from "@halo-dev/api-client";
import { arrayToTree } from "performant-array-to-tree";
import type {
Category,
Expand All @@ -15,10 +16,11 @@ import type {
Journal,
Photo,
Link,
Attachment as AttachmentModel,
} from "../types/models";
import axios, { type AxiosResponse } from "axios";
import groupBy from "lodash.groupby";
import type { MenuItem } from "@halo-dev/api-client/index";
import type { Attachment, MenuItem } from "@halo-dev/api-client/index";

export interface MigrateRequestTask<T> {
item: T;
Expand All @@ -37,6 +39,10 @@ interface useMigrateFromHaloReturn {
createMomentCommentTasks: () => MigrateRequestTask<Comment>[];
createPhotoTasks: () => MigrateRequestTask<string | Photo>[];
createLinkTasks: () => MigrateRequestTask<string | Link>[];
createAttachmentTasks: (
typeToPolicyMap: Map<string, string>,
user: User
) => MigrateRequestTask<string | MenuItem>[];
}

class TagTask implements MigrateRequestTask<Tag> {
Expand Down Expand Up @@ -500,6 +506,103 @@ class LinkTask implements MigrateRequestTask<Link> {
}
}

interface AttachmentTask extends MigrateRequestTask<AttachmentModel> {
item: AttachmentModel;

run: () => Promise<AxiosResponse<any, any>>;
}

class NoSupportAttachmentTask implements AttachmentTask {
item: AttachmentModel;
constructor(item: AttachmentModel) {
this.item = item;
}

run() {
return Promise.reject(
new Error("尚未支持 【" + this.item.type + "】 类型的附件迁移")
);
}
}

abstract class AbstractAttachmentTask implements AttachmentTask {
item: AttachmentModel;
policyName: string;
ownerName: string;
constructor(item: AttachmentModel, policyName: string, ownerName: string) {
this.item = item;
this.policyName = policyName;
this.ownerName = ownerName;
}

abstract buildModel(): Attachment;

run() {
return apiClient.extension.storage.attachment.createstorageHaloRunV1alpha1Attachment(
{
attachment: this.buildModel(),
}
);
}
}

class LocalAttachmentTask extends AbstractAttachmentTask {
buildModel() {
let relativePath = this.item.path;
if (this.item.path.startsWith("upload/")) {
relativePath = relativePath.replace("upload/", "");
}
return {
apiVersion: "storage.halo.run/v1alpha1",
kind: "Attachment",
metadata: {
name: this.item.id + "",
annotations: {
"storage.halo.run/local-relative-path": `migrate-from-1.x/${relativePath}`,
"storage.halo.run/uri": `/${this.item.path}`,
"storage.halo.run/suffix": `${this.item.suffix}`,
"storage.halo.run/width": `${this.item.width}`,
"storage.halo.run/height": `${this.item.height}`,
},
},
spec: {
displayName: `${this.item.name}`,
groupName: ``,
ownerName: `${this.ownerName}`,
policyName: `${this.policyName}`,
mediaType: `${this.item.mediaType}`,
size: Number.parseInt(`${this.item.size}`),
},
};
}
}

class S3OSSAttachmentTask extends AbstractAttachmentTask {
buildModel() {
return {
apiVersion: "storage.halo.run/v1alpha1",
kind: "Attachment",
metadata: {
name: this.item.id + "",
annotations: {
"storage.halo.run/external-link": `${this.item.path}`,
"storage.halo.run/suffix": `${this.item.suffix}`,
"storage.halo.run/width": `${this.item.width}`,
"storage.halo.run/height": `${this.item.height}`,
},
},
spec: {
displayName: `${this.item.name}`,
groupName: "",
policyName: `${this.policyName}`,
ownerName: `${this.ownerName}`,
mediaType: `${this.item.mediaType}`,
size: Number.parseInt(`${this.item.size}`),
},
};
}
}

export function useMigrateFromHalo(
tags: Ref<Tag[]>,
categories: Ref<Category[]>,
Expand All @@ -517,6 +620,7 @@ export function useMigrateFromHalo(
journalComments: Ref<Comment[]>,
photos: Ref<Photo[]>,
links: Ref<Link[]>,
attachments: Ref<AttachmentModel[]>
): useMigrateFromHaloReturn {
function createTagTasks() {
return tags.value.map((item: Tag) => {
Expand Down Expand Up @@ -746,6 +850,47 @@ export function useMigrateFromHalo(
return [...linkGroupRequests, ...linkRequests];
}

function createAttachmentTasks(
typeToPolicyMap: Map<string, string>,
user: User
) {
const typeGroupAttachments = groupBy(attachments.value, "type");

let attachmentRequests: MigrateRequestTask<any>[] = [];
const userName = user.metadata.name;
Object.keys(typeGroupAttachments).forEach((type) => {
const attachments = typeGroupAttachments[type];
attachmentRequests = [
...attachmentRequests,
...attachments
.map((item) => {
switch (item.type) {
case "LOCAL":
return new LocalAttachmentTask(
item,
typeToPolicyMap.get(item.type) || "default-policy",
userName
);
case "ALIOSS":
case "BAIDUBOS":
case "TENCENTCOS":
case "QINIUOSS":
return new S3OSSAttachmentTask(
item,
typeToPolicyMap.get(item.type) || "default-policy",
userName
);
default:
return new NoSupportAttachmentTask(item);
}
})
.filter((item) => item && item != undefined),
];
});

return attachmentRequests;
}

return {
createTagTasks,
createCategoryTasks,
Expand All @@ -758,5 +903,6 @@ export function useMigrateFromHalo(
createMomentCommentTasks,
createPhotoTasks,
createLinkTasks,
createAttachmentTasks,
};
}
25 changes: 25 additions & 0 deletions console/src/types/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,28 @@ export interface Link {
team: string;
priority: number;
}

export interface Attachment {
createTime: number;
updateTime: number;
id: number;
name: string;
path: string;
fileKey: string;
thumbPath: string;
mediaType: string;
suffix: string;
width: number;
height: number;
size: number;
type:
| "LOCAL"
| "UPOSS"
| "QINIUOSS"
| "SMMS"
| "ALIOSS"
| "BAIDUBOS"
| "TENCENTCOS"
| "HUAWEIOBS"
| "MINIO";
}
Loading

0 comments on commit 10b4534

Please sign in to comment.