mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-01-24 14:24:47 +08:00
moved project api to its own service
This commit is contained in:
parent
f3a01dc9bb
commit
5809d70caf
@ -12,7 +12,6 @@ import io.papermc.hangar.model.generated.ProjectSortingStrategy;
|
||||
import io.papermc.hangar.model.generated.ProjectStatsDay;
|
||||
import io.papermc.hangar.model.generated.Tag;
|
||||
import io.papermc.hangar.service.api.ProjectApiService;
|
||||
import io.papermc.hangar.service.project.ProjectService;
|
||||
import io.papermc.hangar.util.ApiUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -37,14 +36,12 @@ public class ProjectsApiController implements ProjectsApi {
|
||||
|
||||
private final HangarConfig hangarConfig;
|
||||
private final ApiAuthInfo apiAuthInfo;
|
||||
private final ProjectService projectService;
|
||||
private final ProjectApiService projectApiService;
|
||||
|
||||
@Autowired
|
||||
public ProjectsApiController(HangarConfig hangarConfig, ApiAuthInfo apiAuthInfo, ProjectService projectService, ProjectApiService projectApiService) {
|
||||
public ProjectsApiController(HangarConfig hangarConfig, ApiAuthInfo apiAuthInfo, ProjectApiService projectApiService) {
|
||||
this.hangarConfig = hangarConfig;
|
||||
this.apiAuthInfo = apiAuthInfo;
|
||||
this.projectService = projectService;
|
||||
this.projectApiService = projectApiService;
|
||||
}
|
||||
|
||||
@ -68,7 +65,7 @@ public class ProjectsApiController implements ProjectsApi {
|
||||
boolean seeHidden = apiAuthInfo.getGlobalPerms().has(Permission.SeeHidden);
|
||||
Long requesterId = apiAuthInfo.getUser() == null ? null : apiAuthInfo.getUser().getId();
|
||||
|
||||
List<Project> projects = projectService.getProjects(
|
||||
List<Project> projects = projectApiService.getProjects(
|
||||
null,
|
||||
categories,
|
||||
parsedTags,
|
||||
@ -82,7 +79,7 @@ public class ProjectsApiController implements ProjectsApi {
|
||||
offset
|
||||
);
|
||||
|
||||
long count = projectService.countProjects(
|
||||
long count = projectApiService.countProjects(
|
||||
null,
|
||||
categories,
|
||||
parsedTags,
|
||||
@ -116,7 +113,8 @@ public class ProjectsApiController implements ProjectsApi {
|
||||
@Override
|
||||
@PreAuthorize("@authenticationService.authApiRequest(T(io.papermc.hangar.model.Permission).ViewPublicInfo, T(io.papermc.hangar.controller.util.ApiScope).forProject(#pluginId))")
|
||||
public ResponseEntity<Project> showProject(String pluginId) {
|
||||
Project project = projectService.getProjectApi(pluginId);
|
||||
boolean seeHidden = apiAuthInfo.getGlobalPerms().has(Permission.SeeHidden);
|
||||
Project project = projectApiService.getProject(pluginId, seeHidden, apiAuthInfo.getUserId());
|
||||
if (project == null) {
|
||||
log.error("Couldn't find a project for that pluginId");
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
|
@ -26,7 +26,7 @@ public interface ProjectsApiDao {
|
||||
@SqlQuery("SELECT p.created_at," +
|
||||
" p.plugin_id," +
|
||||
" p.name," +
|
||||
" p.owner_name," +
|
||||
" p.owner_name \"owner\"," +
|
||||
" p.slug," +
|
||||
" p.promoted_versions," +
|
||||
" p.views," +
|
||||
@ -40,7 +40,7 @@ public interface ProjectsApiDao {
|
||||
" COALESCE(p.last_updated, p.created_at) AS last_updated," +
|
||||
" p.visibility, " +
|
||||
" <if(requesterId)> " +
|
||||
" EXISTS(SELECT * FROM project_stars s WHERE s.project_id = p.id AND s.user_id = :requesterId) AS user_stared, " +
|
||||
" EXISTS(SELECT * FROM project_stars s WHERE s.project_id = p.id AND s.user_id = :requesterId) AS user_starred, " +
|
||||
" EXISTS(SELECT * FROM project_watchers s WHERE s.project_id = p.id AND s.user_id = :requesterId) AS user_watching, " +
|
||||
" <endif>" +
|
||||
" ps.homepage," +
|
||||
@ -60,7 +60,7 @@ public interface ProjectsApiDao {
|
||||
" <if(query)> AND ( <queryStatement> ) <endif> " +
|
||||
" <if(tags)> AND EXISTS ( SELECT pv.tag_name FROM jsonb_to_recordset(p.promoted_versions) " +
|
||||
" AS pv(tag_name TEXT, tag_version TEXT) WHERE (pv.tag_name) in (<tags>) ) <endif> " +
|
||||
" ORDER BY <orderBy> " +
|
||||
" <if(orderBy)>ORDER BY <orderBy><endif> " +
|
||||
" LIMIT :limit" +
|
||||
" OFFSET :offset")
|
||||
@RegisterColumnMapper(PromotedVersionMapper.class)
|
||||
|
@ -18,6 +18,10 @@ public class ApiAuthInfo {
|
||||
return user;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return user == null ? null : user.getId();
|
||||
}
|
||||
|
||||
@Nested("u")
|
||||
public void setUser(UsersTable user) {
|
||||
this.user = user.getName() == null ? null : user;
|
||||
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.jdbi.v3.core.enums.EnumByOrdinal;
|
||||
import org.jdbi.v3.core.mapper.Nested;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
@ -111,6 +112,7 @@ public class Project {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
@Nested
|
||||
public void setNamespace(ProjectNamespace namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
@ -130,6 +132,7 @@ public class Project {
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Nested
|
||||
public void setStats(ProjectStatsAll stats) {
|
||||
this.stats = stats;
|
||||
}
|
||||
@ -174,6 +177,7 @@ public class Project {
|
||||
return userActions;
|
||||
}
|
||||
|
||||
@Nested("user")
|
||||
public void setUserActions(UserActions userActions) {
|
||||
this.userActions = userActions;
|
||||
}
|
||||
@ -182,6 +186,7 @@ public class Project {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Nested
|
||||
public void setSettings(ProjectSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
@ -1,22 +1,91 @@
|
||||
package io.papermc.hangar.service.api;
|
||||
|
||||
import io.papermc.hangar.config.hangar.HangarConfig;
|
||||
import io.papermc.hangar.db.dao.HangarDao;
|
||||
import io.papermc.hangar.db.dao.api.ProjectsApiDao;
|
||||
import io.papermc.hangar.model.Category;
|
||||
import io.papermc.hangar.model.generated.Project;
|
||||
import io.papermc.hangar.model.generated.ProjectMember;
|
||||
import io.papermc.hangar.model.generated.ProjectSortingStrategy;
|
||||
import io.papermc.hangar.model.generated.ProjectStatsDay;
|
||||
import io.papermc.hangar.model.generated.Tag;
|
||||
import io.papermc.hangar.service.pluginupload.ProjectFiles;
|
||||
import io.papermc.hangar.util.RouteHelper;
|
||||
import io.papermc.hangar.util.TemplateHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ProjectApiService {
|
||||
|
||||
private final HangarConfig hangarConfig;
|
||||
private final HangarDao<ProjectsApiDao> projectApiDao;
|
||||
private final ProjectFiles projectFiles;
|
||||
private final RouteHelper routeHelper;
|
||||
private final TemplateHelper templateHelper;
|
||||
|
||||
public ProjectApiService(HangarDao<ProjectsApiDao> projectApiDao) {
|
||||
public ProjectApiService(HangarConfig hangarConfig, HangarDao<ProjectsApiDao> projectApiDao, ProjectFiles projectFiles, RouteHelper routeHelper, TemplateHelper templateHelper) {
|
||||
this.hangarConfig = hangarConfig;
|
||||
this.projectApiDao = projectApiDao;
|
||||
this.projectFiles = projectFiles;
|
||||
this.routeHelper = routeHelper;
|
||||
this.templateHelper = templateHelper;
|
||||
}
|
||||
|
||||
public Project getProject(String pluginId, boolean seeHidden, Long requesterId) {
|
||||
Project project = projectApiDao.get().listProjects(pluginId, null, seeHidden, requesterId, null, null, null, null, null, 1, 0).stream().findFirst().orElse(null);
|
||||
if (project != null) {
|
||||
setProjectIconUrl(project);
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
public List<Project> getProjects(String pluginId, List<Category> categories, List<Tag> tags, String query, String owner, boolean seeHidden, Long requesterId, ProjectSortingStrategy sort, boolean orderWithRelevance, long limit, long offset) {
|
||||
String ordering = sort.getSql();
|
||||
if (orderWithRelevance && query != null && !query.isEmpty()) {
|
||||
String relevance = "ts_rank(p.search_words, websearch_to_tsquery_postfix('english', :query)) DESC";
|
||||
if(query.endsWith(" ")) {
|
||||
relevance = "ts_rank(p.search_words, websearch_to_tsquery('english', :query)) DESC";
|
||||
}
|
||||
String orderingFirstHalf;
|
||||
// 1483056000 is the Ore epoch
|
||||
// 86400 seconds to days
|
||||
// 604800 seconds to weeks
|
||||
switch(sort){
|
||||
case STARS: orderingFirstHalf = "p.starts * "; break;
|
||||
case DOWNLOADS: orderingFirstHalf ="(p.downloads / 100) * "; break;
|
||||
case VIEWS: orderingFirstHalf ="(p.views / 200) *"; break;
|
||||
case NEWEST: orderingFirstHalf ="((EXTRACT(EPOCH FROM p.created_at) - 1483056000) / 86400) *"; break;
|
||||
case UPDATED: orderingFirstHalf ="((EXTRACT(EPOCH FROM p.last_updated) - 1483056000) / 604800) *"; break;
|
||||
case ONLY_RELEVANCE: orderingFirstHalf =""; break;
|
||||
case RECENT_DOWNLOADS : orderingFirstHalf ="p.recent_views *"; break;
|
||||
case RECENT_VIEWS: orderingFirstHalf ="p.recent_downloads*"; break;
|
||||
default:
|
||||
orderingFirstHalf = " "; // Just in case and so that the ide doesnt complain
|
||||
}
|
||||
ordering = orderingFirstHalf + relevance;
|
||||
}
|
||||
List<Project> projects = projectApiDao.get().listProjects(pluginId, owner, seeHidden, requesterId, ordering, getCategoryNumbers(categories), getTagsNames(tags), trimQuery(query), getQueryStatement(query), limit, offset);
|
||||
projects.forEach(this::setProjectIconUrl);
|
||||
return projects;
|
||||
}
|
||||
|
||||
private void setProjectIconUrl(Project project) {
|
||||
Path iconPath = projectFiles.getIconPath(project.getNamespace().getOwner(), project.getNamespace().getSlug());
|
||||
if (iconPath != null) {
|
||||
project.setIconUrl(hangarConfig.getBaseUrl() + routeHelper.getRouteUrl("projects.showIcon", project.getNamespace().getOwner(), project.getNamespace().getSlug()));
|
||||
} else {
|
||||
project.setIconUrl(templateHelper.avatarUrl(project.getNamespace().getOwner()));
|
||||
}
|
||||
}
|
||||
|
||||
public long countProjects(String pluginId, List<Category> categories, List<Tag> tags, String query, String owner, boolean seeHidden, Long requesterId) {
|
||||
return projectApiDao.get().countProjects(pluginId, owner, seeHidden, requesterId, getCategoryNumbers(categories), getTagsNames(tags), trimQuery(query), getQueryStatement(query));
|
||||
}
|
||||
|
||||
public List<ProjectMember> getProjectMembers(String pluginId, long limit, long offset) {
|
||||
@ -26,4 +95,36 @@ public class ProjectApiService {
|
||||
public Map<String, ProjectStatsDay> getProjectStats(String pluginId, LocalDate fromDate, LocalDate toDate) {
|
||||
return projectApiDao.get().projectStats(pluginId, fromDate, toDate);
|
||||
}
|
||||
|
||||
private String trimQuery(String query){
|
||||
String trimmedQuery = null;
|
||||
if(query != null && !query.isBlank()) {
|
||||
trimmedQuery = query.trim(); // Ore#APIV2Queries line 169 && 200
|
||||
}
|
||||
return trimmedQuery;
|
||||
}
|
||||
|
||||
private String getQueryStatement(String query){
|
||||
String queryStatement = null;
|
||||
if(query != null && !query.isBlank()){
|
||||
if(query.endsWith(" ")) {
|
||||
queryStatement = "p.search_words @@ websearch_to_tsquery('english', :query)";
|
||||
} else {
|
||||
queryStatement = "p.search_words @@ websearch_to_tsquery_postfix('english', :query)";
|
||||
}
|
||||
}
|
||||
return queryStatement;
|
||||
}
|
||||
|
||||
private List<Integer> getCategoryNumbers(List<Category> categories){
|
||||
return categories == null ? null : categories.stream().map(Category::getValue).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> getTagsNames(List<Tag> tags){
|
||||
return tags == null ? null : tags.stream().filter(tag -> tag.getData() == null).map(Tag::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> getTagsNamesAndVersion(List<Tag> tags){
|
||||
return tags == null ? null : tags.stream().filter(tag -> tag.getData() != null).map(tag -> " (" + tag.getName() + "," + tag.getData() + ") ").collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -214,71 +214,6 @@ public class ProjectService {
|
||||
return projectDao.get().getUnhealthyProjects(hangarConfig.projects.getStaleAge().toMillis());
|
||||
}
|
||||
|
||||
// TODO move to API daos
|
||||
public List<Project> getProjects(String pluginId, List<Category> categories, List<Tag> tags, String query, String owner, boolean seeHidden, Long requesterId, ProjectSortingStrategy sort, boolean orderWithRelevance, long limit, long offset) {
|
||||
String ordering = sort.getSql();
|
||||
if (orderWithRelevance && query != null && !query.isEmpty()) {
|
||||
String relevance = "ts_rank(p.search_words, websearch_to_tsquery_postfix('english', :query)) DESC";
|
||||
if(query.endsWith(" ")) {
|
||||
relevance = "ts_rank(p.search_words, websearch_to_tsquery('english', :query)) DESC";
|
||||
}
|
||||
String orderingFirstHalf;
|
||||
// 1483056000 is the Ore epoch
|
||||
// 86400 seconds to days
|
||||
// 604800 seconds to weeks
|
||||
switch(sort){
|
||||
case STARS: orderingFirstHalf = "p.starts * "; break;
|
||||
case DOWNLOADS: orderingFirstHalf ="(p.downloads / 100) * "; break;
|
||||
case VIEWS: orderingFirstHalf ="(p.views / 200) *"; break;
|
||||
case NEWEST: orderingFirstHalf ="((EXTRACT(EPOCH FROM p.created_at) - 1483056000) / 86400) *"; break;
|
||||
case UPDATED: orderingFirstHalf ="((EXTRACT(EPOCH FROM p.last_updated) - 1483056000) / 604800) *"; break;
|
||||
case ONLY_RELEVANCE: orderingFirstHalf =""; break;
|
||||
case RECENT_DOWNLOADS : orderingFirstHalf ="p.recent_views *"; break;
|
||||
case RECENT_VIEWS: orderingFirstHalf ="p.recent_downloads*"; break;
|
||||
default:
|
||||
orderingFirstHalf = " "; // Just in case and so that the ide doesnt complain
|
||||
}
|
||||
ordering = orderingFirstHalf + relevance;
|
||||
}
|
||||
return projectApiDao.get().listProjects(pluginId, owner, seeHidden, requesterId, ordering, getCategoryNumbers(categories), getTagsNames(tags), trimQuery(query), getQueryStatement(query), limit, offset);
|
||||
}
|
||||
|
||||
public long countProjects(String pluginId, List<Category> categories, List<Tag> tags, String query, String owner, boolean seeHidden, Long requesterId) {
|
||||
return projectApiDao.get().countProjects(pluginId, owner, seeHidden, requesterId, getCategoryNumbers(categories), getTagsNames(tags), trimQuery(query), getQueryStatement(query));
|
||||
}
|
||||
|
||||
private String trimQuery(String query){
|
||||
String trimmedQuery = null;
|
||||
if(query != null && !query.isBlank()) {
|
||||
trimmedQuery = query.trim(); // Ore#APIV2Queries line 169 && 200
|
||||
}
|
||||
return trimmedQuery;
|
||||
}
|
||||
|
||||
private String getQueryStatement(String query){
|
||||
String queryStatement = null;
|
||||
if(query != null && !query.isBlank()){
|
||||
if(query.endsWith(" ")) {
|
||||
queryStatement = "p.search_words @@ websearch_to_tsquery('english', :query)";
|
||||
} else {
|
||||
queryStatement = "p.search_words @@ websearch_to_tsquery_postfix('english', :query)";
|
||||
}
|
||||
}
|
||||
return queryStatement;
|
||||
}
|
||||
|
||||
private List<Integer> getCategoryNumbers(List<Category> categories){
|
||||
return categories == null ? null : categories.stream().map(Category::getValue).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> getTagsNames(List<Tag> tags){
|
||||
return tags == null ? null : tags.stream().filter(tag -> tag.getData() == null).map(Tag::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> getTagsNamesAndVersion(List<Tag> tags){
|
||||
return tags == null ? null : tags.stream().filter(tag -> tag.getData() != null).map(tag -> " (" + tag.getName() + "," + tag.getData() + ") ").collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<ProjectMissingFile> getPluginsWithMissingFiles() {
|
||||
List<ProjectMissingFile> projectMissingFiles = projectDao.get().allProjectsForMissingFiles();
|
||||
return projectMissingFiles.stream()
|
||||
|
Loading…
Reference in New Issue
Block a user