mirror of https://github.com/halo-dev/halo
feat: add data export and import api. (#672)
* feat: add data export and import api. * refactor: data export and import api.pull/687/head
parent
d6b3d6cb5d
commit
4bc8ad44da
|
@ -62,13 +62,16 @@ public class AdminController {
|
|||
|
||||
@PostMapping("password/code")
|
||||
@ApiOperation("Sends reset password verify code")
|
||||
@CacheLock(autoDelete = false)
|
||||
@DisableOnCondition
|
||||
public void sendResetCode(@RequestBody @Valid ResetPasswordParam param) {
|
||||
adminService.sendResetPasswordCode(param);
|
||||
}
|
||||
|
||||
@PutMapping("password/reset")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Resets password by verify code")
|
||||
@CacheLock(autoDelete = false)
|
||||
@DisableOnCondition
|
||||
public void resetPassword(@RequestBody @Valid ResetPasswordParam param) {
|
||||
adminService.resetPasswordByCode(param);
|
||||
}
|
||||
|
@ -95,32 +98,35 @@ public class AdminController {
|
|||
|
||||
@PutMapping("halo-admin")
|
||||
@ApiOperation("Updates halo-admin manually")
|
||||
@Deprecated
|
||||
public void updateAdmin() {
|
||||
adminService.updateAdminAssets();
|
||||
}
|
||||
|
||||
@GetMapping("spring/application.yaml")
|
||||
@ApiOperation("Gets application config content")
|
||||
@DisableOnCondition
|
||||
public BaseResponse<String> getSpringApplicationConfig() {
|
||||
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), adminService.getApplicationConfig());
|
||||
}
|
||||
|
||||
@PutMapping("spring/application.yaml")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Updates application config content")
|
||||
@DisableOnCondition
|
||||
public void updateSpringApplicationConfig(@RequestParam(name = "content") String content) {
|
||||
adminService.updateApplicationConfig(content);
|
||||
}
|
||||
|
||||
@PostMapping(value = {"halo/restart", "spring/restart"})
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Restarts halo server")
|
||||
@DisableOnCondition
|
||||
public void restartApplication() {
|
||||
Application.restart();
|
||||
}
|
||||
|
||||
@GetMapping(value = "halo/logfile")
|
||||
@ApiOperation("Gets halo log file content")
|
||||
@DisableOnCondition
|
||||
public BaseResponse<String> getLogFiles(@RequestParam("lines") Long lines) {
|
||||
return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), adminService.getLogFiles(lines));
|
||||
}
|
||||
|
|
|
@ -1,26 +1,20 @@
|
|||
package run.halo.app.controller.admin.api;
|
||||
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.exception.FileOperationException;
|
||||
import run.halo.app.model.annotation.DisableOnCondition;
|
||||
import run.halo.app.model.dto.BackupDTO;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
import run.halo.app.service.BackupService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -44,6 +38,7 @@ public class BackupController {
|
|||
|
||||
@PostMapping("halo")
|
||||
@ApiOperation("Backups halo")
|
||||
@DisableOnCondition
|
||||
public BackupDTO backupHalo() {
|
||||
return backupService.zipWorkDirectory();
|
||||
}
|
||||
|
@ -56,6 +51,7 @@ public class BackupController {
|
|||
|
||||
@GetMapping("halo/{fileName:.+}")
|
||||
@ApiOperation("Downloads backup file")
|
||||
@DisableOnCondition
|
||||
public ResponseEntity<Resource> downloadBackup(@PathVariable("fileName") String fileName, HttpServletRequest request) {
|
||||
log.info("Try to download backup file: [{}]", fileName);
|
||||
|
||||
|
@ -79,6 +75,7 @@ public class BackupController {
|
|||
|
||||
@DeleteMapping("halo")
|
||||
@ApiOperation("Deletes a backup")
|
||||
@DisableOnCondition
|
||||
public void deleteBackup(@RequestParam("filename") String filename) {
|
||||
backupService.deleteHaloBackup(filename);
|
||||
}
|
||||
|
@ -89,48 +86,17 @@ public class BackupController {
|
|||
return backupService.importMarkdown(file);
|
||||
}
|
||||
|
||||
@GetMapping("export/hexo")
|
||||
@ApiOperation("export hexo markdown")
|
||||
public void exportMarkdowns(HttpServletResponse response) {
|
||||
final String tmpDir = System.getProperty("java.io.tmpdir");
|
||||
final String date = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
|
||||
String localFilePath = tmpDir + File.separator + "halo-markdown-" + date;
|
||||
log.trace(localFilePath);
|
||||
final File localFile = new File(localFilePath);
|
||||
final File postDir = new File(localFilePath + File.separator + "posts");
|
||||
final File passwordDir = new File(localFilePath + File.separator + "passwords");
|
||||
final File draftDir = new File(localFilePath + File.separator + "drafts");
|
||||
try {
|
||||
if (!postDir.mkdirs()) {
|
||||
throw new Exception("Create dir [" + postDir.getPath() + "] failed");
|
||||
}
|
||||
if (!passwordDir.mkdirs()) {
|
||||
throw new Exception("Create dir [" + passwordDir.getPath() + "] failed");
|
||||
}
|
||||
if (!draftDir.mkdirs()) {
|
||||
throw new Exception("Create dir [" + draftDir.getPath() + "] failed");
|
||||
}
|
||||
final JSONObject result = backupService.exportHexoMDs();
|
||||
final List<JSONObject> posts = (List<JSONObject>) result.opt("posts");
|
||||
backupService.exportHexoMd(posts, postDir.getPath());
|
||||
final List<JSONObject> passwords = (List<JSONObject>) result.opt("passwords");
|
||||
backupService.exportHexoMd(passwords, passwordDir.getPath());
|
||||
final List<JSONObject> drafts = (List<JSONObject>) result.opt("drafts");
|
||||
backupService.exportHexoMd(drafts, draftDir.getPath());
|
||||
@GetMapping("export/data")
|
||||
@DisableOnCondition
|
||||
public ResponseEntity<String> exportData() {
|
||||
|
||||
final File zipFile = ZipUtil.zip(localFile);
|
||||
byte[] zipData;
|
||||
try (final FileInputStream inputStream = new FileInputStream(zipFile)) {
|
||||
zipData = IOUtils.toByteArray(inputStream);
|
||||
response.setContentType("application/zip");
|
||||
final String fileName = "halo-markdown-" + date + ".zip";
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
|
||||
}
|
||||
String contentType = "application/octet-stream;charset=UTF-8";
|
||||
|
||||
response.getOutputStream().write(zipData);
|
||||
} catch (final Exception e) {
|
||||
log.error("Export failed", e);
|
||||
throw new FileOperationException("文章导出失败", e);
|
||||
}
|
||||
String filename = "halo-data-" + DateUtil.format(new Date(), "yyyy-MM-dd-HH-mm-ss.json");
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"")
|
||||
.body(backupService.exportData().toJSONString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,18 +23,18 @@ public class DataProcessController {
|
|||
this.themeSettingService = themeSettingService;
|
||||
}
|
||||
|
||||
@PutMapping("url/replace")
|
||||
@ApiOperation("Replace url in all table.")
|
||||
public void replaceUrl(@RequestParam("oldUrl") String oldUrl,
|
||||
@RequestParam("newUrl") String newUrl) {
|
||||
dataProcessService.replaceAllUrl(oldUrl, newUrl);
|
||||
}
|
||||
|
||||
@DeleteMapping("themes/settings/inactivated")
|
||||
@ApiOperation("Delete inactivated theme settings.")
|
||||
public void deleteInactivatedThemeSettings() {
|
||||
themeSettingService.deleteInactivated();
|
||||
}
|
||||
// @PutMapping("url/replace")
|
||||
// @ApiOperation("Replace url in all table.")
|
||||
// public void replaceUrl(@RequestParam("oldUrl") String oldUrl,
|
||||
// @RequestParam("newUrl") String newUrl) {
|
||||
// dataProcessService.replaceAllUrl(oldUrl, newUrl);
|
||||
// }
|
||||
//
|
||||
// @DeleteMapping("themes/settings/inactivated")
|
||||
// @ApiOperation("Delete inactivated theme settings.")
|
||||
// public void deleteInactivatedThemeSettings() {
|
||||
// themeSettingService.deleteInactivated();
|
||||
// }
|
||||
|
||||
@DeleteMapping("tags/unused")
|
||||
@ApiOperation("Delete unused tags")
|
||||
|
|
|
@ -164,6 +164,12 @@ public class InstallController {
|
|||
return null;
|
||||
}
|
||||
|
||||
long commentCount = postCommentService.count();
|
||||
|
||||
if (commentCount > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PostComment comment = new PostComment();
|
||||
comment.setAuthor("Halo");
|
||||
comment.setAuthorUrl("https://halo.run");
|
||||
|
@ -175,7 +181,9 @@ public class InstallController {
|
|||
|
||||
@Nullable
|
||||
private PostDetailVO createDefaultPostIfAbsent(@Nullable Category category) {
|
||||
|
||||
long publishedCount = postService.countByStatus(PostStatus.PUBLISHED);
|
||||
|
||||
if (publishedCount > 0) {
|
||||
return null;
|
||||
}
|
||||
|
@ -210,6 +218,11 @@ public class InstallController {
|
|||
|
||||
@Nullable
|
||||
private void createDefaultSheet() {
|
||||
long publishedCount = sheetService.countByStatus(PostStatus.PUBLISHED);
|
||||
if (publishedCount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SheetParam sheetParam = new SheetParam();
|
||||
sheetParam.setSlug("about");
|
||||
sheetParam.setTitle("关于页面");
|
||||
|
@ -261,10 +274,19 @@ public class InstallController {
|
|||
properties.put(PrimaryProperties.IS_INSTALLED, Boolean.TRUE.toString());
|
||||
properties.put(BlogProperties.BLOG_LOCALE, installParam.getLocale());
|
||||
properties.put(BlogProperties.BLOG_TITLE, installParam.getTitle());
|
||||
properties.put(BlogProperties.BLOG_URL, StringUtils.isBlank(installParam.getUrl()) ?
|
||||
optionService.getBlogBaseUrl() : installParam.getUrl());
|
||||
properties.put(BlogProperties.BLOG_URL, StringUtils.isBlank(installParam.getUrl()) ? optionService.getBlogBaseUrl() : installParam.getUrl());
|
||||
|
||||
Long birthday = optionService.getByPropertyOrDefault(PrimaryProperties.BIRTHDAY, Long.class, 0L);
|
||||
|
||||
if (birthday.equals(0L)) {
|
||||
properties.put(PrimaryProperties.BIRTHDAY, String.valueOf(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
Boolean globalAbsolutePathEnabled = optionService.getByPropertyOrDefault(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.class, null);
|
||||
|
||||
if (globalAbsolutePathEnabled == null) {
|
||||
properties.put(OtherProperties.GLOBAL_ABSOLUTE_PATH_ENABLED, Boolean.FALSE.toString());
|
||||
}
|
||||
|
||||
// Create properties
|
||||
optionService.saveProperties(properties);
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.mail.MailService;
|
||||
import run.halo.app.model.annotation.DisableOnCondition;
|
||||
import run.halo.app.model.params.MailParam;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
|
||||
|
@ -29,6 +30,7 @@ public class MailController {
|
|||
|
||||
@PostMapping("test")
|
||||
@ApiOperation("Tests the SMTP service")
|
||||
@DisableOnCondition
|
||||
public BaseResponse<String> testMail(@Valid @RequestBody MailParam mailParam) {
|
||||
mailService.sendTextMail(mailParam.getTo(), mailParam.getSubject(), mailParam.getContent());
|
||||
return BaseResponse.ok("已发送,请查收。若确认没有收到邮件,请检查服务器日志");
|
||||
|
@ -36,6 +38,7 @@ public class MailController {
|
|||
|
||||
@PostMapping("test/connection")
|
||||
@ApiOperation("Test connection with email server")
|
||||
@DisableOnCondition
|
||||
public BaseResponse<String> testConnection() {
|
||||
mailService.testConnection();
|
||||
return BaseResponse.ok("您和邮箱服务器的连接通畅");
|
||||
|
|
|
@ -6,8 +6,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.exception.BadRequestException;
|
||||
import run.halo.app.model.enums.MigrateType;
|
||||
import run.halo.app.model.properties.PrimaryProperties;
|
||||
import run.halo.app.service.MigrateService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
/**
|
||||
* Migrate controller
|
||||
|
@ -21,25 +24,32 @@ public class MigrateController {
|
|||
|
||||
private final MigrateService migrateService;
|
||||
|
||||
public MigrateController(MigrateService migrateService) {
|
||||
private final OptionService optionService;
|
||||
|
||||
public MigrateController(MigrateService migrateService,
|
||||
OptionService optionService) {
|
||||
this.migrateService = migrateService;
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@PostMapping("halo_v0_4_4")
|
||||
@ApiOperation("Migrate from Halo 0.4.4")
|
||||
public void migrateHaloOldVersion(@RequestPart("file") MultipartFile file) {
|
||||
migrateService.migrate(file, MigrateType.OLD_VERSION);
|
||||
@PostMapping("halo")
|
||||
@ApiOperation("Migrate from Halo")
|
||||
public void migrateHalo(@RequestPart("file") MultipartFile file) {
|
||||
if (optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false)) {
|
||||
throw new BadRequestException("无法在博客初始化完成之后迁移数据");
|
||||
}
|
||||
migrateService.migrate(file, MigrateType.HALO);
|
||||
}
|
||||
|
||||
@PostMapping("wordpress")
|
||||
@ApiOperation("Migrate from WordPress")
|
||||
public void migrateWordPress(@RequestPart("file") MultipartFile file) {
|
||||
migrateService.migrate(file, MigrateType.WORDPRESS);
|
||||
}
|
||||
|
||||
@PostMapping("cnblogs")
|
||||
@ApiOperation("Migrate from cnblogs")
|
||||
public void migrateCnBlogs(@RequestPart("file") MultipartFile file) {
|
||||
migrateService.migrate(file, MigrateType.CNBLOGS);
|
||||
}
|
||||
// @PostMapping("wordpress")
|
||||
// @ApiOperation("Migrate from WordPress")
|
||||
// public void migrateWordPress(@RequestPart("file") MultipartFile file) {
|
||||
// migrateService.migrate(file, MigrateType.WORDPRESS);
|
||||
// }
|
||||
//
|
||||
// @PostMapping("cnblogs")
|
||||
// @ApiOperation("Migrate from cnblogs")
|
||||
// public void migrateCnBlogs(@RequestPart("file") MultipartFile file) {
|
||||
// migrateService.migrate(file, MigrateType.CNBLOGS);
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ public class OptionController {
|
|||
}
|
||||
|
||||
@PostMapping("saving")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Saves options")
|
||||
@DisableOnCondition
|
||||
public void saveOptions(@Valid @RequestBody List<OptionParam> optionParams) {
|
||||
optionService.save(optionParams);
|
||||
}
|
||||
|
@ -78,30 +78,30 @@ public class OptionController {
|
|||
}
|
||||
|
||||
@PostMapping
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Creates option")
|
||||
@DisableOnCondition
|
||||
public void createBy(@RequestBody @Valid OptionParam optionParam) {
|
||||
optionService.save(optionParam);
|
||||
}
|
||||
|
||||
@PutMapping("{optionId:\\d+}")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Updates option")
|
||||
@DisableOnCondition
|
||||
public void updateBy(@PathVariable("optionId") Integer optionId,
|
||||
@RequestBody @Valid OptionParam optionParam) {
|
||||
optionService.update(optionId, optionParam);
|
||||
}
|
||||
|
||||
@DeleteMapping("{optionId:\\d+}")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Deletes option")
|
||||
@DisableOnCondition
|
||||
public void deletePermanently(@PathVariable("optionId") Integer optionId) {
|
||||
optionService.removePermanently(optionId);
|
||||
}
|
||||
|
||||
@PostMapping("map_view/saving")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Saves options by option map")
|
||||
@DisableOnCondition
|
||||
public void saveOptionsWithMapView(@RequestBody Map<String, Object> optionMap) {
|
||||
optionService.save(optionMap);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.handler.theme.config.support.Group;
|
||||
import run.halo.app.handler.theme.config.support.ThemeProperty;
|
||||
import run.halo.app.model.annotation.DisableOnCondition;
|
||||
import run.halo.app.model.params.ThemeContentParam;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.model.support.ThemeFile;
|
||||
|
@ -75,12 +76,14 @@ public class ThemeController {
|
|||
|
||||
@PutMapping("files/content")
|
||||
@ApiOperation("Updates template content")
|
||||
@DisableOnCondition
|
||||
public void updateContentBy(@RequestBody ThemeContentParam param) {
|
||||
themeService.saveTemplateContent(param.getPath(), param.getContent());
|
||||
}
|
||||
|
||||
@PutMapping("{themeId}/files/content")
|
||||
@ApiOperation("Updates template content by theme id")
|
||||
@DisableOnCondition
|
||||
public void updateContentBy(@PathVariable("themeId") String themeId,
|
||||
@RequestBody ThemeContentParam param) {
|
||||
themeService.saveTemplateContent(themeId, param.getPath(), param.getContent());
|
||||
|
@ -149,6 +152,7 @@ public class ThemeController {
|
|||
|
||||
@DeleteMapping("{themeId}")
|
||||
@ApiOperation("Deletes a theme")
|
||||
@DisableOnCondition
|
||||
public void deleteBy(@PathVariable("themeId") String themeId) {
|
||||
themeService.deleteTheme(themeId);
|
||||
}
|
||||
|
@ -187,7 +191,7 @@ public class ThemeController {
|
|||
|
||||
@GetMapping(value = "activation/template/exists")
|
||||
@ApiOperation("Determines if template exists")
|
||||
public BaseResponse exists(@RequestParam(value = "template") String template) {
|
||||
public BaseResponse<Boolean> exists(@RequestParam(value = "template") String template) {
|
||||
return BaseResponse.ok(themeService.templateExists(template));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public class UserController {
|
|||
|
||||
@PutMapping("profiles")
|
||||
@ApiOperation("Updates user profile")
|
||||
@DisableOnCondition
|
||||
public UserDTO updateProfile(@RequestBody UserParam userParam, User user) {
|
||||
// Validate the user param
|
||||
ValidationUtils.validate(userParam, UpdateCheck.class);
|
||||
|
@ -50,9 +51,9 @@ public class UserController {
|
|||
}
|
||||
|
||||
@PutMapping("profiles/password")
|
||||
@DisableOnCondition
|
||||
@ApiOperation("Updates user's password")
|
||||
public BaseResponse updatePassword(@RequestBody @Valid PasswordParam passwordParam, User user) {
|
||||
@DisableOnCondition
|
||||
public BaseResponse<String> updatePassword(@RequestBody @Valid PasswordParam passwordParam, User user) {
|
||||
userService.updatePassword(passwordParam.getOldPassword(), passwordParam.getNewPassword(), user.getId());
|
||||
return BaseResponse.ok("密码修改成功");
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.exception;
|
|||
|
||||
/**
|
||||
* repeat type exception
|
||||
*
|
||||
* @author bestsort
|
||||
* @date 3/13/20 5:03 PM
|
||||
*/
|
||||
|
@ -9,6 +10,7 @@ public class RepeatTypeException extends ServiceException {
|
|||
public RepeatTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RepeatTypeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ public interface FileHandler {
|
|||
|
||||
/**
|
||||
* Get attachment type is supported.
|
||||
*
|
||||
* @return attachment type
|
||||
*/
|
||||
AttachmentType getAttachmentType();
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package run.halo.app.handler.migrate;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import run.halo.app.model.enums.MigrateType;
|
||||
import run.halo.app.service.BackupService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-03-14
|
||||
*/
|
||||
@Component
|
||||
public class HaloMigrateHandler implements MigrateHandler {
|
||||
|
||||
private final BackupService backupService;
|
||||
|
||||
public HaloMigrateHandler(BackupService backupService) {
|
||||
this.backupService = backupService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(MultipartFile file) {
|
||||
try {
|
||||
backupService.importData(file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportType(MigrateType type) {
|
||||
return MigrateType.HALO.equals(type);
|
||||
}
|
||||
}
|
|
@ -688,6 +688,6 @@ public class OldVersionMigrateHandler implements MigrateHandler {
|
|||
|
||||
@Override
|
||||
public boolean supportType(MigrateType type) {
|
||||
return MigrateType.OLD_VERSION.equals(type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ public abstract class AbstractMailService implements MailService {
|
|||
/**
|
||||
* Test connection with email server.
|
||||
*/
|
||||
@Override
|
||||
public void testConnection() {
|
||||
JavaMailSender javaMailSender = getMailSender();
|
||||
if (javaMailSender instanceof JavaMailSenderImpl) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import run.halo.app.model.enums.AttachmentType;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
@ -22,8 +23,8 @@ import javax.persistence.*;
|
|||
public class Attachment extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import run.halo.app.model.enums.CommentStatus;
|
||||
import run.halo.app.utils.ServiceUtils;
|
||||
|
||||
|
@ -25,7 +26,8 @@ import javax.persistence.*;
|
|||
public class BaseComment extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ package run.halo.app.model.entity;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -23,7 +24,8 @@ import javax.persistence.*;
|
|||
public class BaseMeta extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import run.halo.app.model.enums.PostEditorType;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
|
||||
|
@ -25,7 +26,8 @@ import java.util.Date;
|
|||
public class BasePost extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -24,7 +25,8 @@ import javax.persistence.*;
|
|||
public class Category extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package run.halo.app.model.entity;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
@ -20,7 +21,8 @@ import java.util.Date;
|
|||
@NoArgsConstructor
|
||||
public class CommentBlackList extends BaseEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "ip_address", length = 127, nullable = false)
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import run.halo.app.model.enums.JournalType;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
@ -23,7 +24,8 @@ import javax.persistence.*;
|
|||
public class Journal extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
@Column(name = "source_content", nullable = false)
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -21,8 +22,8 @@ import javax.persistence.*;
|
|||
public class Link extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ package run.halo.app.model.entity;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import run.halo.app.model.enums.LogType;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
@ -21,7 +22,8 @@ import javax.persistence.*;
|
|||
public class Log extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -21,8 +22,8 @@ import javax.persistence.*;
|
|||
public class Menu extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,7 @@ import lombok.EqualsAndHashCode;
|
|||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import run.halo.app.model.enums.OptionType;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
@ -25,7 +26,8 @@ import javax.persistence.*;
|
|||
public class Option extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
@ -44,7 +46,8 @@ public class Option extends BaseEntity {
|
|||
/**
|
||||
* option value
|
||||
*/
|
||||
@Column(name = "option_value", length = 1023, nullable = false)
|
||||
@Column(name = "option_value", nullable = false)
|
||||
@Lob
|
||||
private String value;
|
||||
|
||||
public Option(String key, String value) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package run.halo.app.model.entity;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
@ -21,8 +22,8 @@ import java.util.Date;
|
|||
public class Photo extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.model.entity;
|
|||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Objects;
|
||||
|
@ -20,7 +21,8 @@ import java.util.Objects;
|
|||
public class PostCategory extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.model.entity;
|
|||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Objects;
|
||||
|
@ -21,8 +22,8 @@ import java.util.Objects;
|
|||
public class PostTag extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ package run.halo.app.model.entity;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -20,8 +21,8 @@ import javax.persistence.*;
|
|||
public class Tag extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ package run.halo.app.model.entity;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
@ -22,7 +23,8 @@ import javax.persistence.*;
|
|||
public class ThemeSetting extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
|
||||
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support.CustomIdGenerator")
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
|
@ -35,6 +37,7 @@ public class ThemeSetting extends BaseEntity {
|
|||
* Setting value
|
||||
*/
|
||||
@Column(name = "setting_value", nullable = false)
|
||||
@Lob
|
||||
private String value;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package run.halo.app.model.entity.support;
|
||||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.IdentityGenerator;
|
||||
import run.halo.app.utils.ReflectionUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author ryanwang
|
||||
* @date 2020-03-16
|
||||
*/
|
||||
public class CustomIdGenerator extends IdentityGenerator {
|
||||
@Override
|
||||
public Serializable generate(SharedSessionContractImplementor session, Object object) {
|
||||
Object id = ReflectionUtils.getFieldValue("id", object);
|
||||
if (id != null) {
|
||||
return (Serializable) id;
|
||||
}
|
||||
return super.generate(session, object);
|
||||
}
|
||||
}
|
|
@ -9,9 +9,9 @@ package run.halo.app.model.enums;
|
|||
public enum MigrateType implements ValueEnum<Integer> {
|
||||
|
||||
/**
|
||||
* Halo version 0.4.4
|
||||
* Halo
|
||||
*/
|
||||
OLD_VERSION(0),
|
||||
HALO(0),
|
||||
|
||||
/**
|
||||
* WordPress
|
||||
|
|
|
@ -60,7 +60,7 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
|
|||
"/api/admin/login",
|
||||
"/api/admin/refresh/*",
|
||||
"/api/admin/installations",
|
||||
"/api/admin/migrations/**",
|
||||
"/api/admin/migrations/halo",
|
||||
"/api/admin/is_installed",
|
||||
"/api/admin/password/code",
|
||||
"/api/admin/password/reset"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package run.halo.app.service;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -19,29 +19,14 @@ import java.util.List;
|
|||
public interface BackupService {
|
||||
|
||||
/**
|
||||
* Backup posts and sheets
|
||||
* Import markdown content.
|
||||
*
|
||||
* @param file file
|
||||
* @return post info
|
||||
* @return base post detail dto
|
||||
* @throws IOException throws IOException
|
||||
*/
|
||||
BasePostDetailDTO importMarkdown(MultipartFile file) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* export posts by hexo formatter
|
||||
*
|
||||
* @return json object
|
||||
*/
|
||||
JSONObject exportHexoMDs();
|
||||
|
||||
/**
|
||||
* Exports the specified articles to the specified dir path.
|
||||
*
|
||||
* @param posts
|
||||
* @param path
|
||||
*/
|
||||
void exportHexoMd(List<JSONObject> posts, String path);
|
||||
|
||||
/**
|
||||
* Zips work directory.
|
||||
*
|
||||
|
@ -74,4 +59,21 @@ public interface BackupService {
|
|||
*/
|
||||
@NonNull
|
||||
Resource loadFileAsResource(@NonNull String fileName);
|
||||
|
||||
|
||||
/**
|
||||
* Export all database's data.
|
||||
*
|
||||
* @return data
|
||||
*/
|
||||
@NonNull
|
||||
JSONObject exportData();
|
||||
|
||||
/**
|
||||
* Import data
|
||||
*
|
||||
* @param file file
|
||||
* @throws IOException throws IOException
|
||||
*/
|
||||
void importData(MultipartFile file) throws IOException;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package run.halo.app.service;
|
||||
|
||||
import run.halo.app.model.entity.CommentBlackList;
|
||||
import run.halo.app.model.enums.CommentViolationTypeEnum;
|
||||
import run.halo.app.service.base.CrudService;
|
||||
|
||||
/**
|
||||
* Comment BlackList Service
|
||||
|
@ -8,7 +10,7 @@ import run.halo.app.model.enums.CommentViolationTypeEnum;
|
|||
* @author Lei XinXin
|
||||
* @date 2020/1/3
|
||||
*/
|
||||
public interface CommentBlackListService {
|
||||
public interface CommentBlackListService extends CrudService<CommentBlackList, Long> {
|
||||
/**
|
||||
* 评论封禁状态
|
||||
*
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.springframework.lang.NonNull;
|
|||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import run.halo.app.model.entity.ThemeSetting;
|
||||
import run.halo.app.service.base.CrudService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -14,7 +15,7 @@ import java.util.Map;
|
|||
* @author johnniang
|
||||
* @date 2019-04-08
|
||||
*/
|
||||
public interface ThemeSettingService {
|
||||
public interface ThemeSettingService extends CrudService<ThemeSetting, Integer> {
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,36 +1,31 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.event.options.OptionUpdatedEvent;
|
||||
import run.halo.app.event.theme.ThemeUpdatedEvent;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.model.dto.BackupDTO;
|
||||
import run.halo.app.model.dto.post.BasePostDetailDTO;
|
||||
import run.halo.app.model.entity.Post;
|
||||
import run.halo.app.model.entity.Tag;
|
||||
import run.halo.app.model.enums.PostStatus;
|
||||
import run.halo.app.model.entity.*;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.security.service.OneTimeTokenService;
|
||||
import run.halo.app.service.BackupService;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.service.PostService;
|
||||
import run.halo.app.service.PostTagService;
|
||||
import run.halo.app.service.*;
|
||||
import run.halo.app.utils.HaloUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -40,7 +35,8 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -59,26 +55,79 @@ public class BackupServiceImpl implements BackupService {
|
|||
|
||||
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
|
||||
private final AttachmentService attachmentService;
|
||||
|
||||
private final CategoryService categoryService;
|
||||
|
||||
private final CommentBlackListService commentBlackListService;
|
||||
|
||||
private final JournalService journalService;
|
||||
|
||||
private final JournalCommentService journalCommentService;
|
||||
|
||||
private final LinkService linkService;
|
||||
|
||||
private final LogService logService;
|
||||
|
||||
private final MenuService menuService;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final PhotoService photoService;
|
||||
|
||||
private final PostService postService;
|
||||
|
||||
private final PostCategoryService postCategoryService;
|
||||
|
||||
private final PostCommentService postCommentService;
|
||||
|
||||
private final PostMetaService postMetaService;
|
||||
|
||||
private final PostTagService postTagService;
|
||||
|
||||
private final OptionService optionService;
|
||||
private final SheetService sheetService;
|
||||
|
||||
private final SheetCommentService sheetCommentService;
|
||||
|
||||
private final SheetMetaService sheetMetaService;
|
||||
|
||||
private final TagService tagService;
|
||||
|
||||
private final ThemeSettingService themeSettingService;
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
private final OneTimeTokenService oneTimeTokenService;
|
||||
|
||||
private final HaloProperties haloProperties;
|
||||
|
||||
public BackupServiceImpl(PostService postService,
|
||||
PostTagService postTagService,
|
||||
OptionService optionService,
|
||||
OneTimeTokenService oneTimeTokenService,
|
||||
HaloProperties haloProperties) {
|
||||
this.postService = postService;
|
||||
this.postTagService = postTagService;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public BackupServiceImpl(AttachmentService attachmentService, CategoryService categoryService, CommentBlackListService commentBlackListService, JournalService journalService, JournalCommentService journalCommentService, LinkService linkService, LogService logService, MenuService menuService, OptionService optionService, PhotoService photoService, PostService postService, PostCategoryService postCategoryService, PostCommentService postCommentService, PostMetaService postMetaService, PostTagService postTagService, SheetService sheetService, SheetCommentService sheetCommentService, SheetMetaService sheetMetaService, TagService tagService, ThemeSettingService themeSettingService, UserService userService, OneTimeTokenService oneTimeTokenService, HaloProperties haloProperties, ApplicationEventPublisher eventPublisher) {
|
||||
this.attachmentService = attachmentService;
|
||||
this.categoryService = categoryService;
|
||||
this.commentBlackListService = commentBlackListService;
|
||||
this.journalService = journalService;
|
||||
this.journalCommentService = journalCommentService;
|
||||
this.linkService = linkService;
|
||||
this.logService = logService;
|
||||
this.menuService = menuService;
|
||||
this.optionService = optionService;
|
||||
this.photoService = photoService;
|
||||
this.postService = postService;
|
||||
this.postCategoryService = postCategoryService;
|
||||
this.postCommentService = postCommentService;
|
||||
this.postMetaService = postMetaService;
|
||||
this.postTagService = postTagService;
|
||||
this.sheetService = sheetService;
|
||||
this.sheetCommentService = sheetCommentService;
|
||||
this.sheetMetaService = sheetMetaService;
|
||||
this.tagService = tagService;
|
||||
this.themeSettingService = themeSettingService;
|
||||
this.userService = userService;
|
||||
this.oneTimeTokenService = oneTimeTokenService;
|
||||
this.haloProperties = haloProperties;
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,66 +154,6 @@ public class BackupServiceImpl implements BackupService {
|
|||
return postService.importMarkdown(markdown, file.getOriginalFilename());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject exportHexoMDs() {
|
||||
final JSONObject ret = new JSONObject();
|
||||
final List<JSONObject> posts = new ArrayList<>();
|
||||
ret.put("posts", (Object) posts);
|
||||
final List<JSONObject> passwords = new ArrayList<>();
|
||||
ret.put("passwords", (Object) passwords);
|
||||
final List<JSONObject> drafts = new ArrayList<>();
|
||||
ret.put("drafts", (Object) drafts);
|
||||
|
||||
List<Post> postList = postService.listAll();
|
||||
Map<Integer, List<Tag>> talMap = postTagService.listTagListMapBy(postList.stream().map(Post::getId).collect(Collectors.toList()));
|
||||
for (Post post : postList) {
|
||||
final Map<String, Object> front = new LinkedHashMap<>();
|
||||
final String title = post.getTitle();
|
||||
front.put("title", title);
|
||||
final String date = DateFormatUtils.format(post.getCreateTime(), "yyyy-MM-dd HH:mm:ss");
|
||||
front.put("date", date);
|
||||
front.put("updated", DateFormatUtils.format(post.getUpdateTime(), "yyyy-MM-dd HH:mm:ss"));
|
||||
final List<String> tags = talMap.get(post.getId()).stream().map(Tag::getName).collect(Collectors.toList());
|
||||
if (tags.isEmpty()) {
|
||||
tags.add("halo");
|
||||
}
|
||||
front.put("tags", tags);
|
||||
front.put("permalink", "");
|
||||
final JSONObject one = new JSONObject();
|
||||
one.put("front", new Yaml().dump(front));
|
||||
one.put("title", title);
|
||||
one.put("content", post.getOriginalContent());
|
||||
one.put("created", post.getCreateTime().getTime());
|
||||
|
||||
if (StringUtils.isNotBlank(post.getPassword())) {
|
||||
passwords.add(one);
|
||||
} else if (post.getStatus() == PostStatus.DRAFT) {
|
||||
drafts.add(one);
|
||||
} else {
|
||||
posts.add(one);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportHexoMd(List<JSONObject> posts, String dirPath) {
|
||||
posts.forEach(post -> {
|
||||
final String filename = sanitizeFilename(post.optString("title")) + ".md";
|
||||
final String text = post.optString("front") + "---" + LINE_SEPARATOR + post.optString("content");
|
||||
|
||||
try {
|
||||
final String date = DateFormatUtils.format(post.optLong("created"), "yyyyMM");
|
||||
final String dir = dirPath + File.separator + date + File.separator;
|
||||
new File(dir).mkdirs();
|
||||
FileUtils.writeStringToFile(new File(dir + filename), text, "UTF-8");
|
||||
} catch (final Exception e) {
|
||||
log.error("Write markdown file failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackupDTO zipWorkDirectory() {
|
||||
// Zip work directory to temporary file
|
||||
|
@ -268,6 +257,106 @@ public class BackupServiceImpl implements BackupService {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject exportData() {
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("version", HaloConst.HALO_VERSION);
|
||||
data.put("export_date", DateUtil.now());
|
||||
data.put("attachments", attachmentService.listAll());
|
||||
data.put("categories", categoryService.listAll());
|
||||
data.put("comment_black_list", commentBlackListService.listAll());
|
||||
data.put("journals", journalService.listAll());
|
||||
data.put("journal_comments", journalCommentService.listAll());
|
||||
data.put("links", linkService.listAll());
|
||||
data.put("logs", logService.listAll());
|
||||
data.put("menus", menuService.listAll());
|
||||
data.put("options", optionService.listAll());
|
||||
data.put("photos", photoService.listAll());
|
||||
data.put("posts", postService.listAll());
|
||||
data.put("post_categories", postCategoryService.listAll());
|
||||
data.put("post_comments", postCommentService.listAll());
|
||||
data.put("post_metas", postMetaService.listAll());
|
||||
data.put("post_tags", postTagService.listAll());
|
||||
data.put("sheets", sheetService.listAll());
|
||||
data.put("sheet_comments", sheetCommentService.listAll());
|
||||
data.put("sheet_metas", sheetMetaService.listAll());
|
||||
data.put("tags", tagService.listAll());
|
||||
data.put("theme_settings", themeSettingService.listAll());
|
||||
data.put("user", userService.listAll());
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importData(MultipartFile file) throws IOException {
|
||||
String jsonContent = IoUtil.read(file.getInputStream(), StandardCharsets.UTF_8);
|
||||
|
||||
JSONObject data = JSONObject.parseObject(jsonContent);
|
||||
|
||||
List<Attachment> attachments = data.getJSONArray("attachments").toJavaList(Attachment.class);
|
||||
attachmentService.createInBatch(attachments);
|
||||
|
||||
List<Category> categories = data.getJSONArray("categories").toJavaList(Category.class);
|
||||
categoryService.createInBatch(categories);
|
||||
|
||||
List<Tag> tags = data.getJSONArray("tags").toJavaList(Tag.class);
|
||||
tagService.createInBatch(tags);
|
||||
|
||||
List<CommentBlackList> commentBlackList = data.getJSONArray("comment_black_list").toJavaList(CommentBlackList.class);
|
||||
commentBlackListService.createInBatch(commentBlackList);
|
||||
|
||||
List<Journal> journals = data.getJSONArray("journals").toJavaList(Journal.class);
|
||||
journalService.createInBatch(journals);
|
||||
|
||||
List<JournalComment> journalComments = data.getJSONArray("journal_comments").toJavaList(JournalComment.class);
|
||||
journalCommentService.createInBatch(journalComments);
|
||||
|
||||
List<Link> links = data.getJSONArray("links").toJavaList(Link.class);
|
||||
linkService.createInBatch(links);
|
||||
|
||||
List<Log> logs = data.getJSONArray("logs").toJavaList(Log.class);
|
||||
logService.createInBatch(logs);
|
||||
|
||||
List<Menu> menus = data.getJSONArray("menus").toJavaList(Menu.class);
|
||||
menuService.createInBatch(menus);
|
||||
|
||||
List<Option> options = data.getJSONArray("options").toJavaList(Option.class);
|
||||
optionService.createInBatch(options);
|
||||
|
||||
eventPublisher.publishEvent(new OptionUpdatedEvent(this));
|
||||
|
||||
List<Photo> photos = data.getJSONArray("photos").toJavaList(Photo.class);
|
||||
photoService.createInBatch(photos);
|
||||
|
||||
List<Post> posts = data.getJSONArray("posts").toJavaList(Post.class);
|
||||
postService.createInBatch(posts);
|
||||
|
||||
List<PostCategory> postCategories = data.getJSONArray("post_categories").toJavaList(PostCategory.class);
|
||||
postCategoryService.createInBatch(postCategories);
|
||||
|
||||
List<PostComment> postComments = data.getJSONArray("post_comments").toJavaList(PostComment.class);
|
||||
postCommentService.createInBatch(postComments);
|
||||
|
||||
List<PostMeta> postMetas = data.getJSONArray("post_metas").toJavaList(PostMeta.class);
|
||||
postMetaService.createInBatch(postMetas);
|
||||
|
||||
List<PostTag> postTags = data.getJSONArray("post_tags").toJavaList(PostTag.class);
|
||||
postTagService.createInBatch(postTags);
|
||||
|
||||
List<Sheet> sheets = data.getJSONArray("sheets").toJavaList(Sheet.class);
|
||||
sheetService.createInBatch(sheets);
|
||||
|
||||
List<SheetComment> sheetComments = data.getJSONArray("sheet_comments").toJavaList(SheetComment.class);
|
||||
sheetCommentService.createInBatch(sheetComments);
|
||||
|
||||
List<SheetMeta> sheetMetas = data.getJSONArray("sheet_metas").toJavaList(SheetMeta.class);
|
||||
sheetMetaService.createInBatch(sheetMetas);
|
||||
|
||||
List<ThemeSetting> themeSettings = data.getJSONArray("theme_settings").toJavaList(ThemeSetting.class);
|
||||
themeSettingService.createInBatch(themeSettings);
|
||||
|
||||
eventPublisher.publishEvent(new ThemeUpdatedEvent(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds backup dto.
|
||||
*
|
||||
|
|
|
@ -30,7 +30,7 @@ public class ImageUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static ImageReader getImageReaderFromFile(InputStream is,String formatName) {
|
||||
public static ImageReader getImageReaderFromFile(InputStream is, String formatName) {
|
||||
try {
|
||||
Iterator<ImageReader> readerIterator = ImageIO.getImageReadersByFormatName(formatName);
|
||||
ImageReader reader = readerIterator.next();
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.springframework.lang.NonNull;
|
|||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
|
@ -11,6 +12,8 @@ import java.lang.reflect.Type;
|
|||
* Reflection utilities.
|
||||
*
|
||||
* @author johnniang
|
||||
* @author ryanwang
|
||||
* @date 2019-03-15
|
||||
*/
|
||||
public class ReflectionUtils {
|
||||
|
||||
|
@ -89,4 +92,26 @@ public class ReflectionUtils {
|
|||
|
||||
return getParameterizedType(superClassType, extensionClass.getGenericSuperclass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets field value from Object.
|
||||
*
|
||||
* @param fieldName fieldName must not be null
|
||||
* @param object object must not be null.
|
||||
* @return value
|
||||
*/
|
||||
public static Object getFieldValue(@NonNull String fieldName, @NonNull Object object) {
|
||||
Assert.notNull(fieldName, "FieldName must not be null");
|
||||
Assert.notNull(object, "Object type must not be null");
|
||||
Object value = null;
|
||||
try {
|
||||
String firstLetter = fieldName.substring(0, 1).toUpperCase();
|
||||
String getter = "get" + firstLetter + fieldName.substring(1);
|
||||
Method method = object.getClass().getMethod(getter);
|
||||
value = method.invoke(object);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
-- Migrate 1.3.0-beta.2 to 1.3.0-beta.3
|
||||
|
||||
-- Migrate options Table
|
||||
alter table options modify option_value longtext not null;
|
||||
|
||||
-- Migrate theme_settings Table
|
||||
alter table theme_settings modify setting_value longtext not null;
|
Loading…
Reference in New Issue