From d2f9944359006e7ed9f26d91757020365be9e48a Mon Sep 17 00:00:00 2001 From: srosse <stephane.rosse@frentix.com> Date: Thu, 24 Jan 2019 09:38:49 +0100 Subject: [PATCH] OO-3835: add vitero to CSP, cache proxies, link to groups Add the vitero domain to the frame CSP, cache the SOAP proxies (because of Apache CXF), add a link in the file browser to open it in a new window --- .../org/olat/core/servlets/HeadersFilter.java | 13 ++- .../modules/vitero/manager/ViteroManager.java | 92 +++++++++++++++---- .../modules/vitero/ui/_content/opengroup.html | 5 +- .../ui/_i18n/LocalStrings_de.properties | 1 + .../ui/_i18n/LocalStrings_en.properties | 17 +--- .../ui/_i18n/LocalStrings_fr.properties | 17 +--- 6 files changed, 93 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/olat/core/servlets/HeadersFilter.java b/src/main/java/org/olat/core/servlets/HeadersFilter.java index 413a22b4805..b0df9635b57 100644 --- a/src/main/java/org/olat/core/servlets/HeadersFilter.java +++ b/src/main/java/org/olat/core/servlets/HeadersFilter.java @@ -31,6 +31,7 @@ import org.olat.modules.card2brain.Card2BrainModule; import org.olat.modules.edubase.EdubaseModule; import org.olat.modules.edusharing.EdusharingModule; import org.olat.modules.openmeetings.OpenMeetingsModule; +import org.olat.modules.vitero.ViteroModule; import org.springframework.beans.factory.annotation.Autowired; /** @@ -45,6 +46,8 @@ public class HeadersFilter implements Filter { @Autowired private CSPModule securityModule; @Autowired + private ViteroModule viteroModule; + @Autowired private EdubaseModule edubaseModule; @Autowired private AnalyticsModule analyticsModule; @@ -69,7 +72,8 @@ public class HeadersFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if(securityModule == null || edubaseModule != null || analyticsModule != null || card2BrainModule != null - || openMeetingsModule != null|| edusharingModule != null) { + || openMeetingsModule != null|| edusharingModule != null + || viteroModule != null) { CoreSpringFactory.autowireObject(this); } addSecurityHeaders(response); @@ -214,6 +218,7 @@ public class HeadersFilter implements Filter { appendCard2BrainUrl(sb); appendEdubaseUrl(sb); appendEdusharingUrl(sb); + appendViteroUrl(sb); sb.append(";"); } @@ -277,6 +282,12 @@ public class HeadersFilter implements Filter { } } + private void appendViteroUrl(StringBuilder sb) { + if(viteroModule != null && viteroModule.isEnabled()) { + appendUrl(sb, viteroModule.getVmsURI().toString()); + } + } + private void appendUrl(StringBuilder sb, String urlString) { try { URL url = new URL(urlString); diff --git a/src/main/java/org/olat/modules/vitero/manager/ViteroManager.java b/src/main/java/org/olat/modules/vitero/manager/ViteroManager.java index 325e871d0d9..ada7c640250 100644 --- a/src/main/java/org/olat/modules/vitero/manager/ViteroManager.java +++ b/src/main/java/org/olat/modules/vitero/manager/ViteroManager.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.StringWriter; import java.math.BigInteger; import java.net.ConnectException; +import java.net.URI; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -156,6 +157,16 @@ public class ViteroManager implements UserDataDeletable { private static final String VMS_CATEGORY = "vitero-category"; private static final String VMS_CATEGORY_ZOMBIE = "vitero-category-zombie"; + // We cache the ports because of Apache CXF (not the JAX-WS) implementation + // see: http://cxf.apache.org/faq.html#FAQ%2DAreJAX%2DWSclientproxiesthreadsafe%3F + // and because we only use one credential ( one user to access the service + private Mtom mtomWebService; + private Group groupWebService; + private Booking bookingWebService; + private Licence licenseWebService; + private SessionCode sessionCodeWebService; + private de.vitero.schema.user.User userWebService; + @Autowired private ViteroModule viteroModule; @Autowired @@ -1266,7 +1277,7 @@ public class ViteroManager implements UserDataDeletable { public List<ViteroBooking> getBookings(BusinessGroup group, OLATResourceable ores, String subIdentifier) throws VmsNotAvailableException { List<Property> properties = propertyManager.listProperties(null, group, ores, VMS_CATEGORY, null); - List<ViteroBooking> bookings = new ArrayList<ViteroBooking>(); + List<ViteroBooking> bookings = new ArrayList<>(); for(Property property:properties) { String propIdentifier = property.getStringValue(); if((propIdentifier == null || subIdentifier == null) @@ -1347,8 +1358,7 @@ public class ViteroManager implements UserDataDeletable { try { Bookingid bookingId = new Bookingid(); bookingId.setBookingid(id); - Bookingtype booking = getBookingWebService().getBookingById(bookingId); - return booking; + return getBookingWebService().getBookingById(bookingId); } catch(SOAPFaultException f) { ErrorCode code = handleAxisFault(f); switch(code) { @@ -1438,15 +1448,15 @@ public class ViteroManager implements UserDataDeletable { try { LicenceService ss = new LicenceService(); ss.setHandlerResolver(new HandlerResolver() { - @SuppressWarnings("rawtypes") - @Override - public List<Handler> getHandlerChain(PortInfo portInfo) { - List<Handler> handlerList = new ArrayList<Handler>(); - handlerList.add(new ViteroSecurityHandler(login, password)); - return handlerList; - } - + @SuppressWarnings("rawtypes") + @Override + public List<Handler> getHandlerChain(PortInfo portInfo) { + List<Handler> handlerList = new ArrayList<>(); + handlerList.add(new ViteroSecurityHandler(login, password)); + return handlerList; + } }); + Licence port = ss.getLicenceSoap11(); String endPoint = UriBuilder.fromUri(url).path("services").path("LicenseService").build().toString(); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); @@ -1524,7 +1534,7 @@ public class ViteroManager implements UserDataDeletable { if(f.getMessage() != null) { if(sb.length() > 0) sb.append(" -> "); - sb.append(f.getMessage().toString()); + sb.append(f.getMessage()); } if(StringHelper.containsNonWhitespace(f.getMessage())) { @@ -1536,7 +1546,7 @@ public class ViteroManager implements UserDataDeletable { } private final List<ViteroBooking> convert(List<Booking_Type> bookings) { - List<ViteroBooking> viteroBookings = new ArrayList<ViteroBooking>(); + List<ViteroBooking> viteroBookings = new ArrayList<>(); if(bookings != null && bookings.size() > 0) { for(Booking_Type b:bookings) { @@ -1576,7 +1586,7 @@ public class ViteroManager implements UserDataDeletable { } private final List<ViteroUser> convertUsertype(List<Usertype> userTypes) { - List<ViteroUser> vUsers = new ArrayList<ViteroUser>(); + List<ViteroUser> vUsers = new ArrayList<>(); if(userTypes != null) { for(Usertype userType:userTypes) { vUsers.add(convert(userType)); @@ -1625,7 +1635,7 @@ public class ViteroManager implements UserDataDeletable { private final Property createProperty(final BusinessGroup group, final OLATResourceable courseResource, String subIdentifier, ViteroBooking booking) { String serialized = serializeViteroBooking(booking); String bookingId = Integer.toString(booking.getBookingId()); - Long groupId = new Long(booking.getGroupId()); + Long groupId = Long.valueOf(booking.getGroupId()); return propertyManager.createPropertyInstance(null, group, courseResource, VMS_CATEGORY, bookingId, null, groupId, subIdentifier, serialized); } @@ -1647,58 +1657,106 @@ public class ViteroManager implements UserDataDeletable { //Factories for service stubs private final Booking getBookingWebService() { + if(bookingWebService != null && endPointMatch((BindingProvider)bookingWebService)) { + return bookingWebService; + } + BookingService ss = new BookingService(); ss.setHandlerResolver(new VmsSecurityHandlerResolver()); Booking port = ss.getBookingSoap11(); String endPoint = getVmsEndPoint("BookingService"); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); + bookingWebService = port; return port; } private final Licence getLicenceWebService() { + if(licenseWebService != null && endPointMatch((BindingProvider)licenseWebService)) { + return licenseWebService; + } + LicenceService ss = new LicenceService(); ss.setHandlerResolver(new VmsSecurityHandlerResolver()); Licence port = ss.getLicenceSoap11(); String endPoint = getVmsEndPoint("LicenceService"); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); + licenseWebService = port; return port; } + + private final Group getGroupWebService() { + if(groupWebService != null && endPointMatch((BindingProvider)groupWebService)) { + return groupWebService; + } + GroupService ss = new GroupService(); ss.setHandlerResolver(new VmsSecurityHandlerResolver()); Group port = ss.getGroupSoap11(); String endPoint = getVmsEndPoint("GroupService"); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); + groupWebService = port; return port; } private final de.vitero.schema.user.User getUserWebService() { + if(userWebService != null && endPointMatch((BindingProvider)userWebService)) { + return userWebService; + } + UserService ss = new UserService(); ss.setHandlerResolver(new VmsSecurityHandlerResolver()); de.vitero.schema.user.User port = ss.getUserSoap11(); String endPoint = getVmsEndPoint("UserService"); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); + userWebService = port; return port; } private final Mtom getMtomWebService() { + if(mtomWebService != null && endPointMatch((BindingProvider)mtomWebService)) { + return mtomWebService; + } + MtomService ss = new MtomService(); ss.setHandlerResolver(new VmsSecurityHandlerResolver()); Mtom port = ss.getMtomSoap11(); String endPoint = getVmsEndPoint("MtomService"); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); + mtomWebService = port; return port; } + private final SessionCode getSessionCodeWebService() { + if(sessionCodeWebService != null && endPointMatch((BindingProvider)sessionCodeWebService)) { + return sessionCodeWebService; + } + + String endPoint = getVmsEndPoint("SessionCodeService"); SessionCodeService ss = new SessionCodeService(); ss.setHandlerResolver(new VmsSecurityHandlerResolver()); SessionCode port = ss.getSessionCodeSoap11(); - String endPoint = getVmsEndPoint("SessionCodeService"); ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint); + sessionCodeWebService = port; return port; } + + /** + * + * @param webservice The proxy to check + * @return true if the proxy use the host configured in the module + */ + private boolean endPointMatch(BindingProvider webservice) { + Object endPoint = webservice.getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY); + if(endPoint instanceof String) { + URI configuredUri = viteroModule.getVmsURI(); + URI endpointUri = URI.create((String)endPoint); + return endpointUri.getHost().equals(configuredUri.getHost()); + } + return false; + } private final String getVmsEndPoint(String service) { UriBuilder builder = UriBuilder.fromUri(viteroModule.getVmsURI()); @@ -1742,7 +1800,7 @@ public class ViteroManager implements UserDataDeletable { @SuppressWarnings("rawtypes") @Override public List<Handler> getHandlerChain(PortInfo portInfo) { - List<Handler> handlerList = new ArrayList<Handler>(); + List<Handler> handlerList = new ArrayList<>(); handlerList.add(new ViteroSecurityHandler(viteroModule.getAdminLogin(), viteroModule.getAdminPassword())); return handlerList; } diff --git a/src/main/java/org/olat/modules/vitero/ui/_content/opengroup.html b/src/main/java/org/olat/modules/vitero/ui/_content/opengroup.html index 3e4e2006582..427f0e20ead 100644 --- a/src/main/java/org/olat/modules/vitero/ui/_content/opengroup.html +++ b/src/main/java/org/olat/modules/vitero/ui/_content/opengroup.html @@ -1,3 +1,4 @@ <div> - <iframe class=vitero_iframe src="$groupUrl"></iframe> -</div> \ No newline at end of file + <iframe class="vitero_iframe" src="$groupUrl"></iframe> +</div> +<div><a href="$groupUrl" target="_blanck"><i class="o_icon o_icon_content_popup"> </i> $r.translate("booking.group.alternate.url")</a></div> \ No newline at end of file diff --git a/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_de.properties index 7f113eb57c5..6ace4436088 100644 --- a/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_de.properties @@ -37,6 +37,7 @@ booking.beginBuffer=Zeitpuffer vor Terminbeginn booking.end=Ende booking.endBuffer=Zeitpuffer nach Terminende booking.group=Datei Browser +booking.group.alternate.url=Benutzen Sie dieser Link wenn der Dateibrowser nicht richtig angezeigt wird. booking.group.warning=Sie m\u00FCssen Teilnehmer dieses Meetings sein um Zugriff auf diese Dateien zu erhalten. booking.group.open=\u00D6ffnen booking.resource=Ressourcenname diff --git a/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_en.properties index 42fb1d920e5..f112437efa1 100644 --- a/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_en.properties @@ -8,6 +8,7 @@ booking.begin=Start booking.beginBuffer=Start buffer (minutes) booking.end=End booking.endBuffer=End buffer (minutes) +booking.group.alternate.url=Use this link if the file browser doesn't appears correctly. booking.group=File browser booking.group.open=Open booking.group.warning=You need to be a participant of this group in order to open the file browser. @@ -25,21 +26,6 @@ check.ok=The server connection and configuration test was successful. You can no check.users=Validate user check.users.nok=Validation fixed {2} problem. check.users.ok=Validation did not detect any problem - - - - - - - - - - - - - - - delete.confirm=Do you really want to delete the meeting? The meeting will also be removed on the vitero server and can not be restored. delete.nok=The meeting could not be deleted for unknown reasons. Please try again later or contact the administrator. delete.ok=The meeting has successfuly been deleted. @@ -69,7 +55,6 @@ group.id=Group identifyer group.name=Title group.numOfParticipants=Booked seats group.open=File browser - new=Create meeting new.booking.warning=The meeting settings are final and can not be modified later\! option.adminlogin=Web service user name diff --git a/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_fr.properties index 0f4ac2f950d..883a9decf60 100644 --- a/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/modules/vitero/ui/_i18n/LocalStrings_fr.properties @@ -8,6 +8,7 @@ booking.begin=D\u00E9but booking.beginBuffer=Buffer de d\u00E9but (minutes) booking.end=Fin booking.endBuffer=Buffer de fin (minutes) +booking.group.alternate.url=Utilisez ce lien si le navigateur de fichiers n'appara\u00EEt pas correctement. booking.group=Navigateur de fichiers booking.group.open=Ouvrir booking.group.warning=Vous devez \u00EAtre un participant de cette r\u00E9union pour avoir acc\u00E8s aux documents qu'elle contient. @@ -25,21 +26,6 @@ check.ok=Le test de la connection a \u00E9t\u00E9 couronn\u00E9 de succ\u00E8s. check.users=Contr\u00F4ler les utilisateurs check.users.nok=Le contr\u00F4le des utilisateurs a r\u00E9solu {0} probl\u00E8mes. check.users.ok=Le contr\u00F4le des utilisateurs n'a pas trouv\u00E9 de probl\u00E8mes. - - - - - - - - - - - - - - - delete.confirm=Voulez-vous vraiment supprimer ce rendez-vous? Le rendez-vous sera supprim\u00E9 du syst\u00E8me vitero et ne pourra \u00EAtre restaur\u00E9. delete.nok=Le rendez-vous n'a pas pu \u00EAtre supprim\u00E9 pour des raisons ind\u00E9termin\u00E9es. Essayez un peu plus tard ou contactez un administrateur. delete.ok=Le rendez-vous a \u00E9t\u00E9 supprim\u00E9 avec succ\u00E8s. @@ -69,7 +55,6 @@ group.id=Identification du groupe group.name=Titre group.numOfParticipants=Nombre de participants group.open=Navigateur de documents - new=Cr\u00E9er un rendez-vous new.booking.warning=Les donn\u00E9es ne peuvent plus \u00EAtre chang\u00E9es\! option.adminlogin=Nom d'utilisateur du Web Service -- GitLab