added version download counting

This commit is contained in:
Jake Potrebic 2020-09-06 22:13:42 -07:00
parent 97cef3416e
commit c9e4d9575d
No known key found for this signature in database
GPG Key ID: 7C58557EC9C421F8
3 changed files with 68 additions and 10 deletions

View File

@ -26,8 +26,8 @@ import io.papermc.hangar.model.viewhelpers.VersionData;
import io.papermc.hangar.security.annotations.GlobalPermission;
import io.papermc.hangar.security.annotations.UserLock;
import io.papermc.hangar.service.DownloadsService;
import io.papermc.hangar.service.StatsService;
import io.papermc.hangar.service.UserActionLogService;
import io.papermc.hangar.service.UserService;
import io.papermc.hangar.service.VersionService;
import io.papermc.hangar.service.pluginupload.PendingVersion;
import io.papermc.hangar.service.pluginupload.PluginUploadService;
@ -83,7 +83,7 @@ public class VersionsController extends HangarController {
private final ProjectService projectService;
private final VersionService versionService;
private final ProjectFactory projectFactory;
private final UserService userService;
private final StatsService statsService;
private final PluginUploadService pluginUploadService;
private final ChannelService channelService;
private final DownloadsService downloadsService;
@ -105,11 +105,11 @@ public class VersionsController extends HangarController {
@Autowired
public VersionsController(ProjectService projectService, VersionService versionService, ProjectFactory projectFactory, UserService userService, PluginUploadService pluginUploadService, ChannelService channelService, DownloadsService downloadsService, UserActionLogService userActionLogService, CacheManager cacheManager, HangarConfig hangarConfig, HangarDao<ProjectDao> projectDao, ProjectFiles projectFiles, HangarDao<ProjectVersionDownloadWarningDao> downloadWarningDao, MessageSource messageSource, ObjectMapper mapper, HttpServletRequest request, HttpServletResponse response, Supplier<ProjectVersionsTable> projectVersionsTable, Supplier<VersionData> versionData, Supplier<ProjectsTable> projectsTable, Supplier<ProjectData> projectData) {
public VersionsController(ProjectService projectService, VersionService versionService, ProjectFactory projectFactory, StatsService statsService, PluginUploadService pluginUploadService, ChannelService channelService, DownloadsService downloadsService, UserActionLogService userActionLogService, CacheManager cacheManager, HangarConfig hangarConfig, HangarDao<ProjectDao> projectDao, ProjectFiles projectFiles, HangarDao<ProjectVersionDownloadWarningDao> downloadWarningDao, MessageSource messageSource, ObjectMapper mapper, HttpServletRequest request, HttpServletResponse response, Supplier<ProjectVersionsTable> projectVersionsTable, Supplier<VersionData> versionData, Supplier<ProjectsTable> projectsTable, Supplier<ProjectData> projectData) {
this.projectService = projectService;
this.versionService = versionService;
this.projectFactory = projectFactory;
this.userService = userService;
this.statsService = statsService;
this.pluginUploadService = pluginUploadService;
this.channelService = channelService;
this.downloadsService = downloadsService;
@ -558,12 +558,11 @@ public class VersionsController extends HangarController {
}
private FileSystemResource _sendVersion(ProjectsTable project, ProjectVersionsTable version) {
// TODO version download stat
Path path = projectFiles.getVersionDir(project.getOwnerName(), project.getName(), version.getVersionString()).resolve(version.getFileName());
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + version.getFileName() + "\"");
statsService.addVersionDownloaded(version);
return new FileSystemResource(path);
}
@ -611,8 +610,7 @@ public class VersionsController extends HangarController {
String fileName = version.getFileName();
Path path = projectFiles.getVersionDir(project.getOwnerName(), project.getName(), version.getVersionString()).resolve(fileName);
// TODO download stats
statsService.addVersionDownloaded(version);
if (fileName.endsWith(".jar")) {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + version.getFileName() + "\"");

View File

@ -0,0 +1,28 @@
package io.papermc.hangar.db.dao;
import io.papermc.hangar.db.model.ProjectVersionsDownloadsIndividualTable;
import io.papermc.hangar.db.model.ProjectVersionsDownloadsTable;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.customizer.Timestamped;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import org.springframework.stereotype.Repository;
import java.net.InetAddress;
import java.util.Optional;
@Repository
@RegisterBeanMapper(ProjectVersionsDownloadsTable.class)
@RegisterBeanMapper(ProjectVersionsDownloadsIndividualTable.class)
public interface ProjectDownloadCountDao {
@SqlQuery("SELECT pvdi.cookie " +
" FROM project_versions_downloads_individual pvdi" +
" WHERE pvdi.address = :address OR " +
" (:userId IS NOT NULL AND :userId = pvdi.user_id)")
Optional<String> getIndividualDownloadCookie(Long userId, InetAddress address);
@Timestamped
@SqlUpdate("INSERT INTO project_versions_downloads_individual (created_at, project_id, version_id, address, cookie, user_id) VALUES (:now, :projectId, :versionId, :address, :cookie, :userId)")
void addVersionDownload(long projectId, long versionId, InetAddress address, String cookie, Long userId);
}

View File

@ -1,24 +1,42 @@
package io.papermc.hangar.service;
import io.papermc.hangar.db.dao.HangarDao;
import io.papermc.hangar.db.dao.ProjectDownloadCountDao;
import io.papermc.hangar.db.dao.ProjectStatsDao;
import io.papermc.hangar.db.model.ProjectVersionsTable;
import io.papermc.hangar.db.model.Stats;
import io.papermc.hangar.db.model.UsersTable;
import io.papermc.hangar.util.RequestUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.util.WebUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.InetAddress;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class StatsService {
public class StatsService extends HangarService {
private final HangarDao<ProjectStatsDao> projectStatsDao;
private final HangarDao<ProjectDownloadCountDao> projectDownloadCountDao;
private final HttpServletRequest request;
private final HttpServletResponse response;
@Autowired
public StatsService(HangarDao<ProjectStatsDao> projectStatsDao) {
public StatsService(HangarDao<ProjectStatsDao> projectStatsDao, HangarDao<ProjectDownloadCountDao> projectDownloadCountDao, HttpServletRequest request, HttpServletResponse response) {
this.projectStatsDao = projectStatsDao;
this.projectDownloadCountDao = projectDownloadCountDao;
this.request = request;
this.response = response;
}
public Stream<LocalDate> getDaysBetween(LocalDate from, LocalDate to) {
@ -60,4 +78,18 @@ public class StatsService {
public <T> String getJsonListAsString(Stream<T> stream) {
return stream.map(count -> "\"" + count + "\"").collect(Collectors.joining(", ", "[", "]"));
}
public static final String COOKIE_NAME = "_stat";
public void addVersionDownloaded(ProjectVersionsTable versionsTable) {
Long userId = currentUser.get().map(UsersTable::getId).orElse(null);
InetAddress address = RequestUtil.getRemoteInetAddress(request);
Optional<String> existingCookie = projectDownloadCountDao.get().getIndividualDownloadCookie(userId, address);
String cookie = existingCookie.orElse(Optional.ofNullable(WebUtils.getCookie(request, COOKIE_NAME)).map(Cookie::getValue).orElse(UUID.randomUUID().toString()));
projectDownloadCountDao.get().addVersionDownload(versionsTable.getProjectId(), versionsTable.getId(), address, cookie, userId);
// TODO maybe secure?
Cookie newCookie = new Cookie(COOKIE_NAME, cookie);
newCookie.setMaxAge(Integer.MAX_VALUE);
response.addCookie(newCookie);
}
}