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>

Reply via email to