Fix issue #992 - Unable to access OneDev UI if user belongs to login

group
This commit is contained in:
Robin Shen 2022-11-23 15:40:39 +08:00
parent ee44f342db
commit b6f615a001
4 changed files with 119 additions and 22 deletions

View File

@ -10,19 +10,29 @@ import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order; import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import com.hazelcast.core.HazelcastInstance;
import io.onedev.server.cluster.ClusterManager;
import io.onedev.server.entitymanager.GroupManager; import io.onedev.server.entitymanager.GroupManager;
import io.onedev.server.entitymanager.IssueFieldManager; import io.onedev.server.entitymanager.IssueFieldManager;
import io.onedev.server.entitymanager.ProjectManager; import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.entitymanager.SettingManager; import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.event.Listen;
import io.onedev.server.event.entity.EntityPersisted;
import io.onedev.server.event.entity.EntityRemoved;
import io.onedev.server.event.system.SystemStarted;
import io.onedev.server.model.Group; import io.onedev.server.model.Group;
import io.onedev.server.model.Project; import io.onedev.server.model.Project;
import io.onedev.server.model.support.BranchProtection; import io.onedev.server.model.support.BranchProtection;
import io.onedev.server.model.support.TagProtection; import io.onedev.server.model.support.TagProtection;
import io.onedev.server.persistence.TransactionManager;
import io.onedev.server.persistence.annotation.Sessional; import io.onedev.server.persistence.annotation.Sessional;
import io.onedev.server.persistence.annotation.Transactional; import io.onedev.server.persistence.annotation.Transactional;
import io.onedev.server.persistence.dao.BaseEntityManager; 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.persistence.dao.EntityCriteria; import io.onedev.server.persistence.dao.EntityCriteria;
import io.onedev.server.util.facade.GroupCache;
import io.onedev.server.util.facade.GroupFacade;
import io.onedev.server.util.usage.Usage; import io.onedev.server.util.usage.Usage;
@Singleton @Singleton
@ -34,13 +44,68 @@ public class DefaultGroupManager extends BaseEntityManager<Group> implements Gro
private final IssueFieldManager issueFieldManager; private final IssueFieldManager issueFieldManager;
private final ClusterManager clusterManager;
private final TransactionManager transactionManager;
private volatile GroupCache cache;
@Inject @Inject
public DefaultGroupManager(Dao dao, ProjectManager projectManager, SettingManager settingManager, public DefaultGroupManager(Dao dao, ProjectManager projectManager, SettingManager settingManager,
IssueFieldManager issueFieldManager) { IssueFieldManager issueFieldManager, ClusterManager clusterManager,
TransactionManager transactionManager) {
super(dao); super(dao);
this.projectManager = projectManager; this.projectManager = projectManager;
this.settingManager = settingManager; this.settingManager = settingManager;
this.issueFieldManager = issueFieldManager; this.issueFieldManager = issueFieldManager;
this.clusterManager = clusterManager;
this.transactionManager = transactionManager;
}
@Sessional
@Listen
public void on(SystemStarted event) {
HazelcastInstance hazelcastInstance = clusterManager.getHazelcastInstance();
cache = new GroupCache(hazelcastInstance.getReplicatedMap("groupCache"));
for (Group group: query())
cache.put(group.getId(), group.getFacade());
}
@Transactional
@Listen
public void on(EntityRemoved event) {
if (event.getEntity() instanceof Group) {
Long id = event.getEntity().getId();
transactionManager.runAfterCommit(new Runnable() {
@Override
public void run() {
cache.remove(id);
}
});
}
}
@Transactional
@Listen
public void on(EntityPersisted event) {
if (event.getEntity() instanceof Group)
cacheAfterCommit((Group) event.getEntity());
}
private void cacheAfterCommit(Group group) {
GroupFacade facade = group.getFacade();
transactionManager.runAfterCommit(new Runnable() {
@Override
public void run() {
if (cache != null)
cache.put(facade.getId(), facade);
}
});
} }
@Transactional @Transactional
@ -83,11 +148,12 @@ public class DefaultGroupManager extends BaseEntityManager<Group> implements Gro
@Sessional @Sessional
@Override @Override
public Group find(String name) { public Group find(String groupName) {
EntityCriteria<Group> criteria = newCriteria(); GroupFacade facade = cache.find(groupName);
criteria.add(Restrictions.ilike("name", name)); if (facade != null)
criteria.setCacheable(true); return load(facade.getId());
return find(criteria); else
return null;
} }
@Override @Override

