Invalidate authorization cache when namespace permissions are changed

This commit is contained in:
René Pfeuffer
2020-09-17 15:31:47 +02:00
parent c679c064f3
commit a24abe245b
6 changed files with 211 additions and 10 deletions

View File

@@ -24,6 +24,10 @@
package sonia.scm.repository;
import com.github.legman.EventBus;
import sonia.scm.HandlerEventType;
import sonia.scm.event.ScmEventBus;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Optional;
@@ -36,11 +40,13 @@ public class DefaultNamespaceManager implements NamespaceManager {
private final RepositoryManager repositoryManager;
private final NamespaceDao dao;
private final EventBus eventBus;
@Inject
public DefaultNamespaceManager(RepositoryManager repositoryManager, NamespaceDao dao) {
public DefaultNamespaceManager(RepositoryManager repositoryManager, NamespaceDao dao, EventBus eventBus) {
this.repositoryManager = repositoryManager;
this.dao = dao;
this.eventBus = eventBus;
}
@Override
@@ -64,10 +70,14 @@ public class DefaultNamespaceManager implements NamespaceManager {
@Override
public void modify(Namespace namespace) {
Namespace oldNamespace = get(namespace.getNamespace())
.orElseThrow(() -> notFound(entity(Namespace.class, namespace.getNamespace())));
fireEvent(HandlerEventType.BEFORE_MODIFY, namespace, oldNamespace);
if (!get(namespace.getNamespace()).isPresent()) {
throw notFound(entity("Namespace", namespace.getNamespace()));
}
dao.add(namespace);
fireEvent(HandlerEventType.MODIFY, namespace, oldNamespace);
}
private Namespace createNamespaceForName(String namespace) {
@@ -75,4 +85,8 @@ public class DefaultNamespaceManager implements NamespaceManager {
.map(Namespace::clone)
.orElse(new Namespace(namespace));
}
protected void fireEvent(HandlerEventType event, Namespace namespace, Namespace oldNamespace) {
eventBus.post(new NamespaceModificationEvent(event, namespace, oldNamespace));
}
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.security;
import com.github.legman.Subscribe;
@@ -35,14 +35,19 @@ import sonia.scm.event.ScmEventBus;
import sonia.scm.group.Group;
import sonia.scm.group.GroupEvent;
import sonia.scm.group.GroupModificationEvent;
import sonia.scm.repository.Namespace;
import sonia.scm.repository.NamespaceEvent;
import sonia.scm.repository.NamespaceModificationEvent;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryEvent;
import sonia.scm.repository.RepositoryModificationEvent;
import sonia.scm.repository.RepositoryPermission;
import sonia.scm.user.User;
import sonia.scm.user.UserEvent;
import sonia.scm.user.UserModificationEvent;
import javax.inject.Singleton;
import java.util.Collection;
/**
* Receives all kinds of events, which affects authorization relevant data and fires an
@@ -146,23 +151,47 @@ public class AuthorizationChangedEventProducer {
}
}
@Subscribe
public void onEvent(NamespaceEvent event) {
if (event.getEventType().isPost()) {
if (isModificationEvent(event)) {
handleNamespaceModificationEvent((NamespaceModificationEvent) event);
}
}
}
private void handleRepositoryModificationEvent(RepositoryModificationEvent event) {
Repository repository = event.getItem();
if (isAuthorizationDataModified(repository, event.getItemBeforeModification())) {
if (isAuthorizationDataModified(repository.getPermissions(), event.getItemBeforeModification().getPermissions())) {
logger.debug(
"fire authorization changed event, because a relevant field of repository {} has changed", repository.getName()
"fire authorization changed event, because a relevant field of repository {}/{} has changed", repository.getNamespace(), repository.getName()
);
fireEventForEveryUser();
} else {
logger.debug(
"authorization changed event is not fired, because non relevant field of repository {} has changed",
repository.getName()
"authorization changed event is not fired, because non relevant field of repository {}/{} has changed",
repository.getNamespace(), repository.getName()
);
}
}
private boolean isAuthorizationDataModified(Repository repository, Repository beforeModification) {
return !(repository.getPermissions().containsAll(beforeModification.getPermissions()) && beforeModification.getPermissions().containsAll(repository.getPermissions()));
private void handleNamespaceModificationEvent(NamespaceModificationEvent event) {
Namespace namespace = event.getItem();
if (isAuthorizationDataModified(namespace.getPermissions(), event.getItemBeforeModification().getPermissions())) {
logger.debug(
"fire authorization changed event, because a relevant field of namespace {} has changed", namespace.getNamespace()
);
fireEventForEveryUser();
} else {
logger.debug(
"authorization changed event is not fired, because non relevant field of namespace {} has changed",
namespace.getNamespace()
);
}
}
private boolean isAuthorizationDataModified(Collection<RepositoryPermission> newPermissions, Collection<RepositoryPermission> permissionsBeforeModification) {
return !(newPermissions.containsAll(permissionsBeforeModification) && permissionsBeforeModification.containsAll(newPermissions));
}
private void fireEventForEveryUser() {