From 6b585afd7d629520cc3dafe52f5e6ff84853e35c Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sat, 3 Apr 2021 16:53:58 -0700 Subject: [PATCH] sitemap stuff #408 --- docker/hangar/application.yml | 2 +- frontend/assets/main.scss | 4 + frontend/nuxt.config.ts | 5 + .../extras/resolver/PaginationResolver.java | 2 + .../internal/HangarUserController.java | 5 +- .../internal/SitemapController.java | 39 ++++++++ .../projects/ProjectPageController.java | 4 +- .../controllerold/ApplicationController.java | 42 +------- .../controllerold/ProjectsController.java | 19 ---- .../hangar/controllerold/UsersController.java | 18 +--- .../projects/HangarProjectPagesDAO.java | 10 +- .../hangar/db/dao/internal/table/UserDAO.java | 11 ++- .../internal/table/projects/ProjectsDAO.java | 3 + .../table/versions/ProjectVersionsDAO.java | 17 ++++ .../papermc/hangar/db/daoold/ProjectDao.java | 3 - .../io/papermc/hangar/db/daoold/UserDao.java | 30 +----- ...jectPage.java => ExtendedProjectPage.java} | 4 +- .../internal/projects/HangarProjectPage.java | 8 +- .../service/internal/SitemapService.java | 97 +++++++++++++++++++ .../internal/projects/ProjectPageService.java | 8 +- .../hangar/serviceold/SitemapService.java | 84 ---------------- .../serviceold/project/ProjectService.java | 24 ----- .../public => resources/WEB-INF}/robots.txt | 0 src/main/resources/application.yml | 2 +- 24 files changed, 200 insertions(+), 241 deletions(-) create mode 100644 src/main/java/io/papermc/hangar/controller/internal/SitemapController.java rename src/main/java/io/papermc/hangar/model/internal/projects/{HangarViewProjectPage.java => ExtendedProjectPage.java} (75%) create mode 100644 src/main/java/io/papermc/hangar/service/internal/SitemapService.java delete mode 100644 src/main/java/io/papermc/hangar/serviceold/SitemapService.java rename src/main/{frontend-old/public => resources/WEB-INF}/robots.txt (100%) diff --git a/docker/hangar/application.yml b/docker/hangar/application.yml index cceaa6608..a0551441b 100644 --- a/docker/hangar/application.yml +++ b/docker/hangar/application.yml @@ -35,7 +35,7 @@ fake-user: hangar: dev: true auth-url: "http://localhost:8000" - base-url: "http://localhost:8080" + base-url: "http://localhost:3000" plugin-upload-dir: "/uploads" sponsors: diff --git a/frontend/assets/main.scss b/frontend/assets/main.scss index 318613397..7a87a29dd 100644 --- a/frontend/assets/main.scss +++ b/frontend/assets/main.scss @@ -24,6 +24,10 @@ label { left: 38px !important; } + + .v-file-input__text { + padding-left: 38px; + } } } diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts index 50e4303ef..0789b38b3 100644 --- a/frontend/nuxt.config.ts +++ b/frontend/nuxt.config.ts @@ -4,6 +4,7 @@ import colors from 'vuetify/lib/util/colors'; import en from './locales/en'; import fr from './locales/fr'; +require('events').EventEmitter.defaultMaxListeners = 20; require('dotenv').config(); const proxyHost = process.env.proxyHost || 'http://localhost:8080'; @@ -106,6 +107,10 @@ export default { proxyHost + '/refresh', proxyHost + '/invalidate', proxyHost + '/v2/api-docs/', + proxyHost + '/robots.txt', + proxyHost + '/sitemap.xml', + proxyHost + '/global-sitemap.xml', + proxyHost + '/*/sitemap.xml', // auth authHost + '/avatar', ], diff --git a/src/main/java/io/papermc/hangar/controller/extras/resolver/PaginationResolver.java b/src/main/java/io/papermc/hangar/controller/extras/resolver/PaginationResolver.java index 19f97bb16..1f51bc245 100644 --- a/src/main/java/io/papermc/hangar/controller/extras/resolver/PaginationResolver.java +++ b/src/main/java/io/papermc/hangar/controller/extras/resolver/PaginationResolver.java @@ -62,6 +62,8 @@ public class PaginationResolver implements HandlerMethodArgumentResolver { paramNames.remove("sort"); paramNames.remove("limit"); paramNames.remove("offset"); + // TODO remove these eventually + paramNames.remove("relevance"); // remove request params for (Parameter param : parameter.getExecutable().getParameters()) { diff --git a/src/main/java/io/papermc/hangar/controller/internal/HangarUserController.java b/src/main/java/io/papermc/hangar/controller/internal/HangarUserController.java index f6f19da42..c07e4861e 100644 --- a/src/main/java/io/papermc/hangar/controller/internal/HangarUserController.java +++ b/src/main/java/io/papermc/hangar/controller/internal/HangarUserController.java @@ -19,8 +19,6 @@ import io.papermc.hangar.security.HangarAuthenticationToken; import io.papermc.hangar.security.annotations.permission.PermissionRequired; import io.papermc.hangar.security.annotations.unlocked.Unlocked; import io.papermc.hangar.service.api.UsersApiService; -import io.papermc.hangar.service.internal.perms.members.OrganizationMemberService; -import io.papermc.hangar.service.internal.perms.members.ProjectMemberService; import io.papermc.hangar.service.internal.perms.roles.OrganizationRoleService; import io.papermc.hangar.service.internal.perms.roles.ProjectRoleService; import io.papermc.hangar.service.internal.perms.roles.RoleService; @@ -61,7 +59,7 @@ public class HangarUserController extends HangarController { private final OrganizationInviteService organizationInviteService; @Autowired - public HangarUserController(ObjectMapper mapper, UsersApiService usersApiService, UserService userService, NotificationService notificationService, ProjectRoleService projectRoleService, OrganizationRoleService organizationRoleService, ProjectMemberService projectMemberService, OrganizationMemberService organizationMemberService, ProjectInviteService projectInviteService, OrganizationInviteService organizationInviteService) { + public HangarUserController(ObjectMapper mapper, UsersApiService usersApiService, UserService userService, NotificationService notificationService, ProjectRoleService projectRoleService, OrganizationRoleService organizationRoleService, ProjectInviteService projectInviteService, OrganizationInviteService organizationInviteService) { this.mapper = mapper; this.usersApiService = usersApiService; this.userService = userService; @@ -175,5 +173,4 @@ public class HangarUserController extends HangarController { DECLINE, UNACCEPT, } - } diff --git a/src/main/java/io/papermc/hangar/controller/internal/SitemapController.java b/src/main/java/io/papermc/hangar/controller/internal/SitemapController.java new file mode 100644 index 000000000..c9989fc00 --- /dev/null +++ b/src/main/java/io/papermc/hangar/controller/internal/SitemapController.java @@ -0,0 +1,39 @@ +package io.papermc.hangar.controller.internal; + +import io.papermc.hangar.controller.HangarController; +import io.papermc.hangar.service.internal.SitemapService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class SitemapController extends HangarController { + + private final SitemapService sitemapService; + + @Autowired + public SitemapController(SitemapService sitemapService) { + this.sitemapService = sitemapService; + } + + @GetMapping(value = "/sitemap.xml", produces = MediaType.APPLICATION_XML_VALUE) + @ResponseBody + public String sitemapIndex() { + return sitemapService.getSitemap(); + } + + @GetMapping(value = "/global-sitemap.xml", produces = MediaType.APPLICATION_XML_VALUE) + @ResponseBody + public String globalSitemap() { + return sitemapService.getGlobalSitemap(); + } + + @GetMapping(value = "/{user}/sitemap.xml", produces = MediaType.APPLICATION_XML_VALUE) + @ResponseBody + public String userSitemap(@PathVariable String user) { + return sitemapService.getUserSitemap(user); + } +} diff --git a/src/main/java/io/papermc/hangar/controller/internal/projects/ProjectPageController.java b/src/main/java/io/papermc/hangar/controller/internal/projects/ProjectPageController.java index ac5f21231..a57cbcd6b 100644 --- a/src/main/java/io/papermc/hangar/controller/internal/projects/ProjectPageController.java +++ b/src/main/java/io/papermc/hangar/controller/internal/projects/ProjectPageController.java @@ -5,7 +5,7 @@ import io.papermc.hangar.model.common.NamedPermission; import io.papermc.hangar.model.common.PermissionType; import io.papermc.hangar.model.internal.api.requests.StringContent; import io.papermc.hangar.model.internal.api.requests.projects.NewProjectPage; -import io.papermc.hangar.model.internal.projects.HangarViewProjectPage; +import io.papermc.hangar.model.internal.projects.ExtendedProjectPage; import io.papermc.hangar.security.annotations.Anyone; import io.papermc.hangar.security.annotations.permission.PermissionRequired; import io.papermc.hangar.security.annotations.unlocked.Unlocked; @@ -48,7 +48,7 @@ public class ProjectPageController extends HangarController { @VisibilityRequired(type = Type.PROJECT, args = "{#author, #slug}") @GetMapping(path = "/page/{author}/{slug}/**", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getProjectPage(@PathVariable String author, @PathVariable String slug) { + public ResponseEntity getProjectPage(@PathVariable String author, @PathVariable String slug) { return ResponseEntity.ok(projectPageService.getProjectPage(author, slug, request.getRequestURI())); } diff --git a/src/main/java/io/papermc/hangar/controllerold/ApplicationController.java b/src/main/java/io/papermc/hangar/controllerold/ApplicationController.java index fa06e50c6..8ba0c10d1 100644 --- a/src/main/java/io/papermc/hangar/controllerold/ApplicationController.java +++ b/src/main/java/io/papermc/hangar/controllerold/ApplicationController.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.vladsch.flexmark.ext.admonition.AdmonitionExtension; -import io.papermc.hangar.config.hangar.HangarConfig; import io.papermc.hangar.controllerold.forms.UserAdminForm; import io.papermc.hangar.controllerold.util.StatusZ; import io.papermc.hangar.db.customtypes.RoleCategory; @@ -29,11 +28,9 @@ import io.papermc.hangar.securityold.annotations.GlobalPermission; import io.papermc.hangar.serviceold.JobService; import io.papermc.hangar.serviceold.OrgService; import io.papermc.hangar.serviceold.RoleService; -import io.papermc.hangar.serviceold.SitemapService; import io.papermc.hangar.serviceold.StatsService; import io.papermc.hangar.serviceold.UserActionLogService; import io.papermc.hangar.serviceold.UserService; -import io.papermc.hangar.serviceold.VersionService; import io.papermc.hangar.serviceold.project.ProjectService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; @@ -53,9 +50,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.View; -import javax.servlet.http.HttpServletRequest; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -72,33 +67,25 @@ public class ApplicationController extends HangarController { private final ProjectService projectService; private final OrgService orgService; private final UserActionLogService userActionLogService; - private final VersionService versionService; private final JobService jobService; - private final SitemapService sitemapService; private final StatsService statsService; private final RoleService roleService; private final StatusZ statusZ; private final ObjectMapper mapper; - private final HangarConfig hangarConfig; - private final HttpServletRequest request; private final Supplier userData; @Autowired - public ApplicationController(HangarDao platformVersionsDao, UserService userService, ProjectService projectService, OrgService orgService, VersionService versionService, UserActionLogService userActionLogService, JobService jobService, SitemapService sitemapService, StatsService statsService, RoleService roleService, StatusZ statusZ, ObjectMapper mapper, HangarConfig hangarConfig, HttpServletRequest request, Supplier userData) { + public ApplicationController(HangarDao platformVersionsDao, UserService userService, ProjectService projectService, OrgService orgService, UserActionLogService userActionLogService, JobService jobService, StatsService statsService, RoleService roleService, StatusZ statusZ, ObjectMapper mapper, Supplier userData) { this.platformVersionsDao = platformVersionsDao; this.userService = userService; this.projectService = projectService; this.orgService = orgService; this.userActionLogService = userActionLogService; - this.versionService = versionService; this.jobService = jobService; - this.sitemapService = sitemapService; this.roleService = roleService; this.statusZ = statusZ; this.mapper = mapper; - this.hangarConfig = hangarConfig; - this.request = request; this.statsService = statsService; this.userData = userData; } @@ -311,18 +298,6 @@ public class ApplicationController extends HangarController { } } - @GetMapping(value = "/favicon.ico", produces = "images/x-icon") - @ResponseBody - public ClassPathResource faviconRedirect() { - return new ClassPathResource("public/images/favicon/favicon.ico"); - } - - @GetMapping(value = "/global-sitemap.xml", produces = MediaType.APPLICATION_XML_VALUE) - @ResponseBody - public String globalSitemap() { - return sitemapService.getGlobalSitemap(); - } - @GetMapping("/linkout") public ModelAndView linkOut(@RequestParam(defaultValue = "") String remoteUrl) { ModelAndView view = new ModelAndView("linkout"); @@ -332,19 +307,8 @@ public class ApplicationController extends HangarController { @GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE) @ResponseBody - public Object robots() { - if (hangarConfig.isDev()) { - request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.MOVED_PERMANENTLY); - return new ModelAndView("redirect:http://localhost:8081/robots.txt"); - } else { - return new ClassPathResource("public/robots.txt"); - } - } - - @GetMapping(value = "/sitemap.xml", produces = MediaType.APPLICATION_XML_VALUE) - @ResponseBody - public String sitemapIndex() { - return sitemapService.getSitemap(); + public ClassPathResource robots() { + return new ClassPathResource("WEB-INF/robots.txt"); } @GetMapping(value = "/assets-ext/css/admonition.css", produces = "text/css") diff --git a/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java b/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java index 6b6f73f88..1acf22081 100644 --- a/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java +++ b/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java @@ -10,7 +10,6 @@ import io.papermc.hangar.model.common.Permission; import io.papermc.hangar.model.common.projects.Visibility; import io.papermc.hangar.modelold.viewhelpers.ProjectData; import io.papermc.hangar.modelold.viewhelpers.ScopedOrganizationData; -import io.papermc.hangar.modelold.viewhelpers.ScopedProjectData; import io.papermc.hangar.securityold.annotations.GlobalPermission; import io.papermc.hangar.securityold.annotations.ProjectPermission; import io.papermc.hangar.securityold.annotations.UserLock; @@ -27,7 +26,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -109,23 +107,6 @@ public class ProjectsController extends HangarController { } } - @GetMapping("/{author}/{slug}/discuss") - public ModelAndView showDiscussion(@PathVariable String author, @PathVariable String slug) { - ModelAndView mv = new ModelAndView("projects/discuss"); - ProjectData projData = projectData.get(); - ScopedProjectData scopedProjectData = projectService.getScopedProjectData(projData.getProject().getId()); - mv.addObject("p", projData); - mv.addObject("sp", scopedProjectData); - statsService.addProjectView(projData.getProject()); // TODO this is in ore, but I'm not sure why - return fillModel(mv); - } - - @Secured("ROLE_USER") - @PostMapping("/{author}/{slug}/discuss/reply") - public Object postDiscussionReply(@PathVariable String author, @PathVariable String slug) { - return null; // TODO implement postDiscussionReply request controller - } - @ProjectPermission(NamedPermission.DELETE_PROJECT) @UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}") @Secured("ROLE_USER") diff --git a/src/main/java/io/papermc/hangar/controllerold/UsersController.java b/src/main/java/io/papermc/hangar/controllerold/UsersController.java index c3a974c55..113e0d933 100644 --- a/src/main/java/io/papermc/hangar/controllerold/UsersController.java +++ b/src/main/java/io/papermc/hangar/controllerold/UsersController.java @@ -14,27 +14,23 @@ import io.papermc.hangar.service.PermissionService; import io.papermc.hangar.service.internal.auth.SSOService; import io.papermc.hangar.serviceold.ApiKeyService; import io.papermc.hangar.serviceold.OrgService; -import io.papermc.hangar.serviceold.SitemapService; import io.papermc.hangar.serviceold.SsoService.SignatureException; import io.papermc.hangar.serviceold.UserService; import io.papermc.hangar.util.Routes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.ModelAndView; import java.util.List; import java.util.Optional; -import java.util.function.Supplier; import java.util.stream.Collectors; @Controller("oldUsersController") @@ -47,13 +43,10 @@ public class UsersController extends HangarController { private final ApiKeyService apiKeyService; private final PermissionService permissionService; private final SSOService ssoService; - private final SitemapService sitemapService; - - private final Supplier usersTable; @Autowired - public UsersController(ObjectMapper mapper, HangarConfig hangarConfig, UserService userService, OrgService orgService, ApiKeyService apiKeyService, PermissionService permissionService, SSOService ssoService, SitemapService sitemapService, Supplier usersTable) { + public UsersController(ObjectMapper mapper, HangarConfig hangarConfig, UserService userService, OrgService orgService, ApiKeyService apiKeyService, PermissionService permissionService, SSOService ssoService) { this.mapper = mapper; this.hangarConfig = hangarConfig; this.userService = userService; @@ -61,8 +54,6 @@ public class UsersController extends HangarController { this.apiKeyService = apiKeyService; this.permissionService = permissionService; this.ssoService = ssoService; - this.sitemapService = sitemapService; - this.usersTable = usersTable; } @Secured("ROLE_USER") @@ -116,12 +107,5 @@ public class UsersController extends HangarController { return Routes.USERS_SHOW_PROJECTS.getRedirect(user); } - @GetMapping(value = "/{user}/sitemap.xml", produces = MediaType.APPLICATION_XML_VALUE) - @ResponseBody - public String userSitemap(@PathVariable("user") String username) { - UsersTable user = usersTable.get(); - return sitemapService.getUserSitemap(user); - } - } diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java index b97b574e5..f0ce89459 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java @@ -1,6 +1,6 @@ package io.papermc.hangar.db.dao.internal.projects; -import io.papermc.hangar.model.internal.projects.HangarViewProjectPage; +import io.papermc.hangar.model.internal.projects.ExtendedProjectPage; import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.springframework.stereotype.Repository; @@ -8,7 +8,7 @@ import org.springframework.stereotype.Repository; import java.util.List; @Repository -@RegisterConstructorMapper(HangarViewProjectPage.class) +@RegisterConstructorMapper(ExtendedProjectPage.class) public interface HangarProjectPagesDAO { @SqlQuery("SELECT pp.*," + @@ -16,19 +16,19 @@ public interface HangarProjectPagesDAO { " FROM project_pages pp" + " WHERE pp.project_id = :projectId" + " ORDER BY created_at") - List getProjectPages(long projectId); + List getProjectPages(long projectId); @SqlQuery("SELECT pp.*," + " exists(SELECT 1 FROM project_home_pages php WHERE php.page_id = pp.id AND php.project_id = p.id) AS home" + " FROM project_pages pp" + " JOIN projects p ON pp.project_id = p.id" + " WHERE lower(p.owner_name) = lower(:author) AND lower(p.slug) = lower(:slug) AND pp.slug = :pageSlug") - HangarViewProjectPage getProjectPage(String author, String slug, String pageSlug); + ExtendedProjectPage getProjectPage(String author, String slug, String pageSlug); @SqlQuery("SELECT pp.*, TRUE AS home " + " FROM project_pages pp" + " JOIN projects p ON pp.project_id = p.id" + " JOIN project_home_pages php ON pp.id = php.page_id" + " WHERE lower(p.owner_name) = lower(:author) AND lower(p.slug) = lower(:slug)") - HangarViewProjectPage getHomePage(String author, String slug); + ExtendedProjectPage getHomePage(String author, String slug); } diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/table/UserDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/table/UserDAO.java index 7345d9ca3..8405e0fdf 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/table/UserDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/table/UserDAO.java @@ -10,6 +10,8 @@ import org.jdbi.v3.sqlobject.statement.SqlUpdate; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository @RegisterConstructorMapper(UserTable.class) public interface UserDAO { @@ -24,7 +26,7 @@ public interface UserDAO { @SqlUpdate("UPDATE users SET full_name = :fullName, name = :name, email = :email, tagline = :tagline, read_prompts = :readPrompts, locked = :locked, language = :language WHERE id = :id") UserTable update(@BindBean UserTable user); - @SqlQuery("SELECT * FROM users WHERE id = :id OR name = :name") + @SqlQuery("SELECT * FROM users WHERE id = :id OR lower(name) = lower(:name)") UserTable _getUserTable(Long id, String name); default UserTable getUserTable(long id) { return _getUserTable(id, null); @@ -33,6 +35,9 @@ public interface UserDAO { return _getUserTable(null, name); } - @SqlQuery("SELECT * FROM users WHERE LOWER(name) = LOWER(:name)") - UserTable getByName(String name); + @SqlQuery("SELECT u.name" + + " FROM users u" + + " ORDER BY (SELECT count(*) FROM project_members_all pma WHERE pma.user_id = u.id) DESC" + + " LIMIT 49000") + List getAuthorNames(); } diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectsDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectsDAO.java index 95e90c8c7..0144d9bda 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectsDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectsDAO.java @@ -38,6 +38,9 @@ public interface ProjectsDAO { @SqlQuery("SELECT * FROM projects WHERE id = :projectId") ProjectTable getById(long projectId); + @SqlQuery("SELECT * FROM projects WHERE owner_id = :userId") + List getUserProjects(long userId); + @SqlQuery("SELECT * FROM " + " (SELECT CASE " + " WHEN \"name\" = :name THEN 'OWNER_NAME'" + diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/ProjectVersionsDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/ProjectVersionsDAO.java index de5641340..d0cc688e8 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/ProjectVersionsDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/ProjectVersionsDAO.java @@ -3,7 +3,10 @@ package io.papermc.hangar.db.dao.internal.table.versions; import io.papermc.hangar.model.common.Platform; import io.papermc.hangar.model.db.versions.ProjectVersionTable; import org.jdbi.v3.core.enums.EnumByOrdinal; +import org.jdbi.v3.core.enums.EnumStrategy; +import org.jdbi.v3.sqlobject.SingleValue; import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; +import org.jdbi.v3.sqlobject.config.UseEnumStrategy; import org.jdbi.v3.sqlobject.customizer.BindBean; import org.jdbi.v3.sqlobject.customizer.Timestamped; import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys; @@ -11,6 +14,8 @@ import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository @RegisterConstructorMapper(ProjectVersionTable.class) public interface ProjectVersionsDAO { @@ -34,6 +39,9 @@ public interface ProjectVersionsDAO { @SqlQuery("SELECT * FROM project_versions pv WHERE pv.id = :versionId") ProjectVersionTable getProjectVersionTable(long versionId); + @SqlQuery("SELECT * FROM project_versions WHERE project_id = :projectId") + List getProjectVersions(long projectId); + @SqlQuery("SELECT pv.*" + " FROM project_versions pv" + " JOIN project_channels pc ON pv.channel_id = pc.id" + @@ -55,4 +63,13 @@ public interface ProjectVersionsDAO { @SqlQuery("SELECT * FROM project_versions WHERE project_id = :projectId AND hash = :hash AND version_string = :versionString") ProjectVersionTable getProjectVersionTableFromHashAndName(long projectId, String hash, String versionString); + + @SingleValue + @UseEnumStrategy(EnumStrategy.BY_ORDINAL) + @SqlQuery("SELECT array_agg(DISTINCT plv.platform)" + + " FROM project_versions pv" + + " JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" + + " JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" + + " WHERE pv.id = :versionId GROUP BY pv.id") + List getVersionPlatforms(long versionId); } diff --git a/src/main/java/io/papermc/hangar/db/daoold/ProjectDao.java b/src/main/java/io/papermc/hangar/db/daoold/ProjectDao.java index 9f0da50c8..35b176bcb 100644 --- a/src/main/java/io/papermc/hangar/db/daoold/ProjectDao.java +++ b/src/main/java/io/papermc/hangar/db/daoold/ProjectDao.java @@ -41,9 +41,6 @@ public interface ProjectDao { @SqlQuery("SELECT COUNT(*) FROM projects WHERE owner_id = :id") int getProjectCountByUserId(long id); - @SqlQuery("SELECT * FROM projects WHERE owner_id = :id") - List getProjectsByUserId(long id); - @RegisterBeanMapper(value = ScopedProjectData.class) @RegisterBeanMapper(value = Permission.class, prefix = "perm") @SqlQuery("SELECT sq1.watching, sq2.starred, sq3.uproject_flags FROM" + diff --git a/src/main/java/io/papermc/hangar/db/daoold/UserDao.java b/src/main/java/io/papermc/hangar/db/daoold/UserDao.java index d68b35c93..878028f45 100644 --- a/src/main/java/io/papermc/hangar/db/daoold/UserDao.java +++ b/src/main/java/io/papermc/hangar/db/daoold/UserDao.java @@ -5,9 +5,6 @@ import io.papermc.hangar.modelold.viewhelpers.FlagActivity; import io.papermc.hangar.modelold.viewhelpers.ReviewActivity; import org.jdbi.v3.sqlobject.config.RegisterBeanMapper; import org.jdbi.v3.sqlobject.customizer.BindBean; -import org.jdbi.v3.sqlobject.customizer.BindList; -import org.jdbi.v3.sqlobject.customizer.BindList.EmptyHandling; -import org.jdbi.v3.sqlobject.customizer.Timestamped; import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; @@ -16,15 +13,10 @@ import org.springframework.stereotype.Repository; import java.util.List; @Repository +@Deprecated(forRemoval = true) @RegisterBeanMapper(UsersTable.class) public interface UserDao { - @SqlUpdate("insert into users (id, created_at, full_name, name, email, tagline, join_date, read_prompts, is_locked, language) " + - "values (:id, :now, :fullName, :name, :email, :tagline, :now, :readPrompts, :isLocked, :language)") - @Timestamped - @GetGeneratedKeys - UsersTable insert(@BindBean UsersTable user); - @SqlUpdate("UPDATE users SET full_name = :fullName, name = :name, email = :email, tagline = :tagline, read_prompts = :readPrompts, is_locked = :isLocked, language = :language WHERE id = :id") @GetGeneratedKeys UsersTable update(@BindBean UsersTable user); @@ -35,27 +27,12 @@ public interface UserDao { @SqlQuery("select * from users where LOWER(name) = LOWER(:name)") UsersTable getByName(String name); - @SqlQuery("SELECT * FROM users WHERE name IN ()") - List getUsers(@BindList(onEmpty = EmptyHandling.NULL_STRING) List userNames); - @SqlQuery("SELECT u.* FROM project_watchers pw JOIN users u ON pw.user_id = u.id WHERE project_id = :projectId OFFSET :offset LIMIT :limit") List getProjectWatchers(long projectId, int offset, Integer limit); - @SqlUpdate("INSERT INTO project_watchers (project_id, user_id) VALUES (:projectId, :userId)") - void setWatching(long projectId, long userId); - - @SqlUpdate("DELETE FROM project_watchers WHERE project_id = :projectId AND user_id = :userId") - void removeWatching(long projectId, long userId); - @SqlQuery("SELECT u.* FROM project_stars ps JOIN users u ON ps.user_id = u.id WHERE project_id = :projectId OFFSET :offset LIMIT :limit") List getProjectStargazers(long projectId, int offset, Integer limit); - @SqlUpdate("INSERT INTO project_stars (project_id, user_id) VALUES (:projectId, :userId)") - void setStargazing(long projectId, long userId); - - @SqlUpdate("DELETE FROM project_stars WHERE project_id = :projectId AND user_id = :userId") - void removeStargazing(long projectId, long userId); - @SqlQuery("SELECT pvr.ended_at, pv.version_string, pv.version_string || '.' || pv.id AS version_string_url, p.owner_name \"owner\", p.slug" + " FROM users u" + @@ -76,9 +53,4 @@ public interface UserDao { @RegisterBeanMapper(FlagActivity.class) List getFlagActivity(String username); - @SqlQuery("SELECT u.name" + - " FROM users u" + - " ORDER BY (SELECT COUNT(*) FROM project_members_all pma WHERE pma.user_id = u.id) DESC" + - " LIMIT 49000") - List getAllAuthorNames(); } diff --git a/src/main/java/io/papermc/hangar/model/internal/projects/HangarViewProjectPage.java b/src/main/java/io/papermc/hangar/model/internal/projects/ExtendedProjectPage.java similarity index 75% rename from src/main/java/io/papermc/hangar/model/internal/projects/HangarViewProjectPage.java rename to src/main/java/io/papermc/hangar/model/internal/projects/ExtendedProjectPage.java index 3f989541c..8de24b938 100644 --- a/src/main/java/io/papermc/hangar/model/internal/projects/HangarViewProjectPage.java +++ b/src/main/java/io/papermc/hangar/model/internal/projects/ExtendedProjectPage.java @@ -6,11 +6,11 @@ import io.papermc.hangar.model.db.projects.ProjectPageTable; import java.time.OffsetDateTime; // TODO rename? Different from HangarProjectPage as it just represents one page but needs to include the isHome field -public class HangarViewProjectPage extends ProjectPageTable { +public class ExtendedProjectPage extends ProjectPageTable { private final boolean home; - public HangarViewProjectPage(OffsetDateTime createdAt, long id, long projectId, String name, String slug, String contents, boolean deletable, Long parentId, boolean home) { + public ExtendedProjectPage(OffsetDateTime createdAt, long id, long projectId, String name, String slug, String contents, boolean deletable, Long parentId, boolean home) { super(createdAt, id, projectId, name, slug, contents, deletable, parentId); this.home = home; } diff --git a/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectPage.java b/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectPage.java index 0eb66f786..90019bd8f 100644 --- a/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectPage.java +++ b/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectPage.java @@ -13,14 +13,14 @@ public class HangarProjectPage { private final long id; private final String name; private final String slug; - private final boolean isHome; + private final boolean home; private final Map children; - public HangarProjectPage(ProjectPageTable projectPageTable, boolean isHome) { + public HangarProjectPage(ProjectPageTable projectPageTable, boolean home) { this.id = projectPageTable.getId(); this.name = projectPageTable.getName(); this.slug = projectPageTable.getSlug(); - this.isHome = isHome; + this.home = home; this.children = new LinkedHashMap<>(); } @@ -37,7 +37,7 @@ public class HangarProjectPage { } public boolean isHome() { - return isHome; + return home; } @JsonIgnore diff --git a/src/main/java/io/papermc/hangar/service/internal/SitemapService.java b/src/main/java/io/papermc/hangar/service/internal/SitemapService.java new file mode 100644 index 000000000..28891ea8c --- /dev/null +++ b/src/main/java/io/papermc/hangar/service/internal/SitemapService.java @@ -0,0 +1,97 @@ +package io.papermc.hangar.service.internal; + +import cz.jiripinkas.jsitemapgenerator.ChangeFreq; +import cz.jiripinkas.jsitemapgenerator.WebPage; +import cz.jiripinkas.jsitemapgenerator.generator.SitemapGenerator; +import io.papermc.hangar.db.dao.HangarDao; +import io.papermc.hangar.db.dao.internal.projects.HangarProjectPagesDAO; +import io.papermc.hangar.db.dao.internal.table.UserDAO; +import io.papermc.hangar.db.dao.internal.table.projects.ProjectsDAO; +import io.papermc.hangar.db.dao.internal.table.versions.ProjectVersionsDAO; +import io.papermc.hangar.model.common.Platform; +import io.papermc.hangar.model.db.UserTable; +import io.papermc.hangar.model.db.projects.ProjectTable; +import io.papermc.hangar.model.db.versions.ProjectVersionTable; +import io.papermc.hangar.model.internal.projects.ExtendedProjectPage; +import io.papermc.hangar.service.HangarService; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Locale; + +@Service +public class SitemapService extends HangarService { + + private final UserDAO userDAO; + private final ProjectsDAO projectsDAO; + private final ProjectVersionsDAO projectVersionsDAO; + private final HangarProjectPagesDAO hangarProjectPagesDAO; + + public SitemapService(HangarDao userDAO, HangarDao projectsDAO, HangarDao projectVersionsDAO, HangarDao hangarProjectPagesDAO) { + this.userDAO = userDAO.get(); + this.projectsDAO = projectsDAO.get(); + this.projectVersionsDAO = projectVersionsDAO.get(); + this.hangarProjectPagesDAO = hangarProjectPagesDAO.get(); + } + + @Cacheable("indexSitemap") + public String getSitemap() { + SitemapGenerator generator = SitemapGenerator.of(config.getBaseUrl()) + .addPage(WebPage.builder().name("global-sitemap.xml").build()); + + userDAO.getAuthorNames().forEach(name -> generator.addPage(name + "/sitemap.xml")); + return generator.toString(); + } + + @Cacheable("globalSitemap") + public String getGlobalSitemap() { + return SitemapGenerator.of(config.getBaseUrl()) + .addPage(WebPage.builder().name("").changeFreq(ChangeFreq.HOURLY).build()) + .addPage(WebPage.builder().name("authors").changeFreq(ChangeFreq.WEEKLY).build()) + .addPage(WebPage.builder().name("staff").changeFreq(ChangeFreq.WEEKLY).build()) + .addPage(WebPage.builder().name("api").build()) + .toString(); + } + + @Cacheable(value = "userSitemap", key = "#username") + public String getUserSitemap(String username) { + final UserTable userTable = userDAO.getUserTable(username); + final SitemapGenerator generator = SitemapGenerator.of(config.getBaseUrl()); + + // add all projects + List projects = projectsDAO.getUserProjects(userTable.getId()); + projects.forEach(p -> generator.addPage(userTable.getName() + "/" + p.getSlug())); + + // add all versions of said projects + projects.forEach(p -> { + List projectVersions = projectVersionsDAO.getProjectVersions(p.getId()); + + projectVersions.forEach(pv -> { + List platforms = projectVersionsDAO.getVersionPlatforms(pv.getId()); + platforms.forEach(platform -> generator.addPage(path(userTable.getName(), p.getSlug(), "versions", pv.getVersionString(), platform.name().toLowerCase(Locale.ROOT)))); + + }); + }); + + // add all pages of said projects + projects.forEach(project -> { + List projectPages = hangarProjectPagesDAO.getProjectPages(project.getId()); + for (ExtendedProjectPage pp : projectPages) { + if (pp.isHome()) { + continue; + } + generator.addPage(path(userTable.getName(), project.getSlug(), pp.getSlug())); + } + }); + + // lastly, add user page + generator.addPage(WebPage.builder().name(userTable.getName()).changeFreq(ChangeFreq.WEEKLY).build()); + + return generator.toString(); + } + + private String path(String...paths) { + return String.join("/", paths); + } +} diff --git a/src/main/java/io/papermc/hangar/service/internal/projects/ProjectPageService.java b/src/main/java/io/papermc/hangar/service/internal/projects/ProjectPageService.java index 400d53a17..c50f3465a 100644 --- a/src/main/java/io/papermc/hangar/service/internal/projects/ProjectPageService.java +++ b/src/main/java/io/papermc/hangar/service/internal/projects/ProjectPageService.java @@ -9,8 +9,8 @@ import io.papermc.hangar.model.db.projects.ProjectPageTable; import io.papermc.hangar.model.internal.api.requests.projects.NewProjectPage; import io.papermc.hangar.model.internal.logs.LogAction; import io.papermc.hangar.model.internal.logs.contexts.PageContext; +import io.papermc.hangar.model.internal.projects.ExtendedProjectPage; import io.papermc.hangar.model.internal.projects.HangarProjectPage; -import io.papermc.hangar.model.internal.projects.HangarViewProjectPage; import io.papermc.hangar.service.HangarService; import io.papermc.hangar.util.StringUtils; import org.jetbrains.annotations.Nullable; @@ -68,7 +68,7 @@ public class ProjectPageService extends HangarService { public Map getProjectPages(long projectId) { Map hangarProjectPages = new LinkedHashMap<>(); - for (HangarViewProjectPage projectPage : hangarProjectPagesDAO.getProjectPages(projectId)) { + for (ExtendedProjectPage projectPage : hangarProjectPagesDAO.getProjectPages(projectId)) { if (projectPage.getParentId() == null) { hangarProjectPages.put(projectPage.getId(), new HangarProjectPage(projectPage, projectPage.isHome())); } else { @@ -97,9 +97,9 @@ public class ProjectPageService extends HangarService { } } - public HangarViewProjectPage getProjectPage(String author, String slug, String requestUri) { + public ExtendedProjectPage getProjectPage(String author, String slug, String requestUri) { String[] path = requestUri.split("/", 8); - HangarViewProjectPage pageTable; + ExtendedProjectPage pageTable; if (path.length < 8) { pageTable = hangarProjectPagesDAO.getHomePage(author, slug); } else { diff --git a/src/main/java/io/papermc/hangar/serviceold/SitemapService.java b/src/main/java/io/papermc/hangar/serviceold/SitemapService.java deleted file mode 100644 index 4a83384d3..000000000 --- a/src/main/java/io/papermc/hangar/serviceold/SitemapService.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.papermc.hangar.serviceold; - -import cz.jiripinkas.jsitemapgenerator.ChangeFreq; -import cz.jiripinkas.jsitemapgenerator.WebPage; -import cz.jiripinkas.jsitemapgenerator.generator.SitemapGenerator; -import io.papermc.hangar.config.hangar.HangarConfig; -import io.papermc.hangar.db.dao.HangarDao; -import io.papermc.hangar.db.daoold.ProjectDao; -import io.papermc.hangar.db.daoold.ProjectPageDao; -import io.papermc.hangar.db.daoold.ProjectVersionDao; -import io.papermc.hangar.db.daoold.UserDao; -import io.papermc.hangar.db.modelold.ProjectVersionsTable; -import io.papermc.hangar.db.modelold.ProjectsTable; -import io.papermc.hangar.db.modelold.UsersTable; -import io.papermc.hangar.modelold.viewhelpers.ProjectPage; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class SitemapService { - - private final HangarConfig hangarConfig; - private final HangarDao userDao; - private final HangarDao projectDao; - private final HangarDao versionDao; - private final HangarDao pageDao; - - @Autowired - public SitemapService(HangarConfig hangarConfig, HangarDao userDao, HangarDao projectDao, HangarDao versionDao, HangarDao pageDao) { - this.hangarConfig = hangarConfig; - this.userDao = userDao; - this.projectDao = projectDao; - this.versionDao = versionDao; - this.pageDao = pageDao; - } - - @Cacheable("indexSitemap") - public String getSitemap() { - SitemapGenerator generator = SitemapGenerator.of(hangarConfig.getBaseUrl()) - .addPage(WebPage.builder().name("global-sitemap.xml").build()); - - userDao.get().getAllAuthorNames().forEach(user -> generator.addPage(user + "/sitemap.xml")); - - return generator.toString(); - } - - @Cacheable("globalSitemap") - public String getGlobalSitemap() { - return SitemapGenerator.of(hangarConfig.getBaseUrl()) - .addPage(WebPage.builder().name("").changeFreq(ChangeFreq.HOURLY).build()) - .addPage(WebPage.builder().name("authors").changeFreq(ChangeFreq.WEEKLY).build()) - .addPage(WebPage.builder().name("api").build()) - .toString(); - } - - @Cacheable(value = "userSitemap", key = "#user.name") - public String getUserSitemap(UsersTable user) { - SitemapGenerator generator = SitemapGenerator.of(hangarConfig.getBaseUrl()); - - // add all projects - List projects = projectDao.get().getProjectsByUserId(user.getId()); - projects.forEach(p -> generator.addPage(user.getName() + "/" + p.getSlug())); - - // add all versions of said projects - projects.forEach(p -> { - List versions = versionDao.get().getProjectVersions(p.getId()); - versions.forEach(v -> generator.addPage(user.getName() + "/" + p.getSlug() + "/" + v.getVersionString())); - }); - - // add all pages of said projects - projects.forEach(project -> { - List pages = pageDao.get().getPages(project.getOwnerName(), project.getSlug()); - pages.forEach(page -> generator.addPage(user.getName() + "/" + project.getSlug() + "/" + page.getSlug())); - }); - - // lastly, add user page - generator.addPage(WebPage.builder().name(user.getName()).changeFreq(ChangeFreq.WEEKLY).build()); - - return generator.toString(); - } -} diff --git a/src/main/java/io/papermc/hangar/serviceold/project/ProjectService.java b/src/main/java/io/papermc/hangar/serviceold/project/ProjectService.java index 13f841a02..31711c3c2 100644 --- a/src/main/java/io/papermc/hangar/serviceold/project/ProjectService.java +++ b/src/main/java/io/papermc/hangar/serviceold/project/ProjectService.java @@ -17,7 +17,6 @@ import io.papermc.hangar.modelold.viewhelpers.ProjectData; import io.papermc.hangar.modelold.viewhelpers.ProjectFlag; import io.papermc.hangar.modelold.viewhelpers.ProjectMissingFile; import io.papermc.hangar.modelold.viewhelpers.ProjectViewSettings; -import io.papermc.hangar.modelold.viewhelpers.ScopedProjectData; import io.papermc.hangar.modelold.viewhelpers.UnhealthyProject; import io.papermc.hangar.modelold.viewhelpers.UserRole; import io.papermc.hangar.service.PermissionService; @@ -38,7 +37,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -144,20 +142,6 @@ public class ProjectService extends HangarService { ); } - public ScopedProjectData getScopedProjectData(long projectId) { - Optional curUser = currentUser.get(); - if (curUser.isEmpty()) { - return new ScopedProjectData(); - } else { - ScopedProjectData sp = projectDao.get().getScopedProjectData(projectId, curUser.get().getId()); - if (sp == null) { - return new ScopedProjectData(); - } - sp.setPermissions(permissionService.getProjectPermissions(curUser.get().getId(), projectId)); - return sp; - } - } - public ProjectsTable getProjectsTable(long projectId) { return null; // return visibilityService.checkVisibility(projectDao.get().getById(projectId), ProjectsTable::getId); @@ -179,14 +163,6 @@ public class ProjectService extends HangarService { projectDao.get().update(project); } - public List getProjectWatchers(long projectId, int offset, Integer limit) { - return userDao.get().getProjectWatchers(projectId, offset, limit); - } - - public List getProjectStargazers(long projectId, int offset, int limit) { - return userDao.get().getProjectStargazers(projectId, offset, limit); - } - public Map> getProjectsAndRoles(long userId) { Map dbMap = projectDao.get().getProjectsAndRoles(userId); Map> map = new HashMap<>(); diff --git a/src/main/frontend-old/public/robots.txt b/src/main/resources/WEB-INF/robots.txt similarity index 100% rename from src/main/frontend-old/public/robots.txt rename to src/main/resources/WEB-INF/robots.txt diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 97a56f87e..242d39ce0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -47,7 +47,7 @@ fake-user: hangar: dev: true auth-url: "http://localhost:8000" - base-url: "http://localhost:8080" + base-url: "http://localhost:3000" ga-code: "UA-38006759-9" licences: