sitemap stuff

#408
This commit is contained in:
Jake Potrebic 2021-04-03 16:53:58 -07:00
parent ccb4666c2b
commit 6b585afd7d
No known key found for this signature in database
GPG Key ID: 7C58557EC9C421F8
24 changed files with 200 additions and 241 deletions

View File

@ -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:

View File

@ -24,6 +24,10 @@
label {
left: 38px !important;
}
.v-file-input__text {
padding-left: 38px;
}
}
}

View File

@ -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',
],

View File

@ -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()) {

View File

@ -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,
}
}

View File

@ -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);
}
}

View File

@ -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<HangarViewProjectPage> getProjectPage(@PathVariable String author, @PathVariable String slug) {
public ResponseEntity<ExtendedProjectPage> getProjectPage(@PathVariable String author, @PathVariable String slug) {
return ResponseEntity.ok(projectPageService.getProjectPage(author, slug, request.getRequestURI()));
}

View File

@ -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> userData;
@Autowired
public ApplicationController(HangarDao<PlatformVersionsDao> 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> userData) {
public ApplicationController(HangarDao<PlatformVersionsDao> platformVersionsDao, UserService userService, ProjectService projectService, OrgService orgService, UserActionLogService userActionLogService, JobService jobService, StatsService statsService, RoleService roleService, StatusZ statusZ, ObjectMapper mapper, Supplier<UserData> 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")

View File

@ -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")

View File

@ -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> usersTable;
@Autowired
public UsersController(ObjectMapper mapper, HangarConfig hangarConfig, UserService userService, OrgService orgService, ApiKeyService apiKeyService, PermissionService permissionService, SSOService ssoService, SitemapService sitemapService, Supplier<UsersTable> 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);
}
}

View File

@ -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<HangarViewProjectPage> getProjectPages(long projectId);
List<ExtendedProjectPage> 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);
}

View File

@ -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<String> getAuthorNames();
}

View File

@ -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<ProjectTable> getUserProjects(long userId);
@SqlQuery("SELECT * FROM " +
" (SELECT CASE " +
" WHEN \"name\" = :name THEN 'OWNER_NAME'" +

View File

@ -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<ProjectVersionTable> 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<Platform> getVersionPlatforms(long versionId);
}

View File

@ -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<ProjectsTable> getProjectsByUserId(long id);
@RegisterBeanMapper(value = ScopedProjectData.class)
@RegisterBeanMapper(value = Permission.class, prefix = "perm")
@SqlQuery("SELECT sq1.watching, sq2.starred, sq3.uproject_flags FROM" +

View File

@ -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 (<userNames>)")
List<UsersTable> getUsers(@BindList(onEmpty = EmptyHandling.NULL_STRING) List<String> 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<UsersTable> 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<UsersTable> 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<FlagActivity> 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<String> getAllAuthorNames();
}

View File

@ -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;
}

View File

@ -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<Long, HangarProjectPage> 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

View File

@ -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> userDAO, HangarDao<ProjectsDAO> projectsDAO, HangarDao<ProjectVersionsDAO> projectVersionsDAO, HangarDao<HangarProjectPagesDAO> 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<ProjectTable> projects = projectsDAO.getUserProjects(userTable.getId());
projects.forEach(p -> generator.addPage(userTable.getName() + "/" + p.getSlug()));
// add all versions of said projects
projects.forEach(p -> {
List<ProjectVersionTable> projectVersions = projectVersionsDAO.getProjectVersions(p.getId());
projectVersions.forEach(pv -> {
List<Platform> 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<ExtendedProjectPage> 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);
}
}

View File

@ -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<Long, HangarProjectPage> getProjectPages(long projectId) {
Map<Long, HangarProjectPage> 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 {

View File

@ -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> userDao;
private final HangarDao<ProjectDao> projectDao;
private final HangarDao<ProjectVersionDao> versionDao;
private final HangarDao<ProjectPageDao> pageDao;
@Autowired
public SitemapService(HangarConfig hangarConfig, HangarDao<UserDao> userDao, HangarDao<ProjectDao> projectDao, HangarDao<ProjectVersionDao> versionDao, HangarDao<ProjectPageDao> 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<ProjectsTable> 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<ProjectVersionsTable> 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<ProjectPage> 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();
}
}

View File

@ -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<UsersTable> 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<UsersTable> getProjectWatchers(long projectId, int offset, Integer limit) {
return userDao.get().getProjectWatchers(projectId, offset, limit);
}
public List<UsersTable> getProjectStargazers(long projectId, int offset, int limit) {
return userDao.get().getProjectStargazers(projectId, offset, limit);
}
public Map<ProjectData, UserRole<UserProjectRolesTable>> getProjectsAndRoles(long userId) {
Map<ProjectsTable, UserProjectRolesTable> dbMap = projectDao.get().getProjectsAndRoles(userId);
Map<ProjectData, UserRole<UserProjectRolesTable>> map = new HashMap<>();

View File

@ -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: