mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-02-23 15:12:52 +08:00
parent
8b53dc18a0
commit
0ff4ff0687
@ -6,7 +6,30 @@ create type role_category as enum ('global', 'project', 'organization');
|
||||
|
||||
alter type role_category owner to hangar;
|
||||
|
||||
create type logged_action_type as enum ('project_visibility_change', 'project_renamed', 'project_flagged', 'project_settings_changed', 'project_member_removed', 'project_icon_changed', 'project_page_edited', 'project_flag_resolved', 'version_deleted', 'version_uploaded', 'version_description_changed', 'version_review_state_changed', 'user_tagline_changed');
|
||||
create type logged_action_type as enum (
|
||||
'project_visibility_change',
|
||||
'project_renamed',
|
||||
'project_flagged',
|
||||
'project_settings_changed',
|
||||
'project_member_removed',
|
||||
'project_icon_changed',
|
||||
'project_flag_resolved',
|
||||
'project_page_created',
|
||||
'project_page_deleted',
|
||||
'project_page_edited',
|
||||
'version_deleted',
|
||||
'version_uploaded',
|
||||
'version_description_changed',
|
||||
'version_review_state_changed',
|
||||
'user_tagline_changed',
|
||||
'user_locked',
|
||||
'user_unlocked',
|
||||
'user_apikey_create',
|
||||
'user_apikey_delete',
|
||||
'org_members_added',
|
||||
'org_member_removed',
|
||||
'org_member_roles_updated'
|
||||
);
|
||||
|
||||
alter type logged_action_type owner to hangar;
|
||||
|
||||
|
@ -6,7 +6,30 @@ create type role_category as enum ('global', 'project', 'organization');
|
||||
|
||||
alter type role_category owner to hangar;
|
||||
|
||||
create type logged_action_type as enum ('project_visibility_change', 'project_renamed', 'project_flagged', 'project_settings_changed', 'project_member_removed', 'project_icon_changed', 'project_page_edited', 'project_flag_resolved', 'version_deleted', 'version_uploaded', 'version_description_changed', 'version_review_state_changed', 'user_tagline_changed');
|
||||
create type logged_action_type as enum (
|
||||
'project_visibility_change',
|
||||
'project_renamed',
|
||||
'project_flagged',
|
||||
'project_settings_changed',
|
||||
'project_member_removed',
|
||||
'project_icon_changed',
|
||||
'project_flag_resolved',
|
||||
'project_page_created',
|
||||
'project_page_deleted',
|
||||
'project_page_edited',
|
||||
'version_deleted',
|
||||
'version_uploaded',
|
||||
'version_description_changed',
|
||||
'version_review_state_changed',
|
||||
'user_tagline_changed',
|
||||
'user_locked',
|
||||
'user_unlocked',
|
||||
'user_apikey_create',
|
||||
'user_apikey_delete',
|
||||
'org_members_added',
|
||||
'org_member_removed',
|
||||
'org_member_roles_updated'
|
||||
);
|
||||
|
||||
alter type logged_action_type owner to hangar;
|
||||
|
||||
|
@ -2,6 +2,8 @@ package io.papermc.hangar.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import io.papermc.hangar.config.hangar.HangarConfig;
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType;
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType.OrganizationContext;
|
||||
import io.papermc.hangar.db.model.OrganizationsTable;
|
||||
import io.papermc.hangar.db.model.UserOrganizationRolesTable;
|
||||
import io.papermc.hangar.db.model.UsersTable;
|
||||
@ -16,6 +18,7 @@ import io.papermc.hangar.service.NotificationService;
|
||||
import io.papermc.hangar.service.OrgFactory;
|
||||
import io.papermc.hangar.service.OrgService;
|
||||
import io.papermc.hangar.service.RoleService;
|
||||
import io.papermc.hangar.service.UserActionLogService;
|
||||
import io.papermc.hangar.service.UserService;
|
||||
import io.papermc.hangar.util.AlertUtil;
|
||||
import io.papermc.hangar.util.AlertUtil.AlertType;
|
||||
@ -36,7 +39,9 @@ import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -53,18 +58,23 @@ public class OrgController extends HangarController {
|
||||
private final OrgFactory orgFactory;
|
||||
private final UserService userService;
|
||||
private final RoleService roleService;
|
||||
private final UserActionLogService userActionLogService;
|
||||
private final NotificationService notificationService;
|
||||
private final HangarConfig hangarConfig;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public OrgController(AuthenticationService authenticationService, OrgService orgService, OrgFactory orgFactory, UserService userService, RoleService roleService, NotificationService notificationService, HangarConfig hangarConfig) {
|
||||
public OrgController(AuthenticationService authenticationService, OrgService orgService, OrgFactory orgFactory, UserService userService, RoleService roleService, UserActionLogService userActionLogService, NotificationService notificationService, HangarConfig hangarConfig, HttpServletRequest request) {
|
||||
this.authenticationService = authenticationService;
|
||||
this.orgService = orgService;
|
||||
this.orgFactory = orgFactory;
|
||||
this.userService = userService;
|
||||
this.roleService = roleService;
|
||||
this.userActionLogService = userActionLogService;
|
||||
this.notificationService = notificationService;
|
||||
this.hangarConfig = hangarConfig;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Secured("ROLE_USER")
|
||||
@ -107,10 +117,11 @@ public class OrgController extends HangarController {
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping(value = "/organizations/new", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView create(@RequestParam String name, @RequestParam(required = false) List<Long> users, @RequestParam(required = false) List<Role> roles, RedirectAttributes attributes) {
|
||||
UsersTable currUser = getCurrentUser();
|
||||
if (orgService.getUserOwnedOrgs(getCurrentUser().getId()).size() >= hangarConfig.org.getCreateLimit()) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "at create limit");
|
||||
}
|
||||
if (currentUser.get().get().isLocked()) throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||
if (currUser.isLocked()) throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||
if (!hangarConfig.org.isEnabled()) {
|
||||
AlertUtil.showAlert(attributes, AlertType.ERROR, "error.org.disabled");
|
||||
return Routes.ORG_SHOW_CREATOR.getRedirect();
|
||||
@ -119,7 +130,7 @@ public class OrgController extends HangarController {
|
||||
|
||||
OrganizationsTable org;
|
||||
try {
|
||||
org = orgFactory.createOrganization(name, currentUser.get().get().getId(), userRoles);
|
||||
org = orgFactory.createOrganization(name, currUser.getId(), userRoles);
|
||||
} catch (HangarException e) {
|
||||
AlertUtil.showAlert(attributes, AlertType.ERROR, e.getMessageKey(), e.getArgs());
|
||||
return Routes.ORG_SHOW_CREATOR.getRedirect();
|
||||
@ -134,7 +145,7 @@ public class OrgController extends HangarController {
|
||||
public ModelAndView updateAvatar(@PathVariable String organization) {
|
||||
try {
|
||||
URI uri = authenticationService.changeAvatarUri(getCurrentUser().getName(), organization);
|
||||
return new ModelAndView("redirect:" + uri.toString());
|
||||
return Routes.getRedirectToUrl(uri.toString());
|
||||
} catch (JsonProcessingException e) {
|
||||
ModelAndView mav = Routes.USERS_SHOW_PROJECTS.getRedirect(organization);
|
||||
AlertUtil.showAlert(mav, AlertType.ERROR, "organization.avatarFailed");
|
||||
@ -152,16 +163,26 @@ public class OrgController extends HangarController {
|
||||
@RequestParam(required = false) List<Role> roleUps) {
|
||||
OrganizationsTable org = orgService.getOrganization(organization); // Won't be null because the PreAuth check should catch that
|
||||
Map<Long, Role> userRoles = zip(users, roles);
|
||||
List<String> newState = new ArrayList<>();
|
||||
userRoles.forEach((memberId, role) -> {
|
||||
UsersTable memberUser = userService.getUsersTable(memberId);
|
||||
newState.add(memberUser.getName() + ": " + role.getTitle());
|
||||
roleService.addOrgMemberRole(org.getId(), memberId, role, false);
|
||||
notificationService.sendNotification(memberId, org.getId(), NotificationType.ORGANIZATION_INVITE, new String[]{"notification.organization.invite", role.getTitle(), org.getName()});
|
||||
});
|
||||
if (!newState.isEmpty()) {
|
||||
userActionLogService.organization(request, LoggedActionType.ORG_MEMBERS_ADDED.with(OrganizationContext.of(org.getId())), String.join("<br>", newState), "");
|
||||
newState.clear();
|
||||
}
|
||||
|
||||
Map<UsersTable, Role> userRoleUpdates = zip(userService.getUsers(userUps), roleUps);
|
||||
userRoleUpdates.forEach((user, role) -> {
|
||||
newState.add(user.getName() + ": " + role.getTitle());
|
||||
roleService.updateRole(org, user.getId(), role);
|
||||
});
|
||||
// TODO user action logging for orgs
|
||||
if (!newState.isEmpty()) {
|
||||
userActionLogService.organization(request, LoggedActionType.ORG_MEMBER_ROLES_UPDATED.with(OrganizationContext.of(org.getId())), String.join("<br>", newState), "");
|
||||
}
|
||||
return Routes.USERS_SHOW_PROJECTS.getRedirect(organization);
|
||||
}
|
||||
|
||||
@ -172,7 +193,7 @@ public class OrgController extends HangarController {
|
||||
OrganizationsTable org = orgService.getOrganization(organization);
|
||||
UserData user = userService.getUserData(username);
|
||||
if (roleService.removeMember(org, user.getUser().getId()) != 0) {
|
||||
// TODO org logging
|
||||
userActionLogService.organization(request, LoggedActionType.ORG_MEMBER_REMOVED.with(OrganizationContext.of(org.getId())), "Removed " + user.getUser().getName(), "");
|
||||
}
|
||||
return Routes.USERS_SHOW_PROJECTS.getRedirect(organization);
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ public class PagesController extends HangarController {
|
||||
if (!projectPage.getIsDeletable()) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot delete this page");
|
||||
}
|
||||
userActionLogService.projectPage(request, LoggedActionType.PROJECT_PAGE_DELETED.with(ProjectPageContext.of(projectPage.getProjectId(), projectPage.getId())), "", projectPage.getContents());
|
||||
projectPageDao.get().delete(projectPage);
|
||||
return Routes.PROJECTS_SHOW.getRedirect(author, slug);
|
||||
}
|
||||
@ -136,14 +137,15 @@ public class PagesController extends HangarController {
|
||||
parentIdLong = null;
|
||||
}
|
||||
projectPage = pagesFactory.createPage(pageContent, newPageName, pageName, parentIdLong, project.getId());
|
||||
userActionLogService.projectPage(request, LoggedActionType.PROJECT_PAGE_CREATED.with(ProjectPageContext.of(project.getId(), projectPage.getId())), pageContent, "");
|
||||
toReturn = new ResponseEntity<>(HttpStatus.OK); // redirect handled by pageEdit.js
|
||||
} else {
|
||||
oldContents = projectPage.getContents();
|
||||
projectPage.setContents(pageContent);
|
||||
projectPageDao.get().update(projectPage);
|
||||
userActionLogService.projectPage(request, LoggedActionType.PROJECT_PAGE_EDITED.with(ProjectPageContext.of(project.getId(), projectPage.getId())), pageContent, oldContents);
|
||||
toReturn = Routes.PAGES_SHOW.getRedirect(author, slug, StringUtils.slugify(pageName));
|
||||
}
|
||||
userActionLogService.projectPage(request, LoggedActionType.PROJECT_PAGE_EDITED.with(ProjectPageContext.of(project.getId(), projectPage.getId())), pageContent, oldContents);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
@ -650,8 +650,9 @@ public class VersionsController extends HangarController {
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping(value = "/{author}/{slug}/versions/{version}/restore", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView restore(@PathVariable String author, @PathVariable String slug, @PathVariable String version, @RequestParam String comment) {
|
||||
versionService.changeVisibility(versionData.get(), Visibility.PUBLIC, comment, getCurrentUser().getId());
|
||||
userActionLogService.version(request, LoggedActionType.VERSION_DELETED.with(VersionContext.of(versionData.get().getP().getProject().getId(), versionData.get().getV().getId())), "Restore: " + comment, "");
|
||||
VersionData vData = versionData.get();
|
||||
versionService.changeVisibility(vData, Visibility.PUBLIC, comment, getCurrentUser().getId());
|
||||
userActionLogService.version(request, LoggedActionType.VERSION_DELETED.with(VersionContext.of(vData.getP().getProject().getId(), vData.getV().getId())), "Restore: " + comment, "");
|
||||
return Routes.VERSIONS_SHOW.getRedirect(author, slug, version);
|
||||
}
|
||||
|
||||
@ -660,11 +661,12 @@ public class VersionsController extends HangarController {
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping(value = "/{author}/{slug}/versions/{version}/save", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
public ModelAndView saveDescription(@PathVariable String author, @PathVariable String slug, @PathVariable String version, @RequestParam String content) {
|
||||
String oldDesc = versionData.get().getV().getDescription();
|
||||
VersionData vData = versionData.get();
|
||||
String oldDesc = vData.getV().getDescription();
|
||||
String newDesc = content.trim();
|
||||
versionData.get().getV().setDescription(newDesc);
|
||||
versionService.update(versionData.get().getV());
|
||||
userActionLogService.version(request, LoggedActionType.VERSION_DESCRIPTION_CHANGED.with(VersionContext.of(versionData.get().getP().getProject().getId(), versionData.get().getV().getId())), newDesc, oldDesc);
|
||||
vData.getV().setDescription(newDesc);
|
||||
versionService.update(vData.getV());
|
||||
userActionLogService.version(request, LoggedActionType.VERSION_DESCRIPTION_CHANGED.with(VersionContext.of(vData.getP().getProject().getId(), vData.getV().getId())), newDesc, oldDesc);
|
||||
return Routes.VERSIONS_SHOW.getRedirect(author, slug, version);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
package io.papermc.hangar.controller.api;
|
||||
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType;
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType.UserContext;
|
||||
import io.papermc.hangar.model.ApiAuthInfo;
|
||||
import io.papermc.hangar.model.NamedPermission;
|
||||
import io.papermc.hangar.model.Permission;
|
||||
import io.papermc.hangar.model.generated.ApiKeyRequest;
|
||||
import io.papermc.hangar.model.generated.ApiKeyResponse;
|
||||
import io.papermc.hangar.service.ApiKeyService;
|
||||
import io.papermc.hangar.service.UserActionLogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -13,20 +16,26 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
public class KeysApiController implements KeysApi {
|
||||
|
||||
private final ApiKeyService apiKeyService;
|
||||
private final UserActionLogService userActionLogService;
|
||||
|
||||
private final ApiAuthInfo apiAuthInfo;
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public KeysApiController(ApiKeyService apiKeyService, ApiAuthInfo apiAuthInfo) {
|
||||
public KeysApiController(ApiKeyService apiKeyService, UserActionLogService userActionLogService, ApiAuthInfo apiAuthInfo, HttpServletRequest request) {
|
||||
this.apiKeyService = apiKeyService;
|
||||
this.userActionLogService = userActionLogService;
|
||||
this.apiAuthInfo = apiAuthInfo;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,6 +67,7 @@ public class KeysApiController implements KeysApi {
|
||||
}
|
||||
|
||||
apiKeyService.createApiKey(body.getName(), userId, tokenIdentifier, token, perm);
|
||||
userActionLogService.user(request, LoggedActionType.USER_APIKEY_CREATE.with(UserContext.of(apiAuthInfo.getUserId())), "Key Name: " + body.getName() + "<br>" + perms.stream().map(NamedPermission::getFrontendName).collect(Collectors.joining(",<br>")), "");
|
||||
return ResponseEntity.ok(new ApiKeyResponse().perms(perm.toNamed()).key(tokenIdentifier + "." + token));
|
||||
}
|
||||
|
||||
@ -71,6 +81,7 @@ public class KeysApiController implements KeysApi {
|
||||
if (rowsAffected == 0) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
||||
} else {
|
||||
userActionLogService.user(request, LoggedActionType.USER_APIKEY_DELETE.with(UserContext.of(apiAuthInfo.getUserId())), "", "Key Name: " + name);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
}
|
||||
|
@ -12,13 +12,26 @@ public class LoggedAction extends PGobject {
|
||||
public static final LoggedAction PROJECT_SETTINGS_CHANGED = new LoggedAction("project_settings_changed");
|
||||
public static final LoggedAction PROJECT_MEMBER_REMOVED = new LoggedAction("project_member_removed");
|
||||
public static final LoggedAction PROJECT_ICON_CHANGED = new LoggedAction("project_icon_changed");
|
||||
public static final LoggedAction PROJECT_PAGE_EDITED = new LoggedAction("project_page_edited");
|
||||
public static final LoggedAction PROJECT_FLAG_RESOLVED = new LoggedAction("project_flag_resolved");
|
||||
|
||||
public static final LoggedAction PROJECT_PAGE_CREATED = new LoggedAction("project_page_created");
|
||||
public static final LoggedAction PROJECT_PAGE_DELETED = new LoggedAction("project_page_deleted");
|
||||
public static final LoggedAction PROJECT_PAGE_EDITED = new LoggedAction("project_page_edited");
|
||||
|
||||
public static final LoggedAction VERSION_DELETED = new LoggedAction("version_deleted");
|
||||
public static final LoggedAction VERSION_UPLOADED = new LoggedAction("version_uploaded");
|
||||
public static final LoggedAction VERSION_DESCRIPTION_CHANGED = new LoggedAction("version_description_changed");
|
||||
public static final LoggedAction VERSION_REVIEW_STATE_CHANGED = new LoggedAction("version_review_state_changed");
|
||||
|
||||
public static final LoggedAction USER_TAGLINE_CHANGED = new LoggedAction("user_tagline_changed");
|
||||
public static final LoggedAction USER_LOCKED = new LoggedAction("user_locked");
|
||||
public static final LoggedAction USER_UNLOCKED = new LoggedAction("user_unlocked");
|
||||
public static final LoggedAction USER_APIKEY_CREATE = new LoggedAction("user_apikey_create");
|
||||
public static final LoggedAction USER_APIKEY_DELETE = new LoggedAction("user_apikey_delete");
|
||||
|
||||
public static final LoggedAction ORG_MEMBERS_ADDED = new LoggedAction("org_members_added");
|
||||
public static final LoggedAction ORG_MEMBER_REMOVED = new LoggedAction("org_member_removed");
|
||||
public static final LoggedAction ORG_MEMBER_ROLES_UPDATED = new LoggedAction("org_member_roles_updated");
|
||||
|
||||
private String value;
|
||||
|
||||
|
@ -16,14 +16,26 @@ public class LoggedActionType<C extends AbstractContext<C>> {
|
||||
public static final LoggedActionType<ProjectContext> PROJECT_SETTINGS_CHANGED = new LoggedActionType<>(LoggedAction.PROJECT_SETTINGS_CHANGED, "ProjectSettingsChanged", "The project settings were changed");
|
||||
public static final LoggedActionType<ProjectContext> PROJECT_MEMBER_REMOVED = new LoggedActionType<>(LoggedAction.PROJECT_MEMBER_REMOVED, "ProjectMemberRemoved", "A Member was removed from the project");
|
||||
public static final LoggedActionType<ProjectContext> PROJECT_ICON_CHANGED = new LoggedActionType<>(LoggedAction.PROJECT_ICON_CHANGED, "ProjectIconChanged", "The project icon was changed");
|
||||
public static final LoggedActionType<ProjectPageContext> PROJECT_PAGE_EDITED = new LoggedActionType<>(LoggedAction.PROJECT_PAGE_EDITED, "ProjectPageEdited", "A project page got edited");
|
||||
public static final LoggedActionType<ProjectContext> PROJECT_FLAG_RESOLVED = new LoggedActionType<>(LoggedAction.PROJECT_FLAG_RESOLVED, "ProjectFlagResolved", "The flag was resolved");
|
||||
|
||||
public static final LoggedActionType<ProjectPageContext> PROJECT_PAGE_CREATED = new LoggedActionType<>(LoggedAction.PROJECT_PAGE_CREATED, "ProjectPageCreated", "A project page was created");
|
||||
public static final LoggedActionType<ProjectPageContext> PROJECT_PAGE_DELETED = new LoggedActionType<>(LoggedAction.PROJECT_PAGE_DELETED, "ProjectPageDeleted", "A project page was deleted");
|
||||
public static final LoggedActionType<ProjectPageContext> PROJECT_PAGE_EDITED = new LoggedActionType<>(LoggedAction.PROJECT_PAGE_EDITED, "ProjectPageEdited", "A project page was edited");
|
||||
|
||||
public static final LoggedActionType<VersionContext> VERSION_DELETED = new LoggedActionType<>(LoggedAction.VERSION_DELETED, "VersionDeleted", "The version was deleted");
|
||||
public static final LoggedActionType<VersionContext> VERSION_UPLOADED = new LoggedActionType<>(LoggedAction.VERSION_UPLOADED, "VersionUploaded", "A new version was uploaded");
|
||||
public static final LoggedActionType<VersionContext> VERSION_DESCRIPTION_CHANGED = new LoggedActionType<>(LoggedAction.VERSION_DESCRIPTION_CHANGED, "VersionDescriptionEdited", "The version description was edited");
|
||||
public static final LoggedActionType<VersionContext> VERSION_REVIEW_STATE_CHANGED = new LoggedActionType<>(LoggedAction.VERSION_REVIEW_STATE_CHANGED, "VersionReviewStateChanged", "If the review state changed");
|
||||
public static final LoggedActionType<UserContext> USER_TAGLINE_CHANGED = new LoggedActionType<>(LoggedAction.USER_TAGLINE_CHANGED, "UserTaglineChanged", "The user tagline changed");
|
||||
public static final LoggedActionType<VersionContext> VERSION_REVIEW_STATE_CHANGED = new LoggedActionType<>(LoggedAction.VERSION_REVIEW_STATE_CHANGED, "VersionReviewStateChanged", "The versions review state was changed");
|
||||
|
||||
public static final LoggedActionType<UserContext> USER_TAGLINE_CHANGED = new LoggedActionType<>(LoggedAction.USER_TAGLINE_CHANGED, "UserTaglineChanged", "The user tagline changed");
|
||||
public static final LoggedActionType<UserContext> USER_LOCKED = new LoggedActionType<>(LoggedAction.USER_LOCKED, "UserLocked", "This user is locked");
|
||||
public static final LoggedActionType<UserContext> USER_UNLOCKED = new LoggedActionType<>(LoggedAction.USER_UNLOCKED, "UserUnlocked", "This use is unlocked");
|
||||
public static final LoggedActionType<UserContext> USER_APIKEY_CREATE = new LoggedActionType<>(LoggedAction.USER_APIKEY_CREATE, "UserApikeyCreate", "An apikey was created");
|
||||
public static final LoggedActionType<UserContext> USER_APIKEY_DELETE = new LoggedActionType<>(LoggedAction.USER_APIKEY_DELETE, "UserApikeyDelete", "An apikey was deleted");
|
||||
|
||||
public static final LoggedActionType<OrganizationContext> ORG_MEMBERS_ADDED = new LoggedActionType<>(LoggedAction.ORG_MEMBERS_ADDED, "OrganizationMembersAdded", "Users were added to an organization");
|
||||
public static final LoggedActionType<OrganizationContext> ORG_MEMBER_REMOVED = new LoggedActionType<>(LoggedAction.ORG_MEMBER_REMOVED, "OrganizationMemberRemoved", "User was removed from an organization");
|
||||
public static final LoggedActionType<OrganizationContext> ORG_MEMBER_ROLES_UPDATED = new LoggedActionType<>(LoggedAction.ORG_MEMBER_ROLES_UPDATED, "OrganizationMemberRolesUpdated", "Organization members roles were updated");
|
||||
|
||||
private final LoggedAction value;
|
||||
private final String name;
|
||||
@ -157,7 +169,7 @@ public class LoggedActionType<C extends AbstractContext<C>> {
|
||||
this.orgId = orgId;
|
||||
}
|
||||
|
||||
public long getOrganizationLog() {
|
||||
public long getOrganizationId() {
|
||||
return orgId;
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,10 @@ import io.papermc.hangar.db.model.LoggedActionsPageTable;
|
||||
import io.papermc.hangar.db.model.LoggedActionsProjectTable;
|
||||
import io.papermc.hangar.db.model.LoggedActionsUserTable;
|
||||
import io.papermc.hangar.db.model.LoggedActionsVersionTable;
|
||||
|
||||
import io.papermc.hangar.model.viewhelpers.LoggedActionViewModel;
|
||||
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
|
||||
import org.jdbi.v3.sqlobject.config.RegisterColumnMapper;
|
||||
import org.jdbi.v3.sqlobject.config.RegisterRowMapper;
|
||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||
import org.jdbi.v3.sqlobject.customizer.Define;
|
||||
import org.jdbi.v3.sqlobject.customizer.DefineNamedBindings;
|
||||
import org.jdbi.v3.sqlobject.customizer.Timestamped;
|
||||
import org.jdbi.v3.sqlobject.statement.SqlQuery;
|
||||
@ -54,12 +51,13 @@ public interface ActionsDao {
|
||||
@RegisterRowMapper(LoggedActionViewModelMapper.class)
|
||||
@SqlQuery("SELECT * FROM v_logged_actions la " +
|
||||
" WHERE true " +
|
||||
"<if(userFilter)>AND la.user_name = '<userFilter>'<endif> " +
|
||||
"<if(projectFilter)>AND la.p_plugin_id = '<projectFilter>'<endif> " +
|
||||
"<if(versionFilter)>AND la.pv_version_string = '<versionFilter>'<endif> " +
|
||||
"<if(pageFilter)>AND la.pp_id = '<pageFilter>'<endif> " +
|
||||
"<if(actionFilter)>AND la.action = '<actionFilter>'::LOGGED_ACTION_TYPE<endif> " +
|
||||
"<if(subjectFilter)>AND la.s_name = '<subjectFilter>'<endif> " +
|
||||
"ORDER BY la.created_at DESC OFFSET <offset> LIMIT <pageSize>")
|
||||
List<LoggedActionViewModel<?>> getLog(@Define String userFilter, @Define String projectFilter, @Define String versionFilter, @Define String pageFilter, @Define String actionFilter, @Define String subjectFilter, @Define long offset, @Define long pageSize);
|
||||
"<if(userFilter)>AND la.user_name = :userFilter<endif> " +
|
||||
"<if(projectFilter)>AND la.p_plugin_id = :projectFilter<endif> " +
|
||||
"<if(versionFilter)>AND la.pv_version_string = :versionFilter<endif> " +
|
||||
"<if(pageFilter)>AND la.pp_id = :pageFilter<endif> " +
|
||||
"<if(actionFilter)>AND la.action = :actionFilter::LOGGED_ACTION_TYPE<endif> " +
|
||||
"<if(subjectFilter)>AND la.s_name = :subjectFilter<endif> " +
|
||||
"ORDER BY la.created_at DESC OFFSET :offset LIMIT :pageSize")
|
||||
@DefineNamedBindings
|
||||
List<LoggedActionViewModel<?>> getLog(String userFilter, String projectFilter, String versionFilter, String pageFilter, String actionFilter, String subjectFilter, long offset, long pageSize);
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ public interface ProjectsApiDao {
|
||||
" COALESCE(p.last_updated, p.created_at) AS last_updated," +
|
||||
" p.visibility, " +
|
||||
" <if(requesterId)> " +
|
||||
" EXISTS(SELECT * FROM project_stars s WHERE s.project_id = p.id AND s.user_id = <requesterId>) AS user_starred, " +
|
||||
" EXISTS(SELECT * FROM project_watchers s WHERE s.project_id = p.id AND s.user_id = <requesterId>) AS user_watching, " +
|
||||
" EXISTS(SELECT * FROM project_stars s WHERE s.project_id = p.id AND s.user_id = :requesterId) AS user_starred, " +
|
||||
" EXISTS(SELECT * FROM project_watchers s WHERE s.project_id = p.id AND s.user_id = :requesterId) AS user_watching, " +
|
||||
" <endif>" +
|
||||
" ps.homepage," +
|
||||
" ps.issues," +
|
||||
@ -53,22 +53,22 @@ public interface ProjectsApiDao {
|
||||
" FROM home_projects p" +
|
||||
" JOIN projects ps ON p.id = ps.id" +
|
||||
" WHERE true " + //Not sure how else to get here a single Where
|
||||
" <if(pluginId)> AND (p.plugin_id = '<pluginId>') <endif> " +
|
||||
" <if(pluginId)> AND (p.plugin_id = :pluginId) <endif> " +
|
||||
" <if(owner)> AND (p.owner_name = :owner) <endif> " +
|
||||
" <if(!seeHidden)> AND (p.visibility = 0 <if(requesterId)>OR (<requesterId> = ANY(p.project_members) AND p.visibility != 4)<endif>) <endif> " +
|
||||
" <if(!seeHidden)> AND (p.visibility = 0 <if(requesterId)>OR (:requesterId = ANY(p.project_members) AND p.visibility != 4)<endif>) <endif> " +
|
||||
" <if(categories)> AND (p.category in (<categories>)) <endif> " +
|
||||
" <if(query)> AND ( <queryStatement> ) <endif> " +
|
||||
" <if(query)> AND ( :queryStatement ) <endif> " +
|
||||
" <if(tags)> AND EXISTS ( SELECT pv.tag_name FROM jsonb_to_recordset(p.promoted_versions) " +
|
||||
" AS pv(tag_name TEXT, tag_version TEXT) WHERE (pv.tag_name) in (<tags>) ) <endif> " +
|
||||
" <if(orderBy)>ORDER BY <orderBy><endif> " +
|
||||
" <if(orderBy)>ORDER BY :orderBy<endif> " +
|
||||
" LIMIT :limit" +
|
||||
" OFFSET :offset")
|
||||
@RegisterColumnMapper(PromotedVersionMapper.class)
|
||||
// @DefineNamedBindings
|
||||
List<Project> listProjects(@Define String pluginId, @Define String owner, @Define boolean seeHidden, @Define Long requesterId, @Define String orderBy,
|
||||
@DefineNamedBindings
|
||||
List<Project> listProjects(String pluginId, String owner, @Define boolean seeHidden, Long requesterId, String orderBy,
|
||||
@BindList(onEmpty = BindList.EmptyHandling.NULL_VALUE) List<Integer> categories,
|
||||
@BindList(onEmpty = BindList.EmptyHandling.NULL_VALUE) List<String> tags, //TODO: implement tags with mc_version('data')
|
||||
@Define String query, @Define String queryStatement, long limit, long offset);
|
||||
@Define String query, String queryStatement, long limit, long offset);
|
||||
|
||||
@UseStringTemplateEngine
|
||||
@SqlQuery("SELECT COUNT(*) FROM ( SELECT p.created_at," +
|
||||
|
@ -56,6 +56,10 @@ public enum NamedPermission {
|
||||
this.frontendName = frontendName;
|
||||
}
|
||||
|
||||
public String getFrontendName() {
|
||||
return frontendName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonValue
|
||||
public String toString() {
|
||||
|
@ -3,6 +3,8 @@ package io.papermc.hangar.service;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
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.OrganizationContext;
|
||||
import io.papermc.hangar.db.dao.HangarDao;
|
||||
import io.papermc.hangar.db.dao.OrganizationDao;
|
||||
import io.papermc.hangar.db.dao.UserDao;
|
||||
@ -22,6 +24,8 @@ import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@ -35,19 +39,24 @@ public class OrgFactory {
|
||||
private final UserService userService;
|
||||
private final RoleService roleService;
|
||||
private final NotificationService notificationService;
|
||||
private final UserActionLogService userActionLogService;
|
||||
private final RestTemplate restTemplate;
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public OrgFactory(HangarDao<OrganizationDao> organizationDao, HangarDao<UserDao> userDao, HangarConfig hangarConfig, UserService userService, RoleService roleService, NotificationService notificationService, RestTemplate restTemplate, ObjectMapper mapper) {
|
||||
public OrgFactory(HangarDao<OrganizationDao> organizationDao, HangarDao<UserDao> userDao, HangarConfig hangarConfig, UserService userService, RoleService roleService, NotificationService notificationService, UserActionLogService userActionLogService, RestTemplate restTemplate, ObjectMapper mapper, HttpServletRequest request) {
|
||||
this.organizationDao = organizationDao;
|
||||
this.userDao = userDao;
|
||||
this.hangarConfig = hangarConfig;
|
||||
this.userService = userService;
|
||||
this.roleService = roleService;
|
||||
this.notificationService = notificationService;
|
||||
this.userActionLogService = userActionLogService;
|
||||
this.restTemplate = restTemplate;
|
||||
this.mapper = mapper;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public OrganizationsTable createOrganization(String name, long ownerId, Map<Long, Role> members) {
|
||||
@ -83,11 +92,15 @@ public class OrgFactory {
|
||||
UserData orgUser = userService.getUserData(authOrgUser.getId());
|
||||
roleService.addGlobalRole(orgUser.getUser().getId(), Role.ORGANIZATION.getRoleId());
|
||||
roleService.addOrgMemberRole(orgId, ownerId, Role.ORGANIZATION_OWNER, true);
|
||||
List<String> newState = new ArrayList<>();
|
||||
// TODO user action logging for org members
|
||||
members.forEach((memberId, role) -> {
|
||||
UsersTable memberUser = userDao.get().getById(memberId);
|
||||
newState.add(memberUser.getName() + ": " + role.getTitle());
|
||||
roleService.addOrgMemberRole(orgId, memberId, role, false);
|
||||
notificationService.sendNotification(memberId, orgId, NotificationType.ORGANIZATION_INVITE, new String[]{"notification.organization.invite", role.getTitle(), name});
|
||||
});
|
||||
userActionLogService.organization(request, LoggedActionType.ORG_MEMBERS_ADDED.with(OrganizationContext.of(orgId)), String.join("<br>", newState), "<i>No Members</i>");
|
||||
return org;
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,11 @@ import io.papermc.hangar.db.model.LoggedActionsProjectTable;
|
||||
import io.papermc.hangar.db.model.LoggedActionsUserTable;
|
||||
import io.papermc.hangar.db.model.LoggedActionsVersionTable;
|
||||
import io.papermc.hangar.model.viewhelpers.LoggedActionViewModel;
|
||||
import io.papermc.hangar.util.RequestUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -22,18 +21,16 @@ import java.util.Objects;
|
||||
public class UserActionLogService extends HangarService {
|
||||
|
||||
private final HangarDao<ActionsDao> actionsDao;
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public UserActionLogService(HangarDao<ActionsDao> actionsDao, UserService userService) {
|
||||
public UserActionLogService(HangarDao<ActionsDao> actionsDao) {
|
||||
this.actionsDao = actionsDao;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
public void project(HttpServletRequest request, LoggedActionType<LoggedActionType.ProjectContext> loggedActionType, String newState, String oldState) {
|
||||
LoggedActionsProjectTable log = new LoggedActionsProjectTable(
|
||||
getCurrentUser().getId(),
|
||||
getInetAddress(request),
|
||||
RequestUtil.getRemoteInetAddress(request),
|
||||
loggedActionType.getValue(),
|
||||
loggedActionType.getActionContext().getProjectId(),
|
||||
newState,
|
||||
@ -45,7 +42,7 @@ public class UserActionLogService extends HangarService {
|
||||
public void projectPage(HttpServletRequest request, LoggedActionType<LoggedActionType.ProjectPageContext> loggedActionType, String newState, String oldState) {
|
||||
LoggedActionsPageTable log = new LoggedActionsPageTable(
|
||||
getCurrentUser().getId(),
|
||||
getInetAddress(request),
|
||||
RequestUtil.getRemoteInetAddress(request),
|
||||
loggedActionType.getValue(),
|
||||
loggedActionType.getActionContext().getProjectId(),
|
||||
loggedActionType.getActionContext().getPageId(),
|
||||
@ -58,7 +55,7 @@ public class UserActionLogService extends HangarService {
|
||||
public void version(HttpServletRequest request, LoggedActionType<LoggedActionType.VersionContext> loggedActionType, String newState, String oldState) {
|
||||
LoggedActionsVersionTable log = new LoggedActionsVersionTable(
|
||||
getCurrentUser().getId(),
|
||||
getInetAddress(request),
|
||||
RequestUtil.getRemoteInetAddress(request),
|
||||
loggedActionType.getValue(),
|
||||
loggedActionType.getActionContext().getProjectId(),
|
||||
loggedActionType.getActionContext().getVersionId(),
|
||||
@ -71,7 +68,7 @@ public class UserActionLogService extends HangarService {
|
||||
public void user(HttpServletRequest request, LoggedActionType<LoggedActionType.UserContext> loggedActionType, String newState, String oldState) {
|
||||
LoggedActionsUserTable log = new LoggedActionsUserTable(
|
||||
getCurrentUser().getId(),
|
||||
getInetAddress(request),
|
||||
RequestUtil.getRemoteInetAddress(request),
|
||||
loggedActionType.getValue(),
|
||||
loggedActionType.getActionContext().getUserId(),
|
||||
Objects.toString(newState, ""),
|
||||
@ -83,9 +80,9 @@ public class UserActionLogService extends HangarService {
|
||||
public void organization(HttpServletRequest request, LoggedActionType<LoggedActionType.OrganizationContext> loggedActionType, String newState, String oldState) {
|
||||
LoggedActionsOrganizationTable log = new LoggedActionsOrganizationTable(
|
||||
getCurrentUser().getId(),
|
||||
getInetAddress(request),
|
||||
RequestUtil.getRemoteInetAddress(request),
|
||||
loggedActionType.getValue(),
|
||||
loggedActionType.getActionContext().getOrganizationLog(),
|
||||
loggedActionType.getActionContext().getOrganizationId(),
|
||||
Objects.toString(newState, ""),
|
||||
Objects.toString(oldState, "")
|
||||
);
|
||||
@ -102,15 +99,5 @@ public class UserActionLogService extends HangarService {
|
||||
}
|
||||
return actionsDao.get().getLog(userFilter, projectFilter, versionFilter, pageFilter, actionFilter, subjectFilter, offset, pageSize);
|
||||
}
|
||||
|
||||
private InetAddress getInetAddress(HttpServletRequest request) {
|
||||
String host = request.getHeader("X-Forwarded-For");
|
||||
if (host == null) host = request.getRemoteHost();
|
||||
try {
|
||||
return InetAddress.getByName(host);
|
||||
} catch (UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package io.papermc.hangar.service;
|
||||
import io.papermc.hangar.config.CacheConfig;
|
||||
import io.papermc.hangar.config.hangar.HangarConfig;
|
||||
import io.papermc.hangar.controller.UsersController;
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType;
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType.UserContext;
|
||||
import io.papermc.hangar.db.dao.HangarDao;
|
||||
import io.papermc.hangar.db.dao.NotificationsDao;
|
||||
import io.papermc.hangar.db.dao.OrganizationDao;
|
||||
@ -60,12 +62,13 @@ public class UserService extends HangarService {
|
||||
private final PermissionService permissionService;
|
||||
private final OrgService orgService;
|
||||
private final SessionService sessionService;
|
||||
private final UserActionLogService userActionLogService;
|
||||
private final HangarConfig config;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public UserService(HangarDao<UserDao> userDao, HangarConfig config, HangarDao<OrganizationDao> orgDao, HangarDao<ProjectDao> projectDao, HangarDao<OrganizationDao> organizationDao, HangarDao<NotificationsDao> notificationsDao, RoleService roleService, PermissionService permissionService, OrgService orgService, SessionService sessionService, HttpServletRequest request) {
|
||||
public UserService(HangarDao<UserDao> userDao, HangarConfig config, HangarDao<OrganizationDao> orgDao, HangarDao<ProjectDao> projectDao, HangarDao<OrganizationDao> organizationDao, HangarDao<NotificationsDao> notificationsDao, RoleService roleService, PermissionService permissionService, OrgService orgService, SessionService sessionService, UserActionLogService userActionLogService, HttpServletRequest request) {
|
||||
this.userDao = userDao;
|
||||
this.config = config;
|
||||
this.orgDao = orgDao;
|
||||
@ -76,6 +79,7 @@ public class UserService extends HangarService {
|
||||
this.permissionService = permissionService;
|
||||
this.orgService = orgService;
|
||||
this.sessionService = sessionService;
|
||||
this.userActionLogService = userActionLogService;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@ -184,6 +188,11 @@ public class UserService extends HangarService {
|
||||
|
||||
public void setLocked(UsersTable user, boolean locked) {
|
||||
user.setIsLocked(locked);
|
||||
if (locked) {
|
||||
userActionLogService.user(request, LoggedActionType.USER_LOCKED.with(UserContext.of(user.getId())), user.getName() + " is now locked", user.getName() + " was unlocked");
|
||||
} else {
|
||||
userActionLogService.user(request, LoggedActionType.USER_UNLOCKED.with(UserContext.of(user.getId())), user.getName() + " is now unlocked", user.getName() + " was locked");
|
||||
}
|
||||
userDao.get().update(user);
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@
|
||||
</td>
|
||||
</#if>
|
||||
<#-- Show diff only when page edit -->
|
||||
<#if action.action.name == "ProjectPageEdited" || action.action == "VersionDescriptionEdited">
|
||||
<#if action.action.name == "ProjectPageEdited" || action.action.name == "ProjectPageDeleted" || action.action.name == "ProjectPageCreated" || action.action.name == "VersionDescriptionEdited">
|
||||
<td>
|
||||
<a href="#" class="data-view-old" data-view="${offset + action?index}">View</a>
|
||||
<textarea style="display: none" data-oldstate="${offset + action?index}">${action.oldState}</textarea>
|
||||
|
Loading…
Reference in New Issue
Block a user