diff --git a/frontend/locales/en.ts b/frontend/locales/en.ts index 34cbe76cd..6df55599e 100644 --- a/frontend/locales/en.ts +++ b/frontend/locales/en.ts @@ -497,7 +497,7 @@ const msgs: LocaleMessageObject = { notes: { header: 'Notes for', noNotes: 'No notes found', - addNote: 'Add notes', + addNote: 'Add note', notes: 'Notes', placeholder: 'Add a note...', }, diff --git a/frontend/pages/_author/_slug/notes.vue b/frontend/pages/_author/_slug/notes.vue index 983697232..73cd9270d 100644 --- a/frontend/pages/_author/_slug/notes.vue +++ b/frontend/pages/_author/_slug/notes.vue @@ -7,15 +7,21 @@ - + -

{{ $t('notes.notes') }}

- - - +

{{ $t('notes.notes') }}

+ @@ -24,42 +30,49 @@ diff --git a/frontend/types/internal/projects.d.ts b/frontend/types/internal/projects.d.ts index 8f337d0a1..6352f73f7 100644 --- a/frontend/types/internal/projects.d.ts +++ b/frontend/types/internal/projects.d.ts @@ -1,6 +1,6 @@ declare module 'hangar-internal' { import { FlagReason, Joinable, Table } from 'hangar-internal'; - import { Project, User } from 'hangar-api'; + import { Project } from 'hangar-api'; import { ProjectCategory, Visibility } from '~/types/enums'; interface ProjectOwner { @@ -58,8 +58,10 @@ declare module 'hangar-internal' { } interface Note extends Table { + projectId: number; message: string; - user: User; + userId: number; + userName: string | null; } interface ProjectSettingsForm { diff --git a/src/main/java/io/papermc/hangar/controller/internal/ProjectController.java b/src/main/java/io/papermc/hangar/controller/internal/ProjectController.java index 4442af247..d928b2287 100644 --- a/src/main/java/io/papermc/hangar/controller/internal/ProjectController.java +++ b/src/main/java/io/papermc/hangar/controller/internal/ProjectController.java @@ -12,12 +12,14 @@ import io.papermc.hangar.model.internal.api.requests.projects.NewProjectForm; import io.papermc.hangar.model.internal.api.requests.projects.ProjectSettingsForm; import io.papermc.hangar.model.internal.api.responses.PossibleProjectOwner; import io.papermc.hangar.model.internal.projects.HangarProject; +import io.papermc.hangar.model.internal.projects.HangarProjectNote; import io.papermc.hangar.security.annotations.permission.PermissionRequired; import io.papermc.hangar.security.annotations.unlocked.Unlocked; import io.papermc.hangar.security.annotations.visibility.VisibilityRequired; import io.papermc.hangar.security.annotations.visibility.VisibilityRequired.Type; import io.papermc.hangar.service.internal.organizations.OrganizationService; import io.papermc.hangar.service.internal.projects.ProjectFactory; +import io.papermc.hangar.service.internal.projects.ProjectNoteService; import io.papermc.hangar.service.internal.projects.ProjectService; import io.papermc.hangar.service.internal.users.UserService; import org.springframework.beans.factory.annotation.Autowired; @@ -48,13 +50,15 @@ public class ProjectController extends HangarController { private final ProjectService projectService; private final UserService userService; private final OrganizationService organizationService; + private final ProjectNoteService projectNoteService; @Autowired - public ProjectController(ProjectFactory projectFactory, ProjectService projectService, UserService userService, OrganizationService organizationService) { + public ProjectController(ProjectFactory projectFactory, ProjectService projectService, UserService userService, OrganizationService organizationService, ProjectNoteService projectNoteService) { this.projectFactory = projectFactory; this.projectService = projectService; this.userService = userService; this.organizationService = organizationService; + this.projectNoteService = projectNoteService; } @GetMapping("/validateName") @@ -139,8 +143,17 @@ public class ProjectController extends HangarController { userService.toggleWatching(projectId, state); } -// @GetMapping("/project/{author}/{name}/flags") -// public void getProjectFlags(@PathVariable String author, @PathVariable String name) { -// -// } + @PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.MOD_NOTES_AND_FLAGS, args = "{#projectId}") + @GetMapping(path = "/notes/{projectId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getProjectNotes(@PathVariable long projectId) { + return ResponseEntity.ok(projectNoteService.getNotes(projectId)); + } + + @Unlocked + @ResponseStatus(HttpStatus.CREATED) + @PermissionRequired(type = PermissionType.PROJECT, perms = NamedPermission.MOD_NOTES_AND_FLAGS, args = "{#projectId}") + @PostMapping(path = "/notes/{projectId}", consumes = MediaType.APPLICATION_JSON_VALUE) + public void addProjectNote(@PathVariable long projectId, @RequestBody @Valid StringContent content) { + projectNoteService.addNote(projectId, content.getContent()); + } } diff --git a/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java b/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java index 4d9f677ec..eede9ebde 100644 --- a/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java +++ b/src/main/java/io/papermc/hangar/controllerold/ProjectsController.java @@ -1,8 +1,5 @@ package io.papermc.hangar.controllerold; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import io.papermc.hangar.config.hangar.HangarConfig; import io.papermc.hangar.db.customtypes.LoggedActionType; import io.papermc.hangar.db.customtypes.LoggedActionType.ProjectContext; @@ -15,11 +12,9 @@ import io.papermc.hangar.model.common.NamedPermission; import io.papermc.hangar.model.common.Permission; import io.papermc.hangar.model.common.projects.FlagReason; import io.papermc.hangar.model.common.projects.Visibility; -import io.papermc.hangar.modelold.generated.Note; 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.modelold.viewhelpers.UserData; import io.papermc.hangar.securityold.annotations.GlobalPermission; import io.papermc.hangar.securityold.annotations.ProjectPermission; import io.papermc.hangar.securityold.annotations.UserLock; @@ -36,7 +31,6 @@ 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.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -49,8 +43,6 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.List; import java.util.function.Supplier; import java.util.regex.Pattern; @@ -212,44 +204,6 @@ public class ProjectsController extends HangarController { return Routes.PROJECTS_SHOW.getRedirect(author, slug); } - @GlobalPermission(NamedPermission.MOD_NOTES_AND_FLAGS) - @Secured("ROLE_USER") - @GetMapping("/{author}/{slug}/notes") - public ModelAndView showNotes(@PathVariable String author, @PathVariable String slug) { - ModelAndView mv = new ModelAndView("projects/admin/notes"); - ProjectsTable project = projectsTable.get(); - - List notes = new ArrayList<>(); - ArrayNode messages = (ArrayNode) project.getNotes().getJson().get("messages"); - if (messages != null) { - for (JsonNode message : messages) { - Note note = new Note().message(message.get("message").asText()); - notes.add(note); - UserData user = userService.getUserData(message.get("user").asLong()); - note.user(user.getUser().getName()); - } - } - - mv.addObject("project", project); - mv.addObject("notes", notes); - return fillModel(mv); - } - - @GlobalPermission(NamedPermission.MOD_NOTES_AND_FLAGS) - @Secured("ROLE_USER") - @PostMapping("/{author}/{slug}/notes/addmessage") - public ResponseEntity addMessage(@PathVariable String author, @PathVariable String slug, @RequestParam String content) { - ProjectsTable project = projectsTable.get(); - ArrayNode messages = project.getNotes().getJson().withArray("messages"); - ObjectNode note = messages.addObject(); - note.put("message", content); - note.put("user", getCurrentUser().getId()); - - String json = project.getNotes().getJson().toString(); - projectDao.get().updateNotes(json, project.getId()); - return ResponseEntity.ok("Review"); - } - @GlobalPermission(NamedPermission.REVIEWER) @UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}") @Secured("ROLE_USER") diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/HangarFlagsDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectFlagsDAO.java similarity index 96% rename from src/main/java/io/papermc/hangar/db/dao/internal/HangarFlagsDAO.java rename to src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectFlagsDAO.java index af3c94c9d..0462768ce 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/HangarFlagsDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectFlagsDAO.java @@ -1,5 +1,7 @@ -package io.papermc.hangar.db.dao.internal; +package io.papermc.hangar.db.dao.internal.projects; +import io.papermc.hangar.model.db.projects.ProjectFlagTable; +import io.papermc.hangar.model.internal.projects.HangarProjectFlag; import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; import org.jdbi.v3.sqlobject.customizer.BindBean; import org.jdbi.v3.sqlobject.customizer.Timestamped; @@ -11,11 +13,8 @@ import org.springframework.stereotype.Repository; import java.time.OffsetDateTime; import java.util.List; -import io.papermc.hangar.model.db.projects.ProjectFlagTable; -import io.papermc.hangar.model.internal.projects.HangarProjectFlag; - @Repository -public interface HangarFlagsDAO { +public interface HangarProjectFlagsDAO { @Timestamped @GetGeneratedKeys diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectNotesDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectNotesDAO.java new file mode 100644 index 000000000..da7e2e86a --- /dev/null +++ b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectNotesDAO.java @@ -0,0 +1,19 @@ +package io.papermc.hangar.db.dao.internal.projects; + +import io.papermc.hangar.model.internal.projects.HangarProjectNote; +import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; +import org.jdbi.v3.sqlobject.statement.SqlQuery; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RegisterConstructorMapper(HangarProjectNote.class) +public interface HangarProjectNotesDAO { + + @SqlQuery("SELECT pn.*, u.name" + + " FROM project_notes pn" + + " LEFT JOIN users u ON pn.user_id = u.id" + + " WHERE pn.project_id = :projectId") + List getProjectNotes(long projectId); +} diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectPagesDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java similarity index 96% rename from src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectPagesDAO.java rename to src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java index 2c4ef6f1d..b97b574e5 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectPagesDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectPagesDAO.java @@ -1,4 +1,4 @@ -package io.papermc.hangar.db.dao.internal; +package io.papermc.hangar.db.dao.internal.projects; import io.papermc.hangar.model.internal.projects.HangarViewProjectPage; import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectsDAO.java similarity index 91% rename from src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java rename to src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectsDAO.java index 3c942b671..84e6ebab7 100644 --- a/src/main/java/io/papermc/hangar/db/dao/internal/HangarProjectsDAO.java +++ b/src/main/java/io/papermc/hangar/db/dao/internal/projects/HangarProjectsDAO.java @@ -1,4 +1,4 @@ -package io.papermc.hangar.db.dao.internal; +package io.papermc.hangar.db.dao.internal.projects; import io.papermc.hangar.db.mappers.PromotedVersionMapper; import io.papermc.hangar.db.mappers.factories.JoinableMemberFactory; @@ -74,16 +74,17 @@ public interface HangarProjectsDAO { List> getProjectMembers(long projectId, Long userId, @Define boolean canSeePending); @RegisterConstructorMapper(HangarProjectInfo.class) - @SqlQuery("SELECT count(pv.*) public_versions," + - " count(pf.*) flag_count," + - " count(ps.*) star_count," + - " count(pw.*) watcher_count," + - " coalesce(jsonb_array_length(p.notes->'messages'), 0) note_count" + + @SqlQuery("SELECT count(DISTINCT pv.id) public_versions," + + " count(DISTINCT pf.id) flag_count," + + " count(DISTINCT ps.user_id) star_count," + + " count(DISTINCT pw.user_id) watcher_count," + + " count(DISTINCT pn.id) note_count" + " FROM projects p" + " LEFT JOIN project_versions pv ON p.id = pv.project_id AND pv.visibility = 0" + " LEFT JOIN project_stars ps ON p.id = ps.project_id" + " LEFT JOIN project_watchers pw ON p.id = pw.project_id" + " LEFT JOIN project_flags pf ON p.id = pf.project_id" + + " LEFT JOIN project_notes pn ON p.id = pn.project_id" + " WHERE p.id = :projectId" + " GROUP BY p.id") HangarProjectInfo getHangarProjectInfo(long projectId); diff --git a/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectNotesDAO.java b/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectNotesDAO.java new file mode 100644 index 000000000..ea06b0c5a --- /dev/null +++ b/src/main/java/io/papermc/hangar/db/dao/internal/table/projects/ProjectNotesDAO.java @@ -0,0 +1,17 @@ +package io.papermc.hangar.db.dao.internal.table.projects; + +import io.papermc.hangar.model.db.projects.ProjectNoteTable; +import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; +import org.jdbi.v3.sqlobject.customizer.BindBean; +import org.jdbi.v3.sqlobject.customizer.Timestamped; +import org.jdbi.v3.sqlobject.statement.SqlUpdate; +import org.springframework.stereotype.Repository; + +@Repository +@RegisterConstructorMapper(ProjectNoteTable.class) +public interface ProjectNotesDAO { + + @Timestamped + @SqlUpdate("INSERT INTO project_notes (created_at, project_id, message, user_id) VALUES (:now, :projectId, :message, :userId)") + void insert(@BindBean ProjectNoteTable projectNoteTable); +} diff --git a/src/main/java/io/papermc/hangar/model/db/projects/ProjectNoteTable.java b/src/main/java/io/papermc/hangar/model/db/projects/ProjectNoteTable.java new file mode 100644 index 000000000..b8175fa3d --- /dev/null +++ b/src/main/java/io/papermc/hangar/model/db/projects/ProjectNoteTable.java @@ -0,0 +1,48 @@ +package io.papermc.hangar.model.db.projects; + +import io.papermc.hangar.model.db.Table; +import org.jdbi.v3.core.mapper.reflect.JdbiConstructor; + +import java.time.OffsetDateTime; + +public class ProjectNoteTable extends Table { + + private final long projectId; + private final String message; + private final Long userId; + + @JdbiConstructor + public ProjectNoteTable(OffsetDateTime createdAt, long id, long projectId, String message, Long userId) { + super(createdAt, id); + this.projectId = projectId; + this.message = message; + this.userId = userId; + } + + public ProjectNoteTable(long projectId, String message, Long userId) { + this.projectId = projectId; + this.message = message; + this.userId = userId; + } + + public long getProjectId() { + return projectId; + } + + public String getMessage() { + return message; + } + + public Long getUserId() { + return userId; + } + + @Override + public String toString() { + return "ProjectNoteTable{" + + "projectId=" + projectId + + ", message='" + message + '\'' + + ", userId=" + userId + + "} " + super.toString(); + } +} diff --git a/src/main/java/io/papermc/hangar/model/db/projects/ProjectTable.java b/src/main/java/io/papermc/hangar/model/db/projects/ProjectTable.java index 9c6096566..67a2667eb 100644 --- a/src/main/java/io/papermc/hangar/model/db/projects/ProjectTable.java +++ b/src/main/java/io/papermc/hangar/model/db/projects/ProjectTable.java @@ -1,6 +1,5 @@ package io.papermc.hangar.model.db.projects; -import io.papermc.hangar.db.customtypes.JSONB; import io.papermc.hangar.model.ModelVisible; import io.papermc.hangar.model.Visitable; import io.papermc.hangar.model.common.projects.Category; @@ -26,7 +25,6 @@ public class ProjectTable extends Table implements Visitable, ModelVisible, Proj private Category category; private String description; private Visibility visibility; - private JSONB notes; private Collection keywords; private String homepage; private String issues; @@ -63,7 +61,6 @@ public class ProjectTable extends Table implements Visitable, ModelVisible, Proj this.category = other.category; this.description = other.description; this.visibility = other.visibility; - this.notes = other.notes; this.keywords = other.keywords; this.homepage = other.homepage; this.issues = other.issues; @@ -75,7 +72,7 @@ public class ProjectTable extends Table implements Visitable, ModelVisible, Proj } @JdbiConstructor - public ProjectTable(OffsetDateTime createdAt, long id, String name, String slug, String ownerName, long ownerId, long topicId, long postId, @EnumByOrdinal Category category, String description, @EnumByOrdinal Visibility visibility, JSONB notes, Collection keywords, String homepage, String issues, String source, String support, String licenseName, String licenseUrl, boolean forumSync) { + public ProjectTable(OffsetDateTime createdAt, long id, String name, String slug, String ownerName, long ownerId, long topicId, long postId, @EnumByOrdinal Category category, String description, @EnumByOrdinal Visibility visibility, Collection keywords, String homepage, String issues, String source, String support, String licenseName, String licenseUrl, boolean forumSync) { super(createdAt, id); this.name = name; this.slug = slug; @@ -86,7 +83,6 @@ public class ProjectTable extends Table implements Visitable, ModelVisible, Proj this.category = category; this.description = description; this.visibility = visibility; - this.notes = notes; this.keywords = keywords; this.homepage = homepage; this.issues = issues; @@ -168,14 +164,6 @@ public class ProjectTable extends Table implements Visitable, ModelVisible, Proj this.visibility = visibility; } - public JSONB getNotes() { - return notes; - } - - public void setNotes(JSONB notes) { - this.notes = notes; - } - public Collection getKeywords() { return keywords; } @@ -262,7 +250,6 @@ public class ProjectTable extends Table implements Visitable, ModelVisible, Proj ", category=" + category + ", description='" + description + '\'' + ", visibility=" + visibility + - ", notes=" + notes + ", keywords=" + keywords + ", homepage='" + homepage + '\'' + ", issues='" + issues + '\'' + diff --git a/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectNote.java b/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectNote.java new file mode 100644 index 000000000..1e28f582c --- /dev/null +++ b/src/main/java/io/papermc/hangar/model/internal/projects/HangarProjectNote.java @@ -0,0 +1,29 @@ +package io.papermc.hangar.model.internal.projects; + +import io.papermc.hangar.model.db.projects.ProjectNoteTable; +import org.jdbi.v3.core.mapper.reflect.JdbiConstructor; +import org.jetbrains.annotations.Nullable; + +import java.time.OffsetDateTime; + +public class HangarProjectNote extends ProjectNoteTable { + + private final String userName; + + @JdbiConstructor + public HangarProjectNote(OffsetDateTime createdAt, long id, long projectId, String message, Long userId, @Nullable String name) { + super(createdAt, id, projectId, message, userId); + this.userName = name; + } + + public String getUserName() { + return userName; + } + + @Override + public String toString() { + return "HangarProjectNote{" + + "userName='" + userName + '\'' + + "} " + super.toString(); + } +} diff --git a/src/main/java/io/papermc/hangar/modelold/generated/Note.java b/src/main/java/io/papermc/hangar/modelold/generated/Note.java deleted file mode 100644 index 2694c799a..000000000 --- a/src/main/java/io/papermc/hangar/modelold/generated/Note.java +++ /dev/null @@ -1,109 +0,0 @@ -package io.papermc.hangar.modelold.generated; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotNull; -import java.time.Instant; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Objects; - -@Validated -public class Note { - @JsonProperty("message") - private String message = null; - - @JsonProperty("user") - private String user = null; - - @JsonProperty("time") - private Long time = System.currentTimeMillis(); - - /** - * Get message - * - * @return message - **/ - @ApiModelProperty(required = true, value = "") - @NotNull - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public Note message(String message) { - this.message = message; - return this; - } - - - /** - * Get user - * - * @return user - **/ - @ApiModelProperty(required = true, value = "") - @NotNull - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - public Note user(String user) { - this.user = user; - return this; - } - - - /** - * - * Get time - * - * @return time - **/ - @ApiModelProperty(required = true, value = "") - @NotNull - public Long getTime() { - return time; - } - - public void setTime(Long time) { - this.time = time; - } - - public Note slug(Long time) { - this.time = time; - return this; - } - - public OffsetDateTime toDateTime() { - return OffsetDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Note note = (Note) o; - return Objects.equals(this.message, note.message) && - Objects.equals(this.user, note.user) && - Objects.equals(this.time, note.time); - } - - @Override - public int hashCode() { - return Objects.hash(message, user, time); - } -} diff --git a/src/main/java/io/papermc/hangar/service/internal/admin/FlagService.java b/src/main/java/io/papermc/hangar/service/internal/admin/FlagService.java index 053a24c6e..3f9f85a44 100644 --- a/src/main/java/io/papermc/hangar/service/internal/admin/FlagService.java +++ b/src/main/java/io/papermc/hangar/service/internal/admin/FlagService.java @@ -1,7 +1,7 @@ package io.papermc.hangar.service.internal.admin; import io.papermc.hangar.db.dao.HangarDao; -import io.papermc.hangar.db.dao.internal.HangarFlagsDAO; +import io.papermc.hangar.db.dao.internal.projects.HangarProjectFlagsDAO; import io.papermc.hangar.model.common.projects.FlagReason; import io.papermc.hangar.model.db.projects.ProjectFlagTable; import io.papermc.hangar.model.internal.projects.HangarProjectFlag; @@ -14,28 +14,28 @@ import java.util.List; @Service public class FlagService extends HangarService { - private final HangarFlagsDAO flagsDAO; + private final HangarProjectFlagsDAO hangarProjectFlagsDAO; - public FlagService(HangarDao flagsDAO) { - this.flagsDAO = flagsDAO.get(); + public FlagService(HangarDao hangarProjectFlagsDAO) { + this.hangarProjectFlagsDAO = hangarProjectFlagsDAO.get(); } public void createFlag(long projectId, FlagReason reason, String comment) { // TODO idk, we prolly need more checking here, plus notification? logs? - flagsDAO.insert(new ProjectFlagTable( projectId, getHangarPrincipal().getId(), reason, comment)); + hangarProjectFlagsDAO.insert(new ProjectFlagTable( projectId, getHangarPrincipal().getId(), reason, comment)); } public ProjectFlagTable markAsResolved(long flagId, boolean resolved) { Long resolvedBy = resolved ? getHangarPrincipal().getId() : null; OffsetDateTime resolvedAt = resolved ? OffsetDateTime.now() : null; - return flagsDAO.markAsResolved(flagId, resolved, resolvedBy, resolvedAt); + return hangarProjectFlagsDAO.markAsResolved(flagId, resolved, resolvedBy, resolvedAt); } public List getFlags(String author, String slug) { - return flagsDAO.getFlags(author, slug); + return hangarProjectFlagsDAO.getFlags(author, slug); } public List getFlags() { - return flagsDAO.getFlags(); + return hangarProjectFlagsDAO.getFlags(); } } diff --git a/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java b/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java index db8eedf5c..3a4657d14 100644 --- a/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java +++ b/src/main/java/io/papermc/hangar/service/internal/projects/ChannelService.java @@ -1,7 +1,7 @@ package io.papermc.hangar.service.internal.projects; import io.papermc.hangar.db.dao.HangarDao; -import io.papermc.hangar.db.dao.internal.HangarProjectsDAO; +import io.papermc.hangar.db.dao.internal.projects.HangarProjectsDAO; import io.papermc.hangar.db.dao.internal.table.projects.ProjectChannelsDAO; import io.papermc.hangar.exceptions.HangarApiException; import io.papermc.hangar.model.common.Color; diff --git a/src/main/java/io/papermc/hangar/service/internal/projects/ProjectNoteService.java b/src/main/java/io/papermc/hangar/service/internal/projects/ProjectNoteService.java new file mode 100644 index 000000000..9b4c0875a --- /dev/null +++ b/src/main/java/io/papermc/hangar/service/internal/projects/ProjectNoteService.java @@ -0,0 +1,33 @@ +package io.papermc.hangar.service.internal.projects; + +import io.papermc.hangar.db.dao.HangarDao; +import io.papermc.hangar.db.dao.internal.projects.HangarProjectNotesDAO; +import io.papermc.hangar.db.dao.internal.table.projects.ProjectNotesDAO; +import io.papermc.hangar.model.db.projects.ProjectNoteTable; +import io.papermc.hangar.model.internal.projects.HangarProjectNote; +import io.papermc.hangar.service.HangarService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ProjectNoteService extends HangarService { + + private final ProjectNotesDAO projectNotesDAO; + private final HangarProjectNotesDAO hangarProjectNotesDAO; + + @Autowired + public ProjectNoteService(HangarDao projectNotesDAO, HangarDao hangarProjectNotesDAO) { + this.projectNotesDAO = projectNotesDAO.get(); + this.hangarProjectNotesDAO = hangarProjectNotesDAO.get(); + } + + public List getNotes(long projectId) { + return hangarProjectNotesDAO.getProjectNotes(projectId); + } + + public void addNote(long projectId, String msg) { + projectNotesDAO.insert(new ProjectNoteTable(projectId, msg, getHangarPrincipal().getId())); + } +} 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 3fec9e213..9baf6e59b 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 @@ -3,7 +3,7 @@ package io.papermc.hangar.service.internal.projects; import io.papermc.hangar.db.customtypes.LoggedActionType; import io.papermc.hangar.db.customtypes.LoggedActionType.ProjectPageContext; import io.papermc.hangar.db.dao.HangarDao; -import io.papermc.hangar.db.dao.internal.HangarProjectPagesDAO; +import io.papermc.hangar.db.dao.internal.projects.HangarProjectPagesDAO; import io.papermc.hangar.db.dao.internal.table.projects.ProjectPagesDAO; import io.papermc.hangar.exceptions.HangarApiException; import io.papermc.hangar.model.db.projects.ProjectHomePageTable; diff --git a/src/main/java/io/papermc/hangar/service/internal/projects/ProjectService.java b/src/main/java/io/papermc/hangar/service/internal/projects/ProjectService.java index bf7458772..d84fe6b6d 100644 --- a/src/main/java/io/papermc/hangar/service/internal/projects/ProjectService.java +++ b/src/main/java/io/papermc/hangar/service/internal/projects/ProjectService.java @@ -3,8 +3,8 @@ package io.papermc.hangar.service.internal.projects; import io.papermc.hangar.db.customtypes.LoggedActionType; import io.papermc.hangar.db.customtypes.LoggedActionType.ProjectContext; import io.papermc.hangar.db.dao.HangarDao; -import io.papermc.hangar.db.dao.internal.HangarProjectsDAO; import io.papermc.hangar.db.dao.internal.HangarUsersDAO; +import io.papermc.hangar.db.dao.internal.projects.HangarProjectsDAO; import io.papermc.hangar.db.dao.internal.table.UserDAO; import io.papermc.hangar.db.dao.internal.table.projects.ProjectsDAO; import io.papermc.hangar.exceptions.HangarApiException; diff --git a/src/main/resources/db/migration/V1.1.0__addProjectNotesTable.sql b/src/main/resources/db/migration/V1.1.0__addProjectNotesTable.sql new file mode 100644 index 000000000..0b6baedd7 --- /dev/null +++ b/src/main/resources/db/migration/V1.1.0__addProjectNotesTable.sql @@ -0,0 +1,27 @@ +ALTER TABLE project_visibility_changes DROP CONSTRAINT project_visibility_changes_created_by_fkey; +ALTER TABLE project_visibility_changes ADD CONSTRAINT project_visibility_changes_created_by_fkey FOREIGN KEY (created_by) REFERENCES users ON DELETE SET NULL; + +ALTER TABLE project_visibility_changes DROP CONSTRAINT project_visibility_changes_resolved_by_fkey; +ALTER TABLE project_visibility_changes ADD CONSTRAINT project_visibility_changes_resolved_by_fkey FOREIGN KEY (resolved_by) REFERENCES users ON DELETE SET NULL; + +ALTER TABLE project_version_visibility_changes DROP CONSTRAINT project_version_visibility_changes_created_by_fkey; +ALTER TABLE project_version_visibility_changes ADD CONSTRAINT project_version_visibility_changes_created_by_fkey FOREIGN KEY (created_by) REFERENCES users ON DELETE SET NULL; + +ALTER TABLE project_version_visibility_changes DROP CONSTRAINT project_version_visibility_changes_resolved_by_fkey; +ALTER TABLE project_version_visibility_changes ADD CONSTRAINT project_version_visibility_changes_resolved_by_fkey FOREIGN KEY (resolved_by) REFERENCES users ON DELETE SET NULL; + +CREATE TABLE project_notes +( + id bigserial NOT NULL + CONSTRAINT notes_pkey PRIMARY KEY, + created_at timestamp with time zone NOT NULL, + project_id bigint NOT NULL + CONSTRAINT notes_project_id_fkey + REFERENCES projects ON DELETE CASCADE, + message text NOT NULL, + user_id bigint + CONSTRAINT notes_user_id + REFERENCES users ON DELETE SET NULL +); + +ALTER TABLE projects DROP COLUMN notes; diff --git a/src/main/resources/templates/projects/admin/notes.ftlh b/src/main/resources/templates/projects/admin/notes.ftlh deleted file mode 100644 index e9c3b80a7..000000000 --- a/src/main/resources/templates/projects/admin/notes.ftlh +++ /dev/null @@ -1,59 +0,0 @@ -<#import "/spring.ftl" as spring /> -<#import "*/utils/hangar.ftlh" as hangar /> -<#import "*/layout/base.ftlh" as base /> - -<#assign scriptsVar> - - - - -<#assign message><@spring.message "notes" /> -<@base.base title="${message}" additionalScripts=scriptsVar> -
-
-
-

<@spring.message "notes" /> ${project.ownerName}/${project.slug}

-
-
-
-
-
-
- -
<@spring.message "notes.addmessage" />
-
-
-
-
-
-

<@spring.message "notes" />

-
- <#if !notes?has_content> -
- -
- - -
- - - <#list notes as note> - - - - - - - -
${utils.prettifyDateTime(note.toDateTime())}${note.getUser()!"Unknown"}<#outputformat "plainText">${markdownService.render(note.getMessage())}
-
-
-