mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
feat: Audit log for system and project setting changes (OD-2142)
This commit is contained in:
parent
5583a01fda
commit
a47b38e375
@ -371,6 +371,7 @@ import io.onedev.server.util.oauth.OAuthTokenManager;
|
|||||||
import io.onedev.server.util.xstream.CollectionConverter;
|
import io.onedev.server.util.xstream.CollectionConverter;
|
||||||
import io.onedev.server.util.xstream.HibernateProxyConverter;
|
import io.onedev.server.util.xstream.HibernateProxyConverter;
|
||||||
import io.onedev.server.util.xstream.MapConverter;
|
import io.onedev.server.util.xstream.MapConverter;
|
||||||
|
import io.onedev.server.util.xstream.ObjectMapperConverter;
|
||||||
import io.onedev.server.util.xstream.ReflectionConverter;
|
import io.onedev.server.util.xstream.ReflectionConverter;
|
||||||
import io.onedev.server.util.xstream.StringConverter;
|
import io.onedev.server.util.xstream.StringConverter;
|
||||||
import io.onedev.server.util.xstream.VersionedDocumentConverter;
|
import io.onedev.server.util.xstream.VersionedDocumentConverter;
|
||||||
@ -393,7 +394,6 @@ import io.onedev.server.web.editable.EditSupport;
|
|||||||
import io.onedev.server.web.editable.EditSupportLocator;
|
import io.onedev.server.web.editable.EditSupportLocator;
|
||||||
import io.onedev.server.web.editable.EditSupportRegistry;
|
import io.onedev.server.web.editable.EditSupportRegistry;
|
||||||
import io.onedev.server.web.exceptionhandler.PageExpiredExceptionHandler;
|
import io.onedev.server.web.exceptionhandler.PageExpiredExceptionHandler;
|
||||||
import io.onedev.server.web.page.layout.AdministrationMenuContribution;
|
|
||||||
import io.onedev.server.web.page.layout.AdministrationSettingContribution;
|
import io.onedev.server.web.page.layout.AdministrationSettingContribution;
|
||||||
import io.onedev.server.web.page.project.blob.render.BlobRenderer;
|
import io.onedev.server.web.page.project.blob.render.BlobRenderer;
|
||||||
import io.onedev.server.web.page.project.setting.ProjectSettingContribution;
|
import io.onedev.server.web.page.project.setting.ProjectSettingContribution;
|
||||||
@ -691,8 +691,6 @@ public class CoreModule extends AbstractPluginModule {
|
|||||||
bind(UploadManager.class).to(DefaultUploadManager.class);
|
bind(UploadManager.class).to(DefaultUploadManager.class);
|
||||||
|
|
||||||
bind(TaskButton.TaskFutureManager.class);
|
bind(TaskButton.TaskFutureManager.class);
|
||||||
|
|
||||||
contribute(AdministrationMenuContribution.class, (AdministrationMenuContribution) ArrayList::new);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureBuild() {
|
private void configureBuild() {
|
||||||
@ -856,6 +854,7 @@ public class CoreModule extends AbstractPluginModule {
|
|||||||
xstream.registerConverter(new HibernateProxyConverter(), XStream.PRIORITY_VERY_HIGH);
|
xstream.registerConverter(new HibernateProxyConverter(), XStream.PRIORITY_VERY_HIGH);
|
||||||
xstream.registerConverter(new CollectionConverter(xstream.getMapper()), XStream.PRIORITY_VERY_HIGH);
|
xstream.registerConverter(new CollectionConverter(xstream.getMapper()), XStream.PRIORITY_VERY_HIGH);
|
||||||
xstream.registerConverter(new MapConverter(xstream.getMapper()), XStream.PRIORITY_VERY_HIGH);
|
xstream.registerConverter(new MapConverter(xstream.getMapper()), XStream.PRIORITY_VERY_HIGH);
|
||||||
|
xstream.registerConverter(new ObjectMapperConverter(), XStream.PRIORITY_VERY_HIGH);
|
||||||
xstream.registerConverter(new ISO8601DateConverter(), XStream.PRIORITY_VERY_HIGH);
|
xstream.registerConverter(new ISO8601DateConverter(), XStream.PRIORITY_VERY_HIGH);
|
||||||
xstream.registerConverter(new ISO8601SqlTimestampConverter(), XStream.PRIORITY_VERY_HIGH);
|
xstream.registerConverter(new ISO8601SqlTimestampConverter(), XStream.PRIORITY_VERY_HIGH);
|
||||||
xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream.getReflectionProvider()),
|
xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream.getReflectionProvider()),
|
||||||
|
|||||||
@ -99,6 +99,7 @@ import io.onedev.server.model.Setting.Key;
|
|||||||
import io.onedev.server.model.User;
|
import io.onedev.server.model.User;
|
||||||
import io.onedev.server.model.support.administration.AgentSetting;
|
import io.onedev.server.model.support.administration.AgentSetting;
|
||||||
import io.onedev.server.model.support.administration.AlertSetting;
|
import io.onedev.server.model.support.administration.AlertSetting;
|
||||||
|
import io.onedev.server.model.support.administration.AuditSetting;
|
||||||
import io.onedev.server.model.support.administration.BackupSetting;
|
import io.onedev.server.model.support.administration.BackupSetting;
|
||||||
import io.onedev.server.model.support.administration.BrandingSetting;
|
import io.onedev.server.model.support.administration.BrandingSetting;
|
||||||
import io.onedev.server.model.support.administration.ClusterSetting;
|
import io.onedev.server.model.support.administration.ClusterSetting;
|
||||||
@ -897,6 +898,12 @@ public class DefaultDataManager implements DataManager, Serializable {
|
|||||||
clusterSetting.setReplicaCount(1);
|
clusterSetting.setReplicaCount(1);
|
||||||
settingManager.saveClusterSetting(clusterSetting);
|
settingManager.saveClusterSetting(clusterSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setting = settingManager.findSetting(Key.AUDIT);
|
||||||
|
if (setting == null) {
|
||||||
|
AuditSetting auditSetting = new AuditSetting();
|
||||||
|
settingManager.saveAuditSetting(auditSetting);
|
||||||
|
}
|
||||||
|
|
||||||
if (roleManager.get(Role.OWNER_ID) == null) {
|
if (roleManager.get(Role.OWNER_ID) == null) {
|
||||||
Role owner = new Role();
|
Role owner = new Role();
|
||||||
|
|||||||
@ -8129,4 +8129,7 @@ public class DataMigrator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void migrate205(File dataDir, Stack<Integer> versions) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package io.onedev.server.entitymanager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import io.onedev.server.entitymanager.support.AuditQuery;
|
||||||
|
import io.onedev.server.model.Audit;
|
||||||
|
import io.onedev.server.model.Project;
|
||||||
|
import io.onedev.server.persistence.dao.EntityManager;
|
||||||
|
|
||||||
|
public interface AuditManager extends EntityManager<Audit> {
|
||||||
|
|
||||||
|
void audit(@Nullable Project project, String action, @Nullable String oldContent, @Nullable String newContent);
|
||||||
|
|
||||||
|
List<Audit> query(@Nullable Project project, AuditQuery query, int firstResult, int maxResults);
|
||||||
|
|
||||||
|
int count(@Nullable Project project, AuditQuery query);
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,15 +1,16 @@
|
|||||||
package io.onedev.server.entitymanager;
|
package io.onedev.server.entitymanager;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import io.onedev.server.model.LinkAuthorization;
|
import io.onedev.server.model.LinkAuthorization;
|
||||||
import io.onedev.server.model.LinkSpec;
|
import io.onedev.server.model.LinkSpec;
|
||||||
import io.onedev.server.model.Role;
|
import io.onedev.server.model.Role;
|
||||||
import io.onedev.server.persistence.dao.EntityManager;
|
import io.onedev.server.persistence.dao.EntityManager;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public interface LinkAuthorizationManager extends EntityManager<LinkAuthorization> {
|
public interface LinkAuthorizationManager extends EntityManager<LinkAuthorization> {
|
||||||
|
|
||||||
void syncAuthorizations(Role role, Collection<LinkSpec> authorizedLinks);
|
void syncAuthorizations(Role role, Collection<LinkSpec> authorizedLinks);
|
||||||
|
|
||||||
void create(LinkAuthorization authorization);
|
void create(LinkAuthorization authorization);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,20 @@
|
|||||||
package io.onedev.server.entitymanager;
|
package io.onedev.server.entitymanager;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.Path;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
import io.onedev.server.cluster.ClusterTask;
|
import io.onedev.server.cluster.ClusterTask;
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.model.support.code.GitPackConfig;
|
import io.onedev.server.model.support.code.GitPackConfig;
|
||||||
@ -11,19 +26,6 @@ import io.onedev.server.util.criteria.Criteria;
|
|||||||
import io.onedev.server.util.facade.ProjectCache;
|
import io.onedev.server.util.facade.ProjectCache;
|
||||||
import io.onedev.server.util.facade.ProjectFacade;
|
import io.onedev.server.util.facade.ProjectFacade;
|
||||||
import io.onedev.server.util.patternset.PatternSet;
|
import io.onedev.server.util.patternset.PatternSet;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
|
||||||
import org.eclipse.jgit.lib.Repository;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
import javax.persistence.criteria.Path;
|
|
||||||
import javax.persistence.criteria.Predicate;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public interface ProjectManager extends EntityManager<Project> {
|
public interface ProjectManager extends EntityManager<Project> {
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,9 @@ public interface RoleManager extends EntityManager<Role> {
|
|||||||
|
|
||||||
void replicate(Role role);
|
void replicate(Role role);
|
||||||
|
|
||||||
void create(Role role, Collection<LinkSpec> authorizedLinks);
|
void create(Role role, @Nullable Collection<LinkSpec> authorizedLinks);
|
||||||
|
|
||||||
void update(Role role, Collection<LinkSpec> authorizedLinks, @Nullable String oldName);
|
void update(Role role, @Nullable Collection<LinkSpec> authorizedLinks, @Nullable String oldName);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
Role find(String name);
|
Role find(String name);
|
||||||
|
|||||||
@ -83,6 +83,10 @@ public interface SettingManager extends EntityManager<Setting> {
|
|||||||
ClusterSetting getClusterSetting();
|
ClusterSetting getClusterSetting();
|
||||||
|
|
||||||
void saveClusterSetting(ClusterSetting clusterSetting);
|
void saveClusterSetting(ClusterSetting clusterSetting);
|
||||||
|
|
||||||
|
AuditSetting getAuditSetting();
|
||||||
|
|
||||||
|
void saveAuditSetting(AuditSetting auditSetting);
|
||||||
|
|
||||||
SecuritySetting getSecuritySetting();
|
SecuritySetting getSecuritySetting();
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,6 @@ import io.onedev.server.persistence.dao.BaseEntityManager;
|
|||||||
import io.onedev.server.persistence.dao.Dao;
|
import io.onedev.server.persistence.dao.Dao;
|
||||||
import io.onedev.server.util.CryptoUtils;
|
import io.onedev.server.util.CryptoUtils;
|
||||||
import io.onedev.server.util.facade.AccessTokenCache;
|
import io.onedev.server.util.facade.AccessTokenCache;
|
||||||
import io.onedev.server.util.facade.AccessTokenFacade;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class DefaultAccessTokenManager extends BaseEntityManager<AccessToken> implements AccessTokenManager {
|
public class DefaultAccessTokenManager extends BaseEntityManager<AccessToken> implements AccessTokenManager {
|
||||||
@ -134,7 +133,7 @@ public class DefaultAccessTokenManager extends BaseEntityManager<AccessToken> im
|
|||||||
@Listen
|
@Listen
|
||||||
public void on(EntityPersisted event) {
|
public void on(EntityPersisted event) {
|
||||||
if (event.getEntity() instanceof AccessToken) {
|
if (event.getEntity() instanceof AccessToken) {
|
||||||
var facade = (AccessTokenFacade) event.getEntity().getFacade();
|
var facade = ((AccessToken) event.getEntity()).getFacade();
|
||||||
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -190,7 +190,7 @@ public class DefaultGroupManager extends BaseEntityManager<Group> implements Gro
|
|||||||
@Listen
|
@Listen
|
||||||
public void on(EntityPersisted event) {
|
public void on(EntityPersisted event) {
|
||||||
if (event.getEntity() instanceof Group) {
|
if (event.getEntity() instanceof Group) {
|
||||||
var facade = (GroupFacade) event.getEntity().getFacade();
|
var facade = ((Group) event.getEntity()).getFacade();
|
||||||
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1093,7 +1093,6 @@ public class DefaultIssueManager extends BaseEntityManager<Issue> implements Iss
|
|||||||
Project oldProject = issue.getProject();
|
Project oldProject = issue.getProject();
|
||||||
Project numberScope = targetProject.getForkRoot();
|
Project numberScope = targetProject.getForkRoot();
|
||||||
Long nextNumber = getNextNumber(numberScope);
|
Long nextNumber = getNextNumber(numberScope);
|
||||||
issue.setOldVersion(issue.getFacade());
|
|
||||||
issue.setProject(targetProject);
|
issue.setProject(targetProject);
|
||||||
issue.setNumberScope(numberScope);
|
issue.setNumberScope(numberScope);
|
||||||
Long oldNumber = issue.getNumber();
|
Long oldNumber = issue.getNumber();
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import javax.inject.Inject;
|
|||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import io.onedev.server.entitymanager.LinkAuthorizationManager;
|
import io.onedev.server.entitymanager.LinkAuthorizationManager;
|
||||||
import io.onedev.server.model.LinkAuthorization;
|
import io.onedev.server.model.LinkAuthorization;
|
||||||
import io.onedev.server.model.LinkSpec;
|
import io.onedev.server.model.LinkSpec;
|
||||||
|
|||||||
@ -164,7 +164,7 @@ public class DefaultLinkSpecManager extends BaseEntityManager<LinkSpec> implemen
|
|||||||
@Listen
|
@Listen
|
||||||
public void on(EntityPersisted event) {
|
public void on(EntityPersisted event) {
|
||||||
if (event.getEntity() instanceof LinkSpec) {
|
if (event.getEntity() instanceof LinkSpec) {
|
||||||
var facade = (LinkSpecFacade) event.getEntity().getFacade();
|
var facade = ((LinkSpec) event.getEntity()).getFacade();
|
||||||
transactionManager.runAfterCommit(() -> updateCache(facade));
|
transactionManager.runAfterCommit(() -> updateCache(facade));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ public class DefaultLinkSpecManager extends BaseEntityManager<LinkSpec> implemen
|
|||||||
@Listen
|
@Listen
|
||||||
public void on(EntityRemoved event) {
|
public void on(EntityRemoved event) {
|
||||||
if (event.getEntity() instanceof LinkSpec) {
|
if (event.getEntity() instanceof LinkSpec) {
|
||||||
var facade = (LinkSpecFacade) event.getEntity().getFacade();
|
var facade = ((LinkSpec) event.getEntity()).getFacade();
|
||||||
transactionManager.runAfterCommit(() -> {
|
transactionManager.runAfterCommit(() -> {
|
||||||
cache.remove(facade.getId());
|
cache.remove(facade.getId());
|
||||||
idCache.remove(facade.getName());
|
idCache.remove(facade.getName());
|
||||||
|
|||||||
@ -117,6 +117,8 @@ import io.onedev.server.StorageManager;
|
|||||||
import io.onedev.server.attachment.AttachmentManager;
|
import io.onedev.server.attachment.AttachmentManager;
|
||||||
import io.onedev.server.cluster.ClusterManager;
|
import io.onedev.server.cluster.ClusterManager;
|
||||||
import io.onedev.server.cluster.ClusterTask;
|
import io.onedev.server.cluster.ClusterTask;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.BuildManager;
|
import io.onedev.server.entitymanager.BuildManager;
|
||||||
import io.onedev.server.entitymanager.IssueManager;
|
import io.onedev.server.entitymanager.IssueManager;
|
||||||
import io.onedev.server.entitymanager.LinkSpecManager;
|
import io.onedev.server.entitymanager.LinkSpecManager;
|
||||||
@ -256,6 +258,8 @@ public class DefaultProjectManager extends BaseEntityManager<Project>
|
|||||||
private final PackBlobManager packBlobManager;
|
private final PackBlobManager packBlobManager;
|
||||||
|
|
||||||
private final ProjectLabelManager labelManager;
|
private final ProjectLabelManager labelManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
private final Collection<String> reservedNames = Sets.newHashSet("robots.txt", "sitemap.xml", "sitemap.txt",
|
private final Collection<String> reservedNames = Sets.newHashSet("robots.txt", "sitemap.xml", "sitemap.txt",
|
||||||
"favicon.ico", "favicon.png", "logo.png", "wicket", "projects");
|
"favicon.ico", "favicon.png", "logo.png", "wicket", "projects");
|
||||||
@ -282,7 +286,8 @@ public class DefaultProjectManager extends BaseEntityManager<Project>
|
|||||||
AttachmentManager attachmentManager, BatchWorkManager batchWorkManager,
|
AttachmentManager attachmentManager, BatchWorkManager batchWorkManager,
|
||||||
VisitInfoManager visitInfoManager, StorageManager storageManager,
|
VisitInfoManager visitInfoManager, StorageManager storageManager,
|
||||||
PackManager packManager, PackBlobManager packBlobManager,
|
PackManager packManager, PackBlobManager packBlobManager,
|
||||||
ProjectLabelManager labelManager, Set<ProjectNameReservation> nameReservations) {
|
ProjectLabelManager labelManager, AuditManager auditManager,
|
||||||
|
Set<ProjectNameReservation> nameReservations) {
|
||||||
super(dao);
|
super(dao);
|
||||||
|
|
||||||
this.commitInfoManager = commitInfoManager;
|
this.commitInfoManager = commitInfoManager;
|
||||||
@ -308,6 +313,7 @@ public class DefaultProjectManager extends BaseEntityManager<Project>
|
|||||||
this.packManager = packManager;
|
this.packManager = packManager;
|
||||||
this.packBlobManager = packBlobManager;
|
this.packBlobManager = packBlobManager;
|
||||||
this.labelManager = labelManager;
|
this.labelManager = labelManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
|
|
||||||
for (ProjectNameReservation reservation : nameReservations)
|
for (ProjectNameReservation reservation : nameReservations)
|
||||||
reservedNames.addAll(reservation.getReserved());
|
reservedNames.addAll(reservation.getReserved());
|
||||||
@ -369,8 +375,10 @@ public class DefaultProjectManager extends BaseEntityManager<Project>
|
|||||||
public void create(Project project) {
|
public void create(Project project) {
|
||||||
Preconditions.checkState(project.isNew());
|
Preconditions.checkState(project.isNew());
|
||||||
Project parent = project.getParent();
|
Project parent = project.getParent();
|
||||||
if (parent != null && parent.isNew())
|
if (parent != null && parent.isNew()) {
|
||||||
create(parent);
|
create(parent);
|
||||||
|
auditManager.audit(parent, "created project", null, VersionedXmlDoc.fromBean(parent).toXML());
|
||||||
|
}
|
||||||
project.setPath(project.calcPath());
|
project.setPath(project.calcPath());
|
||||||
|
|
||||||
ProjectLastEventDate lastEventDate = new ProjectLastEventDate();
|
ProjectLastEventDate lastEventDate = new ProjectLastEventDate();
|
||||||
@ -440,17 +448,7 @@ public class DefaultProjectManager extends BaseEntityManager<Project>
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public void delete(Collection<Project> projects) {
|
public void delete(Collection<Project> projects) {
|
||||||
Collection<Project> independents = new HashSet<>(projects);
|
for (Project independent : Project.getIndependents(projects))
|
||||||
for (Iterator<Project> it = independents.iterator(); it.hasNext(); ) {
|
|
||||||
Project independent = it.next();
|
|
||||||
for (Project each : independents) {
|
|
||||||
if (!each.equals(independent) && each.isSelfOrAncestorOf(independent)) {
|
|
||||||
it.remove();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Project independent : independents)
|
|
||||||
delete(independent);
|
delete(independent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -112,7 +112,9 @@ public class DefaultRoleManager extends BaseEntityManager<Role> implements RoleM
|
|||||||
public void create(Role role, Collection<LinkSpec> authorizedLinks) {
|
public void create(Role role, Collection<LinkSpec> authorizedLinks) {
|
||||||
Preconditions.checkState(role.isNew());
|
Preconditions.checkState(role.isNew());
|
||||||
dao.persist(role);
|
dao.persist(role);
|
||||||
linkAuthorizationManager.syncAuthorizations(role, authorizedLinks);
|
|
||||||
|
if (authorizedLinks != null)
|
||||||
|
linkAuthorizationManager.syncAuthorizations(role, authorizedLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -122,9 +124,10 @@ public class DefaultRoleManager extends BaseEntityManager<Role> implements RoleM
|
|||||||
|
|
||||||
if (oldName != null && !oldName.equals(role.getName()))
|
if (oldName != null && !oldName.equals(role.getName()))
|
||||||
settingManager.onRenameRole(oldName, role.getName());
|
settingManager.onRenameRole(oldName, role.getName());
|
||||||
dao.persist(role);
|
dao.persist(role);
|
||||||
|
|
||||||
linkAuthorizationManager.syncAuthorizations(role, authorizedLinks);
|
if (authorizedLinks != null)
|
||||||
|
linkAuthorizationManager.syncAuthorizations(role, authorizedLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -343,7 +346,7 @@ public class DefaultRoleManager extends BaseEntityManager<Role> implements RoleM
|
|||||||
@Listen
|
@Listen
|
||||||
public void on(EntityPersisted event) {
|
public void on(EntityPersisted event) {
|
||||||
if (event.getEntity() instanceof Role) {
|
if (event.getEntity() instanceof Role) {
|
||||||
var facade = (RoleFacade) event.getEntity().getFacade();
|
var facade = ((Role) event.getEntity()).getFacade();
|
||||||
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,6 +131,11 @@ public class DefaultSettingManager extends BaseEntityManager<Setting>
|
|||||||
return (ClusterSetting) getSettingValue(Key.CLUSTER_SETTING);
|
return (ClusterSetting) getSettingValue(Key.CLUSTER_SETTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuditSetting getAuditSetting() {
|
||||||
|
return (AuditSetting) getSettingValue(Key.AUDIT);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SecuritySetting getSecuritySetting() {
|
public SecuritySetting getSecuritySetting() {
|
||||||
return (SecuritySetting) getSettingValue(Key.SECURITY);
|
return (SecuritySetting) getSettingValue(Key.SECURITY);
|
||||||
@ -260,6 +265,12 @@ public class DefaultSettingManager extends BaseEntityManager<Setting>
|
|||||||
public void saveClusterSetting(ClusterSetting clusterSetting) {
|
public void saveClusterSetting(ClusterSetting clusterSetting) {
|
||||||
saveSetting(Key.CLUSTER_SETTING, clusterSetting);
|
saveSetting(Key.CLUSTER_SETTING, clusterSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public void saveAuditSetting(AuditSetting auditSetting) {
|
||||||
|
saveSetting(Key.AUDIT, auditSetting);
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public class DefaultSshKeyManager extends BaseEntityManager<SshKey> implements S
|
|||||||
sshKey.setContent(content);
|
sshKey.setContent(content);
|
||||||
sshKey.setOwner(user);
|
sshKey.setOwner(user);
|
||||||
sshKey.setCreatedAt(new Date());
|
sshKey.setCreatedAt(new Date());
|
||||||
sshKey.fingerprint();
|
sshKey.generateFingerprint();
|
||||||
syncMap.put(content, sshKey);
|
syncMap.put(content, sshKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -502,7 +502,7 @@ public class DefaultUserManager extends BaseEntityManager<User> implements UserM
|
|||||||
public void on(EntityPersisted event) {
|
public void on(EntityPersisted event) {
|
||||||
// Cache will be null when we run reset-admin-password command
|
// Cache will be null when we run reset-admin-password command
|
||||||
if (cache != null && event.getEntity() instanceof User) {
|
if (cache != null && event.getEntity() instanceof User) {
|
||||||
var facade = (UserFacade) event.getEntity().getFacade();
|
var facade = ((User) event.getEntity()).getFacade();
|
||||||
if (facade.getId() > 0)
|
if (facade.getId() > 0)
|
||||||
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
transactionManager.runAfterCommit(() -> cache.put(facade.getId(), facade));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,47 @@
|
|||||||
|
package io.onedev.server.entitymanager.support;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import io.onedev.server.model.User;
|
||||||
|
|
||||||
|
public class AuditQuery implements Serializable {
|
||||||
|
|
||||||
|
private final List<User> users;
|
||||||
|
|
||||||
|
private final Date sinceDate;
|
||||||
|
|
||||||
|
private final Date untilDate;
|
||||||
|
|
||||||
|
private final String action;
|
||||||
|
|
||||||
|
public AuditQuery(List<User> users, @Nullable Date sinceDate, @Nullable Date untilDate, @Nullable String action) {
|
||||||
|
this.users = users;
|
||||||
|
this.sinceDate = sinceDate;
|
||||||
|
this.untilDate = untilDate;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<User> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Date getSinceDate() {
|
||||||
|
return sinceDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Date getUntilDate() {
|
||||||
|
return untilDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,24 +1,27 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import static com.fasterxml.jackson.annotation.JsonProperty.Access.READ_ONLY;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import io.onedev.server.model.support.EntityWatch;
|
import java.io.Serializable;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import java.util.ArrayList;
|
||||||
import io.onedev.server.util.facade.EntityFacade;
|
import java.util.Collection;
|
||||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import static com.fasterxml.jackson.annotation.JsonProperty.Access.READ_ONLY;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.model.support.EntityWatch;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
@JsonIgnoreProperties("handler")
|
@JsonIgnoreProperties("handler")
|
||||||
@ -36,7 +39,7 @@ public abstract class AbstractEntity implements Serializable, Comparable<Abstrac
|
|||||||
|
|
||||||
public static final String PROP_NUMBER = "number";
|
public static final String PROP_NUMBER = "number";
|
||||||
|
|
||||||
private transient EntityFacade oldVersion;
|
private transient VersionedXmlDoc oldVersion;
|
||||||
|
|
||||||
@Api(order=1)
|
@Api(order=1)
|
||||||
@Id
|
@Id
|
||||||
@ -117,11 +120,11 @@ public abstract class AbstractEntity implements Serializable, Comparable<Abstrac
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public EntityFacade getOldVersion() {
|
public VersionedXmlDoc getOldVersion() {
|
||||||
return oldVersion;
|
return oldVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOldVersion(@Nullable EntityFacade oldVersion) {
|
public void setOldVersion(VersionedXmlDoc oldVersion) {
|
||||||
this.oldVersion = oldVersion;
|
this.oldVersion = oldVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,10 +149,5 @@ public abstract class AbstractEntity implements Serializable, Comparable<Abstrac
|
|||||||
return entity.getId();
|
return entity.getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public EntityFacade getFacade() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -122,7 +122,6 @@ public class AccessToken extends AbstractEntity implements AuthenticationInfo {
|
|||||||
return SecurityUtils.asSubject(getPrincipals());
|
return SecurityUtils.asSubject(getPrincipals());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AccessTokenFacade getFacade() {
|
public AccessTokenFacade getFacade() {
|
||||||
return new AccessTokenFacade(getId(), getOwner().getId(), getName(), getValue(), getExpireDate());
|
return new AccessTokenFacade(getId(), getOwner().getId(), getName(), getValue(), getExpireDate());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import io.onedev.server.rest.annotation.Immutable;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(
|
@Table(
|
||||||
@ -21,6 +29,7 @@ public class AccessTokenAuthorization extends AbstractEntity {
|
|||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@JoinColumn(nullable=false)
|
@JoinColumn(nullable=false)
|
||||||
|
@Immutable
|
||||||
private AccessToken token;
|
private AccessToken token;
|
||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@ -50,5 +59,5 @@ public class AccessTokenAuthorization extends AbstractEntity {
|
|||||||
public void setRole(Role role) {
|
public void setRole(Role role) {
|
||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
116
server-core/src/main/java/io/onedev/server/model/Audit.java
Normal file
116
server-core/src/main/java/io/onedev/server/model/Audit.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package io.onedev.server.model;
|
||||||
|
|
||||||
|
import static io.onedev.server.model.Audit.PROP_ACTION;
|
||||||
|
import static io.onedev.server.model.Audit.PROP_DATE;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(
|
||||||
|
indexes={
|
||||||
|
@Index(columnList="o_project_id"), @Index(columnList= "o_user_id"),
|
||||||
|
@Index(columnList= PROP_DATE), @Index(columnList= PROP_ACTION)}
|
||||||
|
)
|
||||||
|
public class Audit extends AbstractEntity {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final int MAX_ACTION_LEN = 512;
|
||||||
|
|
||||||
|
private static final int MAX_CONTENT_LEN = 1048576;
|
||||||
|
|
||||||
|
public static final String PROP_PROJECT = "project";
|
||||||
|
|
||||||
|
public static final String PROP_USER = "user";
|
||||||
|
|
||||||
|
public static final String PROP_ACTION = "action";
|
||||||
|
|
||||||
|
public static final String PROP_DATE = "date";
|
||||||
|
|
||||||
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
|
@JoinColumn
|
||||||
|
private Project project;
|
||||||
|
|
||||||
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
|
@JoinColumn(nullable=false)
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
@Column(nullable=false, length=MAX_ACTION_LEN)
|
||||||
|
private String action;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Date date = new Date();
|
||||||
|
|
||||||
|
@Column(length=MAX_CONTENT_LEN)
|
||||||
|
private String oldContent;
|
||||||
|
|
||||||
|
@Column(length=MAX_CONTENT_LEN)
|
||||||
|
private String newContent;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Project getProject() {
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProject(@Nullable Project project) {
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(@Nullable User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAction(String action) {
|
||||||
|
if (action.length() > MAX_ACTION_LEN)
|
||||||
|
throw new IllegalArgumentException("Audit action is too long: " + action);
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getOldContent() {
|
||||||
|
return oldContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOldContent(@Nullable String oldContent) {
|
||||||
|
if (oldContent != null && oldContent.length() > MAX_CONTENT_LEN)
|
||||||
|
throw new IllegalArgumentException("Audit content is too long: " + oldContent);
|
||||||
|
this.oldContent = oldContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getNewContent() {
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewContent(@Nullable String newContent) {
|
||||||
|
if (newContent != null && newContent.length() > MAX_CONTENT_LEN)
|
||||||
|
throw new IllegalArgumentException("Audit content is too long: " + newContent);
|
||||||
|
this.newContent = newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -11,6 +11,8 @@ import javax.persistence.UniqueConstraint;
|
|||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
|
import io.onedev.server.rest.annotation.Immutable;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(
|
@Table(
|
||||||
indexes={@Index(columnList="o_project_id"), @Index(columnList="o_role_id")},
|
indexes={@Index(columnList="o_project_id"), @Index(columnList="o_role_id")},
|
||||||
@ -27,6 +29,7 @@ public class BaseAuthorization extends AbstractEntity {
|
|||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@JoinColumn(nullable=false)
|
@JoinColumn(nullable=false)
|
||||||
|
@Immutable
|
||||||
private Project project;
|
private Project project;
|
||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
|
|||||||
@ -896,7 +896,6 @@ public class Build extends ProjectBelonging
|
|||||||
return commitsCache.get(sincePrevStatus);
|
return commitsCache.get(sincePrevStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BuildFacade getFacade() {
|
public BuildFacade getFacade() {
|
||||||
return new BuildFacade(getId(), getProject().getId(), getNumber(), getCommitHash());
|
return new BuildFacade(getId(), getProject().getId(), getNumber(), getCommitHash());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,7 +103,6 @@ public class EmailAddress extends AbstractEntity {
|
|||||||
return getVerificationCode() == null;
|
return getVerificationCode() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public EmailAddressFacade getFacade() {
|
public EmailAddressFacade getFacade() {
|
||||||
return new EmailAddressFacade(getId(), getOwner().getId(), getValue(),
|
return new EmailAddressFacade(getId(), getOwner().getId(), getValue(),
|
||||||
isPrimary(), isGit(), isOpen(), getVerificationCode());
|
isPrimary(), isGit(), isOpen(), getVerificationCode());
|
||||||
|
|||||||
@ -15,8 +15,9 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
import io.onedev.server.model.support.BaseGpgKey;
|
|
||||||
import io.onedev.server.annotation.Editable;
|
import io.onedev.server.annotation.Editable;
|
||||||
|
import io.onedev.server.model.support.BaseGpgKey;
|
||||||
|
import io.onedev.server.rest.annotation.Immutable;
|
||||||
|
|
||||||
@Editable
|
@Editable
|
||||||
@Entity
|
@Entity
|
||||||
@ -38,6 +39,7 @@ public class GpgKey extends BaseGpgKey {
|
|||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@JoinColumn(nullable=false)
|
@JoinColumn(nullable=false)
|
||||||
|
@Immutable
|
||||||
private User owner;
|
private User owner;
|
||||||
|
|
||||||
public long getKeyId() {
|
public long getKeyId() {
|
||||||
|
|||||||
@ -1,5 +1,20 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.Permission;
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import io.onedev.server.annotation.Editable;
|
import io.onedev.server.annotation.Editable;
|
||||||
import io.onedev.server.annotation.ShowCondition;
|
import io.onedev.server.annotation.ShowCondition;
|
||||||
import io.onedev.server.security.permission.BasePermission;
|
import io.onedev.server.security.permission.BasePermission;
|
||||||
@ -9,19 +24,6 @@ import io.onedev.server.security.permission.SystemAdministration;
|
|||||||
import io.onedev.server.util.EditContext;
|
import io.onedev.server.util.EditContext;
|
||||||
import io.onedev.server.util.facade.GroupFacade;
|
import io.onedev.server.util.facade.GroupFacade;
|
||||||
import io.onedev.server.util.facade.UserFacade;
|
import io.onedev.server.util.facade.UserFacade;
|
||||||
import org.apache.shiro.authz.Permission;
|
|
||||||
import org.hibernate.annotations.Cache;
|
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
|
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
|
||||||
@ -92,7 +94,7 @@ public class Group extends AbstractEntity implements BasePermission {
|
|||||||
return !(boolean) EditContext.get().getInputValue("administrator");
|
return !(boolean) EditContext.get().getInputValue("administrator");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Editable(order=300, name="Can Create Root Projects", description="Whether or not to allow creating root projects (project without parent)")
|
@Editable(order=350, name="Can Create Root Projects", description="Whether or not to allow creating root projects (project without parent)")
|
||||||
@ShowCondition("isAdministratorDisabled")
|
@ShowCondition("isAdministratorDisabled")
|
||||||
public boolean isCreateRootProjects() {
|
public boolean isCreateRootProjects() {
|
||||||
return createRootProjects;
|
return createRootProjects;
|
||||||
@ -145,7 +147,6 @@ public class Group extends AbstractEntity implements BasePermission {
|
|||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public GroupFacade getFacade() {
|
public GroupFacade getFacade() {
|
||||||
return new GroupFacade(getId(), getName());
|
return new GroupFacade(getId(), getName());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -929,7 +929,6 @@ public class Issue extends ProjectBelonging implements AttachmentStorageSupport
|
|||||||
return observables;
|
return observables;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IssueFacade getFacade() {
|
public IssueFacade getFacade() {
|
||||||
return new IssueFacade(getId(), getProject().getId(), getNumber());
|
return new IssueFacade(getId(), getProject().getId(), getNumber());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,7 +81,6 @@ public class IssueComment extends EntityComment {
|
|||||||
this.revisions = revisions;
|
this.revisions = revisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IssueCommentFacade getFacade() {
|
public IssueCommentFacade getFacade() {
|
||||||
return new IssueCommentFacade(getId(), getIssue().getId(), getContent());
|
return new IssueCommentFacade(getId(), getIssue().getId(), getContent());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,28 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
import io.onedev.server.rest.annotation.Immutable;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import javax.persistence.*;
|
import io.onedev.server.rest.annotation.Immutable;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(
|
@Table(
|
||||||
@ -39,11 +54,14 @@ public class Iteration extends AbstractEntity {
|
|||||||
@Column(nullable=false)
|
@Column(nullable=false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Api(description="Description of the iteration. May be null")
|
||||||
@Column(length=MAX_DESCRIPTION_LEN)
|
@Column(length=MAX_DESCRIPTION_LEN)
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@Api(description="Start of the iteration in epoc day. May be null")
|
||||||
private Long startDay;
|
private Long startDay;
|
||||||
|
|
||||||
|
@Api(description="Due of the iteration in epoc day. May be null")
|
||||||
private Long dueDay;
|
private Long dueDay;
|
||||||
|
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
|
|||||||
@ -1,17 +1,24 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
|
import static io.onedev.server.model.LabelSpec.PROP_NAME;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
import io.onedev.server.annotation.Color;
|
import io.onedev.server.annotation.Color;
|
||||||
import io.onedev.server.annotation.Editable;
|
import io.onedev.server.annotation.Editable;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import org.hibernate.annotations.Cache;
|
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import static io.onedev.server.model.LabelSpec.PROP_NAME;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(indexes={@Index(columnList=PROP_NAME)})
|
@Table(indexes={@Index(columnList=PROP_NAME)})
|
||||||
|
|||||||
@ -96,6 +96,14 @@ public class LinkSpec extends AbstractEntity {
|
|||||||
return opposite?getOpposite().getName():getName();
|
return opposite?getOpposite().getName():getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
if (opposite != null) {
|
||||||
|
return getName() + " - " + getOpposite().getName();
|
||||||
|
} else {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
@ -162,7 +170,6 @@ public class LinkSpec extends AbstractEntity {
|
|||||||
return updaters;
|
return updaters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LinkSpecFacade getFacade() {
|
public LinkSpecFacade getFacade() {
|
||||||
return new LinkSpecFacade(getId(), getName(), getOpposite()!=null?getOpposite().getName():null);
|
return new LinkSpecFacade(getId(), getName(), getOpposite()!=null?getOpposite().getName():null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(
|
@Table(
|
||||||
indexes={@Index(columnList="o_user_id"), @Index(columnList="o_group_id")},
|
indexes={@Index(columnList="o_user_id"), @Index(columnList="o_group_id")},
|
||||||
@ -42,5 +48,5 @@ public class Membership extends AbstractEntity {
|
|||||||
public void setGroup(Group group) {
|
public void setGroup(Group group) {
|
||||||
this.group = group;
|
this.group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
import static com.fasterxml.jackson.annotation.JsonProperty.Access.READ_ONLY;
|
|
||||||
import static io.onedev.commons.utils.match.WildcardUtils.matchPath;
|
import static io.onedev.commons.utils.match.WildcardUtils.matchPath;
|
||||||
import static io.onedev.server.model.Project.PROP_NAME;
|
import static io.onedev.server.model.Project.PROP_NAME;
|
||||||
import static io.onedev.server.search.entity.EntitySort.Direction.DESCENDING;
|
import static io.onedev.server.search.entity.EntitySort.Direction.DESCENDING;
|
||||||
@ -58,8 +57,6 @@ import org.hibernate.annotations.Cache;
|
|||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@ -128,7 +125,6 @@ import io.onedev.server.model.support.pack.ProjectPackSetting;
|
|||||||
import io.onedev.server.model.support.pullrequest.MergeStrategy;
|
import io.onedev.server.model.support.pullrequest.MergeStrategy;
|
||||||
import io.onedev.server.model.support.pullrequest.NamedPullRequestQuery;
|
import io.onedev.server.model.support.pullrequest.NamedPullRequestQuery;
|
||||||
import io.onedev.server.model.support.pullrequest.ProjectPullRequestSetting;
|
import io.onedev.server.model.support.pullrequest.ProjectPullRequestSetting;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.search.entity.SortField;
|
import io.onedev.server.search.entity.SortField;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.util.ComponentContext;
|
import io.onedev.server.util.ComponentContext;
|
||||||
@ -251,17 +247,12 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@JoinColumn(nullable=true)
|
@JoinColumn(nullable=true)
|
||||||
@Api(description="Represents the project from which this project is forked. Remove this property if "
|
|
||||||
+ "the project is not a fork when create/update the project. May be null")
|
|
||||||
private Project forkedFrom;
|
private Project forkedFrom;
|
||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@JoinColumn
|
@JoinColumn
|
||||||
@Api(description="Represents the parent project. Remove this property if the project does not " +
|
|
||||||
"have a parent project. May be null")
|
|
||||||
private Project parent;
|
private Project parent;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@OneToOne(fetch = FetchType.LAZY)
|
@OneToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(unique=true, nullable=false)
|
@JoinColumn(unique=true, nullable=false)
|
||||||
private ProjectLastEventDate lastEventDate;
|
private ProjectLastEventDate lastEventDate;
|
||||||
@ -269,21 +260,15 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
@Column(nullable=false)
|
@Column(nullable=false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@JsonProperty(access = READ_ONLY)
|
|
||||||
@Column(nullable=false)
|
@Column(nullable=false)
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private int pathLen;
|
private int pathLen;
|
||||||
|
|
||||||
// SQL Server does not allow duplicate null values for unique column. So we use
|
|
||||||
// special prefix to indicate null
|
|
||||||
@JsonIgnore
|
|
||||||
@Column(unique=true)
|
@Column(unique=true)
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
@Column(length=MAX_DESCRIPTION_LEN)
|
@Column(length=MAX_DESCRIPTION_LEN)
|
||||||
@Api(description = "May be null")
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@OneToMany(mappedBy="project")
|
@OneToMany(mappedBy="project")
|
||||||
@ -298,23 +283,19 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
@OneToMany(mappedBy="project", cascade=CascadeType.REMOVE)
|
@OneToMany(mappedBy="project", cascade=CascadeType.REMOVE)
|
||||||
private Collection<Pack> packs = new ArrayList<>();
|
private Collection<Pack> packs = new ArrayList<>();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(nullable=false, length=65535)
|
@Column(nullable=false, length=65535)
|
||||||
private ArrayList<BranchProtection> branchProtections = new ArrayList<>();
|
private ArrayList<BranchProtection> branchProtections = new ArrayList<>();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(nullable=false, length=65535)
|
@Column(nullable=false, length=65535)
|
||||||
private ArrayList<TagProtection> tagProtections = new ArrayList<>();
|
private ArrayList<TagProtection> tagProtections = new ArrayList<>();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(nullable=false, length=65535)
|
@Column(nullable=false, length=65535)
|
||||||
private LinkedHashMap<String, ContributedProjectSetting> contributedSettings = new LinkedHashMap<>();
|
private LinkedHashMap<String, ContributedProjectSetting> contributedSettings = new LinkedHashMap<>();
|
||||||
|
|
||||||
@Column(nullable=false)
|
@Column(nullable=false)
|
||||||
@JsonProperty(access = READ_ONLY)
|
|
||||||
private Date createDate = new Date();
|
private Date createDate = new Date();
|
||||||
|
|
||||||
@OneToMany(mappedBy="targetProject", cascade=CascadeType.REMOVE)
|
@OneToMany(mappedBy="targetProject", cascade=CascadeType.REMOVE)
|
||||||
@ -387,6 +368,10 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
@OneToMany(mappedBy="project", cascade=CascadeType.REMOVE)
|
@OneToMany(mappedBy="project", cascade=CascadeType.REMOVE)
|
||||||
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
|
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
|
||||||
private Collection<Iteration> iterations = new ArrayList<>();
|
private Collection<Iteration> iterations = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(mappedBy="project", cascade=CascadeType.REMOVE)
|
||||||
|
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
|
||||||
|
private Collection<Audit> audits = new ArrayList<>();
|
||||||
|
|
||||||
private boolean codeManagement = true;
|
private boolean codeManagement = true;
|
||||||
|
|
||||||
@ -409,37 +394,30 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
@Column(unique=true)
|
@Column(unique=true)
|
||||||
private String serviceDeskEmailAddress;
|
private String serviceDeskEmailAddress;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535, nullable=false)
|
@Column(length=65535, nullable=false)
|
||||||
private ProjectIssueSetting issueSetting = new ProjectIssueSetting();
|
private ProjectIssueSetting issueSetting = new ProjectIssueSetting();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535, nullable=false)
|
@Column(length=65535, nullable=false)
|
||||||
private ProjectBuildSetting buildSetting = new ProjectBuildSetting();
|
private ProjectBuildSetting buildSetting = new ProjectBuildSetting();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535, nullable=false)
|
@Column(length=65535, nullable=false)
|
||||||
private ProjectPullRequestSetting pullRequestSetting = new ProjectPullRequestSetting();
|
private ProjectPullRequestSetting pullRequestSetting = new ProjectPullRequestSetting();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535, nullable=false)
|
@Column(length=65535, nullable=false)
|
||||||
private ProjectPackSetting packSetting = new ProjectPackSetting();
|
private ProjectPackSetting packSetting = new ProjectPackSetting();
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535)
|
@Column(length=65535)
|
||||||
private ArrayList<NamedCommitQuery> namedCommitQueries;
|
private ArrayList<NamedCommitQuery> namedCommitQueries;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535)
|
@Column(length=65535)
|
||||||
private ArrayList<NamedCodeCommentQuery> namedCodeCommentQueries;
|
private ArrayList<NamedCodeCommentQuery> namedCodeCommentQueries;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(length=65535, nullable=false)
|
@Column(length=65535, nullable=false)
|
||||||
private ArrayList<WebHook> webHooks = new ArrayList<>();
|
private ArrayList<WebHook> webHooks = new ArrayList<>();
|
||||||
@ -774,7 +752,6 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
return blobCache;
|
return blobCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProjectFacade getFacade() {
|
public ProjectFacade getFacade() {
|
||||||
return new ProjectFacade(getId(), getName(), getKey(), getPath(), getServiceDeskEmailAddress(),
|
return new ProjectFacade(getId(), getName(), getKey(), getPath(), getServiceDeskEmailAddress(),
|
||||||
isCodeManagement(), isIssueManagement(), getGitPackConfig(), lastEventDate.getId(),
|
isCodeManagement(), isIssueManagement(), getGitPackConfig(), lastEventDate.getId(),
|
||||||
@ -1088,15 +1065,13 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
"the system email address in mail setting definition. Emails sent to this address will be " +
|
"the system email address in mail setting definition. Emails sent to this address will be " +
|
||||||
"created as issues in this project. The default value takes form of "
|
"created as issues in this project. The default value takes form of "
|
||||||
+ "<tt><system email address name>+<project path>@<system email address domain></tt>")
|
+ "<tt><system email address name>+<project path>@<system email address domain></tt>")
|
||||||
@Nullable
|
|
||||||
@JsonProperty
|
|
||||||
@Email
|
@Email
|
||||||
@Pattern(regexp = "[^~]+@.+", message = "character '~' not allowed in name part")
|
@Pattern(regexp = "[^~]+@.+", message = "character '~' not allowed in name part")
|
||||||
public String getServiceDeskEmailAddress() {
|
public String getServiceDeskEmailAddress() {
|
||||||
return serviceDeskEmailAddress;
|
return serviceDeskEmailAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServiceDeskEmailAddress(@Nullable String serviceDeskEmailAddress) {
|
public void setServiceDeskEmailAddress(String serviceDeskEmailAddress) {
|
||||||
this.serviceDeskEmailAddress = serviceDeskEmailAddress;
|
this.serviceDeskEmailAddress = serviceDeskEmailAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2042,4 +2017,18 @@ public class Project extends AbstractEntity implements LabelSupport<ProjectLabel
|
|||||||
return decodeRepoNameAsPath(replace(text, FAKED_GITHUB_REPO_OWNER + "/", ""));
|
return decodeRepoNameAsPath(replace(text, FAKED_GITHUB_REPO_OWNER + "/", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Collection<Project> getIndependents(Collection<Project> projects) {
|
||||||
|
Collection<Project> independents = new HashSet<>(projects);
|
||||||
|
for (Iterator<Project> it = independents.iterator(); it.hasNext(); ) {
|
||||||
|
Project independent = it.next();
|
||||||
|
for (Project each : independents) {
|
||||||
|
if (!each.equals(independent) && each.isSelfOrAncestorOf(independent)) {
|
||||||
|
it.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return independents;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,7 +70,6 @@ public class PullRequestComment extends EntityComment {
|
|||||||
this.revisions = revisions;
|
this.revisions = revisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PullRequestCommentFacade getFacade() {
|
public PullRequestCommentFacade getFacade() {
|
||||||
return new PullRequestCommentFacade(getId(), getRequest().getId(), getContent());
|
return new PullRequestCommentFacade(getId(), getRequest().getId(), getContent());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,29 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.Permission;
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
import io.onedev.server.annotation.ChoiceProvider;
|
import io.onedev.server.annotation.ChoiceProvider;
|
||||||
import io.onedev.server.annotation.Editable;
|
import io.onedev.server.annotation.Editable;
|
||||||
@ -8,21 +31,40 @@ import io.onedev.server.annotation.RoleName;
|
|||||||
import io.onedev.server.annotation.ShowCondition;
|
import io.onedev.server.annotation.ShowCondition;
|
||||||
import io.onedev.server.entitymanager.LinkSpecManager;
|
import io.onedev.server.entitymanager.LinkSpecManager;
|
||||||
import io.onedev.server.entitymanager.SettingManager;
|
import io.onedev.server.entitymanager.SettingManager;
|
||||||
import io.onedev.server.model.support.role.*;
|
import io.onedev.server.model.support.role.AllIssueFields;
|
||||||
import io.onedev.server.security.permission.*;
|
import io.onedev.server.model.support.role.CodePrivilege;
|
||||||
|
import io.onedev.server.model.support.role.IssueFieldSet;
|
||||||
|
import io.onedev.server.model.support.role.JobPrivilege;
|
||||||
|
import io.onedev.server.model.support.role.PackPrivilege;
|
||||||
|
import io.onedev.server.security.permission.AccessBuild;
|
||||||
|
import io.onedev.server.security.permission.AccessBuildLog;
|
||||||
|
import io.onedev.server.security.permission.AccessBuildPipeline;
|
||||||
|
import io.onedev.server.security.permission.AccessBuildReports;
|
||||||
|
import io.onedev.server.security.permission.AccessConfidentialIssues;
|
||||||
|
import io.onedev.server.security.permission.AccessProject;
|
||||||
|
import io.onedev.server.security.permission.AccessTimeTracking;
|
||||||
|
import io.onedev.server.security.permission.BasePermission;
|
||||||
|
import io.onedev.server.security.permission.CreateChildren;
|
||||||
|
import io.onedev.server.security.permission.EditIssueField;
|
||||||
|
import io.onedev.server.security.permission.EditIssueLink;
|
||||||
|
import io.onedev.server.security.permission.JobPermission;
|
||||||
|
import io.onedev.server.security.permission.ManageBuilds;
|
||||||
|
import io.onedev.server.security.permission.ManageCodeComments;
|
||||||
|
import io.onedev.server.security.permission.ManageIssues;
|
||||||
|
import io.onedev.server.security.permission.ManageJob;
|
||||||
|
import io.onedev.server.security.permission.ManageProject;
|
||||||
|
import io.onedev.server.security.permission.ManagePullRequests;
|
||||||
|
import io.onedev.server.security.permission.ReadCode;
|
||||||
|
import io.onedev.server.security.permission.ReadPack;
|
||||||
|
import io.onedev.server.security.permission.RunJob;
|
||||||
|
import io.onedev.server.security.permission.ScheduleIssues;
|
||||||
|
import io.onedev.server.security.permission.UploadCache;
|
||||||
|
import io.onedev.server.security.permission.WriteCode;
|
||||||
|
import io.onedev.server.security.permission.WritePack;
|
||||||
import io.onedev.server.util.EditContext;
|
import io.onedev.server.util.EditContext;
|
||||||
import io.onedev.server.util.facade.RoleFacade;
|
import io.onedev.server.util.facade.RoleFacade;
|
||||||
import io.onedev.server.util.facade.UserFacade;
|
import io.onedev.server.util.facade.UserFacade;
|
||||||
import io.onedev.server.web.util.WicketUtils;
|
import io.onedev.server.web.util.WicketUtils;
|
||||||
import org.apache.shiro.authz.Permission;
|
|
||||||
import org.hibernate.annotations.Cache;
|
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author robin
|
* @author robin
|
||||||
@ -37,6 +79,7 @@ public class Role extends AbstractEntity implements BasePermission {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public static final String PROP_NAME = "name";
|
public static final String PROP_NAME = "name";
|
||||||
|
|
||||||
public static final Long OWNER_ID = 1L;
|
public static final Long OWNER_ID = 1L;
|
||||||
|
|
||||||
@Column(nullable=false, unique=true)
|
@Column(nullable=false, unique=true)
|
||||||
@ -272,10 +315,7 @@ public class Role extends AbstractEntity implements BasePermission {
|
|||||||
private static Map<String, String> getIssueLinkDisplayNames() {
|
private static Map<String, String> getIssueLinkDisplayNames() {
|
||||||
Map<String, String> choices = new LinkedHashMap<>();
|
Map<String, String> choices = new LinkedHashMap<>();
|
||||||
for (LinkSpec link: OneDev.getInstance(LinkSpecManager.class).queryAndSort()) {
|
for (LinkSpec link: OneDev.getInstance(LinkSpecManager.class).queryAndSort()) {
|
||||||
if (link.getOpposite() != null)
|
choices.put(link.getName(), link.getDisplayName());
|
||||||
choices.put(link.getName(), link.getName() + " - " + link.getOpposite().getName());
|
|
||||||
else
|
|
||||||
choices.put(link.getName(), link.getName());
|
|
||||||
}
|
}
|
||||||
return choices;
|
return choices;
|
||||||
}
|
}
|
||||||
@ -338,7 +378,6 @@ public class Role extends AbstractEntity implements BasePermission {
|
|||||||
this.linkAuthorizations = linkAuthorizations;
|
this.linkAuthorizations = linkAuthorizations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RoleFacade getFacade() {
|
public RoleFacade getFacade() {
|
||||||
return new RoleFacade(getId(), getName());
|
return new RoleFacade(getId(), getName());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ public class Setting extends AbstractEntity {
|
|||||||
GROOVY_SCRIPTS, PULL_REQUEST, BUILD, PACK, PROJECT, SSH, GPG, SSO_CONNECTORS,
|
GROOVY_SCRIPTS, PULL_REQUEST, BUILD, PACK, PROJECT, SSH, GPG, SSO_CONNECTORS,
|
||||||
EMAIL_TEMPLATES, CONTRIBUTED_SETTINGS, SERVICE_DESK_SETTING,
|
EMAIL_TEMPLATES, CONTRIBUTED_SETTINGS, SERVICE_DESK_SETTING,
|
||||||
AGENT, PERFORMANCE, BRANDING, CLUSTER_SETTING, SUBSCRIPTION_DATA, ALERT,
|
AGENT, PERFORMANCE, BRANDING, CLUSTER_SETTING, SUBSCRIPTION_DATA, ALERT,
|
||||||
SYSTEM_UUID
|
SYSTEM_UUID, AUDIT
|
||||||
};
|
};
|
||||||
|
|
||||||
@Column(nullable=false, unique=true)
|
@Column(nullable=false, unique=true)
|
||||||
|
|||||||
@ -1,26 +1,36 @@
|
|||||||
package io.onedev.server.model;
|
package io.onedev.server.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import java.io.IOException;
|
||||||
import io.onedev.commons.utils.StringUtils;
|
import java.security.GeneralSecurityException;
|
||||||
import io.onedev.server.annotation.ClassValidating;
|
import java.security.PublicKey;
|
||||||
import io.onedev.server.annotation.Editable;
|
import java.util.Date;
|
||||||
import io.onedev.server.annotation.Multiline;
|
|
||||||
import io.onedev.server.annotation.OmitName;
|
import javax.annotation.Nullable;
|
||||||
import io.onedev.server.ssh.SshKeyUtils;
|
import javax.persistence.Column;
|
||||||
import io.onedev.server.validation.Validatable;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Index;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
import org.apache.sshd.common.config.keys.KeyUtils;
|
import org.apache.sshd.common.config.keys.KeyUtils;
|
||||||
import org.apache.sshd.common.digest.BuiltinDigests;
|
import org.apache.sshd.common.digest.BuiltinDigests;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import javax.persistence.*;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import io.onedev.commons.utils.StringUtils;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import io.onedev.server.annotation.ClassValidating;
|
||||||
import java.io.IOException;
|
import io.onedev.server.annotation.Editable;
|
||||||
import java.security.GeneralSecurityException;
|
import io.onedev.server.annotation.Multiline;
|
||||||
import java.security.PublicKey;
|
import io.onedev.server.annotation.OmitName;
|
||||||
import java.util.Date;
|
import io.onedev.server.rest.annotation.Immutable;
|
||||||
|
import io.onedev.server.ssh.SshKeyUtils;
|
||||||
|
import io.onedev.server.validation.Validatable;
|
||||||
|
|
||||||
@Editable
|
@Editable
|
||||||
@Entity
|
@Entity
|
||||||
@ -44,6 +54,7 @@ public class SshKey extends AbstractEntity implements Validatable {
|
|||||||
|
|
||||||
@ManyToOne(fetch=FetchType.LAZY)
|
@ManyToOne(fetch=FetchType.LAZY)
|
||||||
@JoinColumn(nullable=false)
|
@JoinColumn(nullable=false)
|
||||||
|
@Immutable
|
||||||
private User owner;
|
private User owner;
|
||||||
|
|
||||||
@Editable(name="OpenSSH Public Key", placeholder="OpenSSH public key begins with 'ssh-rsa', "
|
@Editable(name="OpenSSH Public Key", placeholder="OpenSSH public key begins with 'ssh-rsa', "
|
||||||
@ -93,7 +104,7 @@ public class SshKey extends AbstractEntity implements Validatable {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fingerprint() {
|
public void generateFingerprint() {
|
||||||
try {
|
try {
|
||||||
PublicKey pubEntry = SshKeyUtils.decodeSshPublicKey(content);
|
PublicKey pubEntry = SshKeyUtils.decodeSshPublicKey(content);
|
||||||
fingerprint = KeyUtils.getFingerPrint(BuiltinDigests.sha256, pubEntry);
|
fingerprint = KeyUtils.getFingerPrint(BuiltinDigests.sha256, pubEntry);
|
||||||
|
|||||||
@ -1076,7 +1076,6 @@ public class User extends AbstractEntity implements AuthenticationInfo {
|
|||||||
return publicEmailAddress.orElse(null);
|
return publicEmailAddress.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserFacade getFacade() {
|
public UserFacade getFacade() {
|
||||||
return new UserFacade(getId(), getName(), getFullName(), isServiceAccount(), isDisabled());
|
return new UserFacade(getId(), getName(), getFullName(), isServiceAccount(), isDisabled());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public class CodeAnalysisSetting implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Api(description = "May be null")
|
@Api(description = "<code>null</code> to inherit from parent project, or all files if no parent")
|
||||||
private String analysisFiles;
|
private String analysisFiles;
|
||||||
|
|
||||||
@Editable(order=100, name="Files to Be Analyzed", placeholder="Inherit from parent", rootPlaceholder ="All files", description="OneDev analyzes repository files for code search, "
|
@Editable(order=100, name="Files to Be Analyzed", placeholder="Inherit from parent", rootPlaceholder ="All files", description="OneDev analyzes repository files for code search, "
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
package io.onedev.server.model.support;
|
package io.onedev.server.model.support;
|
||||||
|
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
import io.onedev.server.model.AbstractEntity;
|
import io.onedev.server.model.AbstractEntity;
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.util.facade.ProjectBelongingFacade;
|
|
||||||
|
|
||||||
import javax.persistence.MappedSuperclass;
|
|
||||||
|
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
public abstract class ProjectBelonging extends AbstractEntity {
|
public abstract class ProjectBelonging extends AbstractEntity {
|
||||||
@ -12,15 +11,5 @@ public abstract class ProjectBelonging extends AbstractEntity {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public abstract Project getProject();
|
public abstract Project getProject();
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProjectBelongingFacade getOldVersion() {
|
|
||||||
return (ProjectBelongingFacade) super.getOldVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProjectBelongingFacade getFacade() {
|
|
||||||
return new ProjectBelongingFacade(getId(), getProject().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
package io.onedev.server.model.support.administration;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
|
||||||
|
import io.onedev.server.annotation.Editable;
|
||||||
|
import io.onedev.server.annotation.OmitName;
|
||||||
|
|
||||||
|
@Editable
|
||||||
|
public class AuditSetting implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final String PROP_PRESERVE_DAYS = "preserveDays";
|
||||||
|
|
||||||
|
private int preserveDays = 365;
|
||||||
|
|
||||||
|
@Editable(order = 100, name="Preserve Days", description = "Audit log will be preserved for the specified number of days. " +
|
||||||
|
"This setting applies to all audit events, including system level and project level")
|
||||||
|
@OmitName
|
||||||
|
@Min(value = 7, message = "At least 7 days should be specified")
|
||||||
|
public int getPreserveDays() {
|
||||||
|
return preserveDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreserveDays(int preserveDays) {
|
||||||
|
this.preserveDays = preserveDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,19 @@
|
|||||||
package io.onedev.server.model.support.administration;
|
package io.onedev.server.model.support.administration;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
import io.onedev.server.ServerConfig;
|
import io.onedev.server.ServerConfig;
|
||||||
import io.onedev.server.annotation.ClassValidating;
|
import io.onedev.server.annotation.ClassValidating;
|
||||||
@ -13,16 +26,6 @@ import io.onedev.server.git.location.SystemGit;
|
|||||||
import io.onedev.server.util.EditContext;
|
import io.onedev.server.util.EditContext;
|
||||||
import io.onedev.server.validation.Validatable;
|
import io.onedev.server.validation.Validatable;
|
||||||
import io.onedev.server.web.util.WicketUtils;
|
import io.onedev.server.web.util.WicketUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
@Editable
|
@Editable
|
||||||
@ClassValidating
|
@ClassValidating
|
||||||
@ -47,7 +50,7 @@ public class SystemSetting implements Serializable, Validatable {
|
|||||||
private GitLocation gitLocation = new SystemGit();
|
private GitLocation gitLocation = new SystemGit();
|
||||||
|
|
||||||
private CurlLocation curlLocation = new SystemCurl();
|
private CurlLocation curlLocation = new SystemCurl();
|
||||||
|
|
||||||
private boolean disableAutoUpdateCheck;
|
private boolean disableAutoUpdateCheck;
|
||||||
|
|
||||||
private boolean disableDashboard;
|
private boolean disableDashboard;
|
||||||
|
|||||||
@ -12,16 +12,16 @@ public class GitPackConfig implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Api(description = "May be null", example = "0")
|
@Api(description = "<code>null</code> for default setting", example = "0")
|
||||||
private String windowMemory;
|
private String windowMemory;
|
||||||
|
|
||||||
@Api(description = "May be null", example="1g")
|
@Api(description = "<code>null</code> for default setting", example="1g")
|
||||||
private String packSizeLimit;
|
private String packSizeLimit;
|
||||||
|
|
||||||
@Api(description = "May be null", example="0")
|
@Api(description = "<code>null</code> for default setting", example="0")
|
||||||
private String threads;
|
private String threads;
|
||||||
|
|
||||||
@Api(description = "May be null", example="10")
|
@Api(description = "<code>null</code> for default setting", example="10")
|
||||||
private String window;
|
private String window;
|
||||||
|
|
||||||
@Editable(order = 100, placeholder = "Use default", description = "Optionally specify value of git config " +
|
@Editable(order = 100, placeholder = "Use default", description = "Optionally specify value of git config " +
|
||||||
|
|||||||
@ -1,6 +1,25 @@
|
|||||||
package io.onedev.server.model.support.issue;
|
package io.onedev.server.model.support.issue;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
import org.unbescape.html.HtmlEscape;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
import io.onedev.server.annotation.ChoiceProvider;
|
import io.onedev.server.annotation.ChoiceProvider;
|
||||||
import io.onedev.server.annotation.Editable;
|
import io.onedev.server.annotation.Editable;
|
||||||
@ -19,15 +38,12 @@ import io.onedev.server.model.support.issue.field.spec.userchoicefield.UserChoic
|
|||||||
import io.onedev.server.search.entity.issue.IssueQueryUpdater;
|
import io.onedev.server.search.entity.issue.IssueQueryUpdater;
|
||||||
import io.onedev.server.util.EditContext;
|
import io.onedev.server.util.EditContext;
|
||||||
import io.onedev.server.util.usage.Usage;
|
import io.onedev.server.util.usage.Usage;
|
||||||
import io.onedev.server.web.component.issue.workflowreconcile.*;
|
import io.onedev.server.web.component.issue.workflowreconcile.ReconcileUtils;
|
||||||
|
import io.onedev.server.web.component.issue.workflowreconcile.UndefinedFieldResolution;
|
||||||
|
import io.onedev.server.web.component.issue.workflowreconcile.UndefinedFieldValue;
|
||||||
|
import io.onedev.server.web.component.issue.workflowreconcile.UndefinedFieldValuesResolution;
|
||||||
|
import io.onedev.server.web.component.issue.workflowreconcile.UndefinedStateResolution;
|
||||||
import io.onedev.server.web.component.stringchoice.StringChoiceProvider;
|
import io.onedev.server.web.component.stringchoice.StringChoiceProvider;
|
||||||
import org.unbescape.html.HtmlEscape;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.Size;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Editable
|
@Editable
|
||||||
public class BoardSpec implements Serializable {
|
public class BoardSpec implements Serializable {
|
||||||
@ -52,6 +68,8 @@ public class BoardSpec implements Serializable {
|
|||||||
|
|
||||||
private List<String> displayLinks = new ArrayList<>();
|
private List<String> displayLinks = new ArrayList<>();
|
||||||
|
|
||||||
|
@XStreamOmitField
|
||||||
|
@JsonIgnore
|
||||||
private List<String> editColumns;
|
private List<String> editColumns;
|
||||||
|
|
||||||
@Editable(order=100)
|
@Editable(order=100)
|
||||||
|
|||||||
@ -1,18 +1,30 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.server.entitymanager.AccessTokenAuthorizationManager;
|
import static io.onedev.server.security.SecurityUtils.canManageProject;
|
||||||
import io.onedev.server.model.AccessTokenAuthorization;
|
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import static io.onedev.server.security.SecurityUtils.isAdministrator;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.BadRequestException;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import static io.onedev.server.security.SecurityUtils.*;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AccessTokenAuthorizationManager;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.model.AccessTokenAuthorization;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
|
||||||
@Api(order=9500, description = "This resource manages project authorizations of access tokens. Note that " +
|
@Api(order=9500, description = "This resource manages project authorizations of access tokens. Note that " +
|
||||||
"project authorizations will not take effect if option <tt>hasOwnerPermissions</tt> is enabled " +
|
"project authorizations will not take effect if option <tt>hasOwnerPermissions</tt> is enabled " +
|
||||||
@ -25,15 +37,18 @@ public class AccessTokenAuthorizationResource {
|
|||||||
|
|
||||||
private final AccessTokenAuthorizationManager accessTokenAuthorizationManager;
|
private final AccessTokenAuthorizationManager accessTokenAuthorizationManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AccessTokenAuthorizationResource(AccessTokenAuthorizationManager accessTokenAuthorizationManager) {
|
public AccessTokenAuthorizationResource(AccessTokenAuthorizationManager accessTokenAuthorizationManager, AuditManager auditManager) {
|
||||||
this.accessTokenAuthorizationManager = accessTokenAuthorizationManager;
|
this.accessTokenAuthorizationManager = accessTokenAuthorizationManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100, description = "Get access token authorization of specified id")
|
@Api(order=100, description = "Get access token authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@GET
|
@GET
|
||||||
public AccessTokenAuthorization get(@PathParam("authorizationId") Long authorizationId) {
|
public AccessTokenAuthorization getAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
var authorization = accessTokenAuthorizationManager.load(authorizationId);
|
var authorization = accessTokenAuthorizationManager.load(authorizationId);
|
||||||
var owner = authorization.getToken().getOwner();
|
var owner = authorization.getToken().getOwner();
|
||||||
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
@ -43,38 +58,53 @@ public class AccessTokenAuthorizationResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create access token authorization. Access token owner should have permission to manage authorized project")
|
@Api(order=200, description="Create access token authorization. Access token owner should have permission to manage authorized project")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull AccessTokenAuthorization authorization) {
|
public Long createAuthorization(@NotNull AccessTokenAuthorization authorization) {
|
||||||
var owner = authorization.getToken().getOwner();
|
var owner = authorization.getToken().getOwner();
|
||||||
if (!isAdministrator() && !owner.equals(getAuthUser())
|
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
|| !canManageProject(owner.asSubject(), authorization.getProject())) {
|
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
}
|
if (!canManageProject(owner.asSubject(), authorization.getProject()))
|
||||||
|
throw new BadRequestException("Access token owner should have permission to manage authorized project");
|
||||||
|
|
||||||
accessTokenAuthorizationManager.createOrUpdate(authorization);
|
accessTokenAuthorizationManager.createOrUpdate(authorization);
|
||||||
|
if (!getAuthUser().equals(owner)) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(null, "created access token authorization for account \"" + owner.getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
|
}
|
||||||
return authorization.getId();
|
return authorization.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=250, description="Update access authorization of specified id. Access token owner should have permission to manage authorized project")
|
@Api(order=250, description="Update access authorization of specified id. Access token owner should have permission to manage authorized project")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("authorizationId") Long authorizationId, @NotNull AccessTokenAuthorization authorization) {
|
public Response updateAuthorization(@PathParam("authorizationId") Long authorizationId, @NotNull AccessTokenAuthorization authorization) {
|
||||||
var owner = authorization.getToken().getOwner();
|
var owner = authorization.getToken().getOwner();
|
||||||
if (!isAdministrator() && !owner.equals(getAuthUser())
|
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
|| !canManageProject(owner.asSubject(), authorization.getProject())) {
|
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
}
|
if (!canManageProject(owner.asSubject(), authorization.getProject()))
|
||||||
|
throw new BadRequestException("Access token owner should have permission to manage authorized project");
|
||||||
|
|
||||||
accessTokenAuthorizationManager.createOrUpdate(authorization);
|
accessTokenAuthorizationManager.createOrUpdate(authorization);
|
||||||
|
if (!getAuthUser().equals(owner)) {
|
||||||
|
var oldAuditContent = authorization.getOldVersion().toXML();
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(null, "changed access token authorization for account \"" + owner.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
|
}
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300, description = "Delete access token authorization of specified id")
|
@Api(order=300, description = "Delete access token authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("authorizationId") Long authorizationId) {
|
public Response deleteAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
var authorization = accessTokenAuthorizationManager.load(authorizationId);
|
var authorization = accessTokenAuthorizationManager.load(authorizationId);
|
||||||
var owner = authorization.getToken().getOwner();
|
var owner = authorization.getToken().getOwner();
|
||||||
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
accessTokenAuthorizationManager.delete(authorization);
|
accessTokenAuthorizationManager.delete(authorization);
|
||||||
|
if (!getAuthUser().equals(owner)) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(null, "deleted access token authorization for account \"" + owner.getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
|
}
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,34 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
||||||
import io.onedev.server.entitymanager.AccessTokenManager;
|
import static io.onedev.server.security.SecurityUtils.isAdministrator;
|
||||||
import io.onedev.server.model.AccessToken;
|
|
||||||
import io.onedev.server.model.AccessTokenAuthorization;
|
import java.util.Collection;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.BadRequestException;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
import static io.onedev.server.security.SecurityUtils.isAdministrator;
|
|
||||||
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AccessTokenManager;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.model.AccessToken;
|
||||||
|
import io.onedev.server.model.AccessTokenAuthorization;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
|
||||||
@Api(order=5030)
|
@Api(order=5030)
|
||||||
@Path("/access-tokens")
|
@Path("/access-tokens")
|
||||||
@ -27,16 +38,19 @@ import static io.onedev.server.security.SecurityUtils.isAdministrator;
|
|||||||
public class AccessTokenResource {
|
public class AccessTokenResource {
|
||||||
|
|
||||||
private final AccessTokenManager accessTokenManager;
|
private final AccessTokenManager accessTokenManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AccessTokenResource(AccessTokenManager accessTokenManager) {
|
public AccessTokenResource(AccessTokenManager accessTokenManager, AuditManager auditManager) {
|
||||||
this.accessTokenManager = accessTokenManager;
|
this.accessTokenManager = accessTokenManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{accessTokenId}")
|
@Path("/{accessTokenId}")
|
||||||
@GET
|
@GET
|
||||||
public AccessToken get(@PathParam("accessTokenId") Long accessTokenId) {
|
public AccessToken getToken(@PathParam("accessTokenId") Long accessTokenId) {
|
||||||
var accessToken = accessTokenManager.load(accessTokenId);
|
var accessToken = accessTokenManager.load(accessTokenId);
|
||||||
if (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))
|
if (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -55,7 +69,7 @@ public class AccessTokenResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create access token")
|
@Api(order=200, description="Create access token")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull @Valid AccessToken accessToken) {
|
public Long createToken(@NotNull @Valid AccessToken accessToken) {
|
||||||
var owner = accessToken.getOwner();
|
var owner = accessToken.getOwner();
|
||||||
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -64,35 +78,55 @@ public class AccessTokenResource {
|
|||||||
|
|
||||||
if (accessTokenManager.findByOwnerAndName(owner, accessToken.getName()) != null)
|
if (accessTokenManager.findByOwnerAndName(owner, accessToken.getName()) != null)
|
||||||
throw new ExplicitException("Name already used by another access token of the owner");
|
throw new ExplicitException("Name already used by another access token of the owner");
|
||||||
|
|
||||||
accessTokenManager.createOrUpdate(accessToken);
|
accessTokenManager.createOrUpdate(accessToken);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(owner)) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(accessToken.getFacade()).toXML();
|
||||||
|
auditManager.audit(null, "created access token \"" + accessToken.getName() + "\" for account \"" + owner.getName() + "\" via RESTful API",
|
||||||
|
null, newAuditContent);
|
||||||
|
}
|
||||||
|
|
||||||
return accessToken.getId();
|
return accessToken.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=250, description="Update access token")
|
@Api(order=250, description="Update access token")
|
||||||
@Path("/{accessTokenId}")
|
@Path("/{accessTokenId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("accessTokenId") Long accessTokenId, @NotNull @Valid AccessToken accessToken) {
|
public Response updateToken(@PathParam("accessTokenId") Long accessTokenId, @NotNull @Valid AccessToken accessToken) {
|
||||||
var owner = accessToken.getOwner();
|
var owner = accessToken.getOwner();
|
||||||
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
if (!isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
var accessTokenWithSameName = accessTokenManager.findByOwnerAndName(owner, accessToken.getName());
|
var accessTokenWithSameName = accessTokenManager.findByOwnerAndName(owner, accessToken.getName());
|
||||||
if (accessTokenWithSameName != null && !accessTokenWithSameName.equals(accessToken))
|
if (accessTokenWithSameName != null && !accessTokenWithSameName.equals(accessToken))
|
||||||
throw new ExplicitException("Name already used by another access token of the owner");
|
throw new BadRequestException("Name already used by another access token of the owner");
|
||||||
|
|
||||||
accessTokenManager.createOrUpdate(accessToken);
|
accessTokenManager.createOrUpdate(accessToken);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(owner)) {
|
||||||
|
var oldAuditContent = accessToken.getOldVersion().toXML();
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(accessToken).toXML();
|
||||||
|
auditManager.audit(null, "changed access token \"" + accessToken.getName() + "\" for account \"" + owner.getName() + "\" via RESTful API",
|
||||||
|
oldAuditContent, newAuditContent);
|
||||||
|
}
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{accessTokenId}")
|
@Path("/{accessTokenId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("accessTokenId") Long accessTokenId) {
|
public Response deleteToken(@PathParam("accessTokenId") Long accessTokenId) {
|
||||||
var accessToken = accessTokenManager.load(accessTokenId);
|
var accessToken = accessTokenManager.load(accessTokenId);
|
||||||
if (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))
|
if (!isAdministrator() && !accessToken.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
accessTokenManager.delete(accessToken);
|
accessTokenManager.delete(accessToken);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(accessToken.getOwner())) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(accessToken.getFacade()).toXML();
|
||||||
|
auditManager.audit(null, "deleted access token \"" + accessToken.getName() + "\" for account \"" + accessToken.getOwner().getName() + "\" via RESTful API",
|
||||||
|
oldAuditContent, null);
|
||||||
|
}
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,11 +18,13 @@ import javax.ws.rs.core.Response;
|
|||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
import io.onedev.server.entitymanager.AgentAttributeManager;
|
import io.onedev.server.entitymanager.AgentAttributeManager;
|
||||||
import io.onedev.server.entitymanager.AgentManager;
|
import io.onedev.server.entitymanager.AgentManager;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.model.Agent;
|
import io.onedev.server.model.Agent;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import io.onedev.server.search.entity.agent.AgentQuery;
|
import io.onedev.server.search.entity.agent.AgentQuery;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
|
||||||
@ -37,16 +39,19 @@ public class AgentResource {
|
|||||||
|
|
||||||
private final AgentAttributeManager agentAttributeManager;
|
private final AgentAttributeManager agentAttributeManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AgentResource(AgentManager agentManager, AgentAttributeManager agentAttributeManager) {
|
public AgentResource(AgentManager agentManager, AgentAttributeManager agentAttributeManager, AuditManager auditManager) {
|
||||||
this.agentManager = agentManager;
|
this.agentManager = agentManager;
|
||||||
this.agentAttributeManager = agentAttributeManager;
|
this.agentAttributeManager = agentAttributeManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{agentId}")
|
@Path("/{agentId}")
|
||||||
@GET
|
@GET
|
||||||
public Agent getBasicInfo(@PathParam("agentId") Long agentId) {
|
public Agent getAgent(@PathParam("agentId") Long agentId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return agentManager.load(agentId);
|
return agentManager.load(agentId);
|
||||||
@ -63,7 +68,7 @@ public class AgentResource {
|
|||||||
|
|
||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@GET
|
@GET
|
||||||
public List<Agent> queryBasicInfo(
|
public List<Agent> queryAgents(
|
||||||
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~administration/agents'>agent management page</a>", example="\"Name\" is \"agentName\"") String query,
|
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~administration/agents'>agent management page</a>", example="\"Name\" is \"agentName\"") String query,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
@ -89,8 +94,12 @@ public class AgentResource {
|
|||||||
Agent agent = agentManager.load(agentId);
|
Agent agent = agentManager.load(agentId);
|
||||||
if (!agent.isOnline())
|
if (!agent.isOnline())
|
||||||
throw new ExplicitException("Unable to update attributes as agent is offline");
|
throw new ExplicitException("Unable to update attributes as agent is offline");
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(agent.getAttributeMap()).toXML();
|
||||||
agentAttributeManager.syncAttributes(agent, attributes);
|
agentAttributeManager.syncAttributes(agent, attributes);
|
||||||
agentManager.attributesUpdated(agent);
|
agentManager.attributesUpdated(agent);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(agent.getAttributeMap()).toXML();
|
||||||
|
auditManager.audit(null, "changed attributes of agent \"" + agent.getName() + "\" via RESTful API",
|
||||||
|
oldAuditContent, newAuditContent);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,33 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.server.entitymanager.AgentManager;
|
import java.util.List;
|
||||||
import io.onedev.server.entitymanager.AgentTokenManager;
|
|
||||||
import io.onedev.server.model.Agent;
|
|
||||||
import io.onedev.server.model.AgentToken;
|
|
||||||
import io.onedev.server.persistence.dao.EntityCriteria;
|
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
|
||||||
import io.onedev.server.rest.resource.support.RestConstants;
|
|
||||||
import io.onedev.server.security.SecurityUtils;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
import org.hibernate.criterion.Restrictions;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.List;
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
|
||||||
|
import io.onedev.server.entitymanager.AgentManager;
|
||||||
|
import io.onedev.server.entitymanager.AgentTokenManager;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.model.Agent;
|
||||||
|
import io.onedev.server.model.AgentToken;
|
||||||
|
import io.onedev.server.persistence.dao.EntityCriteria;
|
||||||
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
import io.onedev.server.rest.resource.support.RestConstants;
|
||||||
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
|
||||||
@Api(order=10100)
|
@Api(order=10100)
|
||||||
@Path("/agent-tokens")
|
@Path("/agent-tokens")
|
||||||
@ -30,22 +40,25 @@ public class AgentTokenResource {
|
|||||||
|
|
||||||
private final AgentManager agentManager;
|
private final AgentManager agentManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AgentTokenResource(AgentTokenManager tokenManager, AgentManager agentManager) {
|
public AgentTokenResource(AgentTokenManager tokenManager, AgentManager agentManager, AuditManager auditManager) {
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
this.agentManager = agentManager;
|
this.agentManager = agentManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{tokenId}")
|
@Path("/{tokenId}")
|
||||||
@GET
|
@GET
|
||||||
public AgentToken getBasicInfo(@PathParam("tokenId") Long tokenId) {
|
public AgentToken getToken(@PathParam("tokenId") Long tokenId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return tokenManager.load(tokenId);
|
return tokenManager.load(tokenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100, description="Get agent using specified token")
|
||||||
@Path("/{tokenId}/agent")
|
@Path("/{tokenId}/agent")
|
||||||
@GET
|
@GET
|
||||||
public Agent getAgent(@PathParam("tokenId") Long tokenId) {
|
public Agent getAgent(@PathParam("tokenId") Long tokenId) {
|
||||||
@ -57,7 +70,7 @@ public class AgentTokenResource {
|
|||||||
|
|
||||||
@Api(order=200)
|
@Api(order=200)
|
||||||
@GET
|
@GET
|
||||||
public List<AgentToken> queryBasicInfo(@QueryParam("value") String value,
|
public List<AgentToken> queryTokens(@QueryParam("value") String value,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
@ -76,21 +89,23 @@ public class AgentTokenResource {
|
|||||||
|
|
||||||
@Api(order=500, description="Create new token")
|
@Api(order=500, description="Create new token")
|
||||||
@POST
|
@POST
|
||||||
public Long create() {
|
public Long createToken() {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
AgentToken token = new AgentToken();
|
AgentToken token = new AgentToken();
|
||||||
tokenManager.createOrUpdate(token);
|
tokenManager.createOrUpdate(token);
|
||||||
|
auditManager.audit(null, "created agent token via RESTful API", null, null);
|
||||||
return token.getId();
|
return token.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=600)
|
@Api(order=600)
|
||||||
@Path("/{tokenId}")
|
@Path("/{tokenId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("tokenId") Long tokenId) {
|
public Response deleteToken(@PathParam("tokenId") Long tokenId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
tokenManager.delete(tokenManager.load(tokenId));
|
tokenManager.delete(tokenManager.load(tokenId));
|
||||||
|
auditManager.audit(null, "deleted agent token via RESTful API", null, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ public class ArtifactResource {
|
|||||||
|
|
||||||
private final BuildManager buildManager;
|
private final BuildManager buildManager;
|
||||||
|
|
||||||
private final ClusterManager clusterManager;
|
private final ClusterManager clusterManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ArtifactResource(ProjectManager projectManager, BuildManager buildManager,
|
public ArtifactResource(ProjectManager projectManager, BuildManager buildManager,
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import javax.ws.rs.core.Response;
|
|||||||
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.BaseAuthorizationManager;
|
import io.onedev.server.entitymanager.BaseAuthorizationManager;
|
||||||
import io.onedev.server.model.BaseAuthorization;
|
import io.onedev.server.model.BaseAuthorization;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
@ -29,15 +31,18 @@ public class BaseAuthorizationResource {
|
|||||||
|
|
||||||
private final BaseAuthorizationManager authorizationManager;
|
private final BaseAuthorizationManager authorizationManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BaseAuthorizationResource(BaseAuthorizationManager authorizationManager) {
|
public BaseAuthorizationResource(BaseAuthorizationManager authorizationManager, AuditManager auditManager) {
|
||||||
this.authorizationManager = authorizationManager;
|
this.authorizationManager = authorizationManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100, description = "Get base authorization of specified id")
|
@Api(order=100, description = "Get base authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@GET
|
@GET
|
||||||
public BaseAuthorization get(@PathParam("authorizationId") Long authorizationId) {
|
public BaseAuthorization getAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
var authorization = authorizationManager.load(authorizationId);
|
var authorization = authorizationManager.load(authorizationId);
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -46,21 +51,25 @@ public class BaseAuthorizationResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create base authorization")
|
@Api(order=200, description="Create base authorization")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull BaseAuthorization authorization) {
|
public Long createAuthorization(@NotNull BaseAuthorization authorization) {
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
authorizationManager.create(authorization);
|
authorizationManager.create(authorization);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(authorization.getProject(), "created base authorization via RESTful API", null, newAuditContent);
|
||||||
return authorization.getId();
|
return authorization.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300, description = "Delete base authorization of specified id")
|
@Api(order=300, description = "Delete base authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("authorizationId") Long authorizationId) {
|
public Response deleteAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
var authorization = authorizationManager.load(authorizationId);
|
var authorization = authorizationManager.load(authorizationId);
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
authorizationManager.delete(authorization);
|
authorizationManager.delete(authorization);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(authorization.getProject(), "deleted base authorization via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class BuildLabelResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create build label")
|
@Api(order=200, description="Create build label")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull BuildLabel buildLabel) {
|
public Long createLabel(@NotNull BuildLabel buildLabel) {
|
||||||
if (!SecurityUtils.canManageBuild(buildLabel.getBuild()))
|
if (!SecurityUtils.canManageBuild(buildLabel.getBuild()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
buildLabelManager.create(buildLabel);
|
buildLabelManager.create(buildLabel);
|
||||||
@ -39,7 +39,7 @@ public class BuildLabelResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{buildLabelId}")
|
@Path("/{buildLabelId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("buildLabelId") Long buildLabelId) {
|
public Response deleteLabel(@PathParam("buildLabelId") Long buildLabelId) {
|
||||||
BuildLabel buildLabel = buildLabelManager.load(buildLabelId);
|
BuildLabel buildLabel = buildLabelManager.load(buildLabelId);
|
||||||
if (!SecurityUtils.canManageBuild(buildLabel.getBuild()))
|
if (!SecurityUtils.canManageBuild(buildLabel.getBuild()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|||||||
@ -17,18 +17,20 @@ import javax.ws.rs.QueryParam;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import io.onedev.server.model.BuildLabel;
|
|
||||||
import org.apache.commons.lang3.SerializationUtils;
|
import org.apache.commons.lang3.SerializationUtils;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
import io.onedev.server.buildspec.param.spec.ParamSpec;
|
import io.onedev.server.buildspec.param.spec.ParamSpec;
|
||||||
|
import io.onedev.server.buildspecmodel.inputspec.SecretInput;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.BuildManager;
|
import io.onedev.server.entitymanager.BuildManager;
|
||||||
import io.onedev.server.model.Build;
|
import io.onedev.server.model.Build;
|
||||||
import io.onedev.server.model.BuildDependence;
|
import io.onedev.server.model.BuildDependence;
|
||||||
|
import io.onedev.server.model.BuildLabel;
|
||||||
import io.onedev.server.model.BuildParam;
|
import io.onedev.server.model.BuildParam;
|
||||||
import io.onedev.server.buildspecmodel.inputspec.SecretInput;
|
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import io.onedev.server.rest.resource.support.RestConstants;
|
import io.onedev.server.rest.resource.support.RestConstants;
|
||||||
import io.onedev.server.search.entity.build.BuildQuery;
|
import io.onedev.server.search.entity.build.BuildQuery;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
@ -44,15 +46,18 @@ public class BuildResource {
|
|||||||
|
|
||||||
private final BuildManager buildManager;
|
private final BuildManager buildManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BuildResource(BuildManager buildManager) {
|
public BuildResource(BuildManager buildManager, AuditManager auditManager) {
|
||||||
this.buildManager = buildManager;
|
this.buildManager = buildManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{buildId}")
|
@Path("/{buildId}")
|
||||||
@GET
|
@GET
|
||||||
public Build getBasicInfo(@PathParam("buildId") Long buildId) {
|
public Build getBuild(@PathParam("buildId") Long buildId) {
|
||||||
Build build = buildManager.load(buildId);
|
Build build = buildManager.load(buildId);
|
||||||
if (!SecurityUtils.canAccessBuild(build))
|
if (!SecurityUtils.canAccessBuild(build))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -118,7 +123,7 @@ public class BuildResource {
|
|||||||
|
|
||||||
@Api(order=600)
|
@Api(order=600)
|
||||||
@GET
|
@GET
|
||||||
public List<Build> queryBasicInfo(
|
public List<Build> queryBuilds(
|
||||||
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~builds'>builds page</a>", example="\"Job\" is \"Release\"") String query,
|
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~builds'>builds page</a>", example="\"Job\" is \"Release\"") String query,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
@ -139,11 +144,13 @@ public class BuildResource {
|
|||||||
@Api(order=700)
|
@Api(order=700)
|
||||||
@Path("/{buildId}")
|
@Path("/{buildId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("buildId") Long buildId) {
|
public Response deleteBuild(@PathParam("buildId") Long buildId) {
|
||||||
Build build = buildManager.load(buildId);
|
Build build = buildManager.load(buildId);
|
||||||
if (!SecurityUtils.canManageBuild(build))
|
if (!SecurityUtils.canManageBuild(build))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
buildManager.delete(build);
|
buildManager.delete(build);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(build).toXML();
|
||||||
|
auditManager.audit(build.getProject(), "deleted build \"" + build.getReference().toString(build.getProject()) + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,24 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.CodeCommentManager;
|
import io.onedev.server.entitymanager.CodeCommentManager;
|
||||||
import io.onedev.server.model.CodeComment;
|
import io.onedev.server.model.CodeComment;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.ws.rs.*;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
@Api(order=4700)
|
@Api(order=4700)
|
||||||
@Path("/code-comments")
|
@Path("/code-comments")
|
||||||
@ -21,15 +29,18 @@ public class CodeCommentResource {
|
|||||||
|
|
||||||
private final CodeCommentManager commentManager;
|
private final CodeCommentManager commentManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CodeCommentResource(CodeCommentManager commentManager) {
|
public CodeCommentResource(CodeCommentManager commentManager, AuditManager auditManager) {
|
||||||
this.commentManager = commentManager;
|
this.commentManager = commentManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{commentId}")
|
@Path("/{commentId}")
|
||||||
@GET
|
@GET
|
||||||
public CodeComment get(@PathParam("commentId") Long commentId) {
|
public CodeComment getComment(@PathParam("commentId") Long commentId) {
|
||||||
var comment = commentManager.load(commentId);
|
var comment = commentManager.load(commentId);
|
||||||
if (!SecurityUtils.canReadCode(comment.getProject()))
|
if (!SecurityUtils.canReadCode(comment.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -39,11 +50,13 @@ public class CodeCommentResource {
|
|||||||
@Api(order=200)
|
@Api(order=200)
|
||||||
@Path("/{commentId}")
|
@Path("/{commentId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("commentId") Long commentId) {
|
public Response deleteComment(@PathParam("commentId") Long commentId) {
|
||||||
var comment = commentManager.load(commentId);
|
var comment = commentManager.load(commentId);
|
||||||
if (!SecurityUtils.canModifyOrDelete(comment))
|
if (!SecurityUtils.canModifyOrDelete(comment))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
commentManager.delete(comment);
|
commentManager.delete(comment);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(comment).toXML();
|
||||||
|
auditManager.audit(comment.getProject(), "deleted code comment on file \"" + comment.getMark().getPath() + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,30 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
||||||
import io.onedev.server.entitymanager.EmailAddressManager;
|
|
||||||
import io.onedev.server.entitymanager.SettingManager;
|
|
||||||
import io.onedev.server.model.EmailAddress;
|
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.security.SecurityUtils;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.EmailAddressManager;
|
||||||
|
import io.onedev.server.entitymanager.SettingManager;
|
||||||
|
import io.onedev.server.model.EmailAddress;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
|
||||||
@Api(order=5010)
|
@Api(order=5010)
|
||||||
@Path("/email-addresses")
|
@Path("/email-addresses")
|
||||||
@ -29,16 +37,19 @@ public class EmailAddressResource {
|
|||||||
|
|
||||||
private final SettingManager settingManager;
|
private final SettingManager settingManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public EmailAddressResource(EmailAddressManager emailAddressManager, SettingManager settingManager) {
|
public EmailAddressResource(EmailAddressManager emailAddressManager, SettingManager settingManager, AuditManager auditManager) {
|
||||||
this.emailAddressManager = emailAddressManager;
|
this.emailAddressManager = emailAddressManager;
|
||||||
this.settingManager = settingManager;
|
this.settingManager = settingManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{emailAddressId}")
|
@Path("/{emailAddressId}")
|
||||||
@GET
|
@GET
|
||||||
public EmailAddress get(@PathParam("emailAddressId") Long emailAddressId) {
|
public EmailAddress getEmailAddress(@PathParam("emailAddressId") Long emailAddressId) {
|
||||||
EmailAddress emailAddress = emailAddressManager.load(emailAddressId);
|
EmailAddress emailAddress = emailAddressManager.load(emailAddressId);
|
||||||
if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -48,7 +59,7 @@ public class EmailAddressResource {
|
|||||||
@Api(order=150)
|
@Api(order=150)
|
||||||
@Path("/{emailAddressId}/verified")
|
@Path("/{emailAddressId}/verified")
|
||||||
@GET
|
@GET
|
||||||
public boolean getVerified(@PathParam("emailAddressId") Long emailAddressId) {
|
public boolean isEmailAddressVerified(@PathParam("emailAddressId") Long emailAddressId) {
|
||||||
EmailAddress emailAddress = emailAddressManager.load(emailAddressId);
|
EmailAddress emailAddress = emailAddressManager.load(emailAddressId);
|
||||||
if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -57,7 +68,7 @@ public class EmailAddressResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new email address")
|
@Api(order=200, description="Create new email address")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull @Valid EmailAddress emailAddress) {
|
public Long createEmailAddress(@NotNull @Valid EmailAddress emailAddress) {
|
||||||
var owner = emailAddress.getOwner();
|
var owner = emailAddress.getOwner();
|
||||||
if (!SecurityUtils.isAdministrator() && !owner.equals(getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -72,9 +83,46 @@ public class EmailAddressResource {
|
|||||||
emailAddress.setVerificationCode(null);
|
emailAddress.setVerificationCode(null);
|
||||||
|
|
||||||
emailAddressManager.create(emailAddress);
|
emailAddressManager.create(emailAddress);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(owner))
|
||||||
|
auditManager.audit(null, "added email address \"" + emailAddress.getValue() + "\" for account \"" + owner.getName() + "\" via RESTful API", null, null);
|
||||||
return emailAddress.getId();
|
return emailAddress.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Api(order=220, description="Set as public email address")
|
||||||
|
@Path("/public")
|
||||||
|
@POST
|
||||||
|
public Long setAsPublic(@NotNull Long emailAddressId) {
|
||||||
|
var emailAddress = emailAddressManager.load(emailAddressId);
|
||||||
|
var owner = emailAddress.getOwner();
|
||||||
|
if (!SecurityUtils.isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
|
emailAddressManager.setAsPublic(emailAddress);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(owner))
|
||||||
|
auditManager.audit(null, "set email address \"" + emailAddress.getValue() + "\" as public for account \"" + owner.getName() + "\" via RESTful API", null, null);
|
||||||
|
|
||||||
|
return emailAddressId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Api(order=230, description="Set as private email address")
|
||||||
|
@Path("/private")
|
||||||
|
@POST
|
||||||
|
public Long setAsPrivate(@NotNull Long emailAddressId) {
|
||||||
|
var emailAddress = emailAddressManager.load(emailAddressId);
|
||||||
|
var owner = emailAddress.getOwner();
|
||||||
|
if (!SecurityUtils.isAdministrator() && !owner.equals(getAuthUser()))
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
|
emailAddressManager.setAsPrivate(emailAddress);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(owner))
|
||||||
|
auditManager.audit(null, "set email address \"" + emailAddress.getValue() + "\" as private for account \"" + owner.getName() + "\" via RESTful API", null, null);
|
||||||
|
|
||||||
|
return emailAddressId;
|
||||||
|
}
|
||||||
|
|
||||||
@Api(order=250, description="Set as primary email address")
|
@Api(order=250, description="Set as primary email address")
|
||||||
@Path("/primary")
|
@Path("/primary")
|
||||||
@POST
|
@POST
|
||||||
@ -88,6 +136,9 @@ public class EmailAddressResource {
|
|||||||
throw new ExplicitException("Can not set primary email address for externally authenticated user");
|
throw new ExplicitException("Can not set primary email address for externally authenticated user");
|
||||||
|
|
||||||
emailAddressManager.setAsPrimary(emailAddress);
|
emailAddressManager.setAsPrimary(emailAddress);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(owner))
|
||||||
|
auditManager.audit(null, "set email address \"" + emailAddress.getValue() + "\" as primary for account \"" + owner.getName() + "\" via RESTful API", null, null);
|
||||||
|
|
||||||
return emailAddressId;
|
return emailAddressId;
|
||||||
}
|
}
|
||||||
@ -102,6 +153,9 @@ public class EmailAddressResource {
|
|||||||
|
|
||||||
emailAddressManager.useForGitOperations(emailAddress);
|
emailAddressManager.useForGitOperations(emailAddress);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(emailAddress.getOwner()))
|
||||||
|
auditManager.audit(null, "specified email address \"" + emailAddress.getValue() + "\" for git operations for account \"" + emailAddress.getOwner().getName() + "\" via RESTful API", null, null);
|
||||||
|
|
||||||
return emailAddressId;
|
return emailAddressId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +180,7 @@ public class EmailAddressResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{emailAddressId}")
|
@Path("/{emailAddressId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("emailAddressId") Long emailAddressId) {
|
public Response deleteEmailAddress(@PathParam("emailAddressId") Long emailAddressId) {
|
||||||
var emailAddress = emailAddressManager.load(emailAddressId);
|
var emailAddress = emailAddressManager.load(emailAddressId);
|
||||||
if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -138,6 +192,10 @@ public class EmailAddressResource {
|
|||||||
if (emailAddress.getOwner().getEmailAddresses().size() == 1)
|
if (emailAddress.getOwner().getEmailAddresses().size() == 1)
|
||||||
throw new ExplicitException("At least one email address should be present for a user");
|
throw new ExplicitException("At least one email address should be present for a user");
|
||||||
emailAddressManager.delete(emailAddress);
|
emailAddressManager.delete(emailAddress);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(emailAddress.getOwner()))
|
||||||
|
auditManager.audit(null, "deleted email address \"" + emailAddress.getValue() + "\" for account \"" + emailAddress.getOwner().getName() + "\" via RESTful API", null, null);
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import javax.ws.rs.core.Response;
|
|||||||
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.GroupAuthorizationManager;
|
import io.onedev.server.entitymanager.GroupAuthorizationManager;
|
||||||
import io.onedev.server.model.GroupAuthorization;
|
import io.onedev.server.model.GroupAuthorization;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
@ -29,15 +31,18 @@ public class GroupAuthorizationResource {
|
|||||||
|
|
||||||
private final GroupAuthorizationManager authorizationManager;
|
private final GroupAuthorizationManager authorizationManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public GroupAuthorizationResource(GroupAuthorizationManager authorizationManager) {
|
public GroupAuthorizationResource(GroupAuthorizationManager authorizationManager, AuditManager auditManager) {
|
||||||
this.authorizationManager = authorizationManager;
|
this.authorizationManager = authorizationManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100, description = "Get group authorization of specified id")
|
@Api(order=100, description = "Get group authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@GET
|
@GET
|
||||||
public GroupAuthorization get(@PathParam("authorizationId") Long authorizationId) {
|
public GroupAuthorization getAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
var authorization = authorizationManager.load(authorizationId);
|
var authorization = authorizationManager.load(authorizationId);
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -46,21 +51,25 @@ public class GroupAuthorizationResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new group authorization")
|
@Api(order=200, description="Create new group authorization")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull GroupAuthorization authorization) {
|
public Long createAuthorization(@NotNull GroupAuthorization authorization) {
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
authorizationManager.createOrUpdate(authorization);
|
authorizationManager.createOrUpdate(authorization);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(authorization.getProject(), "created group authorization via RESTful API", null, newAuditContent);
|
||||||
return authorization.getId();
|
return authorization.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300, description = "Delete group authorization of specified id")
|
@Api(order=300, description = "Delete group authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("authorizationId") Long authorizationId) {
|
public Response deleteAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
var authorization = authorizationManager.load(authorizationId);
|
var authorization = authorizationManager.load(authorizationId);
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
authorizationManager.delete(authorization);
|
authorizationManager.delete(authorization);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(authorization.getProject(), "deleted group authorization via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,15 @@ import java.util.List;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
@ -14,6 +22,8 @@ import org.apache.shiro.authz.UnauthorizedException;
|
|||||||
import org.hibernate.criterion.MatchMode;
|
import org.hibernate.criterion.MatchMode;
|
||||||
import org.hibernate.criterion.Restrictions;
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.GroupManager;
|
import io.onedev.server.entitymanager.GroupManager;
|
||||||
import io.onedev.server.model.Group;
|
import io.onedev.server.model.Group;
|
||||||
import io.onedev.server.model.GroupAuthorization;
|
import io.onedev.server.model.GroupAuthorization;
|
||||||
@ -21,7 +31,6 @@ import io.onedev.server.model.Membership;
|
|||||||
import io.onedev.server.persistence.dao.EntityCriteria;
|
import io.onedev.server.persistence.dao.EntityCriteria;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.util.facade.GroupFacade;
|
|
||||||
|
|
||||||
@Api(order=6000)
|
@Api(order=6000)
|
||||||
@Path("/groups")
|
@Path("/groups")
|
||||||
@ -32,15 +41,18 @@ public class GroupResource {
|
|||||||
|
|
||||||
private final GroupManager groupManager;
|
private final GroupManager groupManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public GroupResource(GroupManager groupManager) {
|
public GroupResource(GroupManager groupManager, AuditManager auditManager) {
|
||||||
this.groupManager = groupManager;
|
this.groupManager = groupManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{groupId}")
|
@Path("/{groupId}")
|
||||||
@GET
|
@GET
|
||||||
public Group getBasicInfo(@PathParam("groupId") Long groupId) {
|
public Group getGroup(@PathParam("groupId") Long groupId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return groupManager.load(groupId);
|
return groupManager.load(groupId);
|
||||||
@ -66,7 +78,7 @@ public class GroupResource {
|
|||||||
|
|
||||||
@Api(order=400)
|
@Api(order=400)
|
||||||
@GET
|
@GET
|
||||||
public List<Group> queryBasicInfo(@QueryParam("name") String name, @QueryParam("offset") @Api(example="0") int offset,
|
public List<Group> queryGroups(@QueryParam("name") String name, @QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -81,7 +93,7 @@ public class GroupResource {
|
|||||||
@Api(order=450)
|
@Api(order=450)
|
||||||
@Path("/ids/{name}")
|
@Path("/ids/{name}")
|
||||||
@GET
|
@GET
|
||||||
public Long getId(@PathParam("name") @Api(description = "Group name") String name) {
|
public Long getGroupId(@PathParam("name") @Api(description = "Group name") String name) {
|
||||||
var group = groupManager.find(name);
|
var group = groupManager.find(name);
|
||||||
if (group != null)
|
if (group != null)
|
||||||
return group.getId();
|
return group.getId();
|
||||||
@ -91,35 +103,42 @@ public class GroupResource {
|
|||||||
|
|
||||||
@Api(order=500, description="Create new group")
|
@Api(order=500, description="Create new group")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull Group group) {
|
public Long createGroup(@NotNull Group group) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
groupManager.create(group);
|
groupManager.create(group);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(group).toXML();
|
||||||
|
auditManager.audit(null, "created group \"" + group.getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
return group.getId();
|
return group.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=550, description="Update group of specified id")
|
@Api(order=550, description="Update group of specified id")
|
||||||
@Path("/{groupId}")
|
@Path("/{groupId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("groupId") Long groupId, @NotNull Group group) {
|
public Response updateGroup(@PathParam("groupId") Long groupId, @NotNull Group group) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
if (group.getOldVersion() != null)
|
var oldName = group.getOldVersion().getRootElement().elementText(Group.PROP_NAME);
|
||||||
groupManager.update(group, ((GroupFacade) group.getOldVersion()).getName());
|
groupManager.update(group, oldName);
|
||||||
else
|
|
||||||
groupManager.update(group, null);
|
var oldAuditContent = group.getOldVersion().toXML();
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(group).toXML();
|
||||||
|
auditManager.audit(null, "changed group \"" + group.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=600)
|
@Api(order=600)
|
||||||
@Path("/{groupId}")
|
@Path("/{groupId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("groupId") Long groupId) {
|
public Response deleteGroup(@PathParam("groupId") Long groupId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
groupManager.delete(groupManager.load(groupId));
|
var group = groupManager.load(groupId);
|
||||||
|
groupManager.delete(group);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(group).toXML();
|
||||||
|
auditManager.audit(null, "deleted group \"" + group.getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ public class IssueCommentResource {
|
|||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{commentId}")
|
@Path("/{commentId}")
|
||||||
@GET
|
@GET
|
||||||
public IssueComment get(@PathParam("commentId") Long commentId) {
|
public IssueComment getComment(@PathParam("commentId") Long commentId) {
|
||||||
IssueComment comment = commentManager.load(commentId);
|
IssueComment comment = commentManager.load(commentId);
|
||||||
if (!SecurityUtils.canAccessProject(comment.getIssue().getProject()))
|
if (!SecurityUtils.canAccessProject(comment.getIssue().getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -56,7 +56,7 @@ public class IssueCommentResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new issue comment")
|
@Api(order=200, description="Create new issue comment")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull IssueComment comment) {
|
public Long createComment(@NotNull IssueComment comment) {
|
||||||
if (!canAccessIssue(comment.getIssue())
|
if (!canAccessIssue(comment.getIssue())
|
||||||
|| !isAdministrator() && !comment.getUser().equals(getUser())) {
|
|| !isAdministrator() && !comment.getUser().equals(getUser())) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -68,7 +68,7 @@ public class IssueCommentResource {
|
|||||||
@Api(order=250, description="Update issue comment of specified id")
|
@Api(order=250, description="Update issue comment of specified id")
|
||||||
@Path("/{commentId}")
|
@Path("/{commentId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("commentId") Long commentId, @NotNull String content) {
|
public Response updateComment(@PathParam("commentId") Long commentId, @NotNull String content) {
|
||||||
var comment = commentManager.load(commentId);
|
var comment = commentManager.load(commentId);
|
||||||
if (!canModifyOrDelete(comment))
|
if (!canModifyOrDelete(comment))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -91,7 +91,7 @@ public class IssueCommentResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{commentId}")
|
@Path("/{commentId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("commentId") Long commentId) {
|
public Response deleteComment(@PathParam("commentId") Long commentId) {
|
||||||
IssueComment comment = commentManager.load(commentId);
|
IssueComment comment = commentManager.load(commentId);
|
||||||
if (!canModifyOrDelete(comment))
|
if (!canModifyOrDelete(comment))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|||||||
@ -32,7 +32,7 @@ public class IssueLinkResource {
|
|||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{linkId}")
|
@Path("/{linkId}")
|
||||||
@GET
|
@GET
|
||||||
public IssueLink get(@PathParam("linkId") Long linkId) {
|
public IssueLink getLink(@PathParam("linkId") Long linkId) {
|
||||||
var link = linkManager.load(linkId);
|
var link = linkManager.load(linkId);
|
||||||
if (!canAccessIssue(link.getTarget()) && !canAccessIssue(link.getSource()))
|
if (!canAccessIssue(link.getTarget()) && !canAccessIssue(link.getSource()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -41,7 +41,7 @@ public class IssueLinkResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new issue link")
|
@Api(order=200, description="Create new issue link")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull IssueLink link) {
|
public Long createLink(@NotNull IssueLink link) {
|
||||||
if (!canEditIssueLink(link.getSource().getProject(), link.getSpec())
|
if (!canEditIssueLink(link.getSource().getProject(), link.getSpec())
|
||||||
&& !canEditIssueLink(link.getTarget().getProject(), link.getSpec())) {
|
&& !canEditIssueLink(link.getTarget().getProject(), link.getSpec())) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -76,7 +76,7 @@ public class IssueLinkResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{linkId}")
|
@Path("/{linkId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("linkId") Long linkId) {
|
public Response deleteLink(@PathParam("linkId") Long linkId) {
|
||||||
var link = linkManager.load(linkId);
|
var link = linkManager.load(linkId);
|
||||||
if (!canEditIssueLink(link.getSource().getProject(), link.getSpec())
|
if (!canEditIssueLink(link.getSource().getProject(), link.getSpec())
|
||||||
&& !canEditIssueLink(link.getTarget().getProject(), link.getSpec())) {
|
&& !canEditIssueLink(link.getTarget().getProject(), link.getSpec())) {
|
||||||
|
|||||||
@ -1,10 +1,57 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.ws.rs.BadRequestException;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
import io.onedev.server.entitymanager.*;
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
import io.onedev.server.model.*;
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.IssueChangeManager;
|
||||||
|
import io.onedev.server.entitymanager.IssueManager;
|
||||||
|
import io.onedev.server.entitymanager.IterationManager;
|
||||||
|
import io.onedev.server.entitymanager.ProjectManager;
|
||||||
|
import io.onedev.server.entitymanager.SettingManager;
|
||||||
|
import io.onedev.server.model.Issue;
|
||||||
|
import io.onedev.server.model.IssueChange;
|
||||||
|
import io.onedev.server.model.IssueComment;
|
||||||
|
import io.onedev.server.model.IssueLink;
|
||||||
|
import io.onedev.server.model.IssueSchedule;
|
||||||
|
import io.onedev.server.model.IssueVote;
|
||||||
|
import io.onedev.server.model.IssueWatch;
|
||||||
|
import io.onedev.server.model.IssueWork;
|
||||||
|
import io.onedev.server.model.Iteration;
|
||||||
|
import io.onedev.server.model.Project;
|
||||||
|
import io.onedev.server.model.PullRequest;
|
||||||
|
import io.onedev.server.model.User;
|
||||||
import io.onedev.server.model.support.issue.transitionspec.ManualSpec;
|
import io.onedev.server.model.support.issue.transitionspec.ManualSpec;
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
@ -16,18 +63,6 @@ import io.onedev.server.security.SecurityUtils;
|
|||||||
import io.onedev.server.util.ProjectScopedCommit;
|
import io.onedev.server.util.ProjectScopedCommit;
|
||||||
import io.onedev.server.web.page.help.ApiHelpUtils;
|
import io.onedev.server.web.page.help.ApiHelpUtils;
|
||||||
import io.onedev.server.web.page.help.ValueInfo;
|
import io.onedev.server.web.page.help.ValueInfo;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.ws.rs.*;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Api(order=2000, description="In most cases, issue resource is operated with issue id, which is different from issue number. "
|
@Api(order=2000, description="In most cases, issue resource is operated with issue id, which is different from issue number. "
|
||||||
+ "To get issue id of a particular issue number, use the <a href='/~help/api/io.onedev.server.rest.IssueResource/queryBasicInfo'>Query Basic Info</a> operation with query for "
|
+ "To get issue id of a particular issue number, use the <a href='/~help/api/io.onedev.server.rest.IssueResource/queryBasicInfo'>Query Basic Info</a> operation with query for "
|
||||||
@ -49,23 +84,26 @@ public class IssueResource {
|
|||||||
private final ProjectManager projectManager;
|
private final ProjectManager projectManager;
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public IssueResource(SettingManager settingManager, IssueManager issueManager,
|
public IssueResource(SettingManager settingManager, IssueManager issueManager,
|
||||||
IssueChangeManager issueChangeManager, IterationManager iterationManager,
|
IssueChangeManager issueChangeManager, IterationManager iterationManager,
|
||||||
ProjectManager projectManager, ObjectMapper objectMapper) {
|
ProjectManager projectManager, ObjectMapper objectMapper, AuditManager auditManager) {
|
||||||
this.settingManager = settingManager;
|
this.settingManager = settingManager;
|
||||||
this.issueManager = issueManager;
|
this.issueManager = issueManager;
|
||||||
this.issueChangeManager = issueChangeManager;
|
this.issueChangeManager = issueChangeManager;
|
||||||
this.iterationManager = iterationManager;
|
this.iterationManager = iterationManager;
|
||||||
this.projectManager = projectManager;
|
this.projectManager = projectManager;
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{issueId}")
|
@Path("/{issueId}")
|
||||||
@GET
|
@GET
|
||||||
public Issue getBasicInfo(@PathParam("issueId") Long issueId) {
|
public Issue getIssue(@PathParam("issueId") Long issueId) {
|
||||||
Issue issue = issueManager.load(issueId);
|
Issue issue = issueManager.load(issueId);
|
||||||
if (!SecurityUtils.canAccessIssue(issue))
|
if (!SecurityUtils.canAccessIssue(issue))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -196,7 +234,7 @@ public class IssueResource {
|
|||||||
|
|
||||||
@Api(order=900, exampleProvider = "getIssuesExample")
|
@Api(order=900, exampleProvider = "getIssuesExample")
|
||||||
@GET
|
@GET
|
||||||
public List<Map<String, Object>> query(
|
public List<Map<String, Object>> queryIssues(
|
||||||
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~issues'>issues page</a>", example="\"State\" is \"Open\"") String query,
|
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~issues'>issues page</a>", example="\"State\" is \"Open\"") String query,
|
||||||
@QueryParam("withFields") @Api(description = "Whether or not to include issue fields. Default to false", example="true") Boolean withFields,
|
@QueryParam("withFields") @Api(description = "Whether or not to include issue fields. Default to false", example="true") Boolean withFields,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@ -235,7 +273,7 @@ public class IssueResource {
|
|||||||
|
|
||||||
@Api(order=1000)
|
@Api(order=1000)
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull @Valid IssueOpenData data) {
|
public Long createIssue(@NotNull @Valid IssueOpenData data) {
|
||||||
User user = SecurityUtils.getUser();
|
User user = SecurityUtils.getUser();
|
||||||
|
|
||||||
Project project = projectManager.load(data.getProjectId());
|
Project project = projectManager.load(data.getProjectId());
|
||||||
@ -384,11 +422,13 @@ public class IssueResource {
|
|||||||
@Api(order=1600)
|
@Api(order=1600)
|
||||||
@Path("/{issueId}")
|
@Path("/{issueId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("issueId") Long issueId) {
|
public Response deleteIssue(@PathParam("issueId") Long issueId) {
|
||||||
Issue issue = issueManager.load(issueId);
|
Issue issue = issueManager.load(issueId);
|
||||||
if (!SecurityUtils.canManageIssues(issue.getProject()))
|
if (!SecurityUtils.canManageIssues(issue.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
issueManager.delete(issue);
|
issueManager.delete(issue);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(issue).toXML();
|
||||||
|
auditManager.audit(issue.getProject(), "deleted issue \"" + issue.getReference().toString(issue.getProject()) + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ public class IssueVoteResource {
|
|||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{voteId}")
|
@Path("/{voteId}")
|
||||||
@GET
|
@GET
|
||||||
public IssueVote get(@PathParam("voteId") Long voteId) {
|
public IssueVote getVote(@PathParam("voteId") Long voteId) {
|
||||||
IssueVote vote = voteManager.load(voteId);
|
IssueVote vote = voteManager.load(voteId);
|
||||||
if (!SecurityUtils.canAccessIssue(vote.getIssue()))
|
if (!SecurityUtils.canAccessIssue(vote.getIssue()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -41,7 +41,7 @@ public class IssueVoteResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new issue vote")
|
@Api(order=200, description="Create new issue vote")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull IssueVote vote) {
|
public Long createVote(@NotNull IssueVote vote) {
|
||||||
if (!SecurityUtils.canAccessIssue(vote.getIssue())
|
if (!SecurityUtils.canAccessIssue(vote.getIssue())
|
||||||
|| !SecurityUtils.isAdministrator() && !vote.getUser().equals(SecurityUtils.getAuthUser())) {
|
|| !SecurityUtils.isAdministrator() && !vote.getUser().equals(SecurityUtils.getAuthUser())) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -53,7 +53,7 @@ public class IssueVoteResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{voteId}")
|
@Path("/{voteId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("voteId") Long voteId) {
|
public Response deleteVote(@PathParam("voteId") Long voteId) {
|
||||||
IssueVote vote = voteManager.load(voteId);
|
IssueVote vote = voteManager.load(voteId);
|
||||||
if (!canModifyOrDelete(vote))
|
if (!canModifyOrDelete(vote))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|||||||
@ -32,7 +32,7 @@ public class IssueWatchResource {
|
|||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{watchId}")
|
@Path("/{watchId}")
|
||||||
@GET
|
@GET
|
||||||
public IssueWatch get(@PathParam("watchId") Long watchId) {
|
public IssueWatch getWatch(@PathParam("watchId") Long watchId) {
|
||||||
IssueWatch watch = watchManager.load(watchId);
|
IssueWatch watch = watchManager.load(watchId);
|
||||||
if (!SecurityUtils.canAccessIssue(watch.getIssue()))
|
if (!SecurityUtils.canAccessIssue(watch.getIssue()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -41,7 +41,7 @@ public class IssueWatchResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new issue watch")
|
@Api(order=200, description="Create new issue watch")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull IssueWatch watch) {
|
public Long createWatch(@NotNull IssueWatch watch) {
|
||||||
if (!SecurityUtils.canAccessIssue(watch.getIssue())
|
if (!SecurityUtils.canAccessIssue(watch.getIssue())
|
||||||
|| !SecurityUtils.isAdministrator() && !watch.getUser().equals(SecurityUtils.getAuthUser())) {
|
|| !SecurityUtils.isAdministrator() && !watch.getUser().equals(SecurityUtils.getAuthUser())) {
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -53,7 +53,7 @@ public class IssueWatchResource {
|
|||||||
@Api(order=250, description="Update issue watch of specified id")
|
@Api(order=250, description="Update issue watch of specified id")
|
||||||
@Path("/{watchId}")
|
@Path("/{watchId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("watchId") Long watchId, @NotNull IssueWatch watch) {
|
public Response updateWatch(@PathParam("watchId") Long watchId, @NotNull IssueWatch watch) {
|
||||||
if (!canModifyOrDelete(watch))
|
if (!canModifyOrDelete(watch))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
watchManager.createOrUpdate(watch);
|
watchManager.createOrUpdate(watch);
|
||||||
@ -63,7 +63,7 @@ public class IssueWatchResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{watchId}")
|
@Path("/{watchId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("watchId") Long watchId) {
|
public Response deleteWatch(@PathParam("watchId") Long watchId) {
|
||||||
IssueWatch watch = watchManager.load(watchId);
|
IssueWatch watch = watchManager.load(watchId);
|
||||||
if (!canModifyOrDelete(watch))
|
if (!canModifyOrDelete(watch))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|||||||
@ -43,7 +43,7 @@ public class IssueWorkResource {
|
|||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{workId}")
|
@Path("/{workId}")
|
||||||
@GET
|
@GET
|
||||||
public IssueWork get(@PathParam("workId") Long workId) {
|
public IssueWork getWork(@PathParam("workId") Long workId) {
|
||||||
if (!subscriptionManager.isSubscriptionActive())
|
if (!subscriptionManager.isSubscriptionActive())
|
||||||
throw new UnsupportedOperationException("This feature requires an active subscription");
|
throw new UnsupportedOperationException("This feature requires an active subscription");
|
||||||
IssueWork work = workManager.load(workId);
|
IssueWork work = workManager.load(workId);
|
||||||
@ -54,7 +54,7 @@ public class IssueWorkResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Log new issue work")
|
@Api(order=200, description="Log new issue work")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull IssueWork work) {
|
public Long createWork(@NotNull IssueWork work) {
|
||||||
if (!subscriptionManager.isSubscriptionActive())
|
if (!subscriptionManager.isSubscriptionActive())
|
||||||
throw new UnsupportedOperationException("This feature requires an active subscription");
|
throw new UnsupportedOperationException("This feature requires an active subscription");
|
||||||
if (!work.getIssue().getProject().isTimeTracking())
|
if (!work.getIssue().getProject().isTimeTracking())
|
||||||
@ -72,7 +72,7 @@ public class IssueWorkResource {
|
|||||||
@Api(order=250, description="Update issue work of specified id")
|
@Api(order=250, description="Update issue work of specified id")
|
||||||
@Path("/{workId}")
|
@Path("/{workId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("workId") Long workId, @NotNull IssueWork work) {
|
public Response updateWork(@PathParam("workId") Long workId, @NotNull IssueWork work) {
|
||||||
if (!canModifyOrDelete(work))
|
if (!canModifyOrDelete(work))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ public class IssueWorkResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{workId}")
|
@Path("/{workId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("workId") Long workId) {
|
public Response deleteWork(@PathParam("workId") Long workId) {
|
||||||
var work = workManager.load(workId);
|
var work = workManager.load(workId);
|
||||||
if (!canModifyOrDelete(work))
|
if (!canModifyOrDelete(work))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import javax.ws.rs.core.Response;
|
|||||||
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.IterationManager;
|
import io.onedev.server.entitymanager.IterationManager;
|
||||||
import io.onedev.server.model.Iteration;
|
import io.onedev.server.model.Iteration;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
@ -29,15 +31,18 @@ public class IterationResource {
|
|||||||
|
|
||||||
private final IterationManager iterationManager;
|
private final IterationManager iterationManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public IterationResource(IterationManager iterationManager) {
|
public IterationResource(IterationManager iterationManager, AuditManager auditManager) {
|
||||||
this.iterationManager = iterationManager;
|
this.iterationManager = iterationManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{iterationId}")
|
@Path("/{iterationId}")
|
||||||
@GET
|
@GET
|
||||||
public Iteration get(@PathParam("iterationId") Long iterationId) {
|
public Iteration getIteration(@PathParam("iterationId") Long iterationId) {
|
||||||
Iteration iteration = iterationManager.load(iterationId);
|
Iteration iteration = iterationManager.load(iterationId);
|
||||||
if (!SecurityUtils.canAccessProject(iteration.getProject()))
|
if (!SecurityUtils.canAccessProject(iteration.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -46,31 +51,38 @@ public class IterationResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new iteration")
|
@Api(order=200, description="Create new iteration")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull Iteration iteration) {
|
public Long createIteration(@NotNull Iteration iteration) {
|
||||||
if (!SecurityUtils.canManageIssues(iteration.getProject()))
|
if (!SecurityUtils.canManageIssues(iteration.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
iterationManager.createOrUpdate(iteration);
|
iterationManager.createOrUpdate(iteration);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(iteration).toXML();
|
||||||
|
auditManager.audit(iteration.getProject(), "created iteration \"" + iteration.getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
return iteration.getId();
|
return iteration.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=250, description="Update iteration of specified id")
|
@Api(order=250, description="Update iteration of specified id")
|
||||||
@Path("/{iterationId}")
|
@Path("/{iterationId}")
|
||||||
@POST
|
@POST
|
||||||
public Long update(@PathParam("iterationId") Long iterationId, @NotNull Iteration iteration) {
|
public Long updateIteration(@PathParam("iterationId") Long iterationId, @NotNull Iteration iteration) {
|
||||||
if (!SecurityUtils.canManageIssues(iteration.getProject()))
|
if (!SecurityUtils.canManageIssues(iteration.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
iterationManager.createOrUpdate(iteration);
|
iterationManager.createOrUpdate(iteration);
|
||||||
|
var oldAuditContent = iteration.getOldVersion().toXML();
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(iteration).toXML();
|
||||||
|
auditManager.audit(iteration.getProject(), "changed iteration \"" + iteration.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
return iteration.getId();
|
return iteration.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{iterationId}")
|
@Path("/{iterationId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("iterationId") Long iterationId) {
|
public Response deleteIteration(@PathParam("iterationId") Long iterationId) {
|
||||||
Iteration iteration = iterationManager.load(iterationId);
|
Iteration iteration = iterationManager.load(iterationId);
|
||||||
if (!SecurityUtils.canManageIssues(iteration.getProject()))
|
if (!SecurityUtils.canManageIssues(iteration.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
iterationManager.delete(iteration);
|
iterationManager.delete(iteration);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(iteration).toXML();
|
||||||
|
auditManager.audit(iteration.getProject(), "deleted iteration \"" + iteration.getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,32 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
import org.hibernate.criterion.MatchMode;
|
||||||
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.LabelSpecManager;
|
import io.onedev.server.entitymanager.LabelSpecManager;
|
||||||
import io.onedev.server.model.LabelSpec;
|
import io.onedev.server.model.LabelSpec;
|
||||||
import io.onedev.server.persistence.dao.EntityCriteria;
|
import io.onedev.server.persistence.dao.EntityCriteria;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
import org.hibernate.criterion.MatchMode;
|
|
||||||
import org.hibernate.criterion.Restrictions;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.ws.rs.*;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Api(order=10200)
|
@Api(order=10200)
|
||||||
@Path("/label-specs")
|
@Path("/label-specs")
|
||||||
@ -26,15 +37,18 @@ public class LabelSpecResource {
|
|||||||
|
|
||||||
private final LabelSpecManager labelSpecManager;
|
private final LabelSpecManager labelSpecManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public LabelSpecResource(LabelSpecManager labelSpecManager) {
|
public LabelSpecResource(LabelSpecManager labelSpecManager, AuditManager auditManager) {
|
||||||
this.labelSpecManager = labelSpecManager;
|
this.labelSpecManager = labelSpecManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{labelSpecId}")
|
@Path("/{labelSpecId}")
|
||||||
@GET
|
@GET
|
||||||
public LabelSpec get(@PathParam("labelSpecId") Long labelSpecId) {
|
public LabelSpec getSpec(@PathParam("labelSpecId") Long labelSpecId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return labelSpecManager.load(labelSpecId);
|
return labelSpecManager.load(labelSpecId);
|
||||||
@ -42,7 +56,7 @@ public class LabelSpecResource {
|
|||||||
|
|
||||||
@Api(order=400)
|
@Api(order=400)
|
||||||
@GET
|
@GET
|
||||||
public List<LabelSpec> query(@QueryParam("name") String name,
|
public List<LabelSpec> querySpecs(@QueryParam("name") String name,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
@ -57,31 +71,39 @@ public class LabelSpecResource {
|
|||||||
|
|
||||||
@Api(order=500, description="Create new label spec")
|
@Api(order=500, description="Create new label spec")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull LabelSpec labelSpec) {
|
public Long createSpec(@NotNull LabelSpec labelSpec) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
labelSpecManager.createOrUpdate(labelSpec);
|
labelSpecManager.createOrUpdate(labelSpec);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(labelSpec).toXML();
|
||||||
|
auditManager.audit(null, "created label spec \"" + labelSpec.getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
return labelSpec.getId();
|
return labelSpec.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=550, description="Update label spec of specified id")
|
@Api(order=550, description="Update label spec of specified id")
|
||||||
@Path("/{labelSpecId}")
|
@Path("/{labelSpecId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("labelSpecId") Long labelSpecId, @NotNull LabelSpec labelSpec) {
|
public Response updateSpec(@PathParam("labelSpecId") Long labelSpecId, @NotNull LabelSpec labelSpec) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
labelSpecManager.createOrUpdate(labelSpec);
|
labelSpecManager.createOrUpdate(labelSpec);
|
||||||
|
var oldAuditContent = labelSpec.getOldVersion().toXML();
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(labelSpec).toXML();
|
||||||
|
auditManager.audit(null, "changed label spec \"" + labelSpec.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=600)
|
@Api(order=600)
|
||||||
@Path("/{labelSpecId}")
|
@Path("/{labelSpecId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("labelSpecId") Long labelSpecId) {
|
public Response deleteSpec(@PathParam("labelSpecId") Long labelSpecId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
labelSpecManager.delete(labelSpecManager.load(labelSpecId));
|
var labelSpec = labelSpecManager.load(labelSpecId);
|
||||||
|
labelSpecManager.delete(labelSpec);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(labelSpec).toXML();
|
||||||
|
auditManager.audit(null, "deleted label spec \"" + labelSpec.getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import javax.ws.rs.core.Response;
|
|||||||
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.MembershipManager;
|
import io.onedev.server.entitymanager.MembershipManager;
|
||||||
import io.onedev.server.model.Membership;
|
import io.onedev.server.model.Membership;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
@ -29,15 +31,18 @@ public class MembershipResource {
|
|||||||
|
|
||||||
private final MembershipManager membershipManager;
|
private final MembershipManager membershipManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MembershipResource(MembershipManager membershipManager) {
|
public MembershipResource(MembershipManager membershipManager, AuditManager auditManager) {
|
||||||
this.membershipManager = membershipManager;
|
this.membershipManager = membershipManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{membershipId}")
|
@Path("/{membershipId}")
|
||||||
@GET
|
@GET
|
||||||
public Membership get(@PathParam("membershipId") Long membershipId) {
|
public Membership getMembership(@PathParam("membershipId") Long membershipId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return membershipManager.load(membershipId);
|
return membershipManager.load(membershipId);
|
||||||
@ -45,20 +50,25 @@ public class MembershipResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create new membership")
|
@Api(order=200, description="Create new membership")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull Membership membership) {
|
public Long createMembership(@NotNull Membership membership) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
membershipManager.create(membership);
|
membershipManager.create(membership);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(membership).toXML();
|
||||||
|
auditManager.audit(null, "created membership via RESTful API", null, newAuditContent);
|
||||||
return membership.getId();
|
return membership.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{membershipId}")
|
@Path("/{membershipId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("membershipId") Long membershipId) {
|
public Response deleteMembership(@PathParam("membershipId") Long membershipId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
membershipManager.delete(membershipManager.load(membershipId));
|
var membership = membershipManager.load(membershipId);
|
||||||
|
membershipManager.delete(membership);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(membership).toXML();
|
||||||
|
auditManager.audit(null, "deleted membership via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class PackLabelResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create package label")
|
@Api(order=200, description="Create package label")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull PackLabel packLabel) {
|
public Long createLabel(@NotNull PackLabel packLabel) {
|
||||||
if (!SecurityUtils.canWritePack(packLabel.getPack().getProject()))
|
if (!SecurityUtils.canWritePack(packLabel.getPack().getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
packLabelManager.create(packLabel);
|
packLabelManager.create(packLabel);
|
||||||
@ -39,7 +39,7 @@ public class PackLabelResource {
|
|||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{packLabelId}")
|
@Path("/{packLabelId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("packLabelId") Long packLabelId) {
|
public Response deleteLabel(@PathParam("packLabelId") Long packLabelId) {
|
||||||
PackLabel buildLabel = packLabelManager.load(packLabelId);
|
PackLabel buildLabel = packLabelManager.load(packLabelId);
|
||||||
if (!SecurityUtils.canWritePack(buildLabel.getPack().getProject()))
|
if (!SecurityUtils.canWritePack(buildLabel.getPack().getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|||||||
@ -1,5 +1,26 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.PackManager;
|
import io.onedev.server.entitymanager.PackManager;
|
||||||
import io.onedev.server.model.Pack;
|
import io.onedev.server.model.Pack;
|
||||||
import io.onedev.server.model.PackBlob;
|
import io.onedev.server.model.PackBlob;
|
||||||
@ -10,17 +31,6 @@ import io.onedev.server.rest.annotation.Api;
|
|||||||
import io.onedev.server.rest.resource.support.RestConstants;
|
import io.onedev.server.rest.resource.support.RestConstants;
|
||||||
import io.onedev.server.search.entity.pack.PackQuery;
|
import io.onedev.server.search.entity.pack.PackQuery;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.ws.rs.*;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
|
|
||||||
@Api(order=4300, name="Package")
|
@Api(order=4300, name="Package")
|
||||||
@Path("/packages")
|
@Path("/packages")
|
||||||
@ -31,15 +41,18 @@ public class PackResource {
|
|||||||
|
|
||||||
private final PackManager packManager;
|
private final PackManager packManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PackResource(PackManager packManager) {
|
public PackResource(PackManager packManager, AuditManager auditManager) {
|
||||||
this.packManager = packManager;
|
this.packManager = packManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{packId}")
|
@Path("/{packId}")
|
||||||
@GET
|
@GET
|
||||||
public Pack getBasicInfo(@PathParam("packId") Long packId) {
|
public Pack getPack(@PathParam("packId") Long packId) {
|
||||||
Pack pack = packManager.load(packId);
|
Pack pack = packManager.load(packId);
|
||||||
if (!SecurityUtils.canReadPack(pack.getProject()))
|
if (!SecurityUtils.canReadPack(pack.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -68,7 +81,7 @@ public class PackResource {
|
|||||||
|
|
||||||
@Api(order=600)
|
@Api(order=600)
|
||||||
@GET
|
@GET
|
||||||
public List<Pack> queryBasicInfo(
|
public List<Pack> queryPacks(
|
||||||
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~packages'>packages page</a>", example="\"Type\" is \"Container Image\"") String query,
|
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~packages'>packages page</a>", example="\"Type\" is \"Container Image\"") String query,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
@ -89,11 +102,13 @@ public class PackResource {
|
|||||||
@Api(order=700)
|
@Api(order=700)
|
||||||
@Path("/{packId}")
|
@Path("/{packId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("packId") Long packId) {
|
public Response deletePack(@PathParam("packId") Long packId) {
|
||||||
Pack pack = packManager.load(packId);
|
Pack pack = packManager.load(packId);
|
||||||
if (!SecurityUtils.canWritePack(pack.getProject()))
|
if (!SecurityUtils.canWritePack(pack.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
packManager.delete(pack);
|
packManager.delete(pack);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(pack).toXML();
|
||||||
|
auditManager.audit(pack.getProject(), "deleted package \"" + pack.getReference(false) + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,25 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.server.entitymanager.ProjectLabelManager;
|
|
||||||
import io.onedev.server.model.ProjectLabel;
|
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.security.SecurityUtils;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.ProjectLabelManager;
|
||||||
|
import io.onedev.server.model.ProjectLabel;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
|
||||||
@Api(order=10300)
|
@Api(order=10300)
|
||||||
@Path("/project-labels")
|
@Path("/project-labels")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ -22,28 +29,33 @@ public class ProjectLabelResource {
|
|||||||
|
|
||||||
private final ProjectLabelManager projectLabelManager;
|
private final ProjectLabelManager projectLabelManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ProjectLabelResource(ProjectLabelManager projectLabelManager) {
|
public ProjectLabelResource(ProjectLabelManager projectLabelManager, AuditManager auditManager) {
|
||||||
this.projectLabelManager = projectLabelManager;
|
this.projectLabelManager = projectLabelManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=200, description="Create project label")
|
@Api(order=200, description="Add project label")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull ProjectLabel projectLabel) {
|
public Long addLabel(@NotNull ProjectLabel projectLabel) {
|
||||||
if (!SecurityUtils.canManageProject(projectLabel.getProject()))
|
if (!SecurityUtils.canManageProject(projectLabel.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
projectLabelManager.create(projectLabel);
|
projectLabelManager.create(projectLabel);
|
||||||
|
auditManager.audit(projectLabel.getProject(), "added label \"" + projectLabel.getSpec().getName() + "\" via RESTful API", null, null);
|
||||||
return projectLabel.getId();
|
return projectLabel.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@Path("/{projectLabelId}")
|
@Path("/{projectLabelId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("projectLabelId") Long projectLabelId) {
|
public Response removeLabel(@PathParam("projectLabelId") Long projectLabelId) {
|
||||||
ProjectLabel projectLabel = projectLabelManager.load(projectLabelId);
|
ProjectLabel projectLabel = projectLabelManager.load(projectLabelId);
|
||||||
if (!SecurityUtils.canManageProject(projectLabel.getProject()))
|
if (!SecurityUtils.canManageProject(projectLabel.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
projectLabelManager.delete(projectLabel);
|
projectLabelManager.delete(projectLabel);
|
||||||
|
auditManager.audit(projectLabel.getProject(), "removed label \"" + projectLabel.getSpec().getName() + "\" via RESTful API", null, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import java.util.Date;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -33,7 +34,11 @@ import javax.ws.rs.core.Response;
|
|||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
import org.hibernate.criterion.Restrictions;
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.IterationManager;
|
import io.onedev.server.entitymanager.IterationManager;
|
||||||
import io.onedev.server.entitymanager.ProjectManager;
|
import io.onedev.server.entitymanager.ProjectManager;
|
||||||
import io.onedev.server.git.GitContribution;
|
import io.onedev.server.git.GitContribution;
|
||||||
@ -44,11 +49,13 @@ import io.onedev.server.model.Iteration;
|
|||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.model.ProjectLabel;
|
import io.onedev.server.model.ProjectLabel;
|
||||||
import io.onedev.server.model.UserAuthorization;
|
import io.onedev.server.model.UserAuthorization;
|
||||||
|
import io.onedev.server.model.support.CodeAnalysisSetting;
|
||||||
import io.onedev.server.model.support.NamedCodeCommentQuery;
|
import io.onedev.server.model.support.NamedCodeCommentQuery;
|
||||||
import io.onedev.server.model.support.NamedCommitQuery;
|
import io.onedev.server.model.support.NamedCommitQuery;
|
||||||
import io.onedev.server.model.support.WebHook;
|
import io.onedev.server.model.support.WebHook;
|
||||||
import io.onedev.server.model.support.build.ProjectBuildSetting;
|
import io.onedev.server.model.support.build.ProjectBuildSetting;
|
||||||
import io.onedev.server.model.support.code.BranchProtection;
|
import io.onedev.server.model.support.code.BranchProtection;
|
||||||
|
import io.onedev.server.model.support.code.GitPackConfig;
|
||||||
import io.onedev.server.model.support.code.TagProtection;
|
import io.onedev.server.model.support.code.TagProtection;
|
||||||
import io.onedev.server.model.support.issue.ProjectIssueSetting;
|
import io.onedev.server.model.support.issue.ProjectIssueSetting;
|
||||||
import io.onedev.server.model.support.pack.ProjectPackSetting;
|
import io.onedev.server.model.support.pack.ProjectPackSetting;
|
||||||
@ -56,11 +63,11 @@ import io.onedev.server.model.support.pullrequest.ProjectPullRequestSetting;
|
|||||||
import io.onedev.server.persistence.dao.EntityCriteria;
|
import io.onedev.server.persistence.dao.EntityCriteria;
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
import io.onedev.server.rest.annotation.EntityCreate;
|
||||||
import io.onedev.server.rest.resource.support.RestConstants;
|
import io.onedev.server.rest.resource.support.RestConstants;
|
||||||
import io.onedev.server.search.entity.project.ProjectQuery;
|
import io.onedev.server.search.entity.project.ProjectQuery;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.util.DateUtils;
|
import io.onedev.server.util.DateUtils;
|
||||||
import io.onedev.server.util.facade.ProjectFacade;
|
|
||||||
import io.onedev.server.web.UrlManager;
|
import io.onedev.server.web.UrlManager;
|
||||||
import io.onedev.server.web.page.project.setting.ContributedProjectSetting;
|
import io.onedev.server.web.page.project.setting.ContributedProjectSetting;
|
||||||
import io.onedev.server.xodus.CommitInfoManager;
|
import io.onedev.server.xodus.CommitInfoManager;
|
||||||
@ -79,24 +86,27 @@ public class ProjectResource {
|
|||||||
private final CommitInfoManager commitInfoManager;
|
private final CommitInfoManager commitInfoManager;
|
||||||
|
|
||||||
private final UrlManager urlManager;
|
private final UrlManager urlManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ProjectResource(ProjectManager projectManager, IterationManager iterationManager,
|
public ProjectResource(ProjectManager projectManager, IterationManager iterationManager,
|
||||||
CommitInfoManager commitInfoManager, UrlManager urlManager) {
|
CommitInfoManager commitInfoManager, UrlManager urlManager, AuditManager auditManager) {
|
||||||
this.projectManager = projectManager;
|
this.projectManager = projectManager;
|
||||||
this.iterationManager = iterationManager;
|
this.iterationManager = iterationManager;
|
||||||
this.commitInfoManager = commitInfoManager;
|
this.commitInfoManager = commitInfoManager;
|
||||||
this.urlManager = urlManager;
|
this.urlManager = urlManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{projectId}")
|
@Path("/{projectId}")
|
||||||
@GET
|
@GET
|
||||||
public Project getBasicInfo(@PathParam("projectId") Long projectId) {
|
public ProjectData getProject(@PathParam("projectId") Long projectId) {
|
||||||
Project project = projectManager.load(projectId);
|
Project project = projectManager.load(projectId);
|
||||||
if (!SecurityUtils.canAccessProject(project))
|
if (!SecurityUtils.canAccessProject(project))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return project;
|
return ProjectData.from(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=150)
|
@Api(order=150)
|
||||||
@ -121,18 +131,7 @@ public class ProjectResource {
|
|||||||
Project project = projectManager.load(projectId);
|
Project project = projectManager.load(projectId);
|
||||||
if (!SecurityUtils.canManageProject(project))
|
if (!SecurityUtils.canManageProject(project))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
ProjectSetting setting = new ProjectSetting();
|
return ProjectSetting.from(project);
|
||||||
setting.branchProtections = project.getBranchProtections();
|
|
||||||
setting.tagProtections = project.getTagProtections();
|
|
||||||
setting.buildSetting = project.getBuildSetting();
|
|
||||||
setting.packSetting = project.getPackSetting();
|
|
||||||
setting.issueSetting = project.getIssueSetting();
|
|
||||||
setting.namedCodeCommentQueries = project.getNamedCodeCommentQueries();
|
|
||||||
setting.namedCommitQueries = project.getNamedCommitQueries();
|
|
||||||
setting.pullRequestSetting = project.getPullRequestSetting();
|
|
||||||
setting.webHooks = project.getWebHooks();
|
|
||||||
setting.contributedSettings.addAll(project.getContributedSettings().values());
|
|
||||||
return setting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300)
|
@Api(order=300)
|
||||||
@ -187,7 +186,7 @@ public class ProjectResource {
|
|||||||
|
|
||||||
@Api(order=700)
|
@Api(order=700)
|
||||||
@GET
|
@GET
|
||||||
public List<Project> queryBasicInfo(
|
public List<ProjectData> queryProjects(
|
||||||
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~projects'>projects page</a>", example="\"Name\" is \"projectName\"") String query,
|
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~projects'>projects page</a>", example="\"Name\" is \"projectName\"") String query,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
@ -202,7 +201,9 @@ public class ProjectResource {
|
|||||||
throw new InvalidParamException("Error parsing query", e);
|
throw new InvalidParamException("Error parsing query", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return projectManager.query(parsedQuery, false, offset, count);
|
return projectManager.query(parsedQuery, false, offset, count).stream()
|
||||||
|
.map(ProjectData::from)
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=750)
|
@Api(order=750)
|
||||||
@ -268,31 +269,34 @@ public class ProjectResource {
|
|||||||
|
|
||||||
@Api(order=800, description="Create new project")
|
@Api(order=800, description="Create new project")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull @Valid Project project) {
|
public Long createProject(@NotNull @Valid ProjectData data) {
|
||||||
Project parent = project.getParent();
|
var project = new Project();
|
||||||
|
data.populate(project, projectManager);
|
||||||
|
|
||||||
checkProjectCreationPermission(parent);
|
checkProjectCreationPermission(project.getParent());
|
||||||
|
|
||||||
if (parent != null && project.isSelfOrAncestorOf(parent))
|
if (project.getParent() != null && project.isSelfOrAncestorOf(project.getParent()))
|
||||||
throw new ExplicitException("Can not use current or descendant project as parent");
|
throw new ExplicitException("Can not use current or descendant project as parent");
|
||||||
|
|
||||||
checkProjectNameDuplication(project);
|
checkProjectNameDuplication(project);
|
||||||
|
|
||||||
projectManager.create(project);
|
projectManager.create(project);
|
||||||
|
|
||||||
|
auditManager.audit(project, "created project via RESTful API", null, VersionedXmlDoc.fromBean(data).toXML());
|
||||||
|
|
||||||
return project.getId();
|
return project.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=850, description="Update projecty basic info of specified id")
|
@Api(order=850, description="Update project")
|
||||||
@Path("/{projectId}")
|
@Path("/{projectId}")
|
||||||
@POST
|
@POST
|
||||||
public Response updateBasicInfo(@PathParam("projectId") Long projectId, @NotNull @Valid Project project) {
|
public Response updateProject(@PathParam("projectId") Long projectId, @NotNull @Valid ProjectData data) {
|
||||||
Project parent = project.getParent();
|
Project project = projectManager.load(projectId);
|
||||||
Long oldParentId;
|
var oldAuditContent = VersionedXmlDoc.fromBean(ProjectData.from(project)).toXML();
|
||||||
if (project.getOldVersion() != null)
|
|
||||||
oldParentId = ((ProjectFacade) project.getOldVersion()).getParentId();
|
data.populate(project, projectManager);
|
||||||
else
|
|
||||||
oldParentId = null;
|
Project parent = data.getParentId() != null? projectManager.load(data.getParentId()) : null;
|
||||||
|
Long oldParentId = Project.idOf(project.getParent());
|
||||||
|
|
||||||
if (!Objects.equals(oldParentId, Project.idOf(parent)))
|
if (!Objects.equals(oldParentId, Project.idOf(parent)))
|
||||||
checkProjectCreationPermission(parent);
|
checkProjectCreationPermission(parent);
|
||||||
@ -306,6 +310,8 @@ public class ProjectResource {
|
|||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
} else {
|
} else {
|
||||||
projectManager.update(project);
|
projectManager.update(project);
|
||||||
|
auditManager.audit(project, "changed project via RESTful API", oldAuditContent,
|
||||||
|
VersionedXmlDoc.fromBean(ProjectData.from(project)).toXML());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
@ -331,38 +337,33 @@ public class ProjectResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=900, description="Update project setting")
|
@Api(order=900, description="Update project settings")
|
||||||
@Path("/{projectId}/setting")
|
@Path("/{projectId}/setting")
|
||||||
@POST
|
@POST
|
||||||
public Response updateSetting(@PathParam("projectId") Long projectId, @NotNull ProjectSetting setting) {
|
public Response updateSetting(@PathParam("projectId") Long projectId, @NotNull ProjectSetting setting) {
|
||||||
Project project = projectManager.load(projectId);
|
Project project = projectManager.load(projectId);
|
||||||
if (!SecurityUtils.canManageProject(project))
|
if (!SecurityUtils.canManageProject(project))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
project.setBranchProtections(setting.branchProtections);
|
var oldAuditContent = VersionedXmlDoc.fromBean(ProjectSetting.from(project)).toXML();
|
||||||
project.setTagProtections(setting.tagProtections);
|
setting.populate(project);
|
||||||
project.setBuildSetting(setting.buildSetting);
|
|
||||||
project.setPackSetting(setting.packSetting);
|
|
||||||
project.setIssueSetting(setting.issueSetting);
|
|
||||||
project.setNamedCodeCommentQueries(setting.namedCodeCommentQueries);
|
|
||||||
project.setNamedCommitQueries(setting.namedCommitQueries);
|
|
||||||
project.setPullRequestSetting(setting.pullRequestSetting);
|
|
||||||
project.setWebHooks(setting.webHooks);
|
|
||||||
var contributedSettings = new LinkedHashMap<String, ContributedProjectSetting>();
|
|
||||||
for (var contributedSetting: setting.getContributedSettings())
|
|
||||||
contributedSettings.put(contributedSetting.getClass().getName(), contributedSetting);
|
|
||||||
project.setContributedSettings(contributedSettings);
|
|
||||||
projectManager.update(project);
|
projectManager.update(project);
|
||||||
|
auditManager.audit(project, "changed project settings via RESTful API", oldAuditContent, VersionedXmlDoc.fromBean(setting).toXML());
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1000)
|
@Api(order=1000)
|
||||||
@Path("/{projectId}")
|
@Path("/{projectId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("projectId") Long projectId) {
|
public Response deleteProject(@PathParam("projectId") Long projectId) {
|
||||||
Project project = projectManager.load(projectId);
|
Project project = projectManager.load(projectId);
|
||||||
if (!SecurityUtils.canManageProject(project))
|
if (!SecurityUtils.canManageProject(project))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
projectManager.delete(project);
|
projectManager.delete(project);
|
||||||
|
if (project.getParent() != null)
|
||||||
|
auditManager.audit(project.getParent(), "deleted child project \"" + project.getName() + "\" via RESTful API", VersionedXmlDoc.fromBean(ProjectData.from(project)).toXML(), null);
|
||||||
|
else
|
||||||
|
auditManager.audit(null, "deleted root project \"" + project.getName() + "\" via RESTful API", VersionedXmlDoc.fromBean(ProjectData.from(project)).toXML(), null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,6 +392,215 @@ public class ProjectResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EntityCreate(Project.class)
|
||||||
|
public static class ProjectData implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Api(order = 100, description="Represents the parent project of this project. Remove this property if "
|
||||||
|
+ "the project is a root project when create/update the project. May be null")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Api(order = 150, description="Represents the project from which this project is forked. Remove this property if "
|
||||||
|
+ "the project is not a fork when create/update the project. May be null")
|
||||||
|
private Long forkedFromId;
|
||||||
|
|
||||||
|
@Api(order = 300)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Api(order = 400, description="May be null")
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
@Api(order = 450)
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@Api(order = 500, description="May be null")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
@Api(order = 550)
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Api(order = 600)
|
||||||
|
private boolean codeManagement = true;
|
||||||
|
|
||||||
|
@Api(order = 650)
|
||||||
|
private boolean packManagement = true;
|
||||||
|
|
||||||
|
@Api(order = 700)
|
||||||
|
private boolean issueManagement = true;
|
||||||
|
|
||||||
|
@Api(order = 750)
|
||||||
|
private boolean timeTracking = false;
|
||||||
|
|
||||||
|
@Api(order = 800, description = "May be null")
|
||||||
|
private String serviceDeskEmailAddress;
|
||||||
|
|
||||||
|
@Api(order = 850)
|
||||||
|
private GitPackConfig gitPackConfig;
|
||||||
|
|
||||||
|
@Api(order = 900)
|
||||||
|
private CodeAnalysisSetting codeAnalysisSetting;
|
||||||
|
|
||||||
|
public Long getParentId() {
|
||||||
|
return parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentId(Long parentId) {
|
||||||
|
this.parentId = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getForkedFromId() {
|
||||||
|
return forkedFromId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForkedFromId(Long forkedFromId) {
|
||||||
|
this.forkedFromId = forkedFromId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateDate(Date createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCodeManagement() {
|
||||||
|
return codeManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCodeManagement(boolean codeManagement) {
|
||||||
|
this.codeManagement = codeManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPackManagement() {
|
||||||
|
return packManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPackManagement(boolean packManagement) {
|
||||||
|
this.packManagement = packManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIssueManagement() {
|
||||||
|
return issueManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIssueManagement(boolean issueManagement) {
|
||||||
|
this.issueManagement = issueManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTimeTracking() {
|
||||||
|
return timeTracking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeTracking(boolean timeTracking) {
|
||||||
|
this.timeTracking = timeTracking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceDeskEmailAddress() {
|
||||||
|
return serviceDeskEmailAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceDeskEmailAddress(String serviceDeskEmailAddress) {
|
||||||
|
this.serviceDeskEmailAddress = serviceDeskEmailAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public GitPackConfig getGitPackConfig() {
|
||||||
|
return gitPackConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGitPackConfig(GitPackConfig gitPackConfig) {
|
||||||
|
this.gitPackConfig = gitPackConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public CodeAnalysisSetting getCodeAnalysisSetting() {
|
||||||
|
return codeAnalysisSetting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCodeAnalysisSetting(CodeAnalysisSetting codeAnalysisSetting) {
|
||||||
|
this.codeAnalysisSetting = codeAnalysisSetting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void populate(Project project, ProjectManager projectManager) {
|
||||||
|
if (parentId != null)
|
||||||
|
project.setParent(projectManager.load(getParentId()));
|
||||||
|
else
|
||||||
|
project.setParent(null);
|
||||||
|
if (forkedFromId != null)
|
||||||
|
project.setForkedFrom(projectManager.load(getForkedFromId()));
|
||||||
|
else
|
||||||
|
project.setForkedFrom(null);
|
||||||
|
project.setName(getName());
|
||||||
|
project.setKey(getKey());
|
||||||
|
project.setDescription(getDescription());
|
||||||
|
project.setCodeManagement(isCodeManagement());
|
||||||
|
project.setPackManagement(isPackManagement());
|
||||||
|
project.setIssueManagement(isIssueManagement());
|
||||||
|
project.setTimeTracking(isTimeTracking());
|
||||||
|
project.setServiceDeskEmailAddress(getServiceDeskEmailAddress());
|
||||||
|
project.setGitPackConfig(getGitPackConfig());
|
||||||
|
project.setCodeAnalysisSetting(getCodeAnalysisSetting());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProjectData from(Project project) {
|
||||||
|
ProjectData data = new ProjectData();
|
||||||
|
data.setParentId(Project.idOf(project.getParent()));
|
||||||
|
data.setForkedFromId(Project.idOf(project.getForkedFrom()));
|
||||||
|
data.setName(project.getName());
|
||||||
|
data.setKey(project.getKey());
|
||||||
|
data.setPath(project.getPath());
|
||||||
|
data.setDescription(project.getDescription());
|
||||||
|
data.setCreateDate(project.getCreateDate());
|
||||||
|
data.setCodeManagement(project.isCodeManagement());
|
||||||
|
data.setPackManagement(project.isPackManagement());
|
||||||
|
data.setIssueManagement(project.isIssueManagement());
|
||||||
|
data.setTimeTracking(project.isTimeTracking());
|
||||||
|
data.setServiceDeskEmailAddress(project.getServiceDeskEmailAddress());
|
||||||
|
data.setGitPackConfig(project.getGitPackConfig());
|
||||||
|
data.setCodeAnalysisSetting(project.getCodeAnalysisSetting());
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static class ProjectSetting implements Serializable {
|
public static class ProjectSetting implements Serializable {
|
||||||
|
|
||||||
@ -496,6 +706,38 @@ public class ProjectResource {
|
|||||||
this.contributedSettings = contributedSettings;
|
this.contributedSettings = contributedSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void populate(Project project) {
|
||||||
|
project.setBranchProtections(getBranchProtections());
|
||||||
|
project.setTagProtections(getTagProtections());
|
||||||
|
project.setBuildSetting(getBuildSetting());
|
||||||
|
project.setPackSetting(getPackSetting());
|
||||||
|
project.setIssueSetting(getIssueSetting());
|
||||||
|
project.setNamedCodeCommentQueries(getNamedCodeCommentQueries());
|
||||||
|
project.setNamedCommitQueries(getNamedCommitQueries());
|
||||||
|
project.setPullRequestSetting(getPullRequestSetting());
|
||||||
|
project.setWebHooks(getWebHooks());
|
||||||
|
var contributedSettings = new LinkedHashMap<String, ContributedProjectSetting>();
|
||||||
|
for (var contributedSetting: getContributedSettings())
|
||||||
|
contributedSettings.put(contributedSetting.getClass().getName(), contributedSetting);
|
||||||
|
project.setContributedSettings(contributedSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProjectSetting from(Project project) {
|
||||||
|
ProjectSetting setting = new ProjectSetting();
|
||||||
|
setting.setBranchProtections(project.getBranchProtections());
|
||||||
|
setting.setTagProtections(project.getTagProtections());
|
||||||
|
setting.setBuildSetting(project.getBuildSetting());
|
||||||
|
setting.setPackSetting(project.getPackSetting());
|
||||||
|
setting.setIssueSetting(project.getIssueSetting());
|
||||||
|
setting.setNamedCodeCommentQueries(project.getNamedCodeCommentQueries());
|
||||||
|
setting.setNamedCommitQueries(project.getNamedCommitQueries());
|
||||||
|
setting.setPullRequestSetting(project.getPullRequestSetting());
|
||||||
|
setting.setWebHooks(project.getWebHooks());
|
||||||
|
setting.getContributedSettings().addAll(project.getContributedSettings().values());
|
||||||
|
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,51 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import static io.onedev.server.model.support.pullrequest.MergeStrategy.SQUASH_SOURCE_BRANCH_COMMITS;
|
||||||
|
import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.PullRequestChangeManager;
|
import io.onedev.server.entitymanager.PullRequestChangeManager;
|
||||||
import io.onedev.server.entitymanager.PullRequestManager;
|
import io.onedev.server.entitymanager.PullRequestManager;
|
||||||
import io.onedev.server.entitymanager.UserManager;
|
import io.onedev.server.entitymanager.UserManager;
|
||||||
import io.onedev.server.git.service.GitService;
|
import io.onedev.server.git.service.GitService;
|
||||||
import io.onedev.server.model.*;
|
import io.onedev.server.model.Build;
|
||||||
|
import io.onedev.server.model.PullRequest;
|
||||||
|
import io.onedev.server.model.PullRequestAssignment;
|
||||||
|
import io.onedev.server.model.PullRequestChange;
|
||||||
|
import io.onedev.server.model.PullRequestComment;
|
||||||
|
import io.onedev.server.model.PullRequestLabel;
|
||||||
|
import io.onedev.server.model.PullRequestReview;
|
||||||
import io.onedev.server.model.PullRequestReview.Status;
|
import io.onedev.server.model.PullRequestReview.Status;
|
||||||
|
import io.onedev.server.model.PullRequestUpdate;
|
||||||
|
import io.onedev.server.model.PullRequestWatch;
|
||||||
|
import io.onedev.server.model.User;
|
||||||
import io.onedev.server.model.support.pullrequest.AutoMerge;
|
import io.onedev.server.model.support.pullrequest.AutoMerge;
|
||||||
import io.onedev.server.model.support.pullrequest.MergePreview;
|
import io.onedev.server.model.support.pullrequest.MergePreview;
|
||||||
import io.onedev.server.model.support.pullrequest.MergeStrategy;
|
import io.onedev.server.model.support.pullrequest.MergeStrategy;
|
||||||
@ -16,26 +56,6 @@ import io.onedev.server.rest.resource.support.RestConstants;
|
|||||||
import io.onedev.server.search.entity.pullrequest.PullRequestQuery;
|
import io.onedev.server.search.entity.pullrequest.PullRequestQuery;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.util.ProjectAndBranch;
|
import io.onedev.server.util.ProjectAndBranch;
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.ws.rs.*;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static io.onedev.server.model.support.pullrequest.MergeStrategy.SQUASH_SOURCE_BRANCH_COMMITS;
|
|
||||||
import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
|
|
||||||
|
|
||||||
@Api(order=3000, description="In most cases, pull request resource is operated with pull request id, which is different from pull request number. "
|
@Api(order=3000, description="In most cases, pull request resource is operated with pull request id, which is different from pull request number. "
|
||||||
+ "To get pull request id of a particular pull request number, use the <a href='/~help/api/io.onedev.server.rest.PullRequestResource/queryBasicInfo'>Query Basic Info</a> operation with query for "
|
+ "To get pull request id of a particular pull request number, use the <a href='/~help/api/io.onedev.server.rest.PullRequestResource/queryBasicInfo'>Query Basic Info</a> operation with query for "
|
||||||
@ -53,21 +73,24 @@ public class PullRequestResource {
|
|||||||
private final UserManager userManager;
|
private final UserManager userManager;
|
||||||
|
|
||||||
private final GitService gitService;
|
private final GitService gitService;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PullRequestResource(PullRequestManager pullRequestManager,
|
public PullRequestResource(PullRequestManager pullRequestManager,
|
||||||
PullRequestChangeManager pullRequestChangeManager,
|
PullRequestChangeManager pullRequestChangeManager,
|
||||||
UserManager userManager, GitService gitService) {
|
UserManager userManager, GitService gitService, AuditManager auditManager) {
|
||||||
this.pullRequestManager = pullRequestManager;
|
this.pullRequestManager = pullRequestManager;
|
||||||
this.pullRequestChangeManager = pullRequestChangeManager;
|
this.pullRequestChangeManager = pullRequestChangeManager;
|
||||||
this.userManager = userManager;
|
this.userManager = userManager;
|
||||||
this.gitService = gitService;
|
this.gitService = gitService;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{requestId}")
|
@Path("/{requestId}")
|
||||||
@GET
|
@GET
|
||||||
public PullRequest getBasicInfo(@PathParam("requestId") Long requestId) {
|
public PullRequest getPullRequest(@PathParam("requestId") Long requestId) {
|
||||||
PullRequest pullRequest = pullRequestManager.load(requestId);
|
PullRequest pullRequest = pullRequestManager.load(requestId);
|
||||||
if (!SecurityUtils.canReadCode(pullRequest.getProject()))
|
if (!SecurityUtils.canReadCode(pullRequest.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -178,7 +201,7 @@ public class PullRequestResource {
|
|||||||
|
|
||||||
@Api(order=1100)
|
@Api(order=1100)
|
||||||
@GET
|
@GET
|
||||||
public List<PullRequest> queryBasicInfo(
|
public List<PullRequest> queryPullRequests(
|
||||||
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~pulls'>pull requests page</a>", example="to be reviewed by me") String query,
|
@QueryParam("query") @Api(description="Syntax of this query is the same as in <a href='/~pulls'>pull requests page</a>", example="to be reviewed by me") String query,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
@ -198,7 +221,7 @@ public class PullRequestResource {
|
|||||||
|
|
||||||
@Api(order=1200)
|
@Api(order=1200)
|
||||||
@POST
|
@POST
|
||||||
public Response create(@NotNull PullRequestOpenData data) {
|
public Response createPullRequest(@NotNull PullRequestOpenData data) {
|
||||||
User user = SecurityUtils.getUser();
|
User user = SecurityUtils.getUser();
|
||||||
|
|
||||||
ProjectAndBranch target = new ProjectAndBranch(data.getTargetProjectId(), data.getTargetBranch());
|
ProjectAndBranch target = new ProjectAndBranch(data.getTargetProjectId(), data.getTargetBranch());
|
||||||
@ -381,7 +404,7 @@ public class PullRequestResource {
|
|||||||
@Api(order=1600)
|
@Api(order=1600)
|
||||||
@Path("/{requestId}/reopen")
|
@Path("/{requestId}/reopen")
|
||||||
@POST
|
@POST
|
||||||
public Response reopen(@PathParam("requestId") Long requestId, String note) {
|
public Response reopenPullRequest(@PathParam("requestId") Long requestId, String note) {
|
||||||
PullRequest request = pullRequestManager.load(requestId);
|
PullRequest request = pullRequestManager.load(requestId);
|
||||||
if (!SecurityUtils.canModifyPullRequest(request))
|
if (!SecurityUtils.canModifyPullRequest(request))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -396,7 +419,7 @@ public class PullRequestResource {
|
|||||||
@Api(order=1700)
|
@Api(order=1700)
|
||||||
@Path("/{requestId}/discard")
|
@Path("/{requestId}/discard")
|
||||||
@POST
|
@POST
|
||||||
public Response discard(@PathParam("requestId") Long requestId, String note) {
|
public Response discardPullRequest(@PathParam("requestId") Long requestId, String note) {
|
||||||
PullRequest request = pullRequestManager.load(requestId);
|
PullRequest request = pullRequestManager.load(requestId);
|
||||||
if (!SecurityUtils.canModifyPullRequest(request))
|
if (!SecurityUtils.canModifyPullRequest(request))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -410,7 +433,7 @@ public class PullRequestResource {
|
|||||||
@Api(order=1800)
|
@Api(order=1800)
|
||||||
@Path("/{requestId}/merge")
|
@Path("/{requestId}/merge")
|
||||||
@POST
|
@POST
|
||||||
public Response merge(@PathParam("requestId") Long requestId, String note) {
|
public Response mergePullRequest(@PathParam("requestId") Long requestId, String note) {
|
||||||
PullRequest request = pullRequestManager.load(requestId);
|
PullRequest request = pullRequestManager.load(requestId);
|
||||||
var user = SecurityUtils.getUser();
|
var user = SecurityUtils.getUser();
|
||||||
if (!SecurityUtils.canWriteCode(user.asSubject(), request.getProject()))
|
if (!SecurityUtils.canWriteCode(user.asSubject(), request.getProject()))
|
||||||
@ -471,11 +494,13 @@ public class PullRequestResource {
|
|||||||
@Api(order=2100)
|
@Api(order=2100)
|
||||||
@Path("/{requestId}")
|
@Path("/{requestId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("requestId") Long requestId) {
|
public Response deletePullRequest(@PathParam("requestId") Long requestId) {
|
||||||
PullRequest pullRequest = pullRequestManager.load(requestId);
|
PullRequest pullRequest = pullRequestManager.load(requestId);
|
||||||
if (!SecurityUtils.canManagePullRequests(pullRequest.getProject()))
|
if (!SecurityUtils.canManagePullRequests(pullRequest.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
pullRequestManager.delete(pullRequest);
|
var oldAuditContent = VersionedXmlDoc.fromBean(pullRequest).toXML();
|
||||||
|
pullRequestManager.delete(pullRequest);
|
||||||
|
auditManager.audit(pullRequest.getProject(), "deleted pull request via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +1,35 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import io.onedev.server.entitymanager.LinkSpecManager;
|
|
||||||
import io.onedev.server.model.LinkSpec;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
import org.hibernate.criterion.MatchMode;
|
import org.hibernate.criterion.MatchMode;
|
||||||
import org.hibernate.criterion.Restrictions;
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.RoleManager;
|
import io.onedev.server.entitymanager.RoleManager;
|
||||||
import io.onedev.server.model.Role;
|
import io.onedev.server.model.Role;
|
||||||
import io.onedev.server.persistence.dao.EntityCriteria;
|
import io.onedev.server.persistence.dao.EntityCriteria;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
import io.onedev.server.rest.resource.support.RestConstants;
|
import io.onedev.server.rest.resource.support.RestConstants;
|
||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.util.facade.RoleFacade;
|
|
||||||
|
|
||||||
@Api(order=7000)
|
@Api(order=7000)
|
||||||
@Path("/roles")
|
@Path("/roles")
|
||||||
@ -35,26 +40,26 @@ public class RoleResource {
|
|||||||
|
|
||||||
private final RoleManager roleManager;
|
private final RoleManager roleManager;
|
||||||
|
|
||||||
private final LinkSpecManager linkSpecManager;
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RoleResource(RoleManager roleManager, LinkSpecManager linkSpecManager) {
|
public RoleResource(RoleManager roleManager, AuditManager auditManager) {
|
||||||
this.roleManager = roleManager;
|
this.roleManager = roleManager;
|
||||||
this.linkSpecManager = linkSpecManager;
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{roleId}")
|
@Path("/{roleId}")
|
||||||
@GET
|
@GET
|
||||||
public Role get(@PathParam("roleId") Long roleId) {
|
public Role getRole(@PathParam("roleId") Long roleId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return roleManager.load(roleId);
|
return roleManager.load(roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=200)
|
@Api(order=200)
|
||||||
@GET
|
@GET
|
||||||
public List<Role> query(@QueryParam("name") String name, @QueryParam("offset") @Api(example="0") int offset,
|
public List<Role> queryRoles(@QueryParam("name") String name, @QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
|
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
@ -67,50 +72,47 @@ public class RoleResource {
|
|||||||
if (name != null)
|
if (name != null)
|
||||||
criteria.add(Restrictions.ilike("name", name.replace('*', '%'), MatchMode.EXACT));
|
criteria.add(Restrictions.ilike("name", name.replace('*', '%'), MatchMode.EXACT));
|
||||||
|
|
||||||
return roleManager.query(criteria, offset, count);
|
return roleManager.query(name, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=250)
|
@Api(order=250)
|
||||||
@Path("/ids/{name}")
|
@Path("/ids/{name}")
|
||||||
@GET
|
@GET
|
||||||
public Long getId(@PathParam("name") String name) {
|
public Long getRoleId(@PathParam("name") String name) {
|
||||||
var role = roleManager.find(name);
|
var role = roleManager.find(name);
|
||||||
if (role != null)
|
if (role != null)
|
||||||
return role.getId();
|
return role.getId();
|
||||||
else
|
else
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300, description="Create new role")
|
@Api(order=300, description="Create new role")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull Role role) {
|
public Long createRole(@NotNull Role role) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
Collection<LinkSpec> authorizedLinks = new ArrayList<>();
|
roleManager.create(role, null);
|
||||||
for (String linkName: role.getEditableIssueLinks())
|
var auditContent = VersionedXmlDoc.fromBean(role).toXML();
|
||||||
authorizedLinks.add(linkSpecManager.find(linkName));
|
auditManager.audit(null, "created role \"" + role.getName() + "\" via RESTful API", null, auditContent);
|
||||||
|
|
||||||
roleManager.create(role, authorizedLinks);
|
|
||||||
|
|
||||||
return role.getId();
|
return role.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=350, description="Update role of specified id")
|
@Api(order=350, description="Update role of specified id")
|
||||||
@Path("/{roleId}")
|
@Path("/{roleId}")
|
||||||
@POST
|
@POST
|
||||||
public Response update(@PathParam("roleId") Long roleId, @NotNull Role role) {
|
public Response updateRole(@PathParam("roleId") Long roleId, @NotNull Role role) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
Collection<LinkSpec> authorizedLinks = new ArrayList<>();
|
var oldAuditContent = role.getOldVersion().toXML();
|
||||||
for (String linkName: role.getEditableIssueLinks())
|
var newAuditContent = VersionedXmlDoc.fromBean(role).toXML();
|
||||||
authorizedLinks.add(linkSpecManager.find(linkName));
|
|
||||||
|
|
||||||
if (role.getOldVersion() != null)
|
var oldName = role.getOldVersion().getRootElement().elementText(Role.PROP_NAME);
|
||||||
roleManager.update(role, authorizedLinks, ((RoleFacade) role.getOldVersion()).getName());
|
roleManager.update(role, null, oldName);
|
||||||
else
|
|
||||||
roleManager.update(role, authorizedLinks, null);
|
auditManager.audit(null, "changed role \"" + role.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
@ -118,11 +120,14 @@ public class RoleResource {
|
|||||||
@Api(order=400)
|
@Api(order=400)
|
||||||
@Path("/{roleId}")
|
@Path("/{roleId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("roleId") Long roleId) {
|
public Response deleteRole(@PathParam("roleId") Long roleId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
roleManager.delete(roleManager.load(roleId));
|
var role = roleManager.load(roleId);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(role).toXML();
|
||||||
|
roleManager.delete(role);
|
||||||
|
auditManager.audit(null, "deleted role \"" + role.getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,47 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import java.util.ArrayList;
|
||||||
import io.onedev.server.entitymanager.SettingManager;
|
import java.util.Collections;
|
||||||
import io.onedev.server.model.support.administration.mailservice.MailService;
|
import java.util.HashMap;
|
||||||
import io.onedev.server.model.support.administration.*;
|
import java.util.List;
|
||||||
import io.onedev.server.model.support.administration.authenticator.Authenticator;
|
import java.util.Map;
|
||||||
import io.onedev.server.model.support.administration.emailtemplates.EmailTemplates;
|
|
||||||
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
|
|
||||||
import io.onedev.server.model.support.administration.sso.SsoConnector;
|
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.rest.InvalidParamException;
|
|
||||||
import io.onedev.server.security.SecurityUtils;
|
|
||||||
import io.onedev.server.web.page.layout.ContributedAdministrationSetting;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.*;
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.SettingManager;
|
||||||
|
import io.onedev.server.model.support.administration.BackupSetting;
|
||||||
|
import io.onedev.server.model.support.administration.GlobalBuildSetting;
|
||||||
|
import io.onedev.server.model.support.administration.GlobalIssueSetting;
|
||||||
|
import io.onedev.server.model.support.administration.GlobalProjectSetting;
|
||||||
|
import io.onedev.server.model.support.administration.GlobalPullRequestSetting;
|
||||||
|
import io.onedev.server.model.support.administration.GroovyScript;
|
||||||
|
import io.onedev.server.model.support.administration.SecuritySetting;
|
||||||
|
import io.onedev.server.model.support.administration.ServiceDeskSetting;
|
||||||
|
import io.onedev.server.model.support.administration.SshSetting;
|
||||||
|
import io.onedev.server.model.support.administration.SystemSetting;
|
||||||
|
import io.onedev.server.model.support.administration.authenticator.Authenticator;
|
||||||
|
import io.onedev.server.model.support.administration.emailtemplates.EmailTemplates;
|
||||||
|
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
|
||||||
|
import io.onedev.server.model.support.administration.mailservice.MailService;
|
||||||
|
import io.onedev.server.model.support.administration.sso.SsoConnector;
|
||||||
|
import io.onedev.server.rest.InvalidParamException;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
import io.onedev.server.web.page.layout.ContributedAdministrationSetting;
|
||||||
|
|
||||||
@Api(order=10000)
|
@Api(order=10000)
|
||||||
@Path("/settings")
|
@Path("/settings")
|
||||||
@ -30,10 +51,13 @@ import java.util.*;
|
|||||||
public class SettingResource {
|
public class SettingResource {
|
||||||
|
|
||||||
private final SettingManager settingManager;
|
private final SettingManager settingManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SettingResource(SettingManager settingManager) {
|
public SettingResource(SettingManager settingManager, AuditManager auditManager) {
|
||||||
this.settingManager = settingManager;
|
this.settingManager = settingManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@ -189,8 +213,10 @@ public class SettingResource {
|
|||||||
String ingressUrl = OneDev.getInstance().getIngressUrl();
|
String ingressUrl = OneDev.getInstance().getIngressUrl();
|
||||||
if (ingressUrl != null && !ingressUrl.equals(systemSetting.getServerUrl()))
|
if (ingressUrl != null && !ingressUrl.equals(systemSetting.getServerUrl()))
|
||||||
throw new InvalidParamException("Server URL can only be \"" + ingressUrl + "\"");
|
throw new InvalidParamException("Server URL can only be \"" + ingressUrl + "\"");
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getSystemSetting()).toXML();
|
||||||
settingManager.saveSystemSetting(systemSetting);
|
settingManager.saveSystemSetting(systemSetting);
|
||||||
|
auditManager.audit(null, "changed system setting via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(systemSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +226,10 @@ public class SettingResource {
|
|||||||
public Response setAuthenticator(Authenticator authenticator) {
|
public Response setAuthenticator(Authenticator authenticator) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getAuthenticator()).toXML();
|
||||||
settingManager.saveAuthenticator(authenticator);
|
settingManager.saveAuthenticator(authenticator);
|
||||||
|
auditManager.audit(null, "changed authenticator via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(authenticator).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +239,10 @@ public class SettingResource {
|
|||||||
public Response setBackupSetting(BackupSetting backupSetting) {
|
public Response setBackupSetting(BackupSetting backupSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getBackupSetting()).toXML();
|
||||||
settingManager.saveBackupSetting(backupSetting);
|
settingManager.saveBackupSetting(backupSetting);
|
||||||
|
auditManager.audit(null, "changed backup settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(backupSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +252,10 @@ public class SettingResource {
|
|||||||
public Response setBuildSetting(@NotNull GlobalBuildSetting buildSetting) {
|
public Response setBuildSetting(@NotNull GlobalBuildSetting buildSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getBuildSetting()).toXML();
|
||||||
settingManager.saveBuildSetting(buildSetting);
|
settingManager.saveBuildSetting(buildSetting);
|
||||||
|
auditManager.audit(null, "changed build settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(buildSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +265,10 @@ public class SettingResource {
|
|||||||
public Response setGroovyScripts(@NotNull List<GroovyScript> groovyScripts) {
|
public Response setGroovyScripts(@NotNull List<GroovyScript> groovyScripts) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getGroovyScripts()).toXML();
|
||||||
settingManager.saveGroovyScripts(groovyScripts);
|
settingManager.saveGroovyScripts(groovyScripts);
|
||||||
|
auditManager.audit(null, "changed groovy scripts via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(groovyScripts).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,8 +278,11 @@ public class SettingResource {
|
|||||||
public Response setIssueSetting(@NotNull GlobalIssueSetting issueSetting) {
|
public Response setIssueSetting(@NotNull GlobalIssueSetting issueSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getIssueSetting()).toXML();
|
||||||
issueSetting.setReconciled(false);
|
issueSetting.setReconciled(false);
|
||||||
settingManager.saveIssueSetting(issueSetting);
|
settingManager.saveIssueSetting(issueSetting);
|
||||||
|
auditManager.audit(null, "changed issue settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(issueSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +292,10 @@ public class SettingResource {
|
|||||||
public Response setJobExecutors(@NotNull List<JobExecutor> jobExecutors) {
|
public Response setJobExecutors(@NotNull List<JobExecutor> jobExecutors) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getJobExecutors()).toXML();
|
||||||
settingManager.saveJobExecutors(jobExecutors);
|
settingManager.saveJobExecutors(jobExecutors);
|
||||||
|
auditManager.audit(null, "changed job executors via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(jobExecutors).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +305,10 @@ public class SettingResource {
|
|||||||
public Response setMailService(MailService mailService) {
|
public Response setMailService(MailService mailService) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getMailService()).toXML();
|
||||||
settingManager.saveMailService(mailService);
|
settingManager.saveMailService(mailService);
|
||||||
|
auditManager.audit(null, "changed mail service via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(mailService).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +318,10 @@ public class SettingResource {
|
|||||||
public Response setServiceDeskSetting(ServiceDeskSetting serviceDeskSetting) {
|
public Response setServiceDeskSetting(ServiceDeskSetting serviceDeskSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getServiceDeskSetting()).toXML();
|
||||||
settingManager.saveServiceDeskSetting(serviceDeskSetting);
|
settingManager.saveServiceDeskSetting(serviceDeskSetting);
|
||||||
|
auditManager.audit(null, "changed service desk settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(serviceDeskSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +331,10 @@ public class SettingResource {
|
|||||||
public Response setNotificationTemplateSetting(EmailTemplates emailTemplates) {
|
public Response setNotificationTemplateSetting(EmailTemplates emailTemplates) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getEmailTemplates()).toXML();
|
||||||
settingManager.saveEmailTemplates(emailTemplates);
|
settingManager.saveEmailTemplates(emailTemplates);
|
||||||
|
auditManager.audit(null, "changed notification template via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(emailTemplates).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +344,10 @@ public class SettingResource {
|
|||||||
public Response setProjectSetting(@NotNull GlobalProjectSetting projectSetting) {
|
public Response setProjectSetting(@NotNull GlobalProjectSetting projectSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getProjectSetting()).toXML();
|
||||||
settingManager.saveProjectSetting(projectSetting);
|
settingManager.saveProjectSetting(projectSetting);
|
||||||
|
auditManager.audit(null, "changed project settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(projectSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +357,10 @@ public class SettingResource {
|
|||||||
public Response setPullRequestSetting(@NotNull GlobalPullRequestSetting pullRequestSetting) {
|
public Response setPullRequestSetting(@NotNull GlobalPullRequestSetting pullRequestSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getPullRequestSetting()).toXML();
|
||||||
settingManager.savePullRequestSetting(pullRequestSetting);
|
settingManager.savePullRequestSetting(pullRequestSetting);
|
||||||
|
auditManager.audit(null, "changed pull request settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(pullRequestSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +370,10 @@ public class SettingResource {
|
|||||||
public Response setSecuritySetting(@NotNull SecuritySetting securitySetting) {
|
public Response setSecuritySetting(@NotNull SecuritySetting securitySetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getSecuritySetting()).toXML();
|
||||||
settingManager.saveSecuritySetting(securitySetting);
|
settingManager.saveSecuritySetting(securitySetting);
|
||||||
|
auditManager.audit(null, "changed security settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(securitySetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +383,10 @@ public class SettingResource {
|
|||||||
public Response setSshSetting(@NotNull SshSetting sshSetting) {
|
public Response setSshSetting(@NotNull SshSetting sshSetting) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getSshSetting()).toXML();
|
||||||
settingManager.saveSshSetting(sshSetting);
|
settingManager.saveSshSetting(sshSetting);
|
||||||
|
auditManager.audit(null, "changed ssh settings via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(sshSetting).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,20 +396,34 @@ public class SettingResource {
|
|||||||
public Response setSsoConnectors(@NotNull List<SsoConnector> ssoConnectors) {
|
public Response setSsoConnectors(@NotNull List<SsoConnector> ssoConnectors) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(settingManager.getSsoConnectors()).toXML();
|
||||||
settingManager.saveSsoConnectors(ssoConnectors);
|
settingManager.saveSsoConnectors(ssoConnectors);
|
||||||
|
auditManager.audit(null, "changed sso connectors via RESTful API",
|
||||||
|
oldAuditContent, VersionedXmlDoc.fromBean(ssoConnectors).toXML());
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getAuditContent(Map<String, ContributedAdministrationSetting> contributedSettings) {
|
||||||
|
var list = new ArrayList<ContributedAdministrationSetting>();
|
||||||
|
for (var entry: contributedSettings.entrySet())
|
||||||
|
list.add(entry.getValue());
|
||||||
|
Collections.sort(list, (a, b) -> {return a.getClass().getName().compareTo(b.getClass().getName());});
|
||||||
|
return VersionedXmlDoc.fromBean(list).toXML();
|
||||||
|
}
|
||||||
|
|
||||||
@Api(order=2800)
|
@Api(order=2800)
|
||||||
@Path("/contributed-settings")
|
@Path("/contributed-settings")
|
||||||
@POST
|
@POST
|
||||||
public Response setContributedSettings(@NotNull List<ContributedAdministrationSetting> contributedSettings) {
|
public Response setContributedSettings(@NotNull List<ContributedAdministrationSetting> contributedSettings) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
var oldAuditContent = getAuditContent(settingManager.getContributedSettings());
|
||||||
var settingMap = new HashMap<String, ContributedAdministrationSetting>();
|
var settingMap = new HashMap<String, ContributedAdministrationSetting>();
|
||||||
for (var setting: contributedSettings)
|
for (var setting: contributedSettings)
|
||||||
settingMap.put(setting.getClass().getName(), setting);
|
settingMap.put(setting.getClass().getName(), setting);
|
||||||
settingManager.saveContributedSettings(settingMap);
|
settingManager.saveContributedSettings(settingMap);
|
||||||
|
auditManager.audit(null, "changed contributed settings via RESTful API",
|
||||||
|
oldAuditContent, getAuditContent(settingMap));
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -16,6 +18,8 @@ import javax.ws.rs.core.Response;
|
|||||||
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.SshKeyManager;
|
import io.onedev.server.entitymanager.SshKeyManager;
|
||||||
import io.onedev.server.model.SshKey;
|
import io.onedev.server.model.SshKey;
|
||||||
import io.onedev.server.rest.annotation.Api;
|
import io.onedev.server.rest.annotation.Api;
|
||||||
@ -30,42 +34,53 @@ public class SshKeyResource {
|
|||||||
|
|
||||||
private final SshKeyManager sshKeyManager;
|
private final SshKeyManager sshKeyManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SshKeyResource(SshKeyManager sshKeyManager) {
|
public SshKeyResource(SshKeyManager sshKeyManager, AuditManager auditManager) {
|
||||||
this.sshKeyManager = sshKeyManager;
|
this.sshKeyManager = sshKeyManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100)
|
@Api(order=100)
|
||||||
@Path("/{sshKeyId}")
|
@Path("/{sshKeyId}")
|
||||||
@GET
|
@GET
|
||||||
public SshKey get(@PathParam("sshKeyId") Long sshKeyId) {
|
public SshKey getKey(@PathParam("sshKeyId") Long sshKeyId) {
|
||||||
SshKey sshKey = sshKeyManager.load(sshKeyId);
|
SshKey sshKey = sshKeyManager.load(sshKeyId);
|
||||||
if (!SecurityUtils.isAdministrator() && !sshKey.getOwner().equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !sshKey.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return sshKey;
|
return sshKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=150, description="Create new ssh key")
|
@Api(order=150, description="Create new ssh key")
|
||||||
@POST
|
@POST
|
||||||
public Long create(SshKey sshKey) {
|
public Long createKey(SshKey sshKey) {
|
||||||
if (!SecurityUtils.isAdministrator() && !sshKey.getOwner().equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !sshKey.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
sshKey.setCreatedAt(new Date());
|
sshKey.setCreatedAt(new Date());
|
||||||
sshKey.fingerprint();
|
sshKey.generateFingerprint();
|
||||||
|
|
||||||
sshKeyManager.create(sshKey);
|
sshKeyManager.create(sshKey);
|
||||||
|
if (!getAuthUser().equals(sshKey.getOwner())) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(sshKey).toXML();
|
||||||
|
auditManager.audit(null, "created ssh key for account \"" + sshKey.getOwner().getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
|
}
|
||||||
return sshKey.getId();
|
return sshKey.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=200)
|
@Api(order=200)
|
||||||
@Path("/{sshKeyId}")
|
@Path("/{sshKeyId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("sshKeyId") Long sshKeyId) {
|
public Response deleteKey(@PathParam("sshKeyId") Long sshKeyId) {
|
||||||
SshKey sshKey = sshKeyManager.load(sshKeyId);
|
SshKey sshKey = sshKeyManager.load(sshKeyId);
|
||||||
if (!SecurityUtils.isAdministrator() && !sshKey.getOwner().equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !sshKey.getOwner().equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
sshKeyManager.delete(sshKey);
|
sshKeyManager.delete(sshKey);
|
||||||
|
if (!getAuthUser().equals(sshKey.getOwner())) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(sshKey).toXML();
|
||||||
|
auditManager.audit(null, "deleted ssh key for account \"" + sshKey.getOwner().getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
|
}
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,27 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
import io.onedev.server.entitymanager.UserAuthorizationManager;
|
|
||||||
import io.onedev.server.model.UserAuthorization;
|
|
||||||
import io.onedev.server.rest.annotation.Api;
|
|
||||||
import io.onedev.server.security.SecurityUtils;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.UserAuthorizationManager;
|
||||||
|
import io.onedev.server.model.UserAuthorization;
|
||||||
|
import io.onedev.server.rest.annotation.Api;
|
||||||
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
|
||||||
@Api(order=8000)
|
@Api(order=8000)
|
||||||
@Path("/user-authorizations")
|
@Path("/user-authorizations")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ -22,15 +31,18 @@ public class UserAuthorizationResource {
|
|||||||
|
|
||||||
private final UserAuthorizationManager authorizationManager;
|
private final UserAuthorizationManager authorizationManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public UserAuthorizationResource(UserAuthorizationManager authorizationManager) {
|
public UserAuthorizationResource(UserAuthorizationManager authorizationManager, AuditManager auditManager) {
|
||||||
this.authorizationManager = authorizationManager;
|
this.authorizationManager = authorizationManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100, description = "Get user authorization of specified id")
|
@Api(order=100, description = "Get user authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@GET
|
@GET
|
||||||
public UserAuthorization get(@PathParam("authorizationId") Long authorizationId) {
|
public UserAuthorization getAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
UserAuthorization authorization = authorizationManager.load(authorizationId);
|
UserAuthorization authorization = authorizationManager.load(authorizationId);
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
@ -39,21 +51,25 @@ public class UserAuthorizationResource {
|
|||||||
|
|
||||||
@Api(order=200, description="Create user authorization")
|
@Api(order=200, description="Create user authorization")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull UserAuthorization authorization) {
|
public Long createAuthorization(@NotNull UserAuthorization authorization) {
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
authorizationManager.createOrUpdate(authorization);
|
authorizationManager.createOrUpdate(authorization);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(null, "created user authorization via RESTful API", null, newAuditContent);
|
||||||
return authorization.getId();
|
return authorization.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=300, description = "Delete user authorization of specified id")
|
@Api(order=300, description = "Delete user authorization of specified id")
|
||||||
@Path("/{authorizationId}")
|
@Path("/{authorizationId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("authorizationId") Long authorizationId) {
|
public Response deleteAuthorization(@PathParam("authorizationId") Long authorizationId) {
|
||||||
UserAuthorization authorization = authorizationManager.load(authorizationId);
|
UserAuthorization authorization = authorizationManager.load(authorizationId);
|
||||||
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
if (!SecurityUtils.canManageProject(authorization.getProject()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
authorizationManager.delete(authorization);
|
authorizationManager.delete(authorization);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(authorization).toXML();
|
||||||
|
auditManager.audit(null, "deleted user authorization via RESTful API", oldAuditContent, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package io.onedev.server.rest.resource;
|
package io.onedev.server.rest.resource;
|
||||||
|
|
||||||
|
import static io.onedev.server.security.SecurityUtils.getAuthUser;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -30,11 +31,12 @@ import javax.ws.rs.core.MediaType;
|
|||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.apache.shiro.authc.credential.PasswordService;
|
import org.apache.shiro.authc.credential.PasswordService;
|
||||||
import org.apache.shiro.authz.UnauthenticatedException;
|
|
||||||
import org.apache.shiro.authz.UnauthorizedException;
|
import org.apache.shiro.authz.UnauthorizedException;
|
||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
import io.onedev.server.annotation.UserName;
|
import io.onedev.server.annotation.UserName;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.EmailAddressManager;
|
import io.onedev.server.entitymanager.EmailAddressManager;
|
||||||
import io.onedev.server.entitymanager.SshKeyManager;
|
import io.onedev.server.entitymanager.SshKeyManager;
|
||||||
import io.onedev.server.entitymanager.UserManager;
|
import io.onedev.server.entitymanager.UserManager;
|
||||||
@ -76,45 +78,48 @@ public class UserResource {
|
|||||||
private final PasswordService passwordService;
|
private final PasswordService passwordService;
|
||||||
|
|
||||||
private final EmailAddressManager emailAddressManager;
|
private final EmailAddressManager emailAddressManager;
|
||||||
|
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public UserResource(UserManager userManager, SshKeyManager sshKeyManager,
|
public UserResource(UserManager userManager, SshKeyManager sshKeyManager,
|
||||||
PasswordService passwordService, EmailAddressManager emailAddressManager) {
|
PasswordService passwordService, EmailAddressManager emailAddressManager, AuditManager auditManager) {
|
||||||
this.userManager = userManager;
|
this.userManager = userManager;
|
||||||
this.sshKeyManager = sshKeyManager;
|
this.sshKeyManager = sshKeyManager;
|
||||||
this.passwordService = passwordService;
|
this.passwordService = passwordService;
|
||||||
this.emailAddressManager = emailAddressManager;
|
this.emailAddressManager = emailAddressManager;
|
||||||
|
this.auditManager = auditManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BasicSetting getBasicSetting(User user) {
|
private UserData getData(User user) {
|
||||||
var basicSetting = new BasicSetting();
|
var data = new UserData();
|
||||||
basicSetting.setDisabled(user.isDisabled());
|
data.setDisabled(user.isDisabled());
|
||||||
basicSetting.setServiceAccount(user.isServiceAccount());
|
data.setServiceAccount(user.isServiceAccount());
|
||||||
basicSetting.setName(user.getName());
|
data.setName(user.getName());
|
||||||
basicSetting.setFullName(user.getFullName());
|
data.setFullName(user.getFullName());
|
||||||
if (!user.isServiceAccount())
|
if (!user.isServiceAccount())
|
||||||
basicSetting.setNotifyOwnEvents(user.isNotifyOwnEvents());
|
data.setNotifyOwnEvents(user.isNotifyOwnEvents());
|
||||||
return basicSetting;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=100, name="Get Basic Settings")
|
@Api(order=100)
|
||||||
@Path("/{userId}")
|
@Path("/{userId}")
|
||||||
@GET
|
@GET
|
||||||
public BasicSetting getBasicSetting(@PathParam("userId") Long userId) {
|
public UserData getUser(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return getBasicSetting(user);
|
return getData(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=200, name="Get Basic Settings of Current User")
|
@Api(order=200)
|
||||||
@Path("/me")
|
@Path("/me")
|
||||||
@GET
|
@GET
|
||||||
public BasicSetting getMyBasicSetting() {
|
public UserData getMe() {
|
||||||
User user = SecurityUtils.getAuthUser();
|
User user = getAuthUser();
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return getBasicSetting(user);
|
return getData(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=250)
|
@Api(order=250)
|
||||||
@ -122,7 +127,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<AccessToken> getAccessTokens(@PathParam("userId") Long userId) {
|
public Collection<AccessToken> getAccessTokens(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getAccessTokens();
|
return user.getAccessTokens();
|
||||||
}
|
}
|
||||||
@ -132,7 +137,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<EmailAddress> getEmailAddresses(@PathParam("userId") Long userId) {
|
public Collection<EmailAddress> getEmailAddresses(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getEmailAddresses();
|
return user.getEmailAddresses();
|
||||||
}
|
}
|
||||||
@ -160,7 +165,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<PullRequestReview> getPullRequestReviews(@PathParam("userId") Long userId) {
|
public Collection<PullRequestReview> getPullRequestReviews(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getPullRequestReviews();
|
return user.getPullRequestReviews();
|
||||||
}
|
}
|
||||||
@ -170,7 +175,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<IssueVote> getIssueVotes(@PathParam("userId") Long userId) {
|
public Collection<IssueVote> getIssueVotes(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getIssueVotes();
|
return user.getIssueVotes();
|
||||||
}
|
}
|
||||||
@ -180,7 +185,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<IssueWatch> getIssueWatches(@PathParam("userId") Long userId) {
|
public Collection<IssueWatch> getIssueWatches(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getIssueWatches();
|
return user.getIssueWatches();
|
||||||
}
|
}
|
||||||
@ -190,7 +195,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<BuildQueryPersonalization> getProjectBuildQueryPersonalizations(@PathParam("userId") Long userId) {
|
public Collection<BuildQueryPersonalization> getProjectBuildQueryPersonalizations(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getBuildQueryPersonalizations();
|
return user.getBuildQueryPersonalizations();
|
||||||
}
|
}
|
||||||
@ -200,7 +205,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<CodeCommentQueryPersonalization> getProjectCodeCommentQueryPersonalizations(@PathParam("userId") Long userId) {
|
public Collection<CodeCommentQueryPersonalization> getProjectCodeCommentQueryPersonalizations(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getCodeCommentQueryPersonalizations();
|
return user.getCodeCommentQueryPersonalizations();
|
||||||
}
|
}
|
||||||
@ -210,7 +215,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<CommitQueryPersonalization> getProjectCommitQueryPersonalizations(@PathParam("userId") Long userId) {
|
public Collection<CommitQueryPersonalization> getProjectCommitQueryPersonalizations(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getCommitQueryPersonalizations();
|
return user.getCommitQueryPersonalizations();
|
||||||
}
|
}
|
||||||
@ -220,7 +225,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<IssueQueryPersonalization> getProjecIssueQueryPersonalizations(@PathParam("userId") Long userId) {
|
public Collection<IssueQueryPersonalization> getProjecIssueQueryPersonalizations(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getIssueQueryPersonalizations();
|
return user.getIssueQueryPersonalizations();
|
||||||
}
|
}
|
||||||
@ -230,7 +235,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<PullRequestQueryPersonalization> getProjecPullRequestQueryPersonalizations(@PathParam("userId") Long userId) {
|
public Collection<PullRequestQueryPersonalization> getProjecPullRequestQueryPersonalizations(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getPullRequestQueryPersonalizations();
|
return user.getPullRequestQueryPersonalizations();
|
||||||
}
|
}
|
||||||
@ -240,7 +245,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<PullRequestAssignment> getPullRequestAssignments(@PathParam("userId") Long userId) {
|
public Collection<PullRequestAssignment> getPullRequestAssignments(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getPullRequestAssignments();
|
return user.getPullRequestAssignments();
|
||||||
}
|
}
|
||||||
@ -250,7 +255,7 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<PullRequestWatch> getPullRequestWatches(@PathParam("userId") Long userId) {
|
public Collection<PullRequestWatch> getPullRequestWatches(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getPullRequestWatches();
|
return user.getPullRequestWatches();
|
||||||
}
|
}
|
||||||
@ -260,18 +265,12 @@ public class UserResource {
|
|||||||
@GET
|
@GET
|
||||||
public Collection<SshKey> getSshKeys(@PathParam("userId") Long userId) {
|
public Collection<SshKey> getSshKeys(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
return user.getSshKeys();
|
return user.getSshKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1700)
|
private QueriesAndWatches getQueriesAndWatches(User user) {
|
||||||
@Path("/{userId}/queries-and-watches")
|
|
||||||
@GET
|
|
||||||
public QueriesAndWatches getQueriesAndWatches(@PathParam("userId") Long userId) {
|
|
||||||
User user = userManager.load(userId);
|
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
|
||||||
throw new UnauthorizedException();
|
|
||||||
QueriesAndWatches queriesAndWatches = new QueriesAndWatches();
|
QueriesAndWatches queriesAndWatches = new QueriesAndWatches();
|
||||||
queriesAndWatches.buildQuerySubscriptions = user.getBuildQuerySubscriptions();
|
queriesAndWatches.buildQuerySubscriptions = user.getBuildQuerySubscriptions();
|
||||||
queriesAndWatches.issueQueryWatches = user.getIssueQueryWatches();
|
queriesAndWatches.issueQueryWatches = user.getIssueQueryWatches();
|
||||||
@ -281,24 +280,34 @@ public class UserResource {
|
|||||||
queriesAndWatches.projectQueries = user.getProjectQueries();
|
queriesAndWatches.projectQueries = user.getProjectQueries();
|
||||||
queriesAndWatches.pullRequestQueries = user.getPullRequestQueries();
|
queriesAndWatches.pullRequestQueries = user.getPullRequestQueries();
|
||||||
return queriesAndWatches;
|
return queriesAndWatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Api(order=1700)
|
||||||
|
@Path("/{userId}/queries-and-watches")
|
||||||
|
@GET
|
||||||
|
public QueriesAndWatches getQueriesAndWatches(@PathParam("userId") Long userId) {
|
||||||
|
User user = userManager.load(userId);
|
||||||
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
return getQueriesAndWatches(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1800, name="Query Basic Settings")
|
@Api(order=1800)
|
||||||
@GET
|
@GET
|
||||||
public List<BasicSetting> queryBasicSetting(
|
public List<UserData> queryUsers(
|
||||||
@QueryParam("term") @Api(description="Any string in login name, full name or email address") String term,
|
@QueryParam("term") @Api(description="Any string in login name, full name or email address") String term,
|
||||||
@QueryParam("offset") @Api(example="0") int offset,
|
@QueryParam("offset") @Api(example="0") int offset,
|
||||||
@QueryParam("count") @Api(example="100") int count) {
|
@QueryParam("count") @Api(example="100") int count) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
return userManager.query(term, offset, count).stream().map(this::getBasicSetting).collect(toList());
|
return userManager.query(term, offset, count).stream().map(this::getData).collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1850)
|
@Api(order=1850)
|
||||||
@Path("/ids/{name}")
|
@Path("/ids/{name}")
|
||||||
@GET
|
@GET
|
||||||
public Long getId(@PathParam("name") @Api(description = "Login name of user") String name) {
|
public Long getUserId(@PathParam("name") @Api(description = "Login name of user") String name) {
|
||||||
var user = userManager.findByName(name);
|
var user = userManager.findByName(name);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
return user.getId();
|
return user.getId();
|
||||||
@ -308,87 +317,105 @@ public class UserResource {
|
|||||||
|
|
||||||
@Api(order=1900, description="Create new user")
|
@Api(order=1900, description="Create new user")
|
||||||
@POST
|
@POST
|
||||||
public Long create(@NotNull @Valid UserCreateData data) {
|
public Long createUser(@NotNull @Valid UserCreateData data) {
|
||||||
if (SecurityUtils.isAdministrator()) {
|
if (!SecurityUtils.isAdministrator())
|
||||||
if (userManager.findByName(data.getName()) != null)
|
throw new UnauthorizedException();
|
||||||
throw new ExplicitException("Login name is already used by another user");
|
|
||||||
if (!data.isServiceAccount() && emailAddressManager.findByValue(data.getEmailAddress()) != null)
|
if (userManager.findByName(data.getName()) != null)
|
||||||
throw new ExplicitException("Email address is already used by another user");
|
throw new ExplicitException("Login name is already used by another user");
|
||||||
|
if (!data.isServiceAccount() && emailAddressManager.findByValue(data.getEmailAddress()) != null)
|
||||||
User user = new User();
|
throw new ExplicitException("Email address is already used by another user");
|
||||||
user.setServiceAccount(data.isServiceAccount());
|
|
||||||
user.setName(data.getName());
|
User user = new User();
|
||||||
user.setFullName(data.getFullName());
|
user.setServiceAccount(data.isServiceAccount());
|
||||||
if (data.isServiceAccount()) {
|
user.setName(data.getName());
|
||||||
userManager.create(user);
|
user.setFullName(data.getFullName());
|
||||||
} else {
|
if (data.isServiceAccount()) {
|
||||||
user.setNotifyOwnEvents(data.isNotifyOwnEvents());
|
userManager.create(user);
|
||||||
user.setPassword(passwordService.encryptPassword(data.getPassword()));
|
|
||||||
userManager.create(user);
|
|
||||||
EmailAddress emailAddress = new EmailAddress();
|
|
||||||
emailAddress.setGit(true);
|
|
||||||
emailAddress.setPrimary(true);
|
|
||||||
emailAddress.setOwner(user);
|
|
||||||
emailAddress.setValue(data.getEmailAddress());
|
|
||||||
emailAddress.setVerificationCode(null);
|
|
||||||
emailAddressManager.create(emailAddress);
|
|
||||||
}
|
|
||||||
return user.getId();
|
|
||||||
} else {
|
} else {
|
||||||
throw new UnauthenticatedException();
|
user.setNotifyOwnEvents(data.isNotifyOwnEvents());
|
||||||
|
user.setPassword(passwordService.encryptPassword(data.getPassword()));
|
||||||
|
userManager.create(user);
|
||||||
|
EmailAddress emailAddress = new EmailAddress();
|
||||||
|
emailAddress.setGit(true);
|
||||||
|
emailAddress.setPrimary(true);
|
||||||
|
emailAddress.setOwner(user);
|
||||||
|
emailAddress.setValue(data.getEmailAddress());
|
||||||
|
emailAddress.setVerificationCode(null);
|
||||||
|
emailAddressManager.create(emailAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(user).toXML();
|
||||||
|
auditManager.audit(null, "created account \"" + user.getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
|
|
||||||
|
return user.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1950, name="Update Basic Settings")
|
@Api(order=1950, name="Update user")
|
||||||
@Path("/{userId}")
|
@Path("/{userId}")
|
||||||
@POST
|
@POST
|
||||||
public Response updateBasicSetting(@PathParam("userId") Long userId, @NotNull @Valid BasicSettingUpdateData data) {
|
public Response updateUser(@PathParam("userId") Long userId, @NotNull @Valid UserUpdateData data) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (SecurityUtils.isAdministrator() || user.equals(SecurityUtils.getAuthUser())) {
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
User existingUser = userManager.findByName(data.getName());
|
throw new UnauthorizedException();
|
||||||
if (existingUser != null && !existingUser.equals(user))
|
|
||||||
throw new ExplicitException("Login name is already used by another user");
|
|
||||||
|
|
||||||
String oldName = user.getName();
|
User existingUser = userManager.findByName(data.getName());
|
||||||
user.setName(data.getName());
|
if (existingUser != null && !existingUser.equals(user))
|
||||||
user.setFullName(data.getFullName());
|
throw new ExplicitException("Login name is already used by another user");
|
||||||
if (!user.isServiceAccount())
|
|
||||||
user.setNotifyOwnEvents(data.isNotifyOwnEvents());
|
var oldData = new UserUpdateData();
|
||||||
userManager.update(user, oldName);
|
oldData.setName(user.getName());
|
||||||
return Response.ok().build();
|
oldData.setFullName(user.getFullName());
|
||||||
} else {
|
oldData.setNotifyOwnEvents(user.isNotifyOwnEvents());
|
||||||
throw new UnauthenticatedException();
|
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(oldData).toXML();
|
||||||
|
|
||||||
|
String oldName = user.getName();
|
||||||
|
user.setName(data.getName());
|
||||||
|
user.setFullName(data.getFullName());
|
||||||
|
if (!user.isServiceAccount())
|
||||||
|
user.setNotifyOwnEvents(data.isNotifyOwnEvents());
|
||||||
|
userManager.update(user, oldName);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(user)) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(data).toXML();
|
||||||
|
auditManager.audit(null, "changed account \"" + user.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1960, description="Disable user")
|
@Api(order=1960, description="Disable user")
|
||||||
@Path("/{userId}/disable")
|
@Path("/{userId}/disable")
|
||||||
@POST
|
@POST
|
||||||
public Response disable(@PathParam("userId") Long userId) {
|
public Response disableUser(@PathParam("userId") Long userId) {
|
||||||
if (SecurityUtils.isAdministrator()) {
|
if (!SecurityUtils.isAdministrator())
|
||||||
if (userId <= User.ROOT_ID)
|
throw new UnauthorizedException();
|
||||||
throw new BadRequestException("Should only disable normal users");
|
|
||||||
var user = userManager.load(userId);
|
if (userId <= User.ROOT_ID)
|
||||||
userManager.disable(user);
|
throw new BadRequestException("Should only disable normal users");
|
||||||
return Response.ok().build();
|
var user = userManager.load(userId);
|
||||||
} else {
|
userManager.disable(user);
|
||||||
throw new UnauthenticatedException();
|
|
||||||
}
|
auditManager.audit(null, "disabled account \"" + user.getName() + "\" via RESTful API", null, null);
|
||||||
|
|
||||||
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=1970, description="Enable user")
|
@Api(order=1970, description="Enable user")
|
||||||
@Path("/{userId}/enable")
|
@Path("/{userId}/enable")
|
||||||
@POST
|
@POST
|
||||||
public Response enable(@PathParam("userId") Long userId) {
|
public Response enableUser(@PathParam("userId") Long userId) {
|
||||||
if (SecurityUtils.isAdministrator()) {
|
if (!SecurityUtils.isAdministrator())
|
||||||
if (userId <= User.ROOT_ID)
|
throw new UnauthorizedException();
|
||||||
throw new BadRequestException("Should only enable normal users");
|
if (userId <= User.ROOT_ID)
|
||||||
var user = userManager.load(userId);
|
throw new BadRequestException("Should only enable normal users");
|
||||||
userManager.enable(user);
|
var user = userManager.load(userId);
|
||||||
return Response.ok().build();
|
userManager.enable(user);
|
||||||
} else {
|
|
||||||
throw new UnauthenticatedException();
|
auditManager.audit(null, "enabled account \"" + user.getName() + "\" via RESTful API", null, null);
|
||||||
}
|
|
||||||
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=2000)
|
@Api(order=2000)
|
||||||
@ -399,12 +426,14 @@ public class UserResource {
|
|||||||
if (SecurityUtils.isAdministrator()) {
|
if (SecurityUtils.isAdministrator()) {
|
||||||
user.setPassword(passwordService.encryptPassword(password));
|
user.setPassword(passwordService.encryptPassword(password));
|
||||||
userManager.update(user, null);
|
userManager.update(user, null);
|
||||||
|
if (!getAuthUser().equals(user))
|
||||||
|
auditManager.audit(null, "changed password of account \"" + user.getName() + "\" via RESTful API", null, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
} else if (user.isDisabled()) {
|
} else if (user.isDisabled()) {
|
||||||
throw new ExplicitException("Can not set password for disabled user");
|
throw new ExplicitException("Can not set password for disabled user");
|
||||||
} else if (user.isServiceAccount()) {
|
} else if (user.isServiceAccount()) {
|
||||||
throw new ExplicitException("Can not set password for service account");
|
throw new ExplicitException("Can not set password for service account");
|
||||||
} else if (user.equals(SecurityUtils.getAuthUser())) {
|
} else if (user.equals(getAuthUser())) {
|
||||||
if (user.getPassword() == null) {
|
if (user.getPassword() == null) {
|
||||||
throw new ExplicitException("The user is currently authenticated via external system, "
|
throw new ExplicitException("The user is currently authenticated via external system, "
|
||||||
+ "please change password there instead");
|
+ "please change password there instead");
|
||||||
@ -422,16 +451,18 @@ public class UserResource {
|
|||||||
@Path("/{userId}/two-factor-authentication")
|
@Path("/{userId}/two-factor-authentication")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response resetTwoFactorAuthentication(@PathParam("userId") Long userId) {
|
public Response resetTwoFactorAuthentication(@PathParam("userId") Long userId) {
|
||||||
User user = userManager.load(userId);
|
if (!SecurityUtils.isAdministrator())
|
||||||
if (!SecurityUtils.isAdministrator()) {
|
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
} else if (user.isDisabled()) {
|
|
||||||
|
User user = userManager.load(userId);
|
||||||
|
if (user.isDisabled()) {
|
||||||
throw new ExplicitException("Can not reset two factor authentication for disabled user");
|
throw new ExplicitException("Can not reset two factor authentication for disabled user");
|
||||||
} else if (user.isServiceAccount()) {
|
} else if (user.isServiceAccount()) {
|
||||||
throw new ExplicitException("Can not reset two factor authentication for service account");
|
throw new ExplicitException("Can not reset two factor authentication for service account");
|
||||||
} else {
|
} else {
|
||||||
user.setTwoFactorAuthentication(null);
|
user.setTwoFactorAuthentication(null);
|
||||||
userManager.update(user, null);
|
userManager.update(user, null);
|
||||||
|
auditManager.audit(null, "reset two factor authentication of account \"" + user.getName() + "\" via RESTful API", null, null);
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,12 +472,16 @@ public class UserResource {
|
|||||||
@POST
|
@POST
|
||||||
public Response setQueriesAndWatches(@PathParam("userId") Long userId, @NotNull QueriesAndWatches queriesAndWatches) {
|
public Response setQueriesAndWatches(@PathParam("userId") Long userId, @NotNull QueriesAndWatches queriesAndWatches) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
else if (user.isDisabled())
|
|
||||||
|
if (user.isDisabled())
|
||||||
throw new ExplicitException("Can not set queries and watches for disabled user");
|
throw new ExplicitException("Can not set queries and watches for disabled user");
|
||||||
else if (user.isServiceAccount())
|
else if (user.isServiceAccount())
|
||||||
throw new ExplicitException("Can not set queries and watches for service account");
|
throw new ExplicitException("Can not set queries and watches for service account");
|
||||||
|
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getQueriesAndWatches(user)).toXML();
|
||||||
|
|
||||||
user.setBuildQuerySubscriptions(queriesAndWatches.buildQuerySubscriptions);
|
user.setBuildQuerySubscriptions(queriesAndWatches.buildQuerySubscriptions);
|
||||||
user.setIssueQueryWatches(queriesAndWatches.issueQueryWatches);
|
user.setIssueQueryWatches(queriesAndWatches.issueQueryWatches);
|
||||||
user.setPullRequestQueryWatches(queriesAndWatches.pullRequestQueryWatches);
|
user.setPullRequestQueryWatches(queriesAndWatches.pullRequestQueryWatches);
|
||||||
@ -456,6 +491,12 @@ public class UserResource {
|
|||||||
user.setProjectQueries(queriesAndWatches.projectQueries);
|
user.setProjectQueries(queriesAndWatches.projectQueries);
|
||||||
user.setPullRequestQueries(queriesAndWatches.pullRequestQueries);
|
user.setPullRequestQueries(queriesAndWatches.pullRequestQueries);
|
||||||
userManager.update(user, null);
|
userManager.update(user, null);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(user)) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(queriesAndWatches).toXML();
|
||||||
|
auditManager.audit(null, "changed queries and watches of account \"" + user.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
|
||||||
|
}
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,37 +505,109 @@ public class UserResource {
|
|||||||
@POST
|
@POST
|
||||||
public Long addSshKey(@PathParam("userId") Long userId, @NotNull String content) {
|
public Long addSshKey(@PathParam("userId") Long userId, @NotNull String content) {
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (!SecurityUtils.isAdministrator() && !user.equals(SecurityUtils.getAuthUser()))
|
if (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser()))
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
else if (user.isDisabled())
|
|
||||||
|
if (user.isDisabled())
|
||||||
throw new ExplicitException("Can not add ssh key for disabled user");
|
throw new ExplicitException("Can not add ssh key for disabled user");
|
||||||
|
|
||||||
SshKey sshKey = new SshKey();
|
SshKey sshKey = new SshKey();
|
||||||
sshKey.setContent(content);
|
sshKey.setContent(content);
|
||||||
sshKey.setCreatedAt(new Date());
|
sshKey.setCreatedAt(new Date());
|
||||||
sshKey.setOwner(user);
|
sshKey.setOwner(user);
|
||||||
sshKey.fingerprint();
|
sshKey.generateFingerprint();
|
||||||
|
|
||||||
sshKeyManager.create(sshKey);
|
sshKeyManager.create(sshKey);
|
||||||
|
|
||||||
|
if (!getAuthUser().equals(user)) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(sshKey).toXML();
|
||||||
|
auditManager.audit(null, "added ssh key to account \"" + user.getName() + "\" via RESTful API", null, newAuditContent);
|
||||||
|
}
|
||||||
|
|
||||||
return sshKey.getId();
|
return sshKey.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Api(order=2300)
|
@Api(order=2300)
|
||||||
@Path("/{userId}")
|
@Path("/{userId}")
|
||||||
@DELETE
|
@DELETE
|
||||||
public Response delete(@PathParam("userId") Long userId) {
|
public Response deleteUser(@PathParam("userId") Long userId) {
|
||||||
if (!SecurityUtils.isAdministrator())
|
if (!SecurityUtils.isAdministrator())
|
||||||
throw new UnauthorizedException();
|
throw new UnauthorizedException();
|
||||||
|
|
||||||
User user = userManager.load(userId);
|
User user = userManager.load(userId);
|
||||||
if (user.isRoot())
|
if (user.isRoot())
|
||||||
throw new ExplicitException("Root user can not be deleted");
|
throw new ExplicitException("Root user can not be deleted");
|
||||||
else if (user.equals(SecurityUtils.getAuthUser()))
|
else if (user.equals(getAuthUser()))
|
||||||
throw new ExplicitException("Can not delete yourself");
|
throw new ExplicitException("Can not delete yourself");
|
||||||
else
|
else
|
||||||
userManager.delete(user);
|
userManager.delete(user);
|
||||||
|
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getData(user)).toXML();
|
||||||
|
auditManager.audit(null, "deleted account \"" + user.getName() + "\" via RESTful API", oldAuditContent, null);
|
||||||
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class UserData implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Api(order=10, description="Whether or not the user is disabled")
|
||||||
|
private boolean disabled;
|
||||||
|
|
||||||
|
@Api(order=50, description="Whether or not the user is a service account")
|
||||||
|
private boolean serviceAccount;
|
||||||
|
|
||||||
|
@Api(order=100, description="Login name of the user")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Api(order=200)
|
||||||
|
private String fullName;
|
||||||
|
|
||||||
|
@Api(order=300, description = "Whether or not to notify user on own events. Only meaningful for non service account")
|
||||||
|
private boolean notifyOwnEvents;
|
||||||
|
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisabled(boolean disabled) {
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isServiceAccount() {
|
||||||
|
return serviceAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceAccount(boolean serviceAccount) {
|
||||||
|
this.serviceAccount = serviceAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotifyOwnEvents() {
|
||||||
|
return notifyOwnEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotifyOwnEvents(boolean notifyOwnEvents) {
|
||||||
|
this.notifyOwnEvents = notifyOwnEvents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EntityCreate(User.class)
|
@EntityCreate(User.class)
|
||||||
public static class UserCreateData implements Serializable {
|
public static class UserCreateData implements Serializable {
|
||||||
|
|
||||||
@ -577,66 +690,7 @@ public class UserResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BasicSetting implements Serializable {
|
public static class UserUpdateData implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Api(order=10, description="Whether or not the user is disabled")
|
|
||||||
private boolean disabled;
|
|
||||||
|
|
||||||
@Api(order=50, description="Whether or not the user is a service account")
|
|
||||||
private boolean serviceAccount;
|
|
||||||
|
|
||||||
@Api(order=100, description="Login name of the user")
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@Api(order=200)
|
|
||||||
private String fullName;
|
|
||||||
|
|
||||||
@Api(order=300, description = "Whether or not to notify user on own events. Only meaningful for non service account")
|
|
||||||
private boolean notifyOwnEvents;
|
|
||||||
|
|
||||||
public boolean isDisabled() {
|
|
||||||
return disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDisabled(boolean disabled) {
|
|
||||||
this.disabled = disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isServiceAccount() {
|
|
||||||
return serviceAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setServiceAccount(boolean serviceAccount) {
|
|
||||||
this.serviceAccount = serviceAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
return fullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFullName(String fullName) {
|
|
||||||
this.fullName = fullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNotifyOwnEvents() {
|
|
||||||
return notifyOwnEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNotifyOwnEvents(boolean notifyOwnEvents) {
|
|
||||||
this.notifyOwnEvents = notifyOwnEvents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class BasicSettingUpdateData implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
package io.onedev.server.util;
|
package io.onedev.server.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.From;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.model.support.ProjectBelonging;
|
import io.onedev.server.model.support.ProjectBelonging;
|
||||||
@ -42,4 +48,16 @@ public class ProjectScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Predicate buildPredicates(CriteriaBuilder builder, From<Project, Project> root) {
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
predicates.add(builder.equal(root, getProject()));
|
||||||
|
if (isInherited()) {
|
||||||
|
for (var ancestor: getProject().getAncestors())
|
||||||
|
predicates.add(builder.equal(root, ancestor));
|
||||||
|
}
|
||||||
|
if (isRecursive())
|
||||||
|
predicates.add(builder.like(root.get(Project.PROP_PATH), getProject().getPath() + "/%"));
|
||||||
|
return builder.or(predicates.toArray(new Predicate[0]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
package io.onedev.server.util.jackson.hibernate;
|
package io.onedev.server.util.jackson.hibernate;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.JsonToken;
|
import com.fasterxml.jackson.core.JsonToken;
|
||||||
@ -8,13 +13,11 @@ import com.fasterxml.jackson.databind.DeserializationContext;
|
|||||||
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
|
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
|
||||||
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
|
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
import io.onedev.server.model.AbstractEntity;
|
import io.onedev.server.model.AbstractEntity;
|
||||||
import io.onedev.server.persistence.dao.Dao;
|
import io.onedev.server.persistence.dao.Dao;
|
||||||
import io.onedev.server.rest.annotation.Immutable;
|
import io.onedev.server.rest.annotation.Immutable;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
public class EntityDeserializer extends BeanDeserializer {
|
public class EntityDeserializer extends BeanDeserializer {
|
||||||
|
|
||||||
@ -52,7 +55,7 @@ public class EntityDeserializer extends BeanDeserializer {
|
|||||||
&& paramsStack.get().peek()[0] instanceof Long) {
|
&& paramsStack.get().peek()[0] instanceof Long) {
|
||||||
Long entityId = (Long) paramsStack.get().peek()[0];
|
Long entityId = (Long) paramsStack.get().peek()[0];
|
||||||
AbstractEntity entity = dao.load(entityClass, entityId);
|
AbstractEntity entity = dao.load(entityClass, entityId);
|
||||||
entity.setOldVersion(entity.getFacade());
|
entity.setOldVersion(VersionedXmlDoc.fromBean(entity));
|
||||||
|
|
||||||
Object bean;
|
Object bean;
|
||||||
if (entity instanceof HibernateProxy)
|
if (entity instanceof HibernateProxy)
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
package io.onedev.server.util.xstream;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
public class ObjectMap extends LinkedHashMap<String, Object> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package io.onedev.server.util.xstream;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.converters.Converter;
|
||||||
|
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||||
|
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||||
|
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||||
|
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||||
|
|
||||||
|
public class ObjectMapperConverter implements Converter {
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public boolean canConvert(Class type) {
|
||||||
|
return type == ObjectMap.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
|
||||||
|
ObjectMap map = (ObjectMap) source;
|
||||||
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
|
if (entry.getValue() != null) {
|
||||||
|
writer.startNode(entry.getKey());
|
||||||
|
context.convertAnother(entry.getValue());
|
||||||
|
writer.endNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1750603967318" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11693" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M411.605333 180.394667c-26.581333 20.096-48.469333 54.144-48.469333 115.114666 0 60.885333 21.162667 96.938667 42.709333 123.477334a417.024 417.024 0 0 0 20.992 23.722666c4.693333 5.12 9.813333 10.538667 14.208 15.658667 9.557333 11.093333 26.666667 31.914667 26.666667 59.605333v4.138667c0 16.938667 0.042667 36.565333-3.754667 51.413333-2.346667 9.386667-7.509333 22.570667-19.882666 32.853334-12.885333 10.666667-27.477333 13.226667-38.613334 13.226666H213.418667L213.333333 725.333333h597.333334v-105.770666h-191.317334c-4.693333 0-18.005333 0-30.933333-7.509334a53.845333 53.845333 0 0 1-24.746667-34.005333 126.805333 126.805333 0 0 1-3.157333-27.008c-0.298667-8.746667-0.298667-19.626667-0.298667-32.426667v-0.64c0-28.330667 14.208-49.408 25.856-63.701333 5.845333-7.168 12.458667-14.208 18.261334-20.437333l0.298666-0.298667c6.186667-6.656 11.946667-12.842667 17.706667-19.626667 21.205333-25.002667 41.898667-57.898667 41.898667-118.4 0-62.549333-20.48-96.554667-44.458667-115.968-25.6-20.778667-61.824-30.208-100.949333-30.208-39.253333 0-78.677333 9.514667-107.221334 31.061334zM360.149333 112.341333C408.32 75.946667 468.053333 64 518.826667 64c50.901333 0 108.714667 12.032 154.666666 49.194667 47.530667 38.528 76.074667 98.944 76.074667 182.314666 0 85.461333-31.317333 137.173333-62.122667 173.568-7.082667 8.362667-14.08 15.872-20.010666 22.186667l-0.426667 0.512a346.752 346.752 0 0 0-14.805333 16.469333 37.802667 37.802667 0 0 0-6.656 9.984v16h186.453333a64 64 0 0 1 64 64V768a42.666667 42.666667 0 0 1-42.666667 42.666667H170.666667a42.666667 42.666667 0 0 1-42.666667-42.666667l0.085333-169.813333a64 64 0 0 1 64-63.957334H382.293333l0.085334-12.458666a78.72 78.72 0 0 0-6.016-7.722667c-3.285333-3.84-6.912-7.722667-11.434667-12.586667a500.224 500.224 0 0 1-25.301333-28.629333c-30.72-37.802667-61.866667-92.245333-61.866667-177.322667 0.042667-84.906667 32.341333-145.322667 82.389333-183.168zM128 896a42.666667 42.666667 0 0 1 42.666667-42.666667h682.666666a42.666667 42.666667 0 1 1 0 85.333334H170.666667a42.666667 42.666667 0 0 1-42.666667-42.666667z" p-id="11694"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,34 @@
|
|||||||
|
<wicket:panel>
|
||||||
|
<div class="audit-list no-autofocus">
|
||||||
|
<div class="head align-items-center d-none d-lg-flex">
|
||||||
|
<div class="clearable-wrapper date-range mr-2">
|
||||||
|
<input wicket:id="dateRange" t:placeholder="Filter date range" class="form-control form-control-sm">
|
||||||
|
</div>
|
||||||
|
<input wicket:id="users" type="hidden" t:placeholder="Filter users" class="form-control form-control-sm users mr-2">
|
||||||
|
<div class="clearable-wrapper action mr-2">
|
||||||
|
<input wicket:id="action" t:placeholder="Filter actions" class="form-control form-control-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="body list-unstyled mb-0">
|
||||||
|
<li wicket:id="audits" class="audit"></li>
|
||||||
|
<li wicket:id="more" class="mt-3"><a wicket:id="link" class="btn btn-primary btn-sm"><wicket:t>More</wicket:t></a></li>
|
||||||
|
</ul>
|
||||||
|
<div wicket:id="noAudits" class="alert alert-light mt-4"><wicket:t>No audits</wicket:t></div>
|
||||||
|
</div>
|
||||||
|
<wicket:fragment wicket:id="dateFrag">
|
||||||
|
<h6 class="mt-4 mb-3 d-flex align-items-center font-weight-bold font-size-lg">
|
||||||
|
<wicket:svg href="calendar" class="icon mr-2"/> <span wicket:id="date"></span>
|
||||||
|
</h6>
|
||||||
|
</wicket:fragment>
|
||||||
|
<wicket:fragment wicket:id="auditFrag">
|
||||||
|
<div class="ml-4 mt-2">
|
||||||
|
<span wicket:id="time" class="text-monospace mr-2"></span>
|
||||||
|
<a wicket:id="user"></a>
|
||||||
|
<span wicket:id="action"></span>
|
||||||
|
<a wicket:id="diff" title="Show change detail"><wicket:svg href="diff2" class="icon"/></a>
|
||||||
|
</div>
|
||||||
|
</wicket:fragment>
|
||||||
|
<wicket:fragment wicket:id="diffFrag">
|
||||||
|
<div wicket:id="content" class="p-3 audit-change-detail"></div>
|
||||||
|
</wicket:fragment>
|
||||||
|
</wicket:panel>
|
||||||
@ -0,0 +1,283 @@
|
|||||||
|
package io.onedev.server.web.component.audit;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.apache.wicket.Component;
|
||||||
|
import org.apache.wicket.ajax.AjaxRequestTarget;
|
||||||
|
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
|
||||||
|
import org.apache.wicket.ajax.markup.html.AjaxLink;
|
||||||
|
import org.apache.wicket.markup.head.CssHeaderItem;
|
||||||
|
import org.apache.wicket.markup.head.IHeaderResponse;
|
||||||
|
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
|
||||||
|
import org.apache.wicket.markup.html.WebMarkupContainer;
|
||||||
|
import org.apache.wicket.markup.html.basic.Label;
|
||||||
|
import org.apache.wicket.markup.html.form.TextField;
|
||||||
|
import org.apache.wicket.markup.html.panel.Fragment;
|
||||||
|
import org.apache.wicket.markup.html.panel.Panel;
|
||||||
|
import org.apache.wicket.markup.repeater.RepeatingView;
|
||||||
|
import org.apache.wicket.model.IModel;
|
||||||
|
import org.apache.wicket.model.LoadableDetachableModel;
|
||||||
|
import org.apache.wicket.model.Model;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
|
||||||
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.UserManager;
|
||||||
|
import io.onedev.server.entitymanager.support.AuditQuery;
|
||||||
|
import io.onedev.server.model.Audit;
|
||||||
|
import io.onedev.server.model.Project;
|
||||||
|
import io.onedev.server.model.User;
|
||||||
|
import io.onedev.server.util.DateRange;
|
||||||
|
import io.onedev.server.util.DateUtils;
|
||||||
|
import io.onedev.server.util.diff.DiffRenderer;
|
||||||
|
import io.onedev.server.util.diff.DiffUtils;
|
||||||
|
import io.onedev.server.web.asset.diff.DiffResourceReference;
|
||||||
|
import io.onedev.server.web.component.datepicker.DateRangePicker;
|
||||||
|
import io.onedev.server.web.component.floating.FloatingPanel;
|
||||||
|
import io.onedev.server.web.component.link.DropdownLink;
|
||||||
|
import io.onedev.server.web.component.user.choice.UserMultiChoice;
|
||||||
|
import io.onedev.server.web.component.user.ident.Mode;
|
||||||
|
import io.onedev.server.web.component.user.ident.UserIdentPanel;
|
||||||
|
|
||||||
|
public abstract class AuditListPanel extends Panel {
|
||||||
|
|
||||||
|
private static final int PAGE_SIZE = 100;
|
||||||
|
|
||||||
|
private final IModel<List<Audit>> auditsModel = new LoadableDetachableModel<List<Audit>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Audit> load() {
|
||||||
|
return getAuditManager().query(getProject(), buildQuery(), currentPage * PAGE_SIZE, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
private final IModel<Integer> countModel = new LoadableDetachableModel<Integer>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer load() {
|
||||||
|
return getAuditManager().count(getProject(), buildQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
private RepeatingView auditsView;
|
||||||
|
|
||||||
|
private int currentPage;
|
||||||
|
|
||||||
|
private LocalDate currentDate;
|
||||||
|
|
||||||
|
private DateRange dateRange;
|
||||||
|
|
||||||
|
private List<String> userNames;
|
||||||
|
|
||||||
|
private String action;
|
||||||
|
|
||||||
|
public AuditListPanel(String id, List<String> userNames, @Nullable DateRange dateRange, @Nullable String action) {
|
||||||
|
super(id);
|
||||||
|
this.userNames = userNames;
|
||||||
|
this.dateRange = dateRange;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuditQuery buildQuery() {
|
||||||
|
Date sinceDate = null;
|
||||||
|
Date untilDate = null;
|
||||||
|
if (dateRange != null) {
|
||||||
|
sinceDate = DateUtils.toDate(dateRange.getFrom().atStartOfDay());
|
||||||
|
untilDate = DateUtils.toDate(dateRange.getTo().atTime(23, 59, 59));
|
||||||
|
}
|
||||||
|
return new AuditQuery(getUsers(), sinceDate, untilDate, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAuditList(AjaxRequestTarget target) {
|
||||||
|
var newPanel = new AuditListPanel(getId(), userNames, dateRange, action) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onQueryUpdated(AjaxRequestTarget target, @Nullable DateRange dateRange, List<String> userNames, @Nullable String action) {
|
||||||
|
AuditListPanel.this.onQueryUpdated(target, dateRange, userNames, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Project getProject() {
|
||||||
|
return AuditListPanel.this.getProject();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
replaceWith(newPanel);
|
||||||
|
target.add(newPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<User> getUsers() {
|
||||||
|
return userNames.stream().map(getUserManager()::findByName).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onInitialize() {
|
||||||
|
super.onInitialize();
|
||||||
|
|
||||||
|
var dateRangePicker = new DateRangePicker("dateRange", Model.of(dateRange));
|
||||||
|
dateRangePicker.add(new AjaxFormComponentUpdatingBehavior("change clear") {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onUpdate(AjaxRequestTarget target) {
|
||||||
|
dateRange = dateRangePicker.getModelObject();
|
||||||
|
updateAuditList(target);
|
||||||
|
onQueryUpdated(target, dateRange, userNames, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
add(dateRangePicker);
|
||||||
|
|
||||||
|
var usersChoice = new UserMultiChoice("users", Model.of(getUsers()), Model.ofList(getUserManager().query()));
|
||||||
|
usersChoice.add(new AjaxFormComponentUpdatingBehavior("change") {
|
||||||
|
@Override
|
||||||
|
protected void onUpdate(AjaxRequestTarget target) {
|
||||||
|
userNames = usersChoice.getModelObject().stream().map(User::getName).collect(Collectors.toList());
|
||||||
|
updateAuditList(target);
|
||||||
|
onQueryUpdated(target, dateRange, userNames, action);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(usersChoice);
|
||||||
|
|
||||||
|
var actionInput = new TextField<String>("action", Model.of(action));
|
||||||
|
actionInput.add(new AjaxFormComponentUpdatingBehavior("change clear") {
|
||||||
|
@Override
|
||||||
|
protected void onUpdate(AjaxRequestTarget target) {
|
||||||
|
action = actionInput.getModelObject();
|
||||||
|
updateAuditList(target);
|
||||||
|
onQueryUpdated(target, dateRange, userNames, action);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(actionInput);
|
||||||
|
|
||||||
|
auditsView = new RepeatingView("audits");
|
||||||
|
for (var audit: auditsModel.getObject()) {
|
||||||
|
for (var row: newAuditRows(auditsView, audit)) {
|
||||||
|
auditsView.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(auditsView);
|
||||||
|
|
||||||
|
var moreContainer = new WebMarkupContainer("more") {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onConfigure() {
|
||||||
|
super.onConfigure();
|
||||||
|
setVisible(PAGE_SIZE * (currentPage + 1) < countModel.getObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
moreContainer.setOutputMarkupId(true);
|
||||||
|
|
||||||
|
moreContainer.add(new AjaxLink<Void>("link") {
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
public void onClick(AjaxRequestTarget target) {
|
||||||
|
target.add(moreContainer);
|
||||||
|
currentPage++;
|
||||||
|
for (var audit: auditsModel.getObject()) {
|
||||||
|
for (var row: newAuditRows(auditsView, audit)) {
|
||||||
|
var script = String.format("$('#%s').after('<li id=\"%s\"></li>');", auditsView.get(auditsView.size() - 1).getMarkupId(), row.getMarkupId());
|
||||||
|
target.prependJavaScript(script);
|
||||||
|
auditsView.add(row);
|
||||||
|
target.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.focusComponent(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
add(moreContainer);
|
||||||
|
|
||||||
|
add(new WebMarkupContainer("noAudits") {
|
||||||
|
@Override
|
||||||
|
protected void onConfigure() {
|
||||||
|
super.onConfigure();
|
||||||
|
setVisible(countModel.getObject() == 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setOutputMarkupId(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserManager getUserManager() {
|
||||||
|
return OneDev.getInstance(UserManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDetach() {
|
||||||
|
auditsModel.detach();
|
||||||
|
countModel.detach();
|
||||||
|
super.onDetach();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderHead(IHeaderResponse response) {
|
||||||
|
super.renderHead(response);
|
||||||
|
response.render(JavaScriptHeaderItem.forReference(new DiffResourceReference()));
|
||||||
|
response.render(CssHeaderItem.forReference(new AuditLogCssResourceReference()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Component> newAuditRows(RepeatingView auditsView, Audit audit) {
|
||||||
|
var rows = new ArrayList<Component>();
|
||||||
|
var auditDate = DateUtils.toLocalDate(audit.getDate());
|
||||||
|
if (currentDate == null || !currentDate.equals(auditDate)) {
|
||||||
|
currentDate = auditDate;
|
||||||
|
var fragment = new Fragment(auditsView.newChildId(), "dateFrag", this);
|
||||||
|
fragment.add(new Label("date", currentDate.format(DateUtils.DATE_FORMATTER)));
|
||||||
|
fragment.setOutputMarkupId(true);
|
||||||
|
rows.add(fragment);
|
||||||
|
}
|
||||||
|
var fragment = new Fragment(auditsView.newChildId(), "auditFrag", this);
|
||||||
|
fragment.add(new Label("time", DateUtils.formatTime(audit.getDate())));
|
||||||
|
fragment.add(new UserIdentPanel("user", audit.getUser(), Mode.AVATAR_AND_NAME));
|
||||||
|
fragment.add(new Label("action", audit.getAction()));
|
||||||
|
var oldContent = audit.getOldContent();
|
||||||
|
var newContent = audit.getNewContent();
|
||||||
|
fragment.add(new DropdownLink("diff") {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Component newContent(String id, FloatingPanel dropdown) {
|
||||||
|
List<String> oldLines = new ArrayList<>();
|
||||||
|
if (oldContent != null)
|
||||||
|
oldLines = Splitter.on('\n').splitToList(oldContent);
|
||||||
|
List<String> newLines = new ArrayList<>();
|
||||||
|
if (newContent != null)
|
||||||
|
newLines = Splitter.on('\n').splitToList(newContent);
|
||||||
|
var fragment = new Fragment(id, "diffFrag", AuditListPanel.this);
|
||||||
|
fragment.add(new Label("content", new DiffRenderer(DiffUtils.diff(oldLines, newLines)).renderDiffs()).setEscapeModelStrings(false));
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onConfigure() {
|
||||||
|
super.onConfigure();
|
||||||
|
setVisible(oldContent != null || newContent != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
fragment.setOutputMarkupId(true);
|
||||||
|
rows.add(fragment);
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected abstract Project getProject();
|
||||||
|
|
||||||
|
protected abstract void onQueryUpdated(AjaxRequestTarget target, @Nullable DateRange dateRange, List<String> userNames, @Nullable String action);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package io.onedev.server.web.component.audit;
|
||||||
|
|
||||||
|
import io.onedev.server.web.page.base.BaseDependentCssResourceReference;
|
||||||
|
|
||||||
|
public class AuditLogCssResourceReference extends BaseDependentCssResourceReference {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public AuditLogCssResourceReference() {
|
||||||
|
super(AuditLogCssResourceReference.class, "audit-list.css");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
.audit-list>.head>.date-range, .audit-list>.head>.users {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
.audit-list>.head>.action {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
.audit-list .body {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 20px;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-list .body::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 2px;
|
||||||
|
background-color: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-mode .audit-list .body::before {
|
||||||
|
background-color: var(--dark-mode-lighter-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-list .body li {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-list .body li.audit::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: -24px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--secondary);
|
||||||
|
border: 2px solid #fff;
|
||||||
|
box-shadow: 0 0 0 2px var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-mode .audit-list .body li.audit::before {
|
||||||
|
background-color: var(--dark-mode-lighter-dark);
|
||||||
|
border-color: var(--dark-mode-darker);
|
||||||
|
box-shadow: 0 0 0 2px var(--dark-mode-lighter-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-list .body li:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-list .body li[wicket\:id="more"]::before {
|
||||||
|
background-color: var(--secondary);
|
||||||
|
box-shadow: 0 0 0 2px var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-mode .audit-list .body li[wicket\:id="more"]::before {
|
||||||
|
background-color: var(--dark-mode-lighter-dark);
|
||||||
|
box-shadow: 0 0 0 2px var(--dark-mode-lighter-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-change-detail {
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
@ -54,6 +54,8 @@ import com.google.common.collect.Sets;
|
|||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.BuildManager;
|
import io.onedev.server.entitymanager.BuildManager;
|
||||||
import io.onedev.server.entitymanager.BuildParamManager;
|
import io.onedev.server.entitymanager.BuildParamManager;
|
||||||
import io.onedev.server.entitymanager.ProjectManager;
|
import io.onedev.server.entitymanager.ProjectManager;
|
||||||
@ -65,6 +67,7 @@ import io.onedev.server.model.Build;
|
|||||||
import io.onedev.server.model.Build.Status;
|
import io.onedev.server.model.Build.Status;
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.model.support.administration.GlobalBuildSetting;
|
import io.onedev.server.model.support.administration.GlobalBuildSetting;
|
||||||
|
import io.onedev.server.persistence.TransactionManager;
|
||||||
import io.onedev.server.search.entity.EntityQuery;
|
import io.onedev.server.search.entity.EntityQuery;
|
||||||
import io.onedev.server.search.entity.EntitySort;
|
import io.onedev.server.search.entity.EntitySort;
|
||||||
import io.onedev.server.search.entity.EntitySort.Direction;
|
import io.onedev.server.search.entity.EntitySort.Direction;
|
||||||
@ -160,6 +163,18 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
private BuildManager getBuildManager() {
|
private BuildManager getBuildManager() {
|
||||||
return OneDev.getInstance(BuildManager.class);
|
return OneDev.getInstance(BuildManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ProjectManager getProjectManager() {
|
||||||
|
return OneDev.getInstance(ProjectManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransactionManager getTransactionManager() {
|
||||||
|
return OneDev.getInstance(TransactionManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private BuildQuery parse(@Nullable String queryString, BuildQuery baseQuery) {
|
private BuildQuery parse(@Nullable String queryString, BuildQuery baseQuery) {
|
||||||
@ -445,10 +460,17 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<Build> builds = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (IModel<Build> each: selectionColumn.getSelections())
|
Collection<Build> builds = new ArrayList<>();
|
||||||
builds.add(each.getObject());
|
for (IModel<Build> each: selectionColumn.getSelections())
|
||||||
OneDev.getInstance(BuildManager.class).delete(builds);
|
builds.add(each.getObject());
|
||||||
|
getBuildManager().delete(builds);
|
||||||
|
for (var build: builds) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(build).toXML();
|
||||||
|
getAuditManager().audit(build.getProject(), "deleted build \"" + build.getReference().toString(build.getProject()) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
@ -655,11 +677,17 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<Build> builds = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (Iterator<Build> it = (Iterator<Build>) dataProvider.iterator(0, buildsTable.getItemCount()); it.hasNext();) {
|
Collection<Build> builds = new ArrayList<>();
|
||||||
builds.add(it.next());
|
for (Iterator<Build> it = (Iterator<Build>) dataProvider.iterator(0, buildsTable.getItemCount()); it.hasNext();) {
|
||||||
}
|
builds.add(it.next());
|
||||||
OneDev.getInstance(BuildManager.class).delete(builds);
|
}
|
||||||
|
getBuildManager().delete(builds);
|
||||||
|
for (var build: builds) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(build).toXML();
|
||||||
|
getAuditManager().audit(build.getProject(), "deleted build \"" + build.getReference().toString(build.getProject()) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
@ -763,11 +791,17 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
|
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
|
||||||
super.onSubmit(target, form);
|
super.onSubmit(target, form);
|
||||||
if (getProject() != null) {
|
if (getProject() != null) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getProject().getBuildSetting().getListParams(true)).toXML();
|
||||||
getProject().getBuildSetting().setListParams(listParams);
|
getProject().getBuildSetting().setListParams(listParams);
|
||||||
OneDev.getInstance(ProjectManager.class).update(getProject());
|
var newAuditContent = VersionedXmlDoc.fromBean(getProject().getBuildSetting().getListParams(true)).toXML();
|
||||||
|
getProjectManager().update(getProject());
|
||||||
|
getAuditManager().audit(getProject(), "changed display params of build list", oldAuditContent, newAuditContent);
|
||||||
} else {
|
} else {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getGlobalBuildSetting().getListParams()).toXML();
|
||||||
getGlobalBuildSetting().setListParams(listParams);
|
getGlobalBuildSetting().setListParams(listParams);
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(getGlobalBuildSetting().getListParams()).toXML();
|
||||||
OneDev.getInstance(SettingManager.class).saveBuildSetting(getGlobalBuildSetting());
|
OneDev.getInstance(SettingManager.class).saveBuildSetting(getGlobalBuildSetting());
|
||||||
|
getAuditManager().audit(null, "changed display params of build list", oldAuditContent, newAuditContent);
|
||||||
}
|
}
|
||||||
setResponsePage(getPage().getClass(), getPage().getPageParameters());
|
setResponsePage(getPage().getClass(), getPage().getPageParameters());
|
||||||
}
|
}
|
||||||
@ -779,8 +813,11 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(AjaxRequestTarget target) {
|
public void onClick(AjaxRequestTarget target) {
|
||||||
modal.close();
|
modal.close();
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getProject().getBuildSetting().getListParams(true)).toXML();
|
||||||
getProject().getBuildSetting().setListParams(null);
|
getProject().getBuildSetting().setListParams(null);
|
||||||
OneDev.getInstance(ProjectManager.class).update(getProject());
|
var newAuditContent = VersionedXmlDoc.fromBean(getProject().getBuildSetting().getListParams(true)).toXML();
|
||||||
|
getProjectManager().update(getProject());
|
||||||
|
getAuditManager().audit(getProject(), "changed display params of build list", oldAuditContent, newAuditContent);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,9 +974,8 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Project> load() {
|
protected List<Project> load() {
|
||||||
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
|
|
||||||
List<Project> projects = new ArrayList<>(SecurityUtils.getAuthorizedProjects(new JobPermission(null, new RunJob())));
|
List<Project> projects = new ArrayList<>(SecurityUtils.getAuthorizedProjects(new JobPermission(null, new RunJob())));
|
||||||
projects.sort(projectManager.cloneCache().comparingPath());
|
projects.sort(getProjectManager().cloneCache().comparingPath());
|
||||||
return projects;
|
return projects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1274,7 +1310,7 @@ public abstract class BuildListPanel extends Panel {
|
|||||||
new FloatingPanel(target, alignment, true, true, null) {
|
new FloatingPanel(target, alignment, true, true, null) {
|
||||||
|
|
||||||
private Project getRevisionProject() {
|
private Project getRevisionProject() {
|
||||||
return OneDev.getInstance(ProjectManager.class).load(projectId);
|
return getProjectManager().load(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -45,6 +45,8 @@ import com.google.common.collect.Sets;
|
|||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
import io.onedev.server.attachment.AttachmentSupport;
|
import io.onedev.server.attachment.AttachmentSupport;
|
||||||
import io.onedev.server.attachment.ProjectAttachmentSupport;
|
import io.onedev.server.attachment.ProjectAttachmentSupport;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.CodeCommentManager;
|
import io.onedev.server.entitymanager.CodeCommentManager;
|
||||||
import io.onedev.server.entitymanager.CodeCommentReplyManager;
|
import io.onedev.server.entitymanager.CodeCommentReplyManager;
|
||||||
import io.onedev.server.entitymanager.CodeCommentStatusChangeManager;
|
import io.onedev.server.entitymanager.CodeCommentStatusChangeManager;
|
||||||
@ -357,6 +359,8 @@ public abstract class CodeCommentPanel extends Panel {
|
|||||||
public void onClick(AjaxRequestTarget target) {
|
public void onClick(AjaxRequestTarget target) {
|
||||||
onDeleteComment(target, getComment());
|
onDeleteComment(target, getComment());
|
||||||
OneDev.getInstance(CodeCommentManager.class).delete(getComment());
|
OneDev.getInstance(CodeCommentManager.class).delete(getComment());
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getComment()).toXML();
|
||||||
|
OneDev.getInstance(AuditManager.class).audit(getComment().getProject(), "deleted code comment on file \"" + getComment().getMark().getPath() + "\"", oldAuditContent, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onConfigure() {
|
protected void onConfigure() {
|
||||||
|
|||||||
@ -64,15 +64,16 @@ public abstract class CommandPalettePanel extends Panel {
|
|||||||
|
|
||||||
private static final PatternSet eeUrlPatterns = PatternSet.parse("" +
|
private static final PatternSet eeUrlPatterns = PatternSet.parse("" +
|
||||||
"~dashboards/** ~code-search/** ~administration/settings/storage-setting " +
|
"~dashboards/** ~code-search/** ~administration/settings/storage-setting " +
|
||||||
"~administration/cluster ~administration/settings/time-tracking ${project}/~timesheets " +
|
"~administration/cluster ~administration/audits ~administration/settings/time-tracking ${project}/~timesheets " +
|
||||||
"${project}/~stats/pull-request-duration ${project}/~stats/build-duration ${project}/~stats/build-frequency");
|
"${project}/~stats/pull-request/duration ${project}/~stats/pull-request/frequency ${project}/~stats/build/duration " +
|
||||||
|
"${project}/~stats/build/frequency ${project}/~stats/issue/state-frequency ${project}/~stats/issue/state-duration " +
|
||||||
|
"${project}/~stats/issue/state-trend ${project}/~audits");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (IRequestMapper mapper: OneDev.getInstance(WebApplication.class).getRequestMappers())
|
for (IRequestMapper mapper: OneDev.getInstance(WebApplication.class).getRequestMappers())
|
||||||
availableUrls.addAll(getMountedPaths(mapper));
|
availableUrls.addAll(getMountedPaths(mapper));
|
||||||
|
|
||||||
Collections.sort(availableUrls, (Comparator<String[]>) (o1, o2) -> PathUtils.compare(Arrays.asList(o1), Arrays.asList(o2)));
|
Collections.sort(availableUrls, (Comparator<String[]>) (o1, o2) -> PathUtils.compare(Arrays.asList(o1), Arrays.asList(o2)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String[]> getMountedPaths(IRequestMapper mapper) {
|
private static List<String[]> getMountedPaths(IRequestMapper mapper) {
|
||||||
|
|||||||
@ -29,32 +29,39 @@ public class DateRangePicker extends TextField<DateRange> {
|
|||||||
public DateRangePicker(String id, IModel<DateRange> model) {
|
public DateRangePicker(String id, IModel<DateRange> model) {
|
||||||
super(id, model);
|
super(id, model);
|
||||||
|
|
||||||
|
setType(DateRange.class);
|
||||||
converter = new IConverter<DateRange>() {
|
converter = new IConverter<DateRange>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DateRange convertToObject(String value, Locale locale) throws ConversionException {
|
public DateRange convertToObject(String value, Locale locale) throws ConversionException {
|
||||||
var errorMessage = _T("Invalid date range, expecting \"yyyy-MM-dd to yyyy-MM-dd\"");
|
if (value == null) {
|
||||||
if (value.contains(" ")) {
|
return null;
|
||||||
try {
|
|
||||||
var fromDate = LocalDate.from(DateUtils.DATE_FORMATTER.parse(StringUtils.substringBefore(value, " ")));
|
|
||||||
var toDate = LocalDate.from(DateUtils.DATE_FORMATTER.parse(StringUtils.substringAfterLast(value, " ")));
|
|
||||||
return new DateRange(fromDate, toDate);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ConversionException(errorMessage);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
var errorMessage = _T("Invalid date range, expecting \"yyyy-MM-dd to yyyy-MM-dd\"");
|
||||||
var date = LocalDate.from(DateUtils.DATE_FORMATTER.parse(value));
|
if (value.contains(" ")) {
|
||||||
return new DateRange(date, date);
|
try {
|
||||||
} catch (Exception e) {
|
var fromDate = LocalDate.from(DateUtils.DATE_FORMATTER.parse(StringUtils.substringBefore(value, " ")));
|
||||||
throw new ConversionException(errorMessage);
|
var toDate = LocalDate.from(DateUtils.DATE_FORMATTER.parse(StringUtils.substringAfterLast(value, " ")));
|
||||||
|
return new DateRange(fromDate, toDate);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ConversionException(errorMessage);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
var date = LocalDate.from(DateUtils.DATE_FORMATTER.parse(value));
|
||||||
|
return new DateRange(date, date);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ConversionException(errorMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String convertToString(DateRange value, Locale locale) {
|
public String convertToString(DateRange value, Locale locale) {
|
||||||
if (!value.getFrom().equals(value.getTo()))
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
else if (!value.getFrom().equals(value.getTo()))
|
||||||
return value.getFrom().format(DateUtils.DATE_FORMATTER) + " to " + value.getTo().format(DateUtils.DATE_FORMATTER);
|
return value.getFrom().format(DateUtils.DATE_FORMATTER) + " to " + value.getTo().format(DateUtils.DATE_FORMATTER);
|
||||||
else
|
else
|
||||||
return value.getFrom().format(DateUtils.DATE_FORMATTER);
|
return value.getFrom().format(DateUtils.DATE_FORMATTER);
|
||||||
|
|||||||
@ -76,6 +76,8 @@ import com.google.common.collect.Sets;
|
|||||||
import edu.emory.mathcs.backport.java.util.Collections;
|
import edu.emory.mathcs.backport.java.util.Collections;
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.IssueLinkManager;
|
import io.onedev.server.entitymanager.IssueLinkManager;
|
||||||
import io.onedev.server.entitymanager.IssueManager;
|
import io.onedev.server.entitymanager.IssueManager;
|
||||||
import io.onedev.server.entitymanager.IssueWatchManager;
|
import io.onedev.server.entitymanager.IssueWatchManager;
|
||||||
@ -93,6 +95,7 @@ import io.onedev.server.model.support.issue.field.spec.DateField;
|
|||||||
import io.onedev.server.model.support.issue.field.spec.FieldSpec;
|
import io.onedev.server.model.support.issue.field.spec.FieldSpec;
|
||||||
import io.onedev.server.model.support.issue.field.spec.IntegerField;
|
import io.onedev.server.model.support.issue.field.spec.IntegerField;
|
||||||
import io.onedev.server.model.support.issue.field.spec.choicefield.ChoiceField;
|
import io.onedev.server.model.support.issue.field.spec.choicefield.ChoiceField;
|
||||||
|
import io.onedev.server.persistence.TransactionManager;
|
||||||
import io.onedev.server.search.entity.EntityQuery;
|
import io.onedev.server.search.entity.EntityQuery;
|
||||||
import io.onedev.server.search.entity.EntitySort;
|
import io.onedev.server.search.entity.EntitySort;
|
||||||
import io.onedev.server.search.entity.EntitySort.Direction;
|
import io.onedev.server.search.entity.EntitySort.Direction;
|
||||||
@ -108,6 +111,7 @@ import io.onedev.server.util.LinkDescriptor;
|
|||||||
import io.onedev.server.util.ProjectScope;
|
import io.onedev.server.util.ProjectScope;
|
||||||
import io.onedev.server.util.facade.ProjectCache;
|
import io.onedev.server.util.facade.ProjectCache;
|
||||||
import io.onedev.server.util.watch.WatchStatus;
|
import io.onedev.server.util.watch.WatchStatus;
|
||||||
|
import io.onedev.server.util.xstream.ObjectMap;
|
||||||
import io.onedev.server.web.WebConstants;
|
import io.onedev.server.web.WebConstants;
|
||||||
import io.onedev.server.web.ajaxlistener.AttachAjaxIndicatorListener;
|
import io.onedev.server.web.ajaxlistener.AttachAjaxIndicatorListener;
|
||||||
import io.onedev.server.web.ajaxlistener.AttachAjaxIndicatorListener.AttachMode;
|
import io.onedev.server.web.ajaxlistener.AttachAjaxIndicatorListener.AttachMode;
|
||||||
@ -191,6 +195,14 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
private IssueLinkManager getIssueLinkManager() {
|
private IssueLinkManager getIssueLinkManager() {
|
||||||
return OneDev.getInstance(IssueLinkManager.class);
|
return OneDev.getInstance(IssueLinkManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TransactionManager getTransactionManager() {
|
||||||
|
return OneDev.getInstance(TransactionManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetach() {
|
protected void onDetach() {
|
||||||
@ -528,6 +540,26 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
|
|
||||||
add(new ModalLink("fieldsAndLinks") {
|
add(new ModalLink("fieldsAndLinks") {
|
||||||
|
|
||||||
|
private String getAuditContent(Project project) {
|
||||||
|
var listFields = project.getIssueSetting().getListFields();
|
||||||
|
if (listFields == null)
|
||||||
|
listFields = getGlobalIssueSetting().getListFields();
|
||||||
|
var listLinks = project.getIssueSetting().getListLinks();
|
||||||
|
if (listLinks == null)
|
||||||
|
listLinks = getGlobalIssueSetting().getListLinks();
|
||||||
|
var auditData = new ObjectMap();
|
||||||
|
auditData.put("listFields", listFields);
|
||||||
|
auditData.put("listLinks", listLinks);
|
||||||
|
return VersionedXmlDoc.fromBean(auditData).toXML();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAuditContent() {
|
||||||
|
var auditData = new ObjectMap();
|
||||||
|
auditData.put("listFields", getGlobalIssueSetting().getListFields());
|
||||||
|
auditData.put("listLinks", getGlobalIssueSetting().getListLinks());
|
||||||
|
return VersionedXmlDoc.fromBean(auditData).toXML();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Component newContent(String id, ModalPanel modal) {
|
protected Component newContent(String id, ModalPanel modal) {
|
||||||
Fragment fragment = new Fragment(id, "fieldsAndLinksFrag", IssueListPanel.this);
|
Fragment fragment = new Fragment(id, "fieldsAndLinksFrag", IssueListPanel.this);
|
||||||
@ -556,13 +588,19 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
super.onSubmit(target, form);
|
super.onSubmit(target, form);
|
||||||
modal.close();
|
modal.close();
|
||||||
if (getProject() != null) {
|
if (getProject() != null) {
|
||||||
|
var oldAuditContent = getAuditContent(getProject());
|
||||||
getProject().getIssueSetting().setListFields(bean.getFields());
|
getProject().getIssueSetting().setListFields(bean.getFields());
|
||||||
getProject().getIssueSetting().setListLinks(bean.getLinks());
|
getProject().getIssueSetting().setListLinks(bean.getLinks());
|
||||||
OneDev.getInstance(ProjectManager.class).update(getProject());
|
var newAuditContent = getAuditContent(getProject());
|
||||||
} else {
|
getProjectManager().update(getProject());
|
||||||
|
getAuditManager().audit(getProject(), "changed display fields/links of issue list", oldAuditContent, newAuditContent);
|
||||||
|
} else {
|
||||||
|
var oldAuditContent = getAuditContent();
|
||||||
getGlobalIssueSetting().setListFields(bean.getFields());
|
getGlobalIssueSetting().setListFields(bean.getFields());
|
||||||
getGlobalIssueSetting().setListLinks(bean.getLinks());
|
getGlobalIssueSetting().setListLinks(bean.getLinks());
|
||||||
|
var newAuditContent = getAuditContent();
|
||||||
OneDev.getInstance(SettingManager.class).saveIssueSetting(getGlobalIssueSetting());
|
OneDev.getInstance(SettingManager.class).saveIssueSetting(getGlobalIssueSetting());
|
||||||
|
getAuditManager().audit(null, "changed display fields/links of issue list", oldAuditContent, newAuditContent);
|
||||||
}
|
}
|
||||||
target.add(body);
|
target.add(body);
|
||||||
onDisplayFieldsAndLinksUpdated(target);
|
onDisplayFieldsAndLinksUpdated(target);
|
||||||
@ -575,9 +613,12 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(AjaxRequestTarget target) {
|
public void onClick(AjaxRequestTarget target) {
|
||||||
modal.close();
|
modal.close();
|
||||||
|
var oldAuditContent = getAuditContent();
|
||||||
getProject().getIssueSetting().setListFields(null);
|
getProject().getIssueSetting().setListFields(null);
|
||||||
getProject().getIssueSetting().setListLinks(null);
|
getProject().getIssueSetting().setListLinks(null);
|
||||||
OneDev.getInstance(ProjectManager.class).update(getProject());
|
var newAuditContent = getAuditContent();
|
||||||
|
getProjectManager().update(getProject());
|
||||||
|
getAuditManager().audit(getProject(), "changed display fields/links of issue list", oldAuditContent, newAuditContent);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
onDisplayFieldsAndLinksUpdated(target);
|
onDisplayFieldsAndLinksUpdated(target);
|
||||||
}
|
}
|
||||||
@ -971,7 +1012,7 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
Collection<Issue> issues = new ArrayList<>();
|
Collection<Issue> issues = new ArrayList<>();
|
||||||
for (IModel<Issue> each : selectionColumn.getSelections())
|
for (IModel<Issue> each : selectionColumn.getSelections())
|
||||||
issues.add(each.getObject());
|
issues.add(each.getObject());
|
||||||
OneDev.getInstance(IssueManager.class).move(issues, getProject(), getTargetProject());
|
getIssueManager().move(issues, getProject(), getTargetProject());
|
||||||
setResponsePage(ProjectIssueListPage.class,
|
setResponsePage(ProjectIssueListPage.class,
|
||||||
ProjectIssueListPage.paramsOf(getTargetProject(), getQueryAfterCopyOrMove(), 0));
|
ProjectIssueListPage.paramsOf(getTargetProject(), getQueryAfterCopyOrMove(), 0));
|
||||||
Session.get().success(_T("Issues moved"));
|
Session.get().success(_T("Issues moved"));
|
||||||
@ -1053,7 +1094,7 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
Collection<Issue> issues = new ArrayList<>();
|
Collection<Issue> issues = new ArrayList<>();
|
||||||
for (IModel<Issue> each : selectionColumn.getSelections())
|
for (IModel<Issue> each : selectionColumn.getSelections())
|
||||||
issues.add(each.getObject());
|
issues.add(each.getObject());
|
||||||
OneDev.getInstance(IssueManager.class).copy(issues, getProject(), getTargetProject());
|
getIssueManager().copy(issues, getProject(), getTargetProject());
|
||||||
setResponsePage(ProjectIssueListPage.class,
|
setResponsePage(ProjectIssueListPage.class,
|
||||||
ProjectIssueListPage.paramsOf(getTargetProject(), getQueryAfterCopyOrMove(), 0));
|
ProjectIssueListPage.paramsOf(getTargetProject(), getQueryAfterCopyOrMove(), 0));
|
||||||
Session.get().success(_T("Issues copied"));
|
Session.get().success(_T("Issues copied"));
|
||||||
@ -1114,10 +1155,16 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<Issue> issues = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (IModel<Issue> each : selectionColumn.getSelections())
|
Collection<Issue> issues = new ArrayList<>();
|
||||||
issues.add(each.getObject());
|
for (IModel<Issue> each : selectionColumn.getSelections())
|
||||||
OneDev.getInstance(IssueManager.class).delete(issues, getProject());
|
issues.add(each.getObject());
|
||||||
|
getIssueManager().delete(issues, getProject());
|
||||||
|
for (var issue: issues) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(issue).toXML();
|
||||||
|
getAuditManager().audit(issue.getProject(), "deleted issue \"" + issue.getReference().toString(issue.getProject()) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
@ -1474,10 +1521,16 @@ public abstract class IssueListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<Issue> issues = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (Iterator<Issue> it = (Iterator<Issue>) dataProvider.iterator(0, issuesTable.getItemCount()); it.hasNext(); )
|
Collection<Issue> issues = new ArrayList<>();
|
||||||
issues.add(it.next());
|
for (Iterator<Issue> it = (Iterator<Issue>) dataProvider.iterator(0, issuesTable.getItemCount()); it.hasNext(); )
|
||||||
OneDev.getInstance(IssueManager.class).delete(issues, getProject());
|
issues.add(it.next());
|
||||||
|
getIssueManager().delete(issues, getProject());
|
||||||
|
for (var issue: issues) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(issue).toXML();
|
||||||
|
getAuditManager().audit(issue.getProject(), "deleted issue \"" + issue.getReference().toString(issue.getProject()) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import org.apache.wicket.markup.html.panel.GenericPanel;
|
|||||||
import org.apache.wicket.model.IModel;
|
import org.apache.wicket.model.IModel;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.IterationManager;
|
import io.onedev.server.entitymanager.IterationManager;
|
||||||
import io.onedev.server.model.Iteration;
|
import io.onedev.server.model.Iteration;
|
||||||
import io.onedev.server.web.ajaxlistener.ConfirmClickListener;
|
import io.onedev.server.web.ajaxlistener.ConfirmClickListener;
|
||||||
@ -37,6 +39,7 @@ public abstract class IterationActionsPanel extends GenericPanel<Iteration> {
|
|||||||
public void onClick(AjaxRequestTarget target) {
|
public void onClick(AjaxRequestTarget target) {
|
||||||
getIteration().setClosed(false);
|
getIteration().setClosed(false);
|
||||||
getIterationManager().createOrUpdate(getIteration());
|
getIterationManager().createOrUpdate(getIteration());
|
||||||
|
getAuditManager().audit(getIteration().getProject(), "reopened iteration \"" + getIteration().getName() + "\"", null, null);
|
||||||
target.add(IterationActionsPanel.this);
|
target.add(IterationActionsPanel.this);
|
||||||
onUpdated(target);
|
onUpdated(target);
|
||||||
getSession().success(MessageFormat.format(_T("Iteration \"{0}\" reopened"), getIteration().getName()));
|
getSession().success(MessageFormat.format(_T("Iteration \"{0}\" reopened"), getIteration().getName()));
|
||||||
@ -62,6 +65,7 @@ public abstract class IterationActionsPanel extends GenericPanel<Iteration> {
|
|||||||
public void onClick(AjaxRequestTarget target) {
|
public void onClick(AjaxRequestTarget target) {
|
||||||
getIteration().setClosed(true);
|
getIteration().setClosed(true);
|
||||||
getIterationManager().createOrUpdate(getIteration());
|
getIterationManager().createOrUpdate(getIteration());
|
||||||
|
getAuditManager().audit(getIteration().getProject(), "closed iteration \"" + getIteration().getName() + "\"", null, null);
|
||||||
target.add(IterationActionsPanel.this);
|
target.add(IterationActionsPanel.this);
|
||||||
onUpdated(target);
|
onUpdated(target);
|
||||||
getSession().success(MessageFormat.format(_T("Iteration \"{0}\" closed"), getIteration().getName()));
|
getSession().success(MessageFormat.format(_T("Iteration \"{0}\" closed"), getIteration().getName()));
|
||||||
@ -84,6 +88,8 @@ public abstract class IterationActionsPanel extends GenericPanel<Iteration> {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(AjaxRequestTarget target) {
|
public void onClick(AjaxRequestTarget target) {
|
||||||
getIterationManager().delete(getIteration());
|
getIterationManager().delete(getIteration());
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getIteration()).toXML();
|
||||||
|
getAuditManager().audit(getIteration().getProject(), "deleted iteration \"" + getIteration().getName() + "\"", oldAuditContent, null);
|
||||||
target.add(IterationActionsPanel.this);
|
target.add(IterationActionsPanel.this);
|
||||||
onDeleted(target);
|
onDeleted(target);
|
||||||
getSession().success(MessageFormat.format(_T("Iteration \"{0}\" deleted"), getIteration().getName()));
|
getSession().success(MessageFormat.format(_T("Iteration \"{0}\" deleted"), getIteration().getName()));
|
||||||
@ -98,6 +104,10 @@ public abstract class IterationActionsPanel extends GenericPanel<Iteration> {
|
|||||||
return OneDev.getInstance(IterationManager.class);
|
return OneDev.getInstance(IterationManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void onDeleted(AjaxRequestTarget target);
|
protected abstract void onDeleted(AjaxRequestTarget target);
|
||||||
|
|
||||||
protected abstract void onUpdated(AjaxRequestTarget target);
|
protected abstract void onUpdated(AjaxRequestTarget target);
|
||||||
|
|||||||
@ -47,10 +47,13 @@ import org.apache.wicket.request.cycle.RequestCycle;
|
|||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.PackManager;
|
import io.onedev.server.entitymanager.PackManager;
|
||||||
import io.onedev.server.model.Pack;
|
import io.onedev.server.model.Pack;
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.pack.PackSupport;
|
import io.onedev.server.pack.PackSupport;
|
||||||
|
import io.onedev.server.persistence.TransactionManager;
|
||||||
import io.onedev.server.search.entity.EntityQuery;
|
import io.onedev.server.search.entity.EntityQuery;
|
||||||
import io.onedev.server.search.entity.EntitySort;
|
import io.onedev.server.search.entity.EntitySort;
|
||||||
import io.onedev.server.search.entity.EntitySort.Direction;
|
import io.onedev.server.search.entity.EntitySort.Direction;
|
||||||
@ -126,6 +129,10 @@ public abstract class PackListPanel extends Panel {
|
|||||||
private PackManager getPackManager() {
|
private PackManager getPackManager() {
|
||||||
return OneDev.getInstance(PackManager.class);
|
return OneDev.getInstance(PackManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TransactionManager getTransactionManager() {
|
||||||
|
return OneDev.getInstance(TransactionManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private PackQuery parse(@Nullable String queryString, PackQuery baseQuery) {
|
private PackQuery parse(@Nullable String queryString, PackQuery baseQuery) {
|
||||||
@ -173,6 +180,10 @@ public abstract class PackListPanel extends Panel {
|
|||||||
protected QuerySaveSupport getQuerySaveSupport() {
|
protected QuerySaveSupport getQuerySaveSupport() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
private void doQuery(AjaxRequestTarget target) {
|
private void doQuery(AjaxRequestTarget target) {
|
||||||
packsTable.setCurrentPage(0);
|
packsTable.setCurrentPage(0);
|
||||||
@ -267,10 +278,16 @@ public abstract class PackListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<Pack> packs = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (IModel<Pack> each: selectionColumn.getSelections())
|
Collection<Pack> packs = new ArrayList<>();
|
||||||
packs.add(each.getObject());
|
for (IModel<Pack> each: selectionColumn.getSelections())
|
||||||
OneDev.getInstance(PackManager.class).delete(packs);
|
packs.add(each.getObject());
|
||||||
|
getPackManager().delete(packs);
|
||||||
|
for (var pack: packs) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(pack).toXML();
|
||||||
|
getAuditManager().audit(pack.getProject(), "deleted package \"" + pack.getReference(false) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
@ -331,11 +348,17 @@ public abstract class PackListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<Pack> packs = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (Iterator<Pack> it = (Iterator<Pack>) dataProvider.iterator(0, packsTable.getItemCount()); it.hasNext();) {
|
Collection<Pack> packs = new ArrayList<>();
|
||||||
packs.add(it.next());
|
for (Iterator<Pack> it = (Iterator<Pack>) dataProvider.iterator(0, packsTable.getItemCount()); it.hasNext();) {
|
||||||
}
|
packs.add(it.next());
|
||||||
OneDev.getInstance(PackManager.class).delete(packs);
|
}
|
||||||
|
getPackManager().delete(packs);
|
||||||
|
for (var pack: packs) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(pack).toXML();
|
||||||
|
getAuditManager().audit(pack.getProject(), "deleted package \"" + pack.getReference(false) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
|
|||||||
@ -23,6 +23,8 @@ import org.apache.wicket.model.IModel;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.BaseAuthorizationManager;
|
import io.onedev.server.entitymanager.BaseAuthorizationManager;
|
||||||
import io.onedev.server.entitymanager.ProjectLabelManager;
|
import io.onedev.server.entitymanager.ProjectLabelManager;
|
||||||
import io.onedev.server.entitymanager.ProjectManager;
|
import io.onedev.server.entitymanager.ProjectManager;
|
||||||
@ -122,9 +124,16 @@ public abstract class ForkOptionPanel extends Panel {
|
|||||||
|
|
||||||
OneDev.getInstance(TransactionManager.class).run(() -> {
|
OneDev.getInstance(TransactionManager.class).run(() -> {
|
||||||
getProjectManager().create(newProject);
|
getProjectManager().create(newProject);
|
||||||
getProjectManager().fork(getProject(), newProject);
|
getProjectManager().fork(getProject(), newProject);
|
||||||
OneDev.getInstance(BaseAuthorizationManager.class).syncRoles(newProject, defaultRolesBean.getRoles());
|
OneDev.getInstance(BaseAuthorizationManager.class).syncRoles(newProject, defaultRolesBean.getRoles());
|
||||||
OneDev.getInstance(ProjectLabelManager.class).sync(newProject, labelsBean.getLabels());
|
OneDev.getInstance(ProjectLabelManager.class).sync(newProject, labelsBean.getLabels());
|
||||||
|
|
||||||
|
var auditData = editor.getPropertyValues();
|
||||||
|
auditData.put("parent", parentBean.getParentPath());
|
||||||
|
auditData.put("forkedFrom", getProject().getPath());
|
||||||
|
auditData.put("defaultRoles", defaultRolesBean.getRoleNames());
|
||||||
|
auditData.put("labels", labelsBean.getLabels());
|
||||||
|
OneDev.getInstance(AuditManager.class).audit(newProject, "created project", null, VersionedXmlDoc.fromBean(auditData).toXML());
|
||||||
});
|
});
|
||||||
Session.get().success(_T("Project forked"));
|
Session.get().success(_T("Project forked"));
|
||||||
setResponsePage(ProjectBlobPage.class, ProjectBlobPage.paramsOf(newProject));
|
setResponsePage(ProjectBlobPage.class, ProjectBlobPage.paramsOf(newProject));
|
||||||
|
|||||||
@ -8,10 +8,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -52,6 +54,8 @@ import org.apache.wicket.request.mapper.parameter.PageParameters;
|
|||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.BuildManager;
|
import io.onedev.server.entitymanager.BuildManager;
|
||||||
import io.onedev.server.entitymanager.IssueManager;
|
import io.onedev.server.entitymanager.IssueManager;
|
||||||
import io.onedev.server.entitymanager.PackManager;
|
import io.onedev.server.entitymanager.PackManager;
|
||||||
@ -207,6 +211,10 @@ public class ProjectListPanel extends Panel {
|
|||||||
private ProjectManager getProjectManager() {
|
private ProjectManager getProjectManager() {
|
||||||
return OneDev.getInstance(ProjectManager.class);
|
return OneDev.getInstance(ProjectManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetach() {
|
protected void onDetach() {
|
||||||
@ -239,6 +247,16 @@ public class ProjectListPanel extends Panel {
|
|||||||
target.add(saveQueryLink);
|
target.add(saveQueryLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void auditDeletions(Collection<Project> projects) {
|
||||||
|
for (var project: Project.getIndependents(projects)) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(project).toXML();
|
||||||
|
if (project.getParent() != null)
|
||||||
|
getAuditManager().audit(project.getParent(), "deleted child project \"" + project.getName() + "\"", oldAuditContent, null);
|
||||||
|
else
|
||||||
|
getAuditManager().audit(null, "deleted root project \"" + project.getName() + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onInitialize() {
|
protected void onInitialize() {
|
||||||
super.onInitialize();
|
super.onInitialize();
|
||||||
@ -426,7 +444,17 @@ public class ProjectListPanel extends Panel {
|
|||||||
Collection<Project> projects = new ArrayList<>();
|
Collection<Project> projects = new ArrayList<>();
|
||||||
for (IModel<Project> each: selectionColumn.getSelections())
|
for (IModel<Project> each: selectionColumn.getSelections())
|
||||||
projects.add(each.getObject());
|
projects.add(each.getObject());
|
||||||
|
Map<Long, String> oldAuditContents = new HashMap<>();
|
||||||
|
for (var project: projects) {
|
||||||
|
oldAuditContents.put(project.getId(), project.getParent()!=null? project.getParent().getPath() : null);
|
||||||
|
}
|
||||||
getProjectManager().move(projects, getTargetProject());
|
getProjectManager().move(projects, getTargetProject());
|
||||||
|
for (var project: projects) {
|
||||||
|
var oldAuditContent = oldAuditContents.get(project.getId());
|
||||||
|
var newAuditContent = project.getParent()!=null? project.getParent().getPath() : null;
|
||||||
|
if (!Objects.equals(oldAuditContent, newAuditContent))
|
||||||
|
getAuditManager().audit(project, "changed parent", oldAuditContent, newAuditContent);
|
||||||
|
}
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
@ -512,7 +540,16 @@ public class ProjectListPanel extends Panel {
|
|||||||
Collection<Project> projects = new ArrayList<>();
|
Collection<Project> projects = new ArrayList<>();
|
||||||
for (IModel<Project> each: selectionColumn.getSelections())
|
for (IModel<Project> each: selectionColumn.getSelections())
|
||||||
projects.add(each.getObject());
|
projects.add(each.getObject());
|
||||||
|
Map<Long, String> oldAuditContents = new HashMap<>();
|
||||||
|
for (var project: projects) {
|
||||||
|
oldAuditContents.put(project.getId(), project.getParent()!=null? project.getParent().getPath() : null);
|
||||||
|
}
|
||||||
getProjectManager().move(projects, null);
|
getProjectManager().move(projects, null);
|
||||||
|
for (var project: projects) {
|
||||||
|
var oldAuditContent = oldAuditContents.get(project.getId());
|
||||||
|
if (oldAuditContent != null)
|
||||||
|
getAuditManager().audit(project, "changed parent", oldAuditContent, null);
|
||||||
|
}
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
@ -592,6 +629,7 @@ public class ProjectListPanel extends Panel {
|
|||||||
observables.add(project.getDeleteChangeObservable());
|
observables.add(project.getDeleteChangeObservable());
|
||||||
}
|
}
|
||||||
getProjectManager().delete(projects);
|
getProjectManager().delete(projects);
|
||||||
|
auditDeletions(projects);
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
@ -696,7 +734,17 @@ public class ProjectListPanel extends Panel {
|
|||||||
Collection<Project> projects = new ArrayList<>();
|
Collection<Project> projects = new ArrayList<>();
|
||||||
for (Iterator<Project> it = (Iterator<Project>) dataProvider.iterator(0, projectsTable.getItemCount()); it.hasNext();)
|
for (Iterator<Project> it = (Iterator<Project>) dataProvider.iterator(0, projectsTable.getItemCount()); it.hasNext();)
|
||||||
projects.add(it.next());
|
projects.add(it.next());
|
||||||
|
Map<Long, String> oldAuditContents = new HashMap<>();
|
||||||
|
for (var project: projects) {
|
||||||
|
oldAuditContents.put(project.getId(), project.getParent()!=null? project.getParent().getPath() : null);
|
||||||
|
}
|
||||||
getProjectManager().move(projects, getTargetProject());
|
getProjectManager().move(projects, getTargetProject());
|
||||||
|
for (var project: projects) {
|
||||||
|
var oldAuditContent = oldAuditContents.get(project.getId());
|
||||||
|
var newAuditContent = project.getParent()!=null? project.getParent().getPath() : null;
|
||||||
|
if (!Objects.equals(oldAuditContent, newAuditContent))
|
||||||
|
getAuditManager().audit(project, "changed parent", oldAuditContent, newAuditContent);
|
||||||
|
}
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
@ -783,7 +831,18 @@ public class ProjectListPanel extends Panel {
|
|||||||
Collection<Project> projects = new ArrayList<>();
|
Collection<Project> projects = new ArrayList<>();
|
||||||
for (Iterator<Project> it = (Iterator<Project>) dataProvider.iterator(0, projectsTable.getItemCount()); it.hasNext();)
|
for (Iterator<Project> it = (Iterator<Project>) dataProvider.iterator(0, projectsTable.getItemCount()); it.hasNext();)
|
||||||
projects.add(it.next());
|
projects.add(it.next());
|
||||||
|
|
||||||
|
var oldAuditContents = new HashMap<Long, String>();
|
||||||
|
for (var project: projects) {
|
||||||
|
oldAuditContents.put(project.getId(), project.getParent()!=null? project.getParent().getPath() : null);
|
||||||
|
}
|
||||||
getProjectManager().move(projects, null);
|
getProjectManager().move(projects, null);
|
||||||
|
for (var project: projects) {
|
||||||
|
var oldAuditContent = oldAuditContents.get(project.getId());
|
||||||
|
if (oldAuditContent != null)
|
||||||
|
getAuditManager().audit(project, "changed parent", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
@ -867,6 +926,7 @@ public class ProjectListPanel extends Panel {
|
|||||||
observables.add(project.getDeleteChangeObservable());
|
observables.add(project.getDeleteChangeObservable());
|
||||||
}
|
}
|
||||||
getProjectManager().delete(projects);
|
getProjectManager().delete(projects);
|
||||||
|
auditDeletions(projects);
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
|
|||||||
@ -57,6 +57,8 @@ import com.google.common.collect.Sets;
|
|||||||
|
|
||||||
import io.onedev.commons.utils.ExplicitException;
|
import io.onedev.commons.utils.ExplicitException;
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.ProjectManager;
|
import io.onedev.server.entitymanager.ProjectManager;
|
||||||
import io.onedev.server.entitymanager.PullRequestManager;
|
import io.onedev.server.entitymanager.PullRequestManager;
|
||||||
import io.onedev.server.entitymanager.PullRequestReviewManager;
|
import io.onedev.server.entitymanager.PullRequestReviewManager;
|
||||||
@ -68,6 +70,7 @@ import io.onedev.server.model.PullRequestLabel;
|
|||||||
import io.onedev.server.model.PullRequestReview;
|
import io.onedev.server.model.PullRequestReview;
|
||||||
import io.onedev.server.model.PullRequestReview.Status;
|
import io.onedev.server.model.PullRequestReview.Status;
|
||||||
import io.onedev.server.model.support.LastActivity;
|
import io.onedev.server.model.support.LastActivity;
|
||||||
|
import io.onedev.server.persistence.TransactionManager;
|
||||||
import io.onedev.server.search.entity.EntityQuery;
|
import io.onedev.server.search.entity.EntityQuery;
|
||||||
import io.onedev.server.search.entity.EntitySort;
|
import io.onedev.server.search.entity.EntitySort;
|
||||||
import io.onedev.server.search.entity.EntitySort.Direction;
|
import io.onedev.server.search.entity.EntitySort.Direction;
|
||||||
@ -148,6 +151,10 @@ public abstract class PullRequestListPanel extends Panel {
|
|||||||
private PullRequestManager getPullRequestManager() {
|
private PullRequestManager getPullRequestManager() {
|
||||||
return OneDev.getInstance(PullRequestManager.class);
|
return OneDev.getInstance(PullRequestManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TransactionManager getTransactionManager() {
|
||||||
|
return OneDev.getInstance(TransactionManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected PagingHistorySupport getPagingHistorySupport() {
|
protected PagingHistorySupport getPagingHistorySupport() {
|
||||||
@ -415,10 +422,16 @@ public abstract class PullRequestListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<PullRequest> requests = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (IModel<PullRequest> each : selectionColumn.getSelections())
|
Collection<PullRequest> requests = new ArrayList<>();
|
||||||
requests.add(each.getObject());
|
for (IModel<PullRequest> each : selectionColumn.getSelections())
|
||||||
OneDev.getInstance(PullRequestManager.class).delete(requests, getProject());
|
requests.add(each.getObject());
|
||||||
|
getPullRequestManager().delete(requests, getProject());
|
||||||
|
for (var request: requests) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(request).toXML();
|
||||||
|
getAuditManager().audit(request.getProject(), "deleted pull request \"" + request.getReference().toString(request.getProject()) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
selectionColumn.getSelections().clear();
|
selectionColumn.getSelections().clear();
|
||||||
@ -614,10 +627,16 @@ public abstract class PullRequestListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfirm(AjaxRequestTarget target) {
|
protected void onConfirm(AjaxRequestTarget target) {
|
||||||
Collection<PullRequest> requests = new ArrayList<>();
|
getTransactionManager().run(()-> {
|
||||||
for (Iterator<PullRequest> it = (Iterator<PullRequest>) dataProvider.iterator(0, requestsTable.getItemCount()); it.hasNext(); )
|
Collection<PullRequest> requests = new ArrayList<>();
|
||||||
requests.add(it.next());
|
for (Iterator<PullRequest> it = (Iterator<PullRequest>) dataProvider.iterator(0, requestsTable.getItemCount()); it.hasNext(); )
|
||||||
OneDev.getInstance(PullRequestManager.class).delete(requests, getProject());
|
requests.add(it.next());
|
||||||
|
getPullRequestManager().delete(requests, getProject());
|
||||||
|
for (var request: requests) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(request).toXML();
|
||||||
|
getAuditManager().audit(request.getProject(), "deleted pull request \"" + request.getReference().toString(request.getProject()) + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
dataProvider.detach();
|
dataProvider.detach();
|
||||||
target.add(countLabel);
|
target.add(countLabel);
|
||||||
target.add(body);
|
target.add(body);
|
||||||
@ -1106,6 +1125,10 @@ public abstract class PullRequestListPanel extends Panel {
|
|||||||
return OneDev.getInstance(PullRequestWatchManager.class);
|
return OneDev.getInstance(PullRequestWatchManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderHead(IHeaderResponse response) {
|
public void renderHead(IHeaderResponse response) {
|
||||||
super.renderHead(response);
|
super.renderHead(response);
|
||||||
|
|||||||
@ -96,15 +96,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.select2-container-multi .select2-choices .select2-search-field input {
|
.select2-container-multi .select2-choices .select2-search-field input {
|
||||||
height: calc(1.5em + 1.3rem);
|
height: calc(1.5em + 1.3rem);
|
||||||
line-height: 1.42857;
|
line-height: 1.42857;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-container-multi.form-control-sm .select2-choices .select2-search-field input,
|
.select2-container-multi.form-control-sm .select2-choices .select2-search-field input,
|
||||||
.input-group-sm .select2-container-multi .select2-choices .select2-search-field input {
|
.input-group-sm .select2-container-multi .select2-choices .select2-search-field input {
|
||||||
height: calc(1.35em + 1.1rem + 2px);
|
height: calc(1.3em + 1.1rem + 1px);
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
border-radius: 0.42rem;
|
border-radius: 0.28rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-sm.select2-container .select2-choice, .form-control-sm.select2-container .select2-choices {
|
||||||
|
border-radius: 0.28rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,19 +1,21 @@
|
|||||||
package io.onedev.server.web.component.user;
|
package io.onedev.server.web.component.user;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
|
||||||
import io.onedev.server.entitymanager.UserManager;
|
|
||||||
import io.onedev.server.model.User;
|
|
||||||
import io.onedev.server.security.SecurityUtils;
|
|
||||||
import io.onedev.server.web.WebSession;
|
|
||||||
import io.onedev.server.web.page.admin.usermanagement.UserListPage;
|
|
||||||
import io.onedev.server.web.util.ConfirmClickModifier;
|
|
||||||
|
|
||||||
import static io.onedev.server.web.translation.Translation._T;
|
import static io.onedev.server.web.translation.Translation._T;
|
||||||
|
|
||||||
import org.apache.wicket.RestartResponseException;
|
import org.apache.wicket.RestartResponseException;
|
||||||
import org.apache.wicket.markup.html.link.Link;
|
import org.apache.wicket.markup.html.link.Link;
|
||||||
import org.apache.wicket.request.flow.RedirectToUrlException;
|
import org.apache.wicket.request.flow.RedirectToUrlException;
|
||||||
|
|
||||||
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
|
import io.onedev.server.entitymanager.UserManager;
|
||||||
|
import io.onedev.server.model.User;
|
||||||
|
import io.onedev.server.security.SecurityUtils;
|
||||||
|
import io.onedev.server.web.WebSession;
|
||||||
|
import io.onedev.server.web.page.admin.usermanagement.UserListPage;
|
||||||
|
import io.onedev.server.web.util.ConfirmClickModifier;
|
||||||
|
|
||||||
public abstract class UserDeleteLink extends Link<Void> {
|
public abstract class UserDeleteLink extends Link<Void> {
|
||||||
|
|
||||||
public UserDeleteLink(String id) {
|
public UserDeleteLink(String id) {
|
||||||
@ -30,13 +32,17 @@ public abstract class UserDeleteLink extends Link<Void> {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick() {
|
public void onClick() {
|
||||||
var userManager = OneDev.getInstance(UserManager.class);
|
var userManager = OneDev.getInstance(UserManager.class);
|
||||||
|
var auditManager = OneDev.getInstance(AuditManager.class);
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(getUser()).toXML();
|
||||||
if (getUser().equals(SecurityUtils.getAuthUser())) {
|
if (getUser().equals(SecurityUtils.getAuthUser())) {
|
||||||
userManager.delete(getUser());
|
userManager.delete(getUser());
|
||||||
|
auditManager.audit(null, "deleted account \"" + getUser().getName() + "\"", oldAuditContent, null);
|
||||||
WebSession.get().success("Account removed");
|
WebSession.get().success("Account removed");
|
||||||
WebSession.get().logout();
|
WebSession.get().logout();
|
||||||
throw new RestartResponseException(getApplication().getHomePage());
|
throw new RestartResponseException(getApplication().getHomePage());
|
||||||
} else {
|
} else {
|
||||||
userManager.delete(getUser());
|
userManager.delete(getUser());
|
||||||
|
auditManager.audit(null, "deleted account \"" + getUser().getName() + "\"", oldAuditContent, null);
|
||||||
WebSession.get().success("Account removed");
|
WebSession.get().success("Account removed");
|
||||||
String redirectUrlAfterDelete = WebSession.get().getRedirectUrlAfterDelete(User.class);
|
String redirectUrlAfterDelete = WebSession.get().getRedirectUrlAfterDelete(User.class);
|
||||||
if (redirectUrlAfterDelete != null)
|
if (redirectUrlAfterDelete != null)
|
||||||
|
|||||||
@ -15,8 +15,10 @@ import org.apache.wicket.markup.html.panel.Panel;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
import io.onedev.server.entitymanager.AccessTokenAuthorizationManager;
|
import io.onedev.server.entitymanager.AccessTokenAuthorizationManager;
|
||||||
import io.onedev.server.entitymanager.AccessTokenManager;
|
import io.onedev.server.entitymanager.AccessTokenManager;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.entitymanager.ProjectManager;
|
import io.onedev.server.entitymanager.ProjectManager;
|
||||||
import io.onedev.server.entitymanager.RoleManager;
|
import io.onedev.server.entitymanager.RoleManager;
|
||||||
import io.onedev.server.model.AccessToken;
|
import io.onedev.server.model.AccessToken;
|
||||||
@ -25,9 +27,12 @@ import io.onedev.server.persistence.TransactionManager;
|
|||||||
import io.onedev.server.util.Path;
|
import io.onedev.server.util.Path;
|
||||||
import io.onedev.server.util.PathNode;
|
import io.onedev.server.util.PathNode;
|
||||||
import io.onedev.server.web.editable.BeanContext;
|
import io.onedev.server.web.editable.BeanContext;
|
||||||
|
import io.onedev.server.web.page.user.UserPage;
|
||||||
|
|
||||||
abstract class AccessTokenEditPanel extends Panel {
|
abstract class AccessTokenEditPanel extends Panel {
|
||||||
|
|
||||||
|
private String oldAuditContent;
|
||||||
|
|
||||||
public AccessTokenEditPanel(String id) {
|
public AccessTokenEditPanel(String id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
@ -40,6 +45,9 @@ abstract class AccessTokenEditPanel extends Panel {
|
|||||||
|
|
||||||
var token = getToken();
|
var token = getToken();
|
||||||
var bean = AccessTokenEditBean.of(token);
|
var bean = AccessTokenEditBean.of(token);
|
||||||
|
|
||||||
|
if (!token.isNew())
|
||||||
|
oldAuditContent = VersionedXmlDoc.fromBean(bean).toXML();
|
||||||
|
|
||||||
var editor = BeanContext.edit("editor", bean, Sets.newHashSet("value"), true);
|
var editor = BeanContext.edit("editor", bean, Sets.newHashSet("value"), true);
|
||||||
form.add(editor);
|
form.add(editor);
|
||||||
@ -89,8 +97,15 @@ abstract class AccessTokenEditPanel extends Panel {
|
|||||||
token.setExpireDate(bean.getExpireDate());
|
token.setExpireDate(bean.getExpireDate());
|
||||||
|
|
||||||
getTransactionManager().run(() -> {
|
getTransactionManager().run(() -> {
|
||||||
|
if (token.isNew())
|
||||||
getTokenManager().createOrUpdate(token);
|
getTokenManager().createOrUpdate(token);
|
||||||
getAuthorizationManager().syncAuthorizations(token, authorizations);
|
getAuthorizationManager().syncAuthorizations(token, authorizations);
|
||||||
|
if (getPage() instanceof UserPage) {
|
||||||
|
var newAuditContent = VersionedXmlDoc.fromBean(bean).toXML();
|
||||||
|
var verb = oldAuditContent != null ? "changed" : "created";
|
||||||
|
getAuditManager().audit(null, verb + " access token \"" + token.getName() + "\" for account \"" + token.getOwner().getName() + "\"", oldAuditContent, newAuditContent);
|
||||||
|
oldAuditContent = newAuditContent;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
onSaved(target);
|
onSaved(target);
|
||||||
}
|
}
|
||||||
@ -115,6 +130,10 @@ abstract class AccessTokenEditPanel extends Panel {
|
|||||||
|
|
||||||
setOutputMarkupId(true);
|
setOutputMarkupId(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
private TransactionManager getTransactionManager() {
|
private TransactionManager getTransactionManager() {
|
||||||
return OneDev.getInstance(TransactionManager.class);
|
return OneDev.getInstance(TransactionManager.class);
|
||||||
|
|||||||
@ -15,9 +15,12 @@ import org.apache.wicket.markup.html.panel.Panel;
|
|||||||
import org.apache.wicket.model.AbstractReadOnlyModel;
|
import org.apache.wicket.model.AbstractReadOnlyModel;
|
||||||
|
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
|
import io.onedev.server.data.migration.VersionedXmlDoc;
|
||||||
import io.onedev.server.entitymanager.AccessTokenManager;
|
import io.onedev.server.entitymanager.AccessTokenManager;
|
||||||
|
import io.onedev.server.entitymanager.AuditManager;
|
||||||
import io.onedev.server.model.AccessToken;
|
import io.onedev.server.model.AccessToken;
|
||||||
import io.onedev.server.model.User;
|
import io.onedev.server.model.User;
|
||||||
|
import io.onedev.server.web.page.user.UserPage;
|
||||||
|
|
||||||
public abstract class AccessTokenListPanel extends Panel {
|
public abstract class AccessTokenListPanel extends Panel {
|
||||||
|
|
||||||
@ -50,7 +53,12 @@ public abstract class AccessTokenListPanel extends Panel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDelete(AjaxRequestTarget target) {
|
protected void onDelete(AjaxRequestTarget target) {
|
||||||
getTokenManager().delete(getToken());
|
var token = getToken();
|
||||||
|
getTokenManager().delete(token);
|
||||||
|
if (getPage() instanceof UserPage) {
|
||||||
|
var oldAuditContent = VersionedXmlDoc.fromBean(token).toXML();
|
||||||
|
getAuditManager().audit(null, "deleted access token \"" + token.getName() + "\" for account \"" + token.getOwner().getName() + "\"", oldAuditContent, null);
|
||||||
|
}
|
||||||
target.add(container);
|
target.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,4 +154,8 @@ public abstract class AccessTokenListPanel extends Panel {
|
|||||||
return OneDev.getInstance(AccessTokenManager.class);
|
return OneDev.getInstance(AccessTokenManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuditManager getAuditManager() {
|
||||||
|
return OneDev.getInstance(AuditManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user