mirror of https://github.com/halo-dev/halo
Support update theme from new theme package.
parent
f70f7560ba
commit
648becf111
|
@ -117,13 +117,6 @@ public class ThemeController {
|
||||||
themeSettingService.save(settings, themeId);
|
themeSettingService.save(settings, themeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("{themeId}")
|
|
||||||
public ThemeProperty updateTheme(@PathVariable("themeId") String themeId,
|
|
||||||
@RequestPart(name = "file", required = false) MultipartFile file) {
|
|
||||||
|
|
||||||
return themeService.update(themeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("{themeId}")
|
@DeleteMapping("{themeId}")
|
||||||
@ApiOperation("Deletes a theme")
|
@ApiOperation("Deletes a theme")
|
||||||
public void deleteBy(@PathVariable("themeId") String themeId) {
|
public void deleteBy(@PathVariable("themeId") String themeId) {
|
||||||
|
@ -136,12 +129,25 @@ public class ThemeController {
|
||||||
return themeService.upload(file);
|
return themeService.upload(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("upload/{themeId}")
|
||||||
|
public ThemeProperty updateThemeByUpload(@PathVariable("themeId") String themeId,
|
||||||
|
@RequestPart("file") MultipartFile file) {
|
||||||
|
return themeService.update(themeId, file);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("fetching")
|
@PostMapping("fetching")
|
||||||
@ApiOperation("Fetches a new theme")
|
@ApiOperation("Fetches a new theme")
|
||||||
public ThemeProperty fetchTheme(@RequestParam("uri") String uri) {
|
public ThemeProperty fetchTheme(@RequestParam("uri") String uri) {
|
||||||
return themeService.fetch(uri);
|
return themeService.fetch(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("fetching/{themeId}")
|
||||||
|
public ThemeProperty updateThemeByFetching(@PathVariable("themeId") String themeId,
|
||||||
|
@RequestPart(name = "file", required = false) MultipartFile file) {
|
||||||
|
|
||||||
|
return themeService.update(themeId);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("reload")
|
@PostMapping("reload")
|
||||||
@ApiOperation("Reloads themes")
|
@ApiOperation("Reloads themes")
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
|
|
@ -24,6 +24,7 @@ public interface ThemeService {
|
||||||
/**
|
/**
|
||||||
* Theme property file name.
|
* Theme property file name.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
String THEME_PROPERTY_FILE_NAME = "theme.yaml";
|
String THEME_PROPERTY_FILE_NAME = "theme.yaml";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -236,6 +237,7 @@ public interface ThemeService {
|
||||||
*
|
*
|
||||||
* @param themeTmpPath theme temporary path must not be null
|
* @param themeTmpPath theme temporary path must not be null
|
||||||
* @return theme property
|
* @return theme property
|
||||||
|
* @throws IOException IOException
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
ThemeProperty add(@NonNull Path themeTmpPath) throws IOException;
|
ThemeProperty add(@NonNull Path themeTmpPath) throws IOException;
|
||||||
|
@ -262,4 +264,13 @@ public interface ThemeService {
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
ThemeProperty update(@NonNull String themeId);
|
ThemeProperty update(@NonNull String themeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates theme by theme id.
|
||||||
|
*
|
||||||
|
* @param themeId theme id must not be blank
|
||||||
|
* @param file multipart file must not be null
|
||||||
|
* @return theme info
|
||||||
|
*/
|
||||||
|
ThemeProperty update(@NonNull String themeId, @NonNull MultipartFile file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class ThemeServiceImpl implements ThemeService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThemeProperty getThemeOfNonNullBy(String themeId) {
|
public ThemeProperty getThemeOfNonNullBy(String themeId) {
|
||||||
return getThemeBy(themeId).orElseThrow(() -> new NotFoundException("Theme with id: " + themeId + " was not found").setErrorData(themeId));
|
return getThemeBy(themeId).orElseThrow(() -> new NotFoundException("没有找到 id 为 " + themeId + " 的主题").setErrorData(themeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -487,6 +487,59 @@ public class ThemeServiceImpl implements ThemeService {
|
||||||
return getThemeOfNonNullBy(themeId);
|
return getThemeOfNonNullBy(themeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ThemeProperty update(String themeId, MultipartFile file) {
|
||||||
|
Assert.hasText(themeId, "Theme id must not be blank");
|
||||||
|
Assert.notNull(themeId, "Theme file must not be blank");
|
||||||
|
|
||||||
|
if (!StringUtils.endsWithIgnoreCase(file.getOriginalFilename(), ".zip")) {
|
||||||
|
throw new UnsupportedMediaTypeException("不支持的文件类型: " + file.getContentType()).setErrorData(file.getOriginalFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
ThemeProperty updatingTheme = getThemeOfNonNullBy(themeId);
|
||||||
|
|
||||||
|
ZipInputStream zis = null;
|
||||||
|
Path tempPath = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create temp directory
|
||||||
|
tempPath = FileUtils.createTempDirectory();
|
||||||
|
|
||||||
|
String basename = FilenameUtils.getBasename(file.getOriginalFilename());
|
||||||
|
Path themeTempPath = tempPath.resolve(basename);
|
||||||
|
|
||||||
|
// Check directory traversal
|
||||||
|
FileUtils.checkDirectoryTraversal(tempPath, themeTempPath);
|
||||||
|
|
||||||
|
// New zip input stream
|
||||||
|
zis = new ZipInputStream(file.getInputStream());
|
||||||
|
|
||||||
|
// Unzip to temp path
|
||||||
|
FileUtils.unzip(zis, themeTempPath);
|
||||||
|
|
||||||
|
Path preparePath = FileUtils.tryToSkipZipParentFolder(themeTempPath);
|
||||||
|
|
||||||
|
ThemeProperty prepareThemeProperty = getProperty(preparePath);
|
||||||
|
|
||||||
|
if (!prepareThemeProperty.getId().equals(updatingTheme.getId())) {
|
||||||
|
throw new ServiceException("上传的主题包不是该主题的更新包: " + file.getOriginalFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coping new theme files to old theme folder.
|
||||||
|
FileUtils.copyFolder(preparePath, Paths.get(updatingTheme.getThemePath()));
|
||||||
|
|
||||||
|
// Gets theme property again.
|
||||||
|
return getProperty(Paths.get(updatingTheme.getThemePath()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ServiceException("更新主题失败: " + file.getOriginalFilename(), e);
|
||||||
|
} finally {
|
||||||
|
// Close zip input stream
|
||||||
|
FileUtils.closeQuietly(zis);
|
||||||
|
// Delete folder after testing
|
||||||
|
FileUtils.deleteFolderQuietly(tempPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void pullFromGit(@NonNull ThemeProperty themeProperty) throws IOException, GitAPIException, URISyntaxException {
|
private void pullFromGit(@NonNull ThemeProperty themeProperty) throws IOException, GitAPIException, URISyntaxException {
|
||||||
Assert.notNull(themeProperty, "Theme property must not be null");
|
Assert.notNull(themeProperty, "Theme property must not be null");
|
||||||
|
|
||||||
|
@ -735,7 +788,7 @@ public class ThemeServiceImpl implements ThemeService {
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
private ThemeProperty getProperty(@NonNull Path themePath) {
|
private ThemeProperty getProperty(@NonNull Path themePath) {
|
||||||
return getPropertyOfNullable(themePath).orElseThrow(() -> new ThemePropertyMissingException("该主题没有说明文件").setErrorData(themePath));
|
return getPropertyOfNullable(themePath).orElseThrow(() -> new ThemePropertyMissingException(themePath + " 没有说明文件").setErrorData(themePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue