This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/master by this push:
new b269736ea [OPENMEETINGS-2826] Room private files are accessible to
authorized users only
b269736ea is described below
commit b269736ea70c5a1ead4105b9bab8f4a9b366cd08
Author: Maxim Solodovnik <[email protected]>
AuthorDate: Wed Aug 26 12:35:20 2026 +0700
[OPENMEETINGS-2826] Room private files are accessible to authorized users
only
---
.../openmeetings/db/manager/RoomManager.java | 87 ++++++++++++++++++++++
.../apache/openmeetings/web/app/Application.java | 57 +-------------
.../apache/openmeetings/web/room/RoomPanel.java | 6 +-
.../apache/openmeetings/ws/TestFileService.java | 5 ++
.../openmeetings/webservice/FileWebService.java | 20 +++--
pom.xml | 3 +
6 files changed, 115 insertions(+), 63 deletions(-)
diff --git
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/RoomManager.java
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/RoomManager.java
new file mode 100644
index 000000000..06ac04f73
--- /dev/null
+++
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/manager/RoomManager.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") + you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.db.manager;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
+import org.apache.openmeetings.db.entity.calendar.Appointment;
+import org.apache.openmeetings.db.entity.calendar.MeetingMember;
+import org.apache.openmeetings.db.entity.room.Room;
+import org.apache.openmeetings.db.entity.room.RoomGroup;
+import org.apache.openmeetings.db.entity.user.Group;
+import org.apache.openmeetings.db.entity.user.GroupUser;
+import org.apache.openmeetings.db.entity.user.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import jakarta.inject.Inject;
+
+@Component
+public class RoomManager {
+ private static final Logger log =
LoggerFactory.getLogger(RoomManager.class);
+
+ @Inject
+ private AppointmentDao appointmentDao;
+
+ private static boolean checkAppointment(Appointment a, User u) {
+ if (a == null || a.isDeleted()) {
+ return false;
+ }
+ if (a.isOwner(u.getId())) {
+ log.debug("[isRoomAllowedToUser] appointed room, Owner
entered");
+ return true;
+ }
+ return a.getMeetingMembers().stream()
+ .map(MeetingMember::getUser)
+ .map(User::getId)
+ .anyMatch(userId -> userId.equals(u.getId()));
+ }
+
+ private static boolean checkGroups(Room r, User u) {
+ if (null == r.getGroups()) { //u.getGroupUsers() can't be null
due to user was able to login
+ return false;
+ }
+ Set<Long> roomGroups = r.getGroups().stream()
+ .map(RoomGroup::getGroup)
+ .map(Group::getId)
+ .collect(Collectors.toSet());
+ return u.getGroupUsers().stream()
+ .map(GroupUser::getGroup)
+ .map(Group::getId)
+ .anyMatch(roomGroups::contains);
+ }
+
+ public boolean isRoomAllowedToUser(Room r, User u) {
+ if (r == null) {
+ return false;
+ }
+ if (r.isAppointment()) {
+ Appointment a = appointmentDao.getByRoom(r.getId());
+ return checkAppointment(a, u);
+ }
+ if (r.getIspublic() || r.isOwner(u.getId())) {
+ log.debug("[isRoomAllowedToUser] public ? {} , ownedId
? {} ALLOWED", r.getIspublic(), r.getOwnerId());
+ return true;
+ }
+ return checkGroups(r, u);
+ }
+}
diff --git
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
index 165305ee8..209a0ec50 100644
---
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
+++
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
@@ -46,7 +46,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
import jakarta.annotation.Nonnull;
@@ -58,23 +57,18 @@ import org.apache.openmeetings.core.sip.SipManager;
import org.apache.openmeetings.core.util.ChatWebSocketHelper;
import org.apache.openmeetings.core.util.WebSocketHelper;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
-import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
import org.apache.openmeetings.db.dao.label.LabelDao;
import org.apache.openmeetings.db.dao.record.RecordingDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.basic.Client;
import org.apache.openmeetings.db.entity.basic.Client.Activity;
import org.apache.openmeetings.db.entity.basic.Configuration;
-import org.apache.openmeetings.db.entity.calendar.Appointment;
-import org.apache.openmeetings.db.entity.calendar.MeetingMember;
import org.apache.openmeetings.db.entity.record.Recording;
import org.apache.openmeetings.db.entity.room.Invitation;
import org.apache.openmeetings.db.entity.room.Room;
-import org.apache.openmeetings.db.entity.room.RoomGroup;
-import org.apache.openmeetings.db.entity.user.Group;
-import org.apache.openmeetings.db.entity.user.GroupUser;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.db.entity.user.User.Type;
+import org.apache.openmeetings.db.manager.RoomManager;
import org.apache.openmeetings.db.util.ApplicationHelper;
import org.apache.openmeetings.db.util.ws.RoomMessage;
import org.apache.openmeetings.db.util.ws.TextRoomMessage;
@@ -206,9 +200,9 @@ public class Application extends
AuthenticatedWebApplication implements IApplica
@Inject
private WhiteboardManager wbManager;
@Inject
- private AppointmentDao appointmentDao;
- @Inject
private SipManager sipManager;
+ @Inject
+ private RoomManager roomManager;
@Value("${remember.me.rotation.days:30}")
private int rememberRotationDays;
@@ -571,7 +565,7 @@ public class Application extends
AuthenticatedWebApplication implements IApplica
User u = i.getInvitee();
if (r != null) {
if ((i.isPasswordProtected() && !r.isOwner(u.getId()))
// invitation is password-protected and invitee is not owner
- || Type.CONTACT == u.getType() ||
Type.EXTERNAL == u.getType() || !get().isRoomAllowedToUser(r, u)) // no-access
+ || Type.CONTACT == u.getType() ||
Type.EXTERNAL == u.getType() || !get().roomManager.isRoomAllowedToUser(r, u))
// no-access
{
PageParameters pp = new PageParameters();
pp.add(INVITATION_HASH, i.getHash());
@@ -590,49 +584,6 @@ public class Application extends
AuthenticatedWebApplication implements IApplica
return link;
}
- private static boolean checkAppointment(Appointment a, User u) {
- if (a == null || a.isDeleted()) {
- return false;
- }
- if (a.isOwner(u.getId())) {
- log.debug("[isRoomAllowedToUser] appointed room, Owner
entered");
- return true;
- }
- return a.getMeetingMembers().stream()
- .map(MeetingMember::getUser)
- .map(User::getId)
- .anyMatch(userId -> userId.equals(u.getId()));
- }
-
- private static boolean checkGroups(Room r, User u) {
- if (null == r.getGroups()) { //u.getGroupUsers() can't be null
due to user was able to login
- return false;
- }
- Set<Long> roomGroups = r.getGroups().stream()
- .map(RoomGroup::getGroup)
- .map(Group::getId)
- .collect(Collectors.toSet());
- return u.getGroupUsers().stream()
- .map(GroupUser::getGroup)
- .map(Group::getId)
- .anyMatch(roomGroups::contains);
- }
-
- public boolean isRoomAllowedToUser(Room r, User u) {
- if (r == null) {
- return false;
- }
- if (r.isAppointment()) {
- Appointment a = appointmentDao.getByRoom(r.getId());
- return checkAppointment(a, u);
- }
- if (r.getIspublic() || r.isOwner(u.getId())) {
- log.debug("[isRoomAllowedToUser] public ? {} , ownedId
? {} ALLOWED", r.getIspublic(), r.getOwnerId());
- return true;
- }
- return checkGroups(r, u);
- }
-
public static boolean isUrlValid(String url) {
return new UrlValidator(new String[] {"http",
"https"}).isValid(url);
}
diff --git
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
index fdbd6f8b7..c84960d29 100644
---
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
+++
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java
@@ -49,11 +49,11 @@ import org.apache.openmeetings.db.entity.room.Room.Right;
import org.apache.openmeetings.db.entity.room.Room.RoomElement;
import org.apache.openmeetings.db.entity.room.RoomGroup;
import org.apache.openmeetings.db.entity.server.SOAPLogin;
+import org.apache.openmeetings.db.manager.RoomManager;
import org.apache.openmeetings.db.util.AuthLevelUtil;
import org.apache.openmeetings.db.util.ws.RoomMessage;
import org.apache.openmeetings.db.util.ws.RoomMessage.Type;
import org.apache.openmeetings.db.util.ws.TextRoomMessage;
-import org.apache.openmeetings.web.app.Application;
import org.apache.openmeetings.web.app.ClientManager;
import org.apache.openmeetings.web.app.QuickPollManager;
import org.apache.openmeetings.web.app.TimerService;
@@ -274,6 +274,8 @@ public class RoomPanel extends BasePanel {
private TimerService timerService;
@Inject
private FileItemDao fileDao;
+ @Inject
+ private RoomManager roomManager;
public RoomPanel(String id, Room r) {
super(id);
@@ -337,7 +339,7 @@ public class RoomPanel extends BasePanel {
} else if (r.getId().equals(WebSession.get().getRoomId())) {
// secureHash/invitationHash, already checked
} else {
- boolean allowed =
Application.get().isRoomAllowedToUser(r, c.getUser());
+ boolean allowed = roomManager.isRoomAllowedToUser(r,
c.getUser());
String deniedMessage = null;
if (r.isAppointment()) {
Appointment a = apptDao.getByRoom(r.getId());
diff --git
a/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestFileService.java
b/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestFileService.java
index 3883144ab..3b1b8ff17 100644
---
a/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestFileService.java
+++
b/openmeetings-web/src/test/java/org/apache/openmeetings/ws/TestFileService.java
@@ -41,6 +41,7 @@ import java.util.function.Consumer;
import javax.imageio.ImageIO;
import org.apache.openmeetings.db.dao.file.FileItemDao;
+import org.apache.openmeetings.db.dao.room.RoomDao;
import org.apache.openmeetings.db.dao.user.GroupDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.dto.basic.ServiceResult;
@@ -48,6 +49,7 @@ import org.apache.openmeetings.db.dto.file.FileExplorerObject;
import org.apache.openmeetings.db.dto.file.FileItemDTO;
import org.apache.openmeetings.db.entity.file.BaseFileItem;
import org.apache.openmeetings.db.entity.file.FileItem;
+import org.apache.openmeetings.db.entity.room.Room;
import org.apache.openmeetings.db.entity.user.Group;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.test.NonJenkinsTest;
@@ -188,6 +190,9 @@ class TestFileService extends AbstractWebServiceTest {
u.addGroup(g);
u = createUser(userDao, u);
+ RoomDao roomDao = getBean(RoomDao.class);
+ Room myRoom = roomDao.getMyRooms(admin.getId(), "conference",
"restricted").get(0);
+ accessRoomByParentDenied(-2l, myRoom.getId(), u.getLogin(),
createPass());
accessRoomByParentDenied(adminFolder.getId(), 5, u.getLogin(),
createPass());
accessRoomByParentGranted(adminFolder.getId(), 5,
ADMIN_USERNAME, USER_PASS);
diff --git
a/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/FileWebService.java
b/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/FileWebService.java
index 3a72163d1..a9f151471 100644
---
a/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/FileWebService.java
+++
b/openmeetings-webservice/src/main/java/org/apache/openmeetings/webservice/FileWebService.java
@@ -51,6 +51,7 @@ import org.apache.openmeetings.db.entity.file.BaseFileItem;
import org.apache.openmeetings.db.entity.file.FileItem;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.db.entity.user.User.Right;
+import org.apache.openmeetings.db.manager.RoomManager;
import org.apache.openmeetings.db.util.AuthLevelUtil;
import org.apache.openmeetings.util.process.ProcessResultList;
import org.apache.openmeetings.webservice.error.InternalServiceException;
@@ -92,6 +93,8 @@ public class FileWebService extends BaseWebService {
private FileProcessor fileProcessor;
@Inject
private GroupUserDao groupUserDao;
+ @Inject
+ private RoomManager roomManager;
/**
* deletes files or folders based on it id
@@ -335,9 +338,12 @@ public class FileWebService extends BaseWebService {
// insufficient rights
return false;
}
- if (parentId < 0) {
- // will get files by room or owner
+ if (parentId == -1) {
+ // will get files by owner
return true;
+ } else if (parentId < 0) {
+ // will get files by room
+ return
roomManager.isRoomAllowedToUser(roomDao.get(roomId), userDao.get(userId));
}
BaseFileItem root = fileDao.getRoot(parentId);
if (root == null) {
@@ -359,12 +365,10 @@ public class FileWebService extends BaseWebService {
return false;
}, sd -> {
List<FileItem> list;
- if (parentId < 0) {
- if (parentId == -1) {
- list =
fileDao.getByOwner(sd.getUserId());
- } else {
- list = fileDao.getByRoom(roomId);
- }
+ if (parentId == -1) {
+ list = fileDao.getByOwner(sd.getUserId());
+ } else if (parentId < 0) {
+ list = fileDao.getByRoom(roomId);
} else {
list = fileDao.getByParent(parentId);
}
diff --git a/pom.xml b/pom.xml
index 3d1855b54..897473dd4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
<project.build.outputTimestamp>2026-07-13T06:45:35Z</project.build.outputTimestamp>
<wicket.configuration>DEPLOYMENT</wicket.configuration>
<om.quick.build>false</om.quick.build>
+ <om.javadoc.skip>false</om.javadoc.skip>
<om.notquick.build>true</om.notquick.build>
<site.skip>false</site.skip>
<logback.console></logback.console>
@@ -1195,6 +1196,7 @@
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<skip>${om.quick.build}</skip>
+ <skip>${om.javadoc.skip}</skip>
</configuration>
<executions>
<execution>
@@ -1824,6 +1826,7 @@
<maven.test.skip>true</maven.test.skip>
<site.skip>true</site.skip>
<om.quick.build>true</om.quick.build>
+ <om.javadoc.skip>true</om.javadoc.skip>
<om.notquick.build>false</om.notquick.build>
<wicket.configuration>DEVELOPMENT</wicket.configuration>
<src.pack.skip>true</src.pack.skip>