View File

@ -8,15 +8,16 @@ import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.validation.constraints.NotEmpty;
import org.apache.shiro.authz.Permission; import org.apache.shiro.authz.Permission;
import org.hibernate.annotations.Cache; import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.validation.constraints.NotEmpty;
import io.onedev.server.security.permission.CreateRootProjects; import io.onedev.server.security.permission.CreateRootProjects;
import io.onedev.server.security.permission.ProjectPermission; import io.onedev.server.security.permission.ProjectPermission;
import io.onedev.server.util.EditContext; import io.onedev.server.util.EditContext;
import io.onedev.server.util.facade.GroupFacade;
import io.onedev.server.web.editable.annotation.Editable; import io.onedev.server.web.editable.annotation.Editable;
import io.onedev.server.web.editable.annotation.ShowCondition; import io.onedev.server.web.editable.annotation.ShowCondition;
@ -142,6 +143,11 @@ public class Group extends AbstractEntity implements Permission {
return members; return members;
} }
@Override
public GroupFacade getFacade() {
return new GroupFacade(getId(), getName());
}
@Override @Override
public int compareTo(AbstractEntity entity) { public int compareTo(AbstractEntity entity) {
Group group = (Group) entity; Group group = (Group) entity;

View File

@ -1,7 +1,6 @@
package io.onedev.server.model.support.administration; package io.onedev.server.model.support.administration;
import java.io.Serializable; import java.io.Serializable;
import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -30,8 +29,6 @@ public class SecuritySetting implements Serializable {
private boolean enforce2FA; private boolean enforce2FA;
private transient Optional<Group> defaultLoginGroup;
@Editable(order=100, description="Whether or not to allow anonymous users to access this server") @Editable(order=100, description="Whether or not to allow anonymous users to access this server")
public boolean isEnableAnonymousAccess() { public boolean isEnableAnonymousAccess() {
return enableAnonymousAccess; return enableAnonymousAccess;
@ -74,17 +71,12 @@ public class SecuritySetting implements Serializable {
@Nullable @Nullable
public Group getDefaultLoginGroup() { public Group getDefaultLoginGroup() {
if (defaultLoginGroup == null) {
if (defaultLoginGroupName != null) { if (defaultLoginGroupName != null) {
Group group = OneDev.getInstance(GroupManager.class).find(defaultLoginGroupName); Group group = OneDev.getInstance(GroupManager.class).find(defaultLoginGroupName);
if (group == null) if (group == null)
logger.error("Unable to find default login group: " + defaultLoginGroupName); logger.error("Unable to find default login group: " + defaultLoginGroupName);
defaultLoginGroup = Optional.ofNullable(group);
} else {
defaultLoginGroup = Optional.empty();
} }
} return null;
return defaultLoginGroup.orElse(null);
} }
public void onRenameGroup(String oldName, String newName) { public void onRenameGroup(String oldName, String newName) {

View File

@ -0,0 +1,33 @@
package io.onedev.server.util.facade;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import io.onedev.server.util.MapProxy;
public class GroupCache extends MapProxy<Long, GroupFacade> implements Serializable {
private static final long serialVersionUID = 1L;
public GroupCache(Map<Long, GroupFacade> delegate) {
super(delegate);
}
@Nullable
public GroupFacade find(String name) {
for (GroupFacade facade: values()) {
if (name.equals(facade.getName()))
return facade;
}
return null;
}
@Override
public GroupCache clone() {
return new GroupCache(new HashMap<>(delegate));
}
}