Compare commits

...

70 Commits

Author SHA1 Message Date
Paulo Gustavo Veiga 1c73a8d79d Fix exception handling on JSP 2023-11-20 19:56:28 -08:00
Paulo Gustavo Veiga 68c8f5c6b8 Add @Transactional to controller. 2023-11-20 19:47:53 -08:00
Paulo Gustavo Veiga d26b516eb9 Clean up. 2023-11-20 19:44:59 -08:00
Paulo Gustavo Veiga 538083ae83 Add transction 2023-11-20 19:37:08 -08:00
Paulo Gustavo Veiga 60923e4c8b Improve error log. 2023-11-20 19:26:08 -08:00
Paulo Gustavo Veiga 214e3938c1 Add JSP comments. 2023-11-20 19:19:57 -08:00
Paulo Gustavo Veiga f49ae37866 Add exception details in JSP. 2023-11-20 19:14:01 -08:00
Paulo Gustavo Veiga ad158e4821 Fix parameter injection. 2023-11-20 18:57:50 -08:00
Paulo Gustavo Veiga 769968376b Add log verbosity. 2023-11-20 08:00:09 -08:00
Paulo Gustavo Veiga 9668823c31 Fix missing URLs. 2023-11-20 07:41:51 -08:00
Paulo Gustavo Veiga 55c104cfbe fix lazy initialization error. 2023-11-20 07:27:56 -08:00
Paulo Gustavo Veiga 92edef9bd6 Minor variable rename. 2023-11-19 20:28:27 -08:00
Paulo Gustavo Veiga 884a93478b Fix been lazy loading issue. 2023-11-19 20:22:05 -08:00
Paulo Gustavo Veiga 63975464ca Add enable_lazy_load_no_trans fix. 2023-11-19 19:11:06 -08:00
Paulo Gustavo Veiga 2b918a0df3 Move collaborations to header to prevent aused by org.hibernate.LazyInitializationException: could not initialize proxy [com.wisemapping.model.Collaborator#758998] - no Session error 2023-11-19 18:55:16 -08:00
Paulo Gustavo Veiga 9c1320b63b Fix logger path location. 2023-11-19 15:59:43 -08:00
Paulo Gustavo Veiga 1589665633 Move log4j2-stdout.xml 2023-11-19 15:56:59 -08:00
Paulo Gustavo Veiga 479eb6db2c Refactor beens loading. 2023-11-19 15:40:16 -08:00
Paulo Gustavo Veiga a739bb3e0b Move more services out of XML definition. 2023-11-19 08:28:40 -08:00
Paulo Gustavo Veiga 50e4a68d28 More classes to annotation. 2023-11-19 08:05:38 -08:00
Paulo Gustavo Veiga 8ec7c4edea Move couple of classes to services
Improve label security.
2023-11-19 07:57:23 -08:00
Paulo Gustavo Veiga 480fd49fd0 Keep transaction simplication 2023-11-19 00:31:41 -08:00
Paulo Gustavo Veiga 61c691fc82 Fix creation. 2023-11-18 23:45:31 -08:00
Paulo Gustavo Veiga 3eaeb8f500 Fix new user creation. 2023-11-18 23:30:06 -08:00
Paulo Gustavo Veiga 07e8259417 WIP 2023-11-18 23:22:25 -08:00
Paulo Gustavo Veiga ab15fb2d36 Fix lock message. 2023-11-15 20:45:15 -08:00
Paulo Veiga 315267e68c Migrate to hibernate 6 2023-10-30 05:34:45 +00:00
Paulo Veiga 881a16b908 messages_ru.properties edited online with Bitbucket 2023-10-09 23:39:25 +00:00
Paulo Veiga dd8f5ab1ea README.md edited online with Bitbucket 2023-10-07 17:55:06 +00:00
Paulo Veiga 0c37ed904a license.md edited online with Bitbucket 2023-10-07 17:51:04 +00:00
Paulo Gustavo Veiga 946ef517d3 Merge branch 'develop' of bitbucket.org:wisemapping/wisemapping-open-source into develop 2023-10-07 10:44:57 -07:00
Paulo Gustavo Veiga 5116a18952 Add database configuration. 2023-10-07 10:44:12 -07:00
Paulo Veiga 3467114a8a README.md edited online with Bitbucket 2023-10-07 17:11:11 +00:00
Paulo Gustavo Veiga cda97891ba Change format. 2023-10-07 10:07:26 -07:00
Paulo Gustavo Veiga 675802dab7 Remove public and try from index. 2023-08-29 20:14:14 -07:00
Paulo Gustavo Veiga 8b72f75b56 Bump up UI version. 2023-08-28 08:45:35 -07:00
Paulo Gustavo Veiga e85a670695 Fix embedded view issue. 2023-08-23 08:15:39 -07:00
Paulo Gustavo Veiga 28dc77c501 Bump mail version. 2023-08-16 20:17:29 -07:00
Paulo Gustavo Veiga c4ae51b50e Add missing dependency. 2023-08-16 19:35:56 -07:00
Paulo Gustavo Veiga 9912897879 Revert "Add mail provider."
This reverts commit 8d3983fd08.
2023-08-16 19:32:17 -07:00
Paulo Gustavo Veiga 8d3983fd08 Add mail provider. 2023-08-16 19:24:16 -07:00
Paulo Gustavo Veiga 169c6e6538 Improve security filters 2023-08-12 18:57:13 -07:00
Paulo Gustavo Veiga 4bb2960716 Increase default_batch_fetch_size 2023-08-11 18:28:50 -07:00
Paulo Gustavo Veiga 70c0b0c532 Update mysql driver. 2023-08-11 18:18:40 -07:00
Paulo Gustavo Veiga 0b96026507 Update tomcat version to 10.1.11-jdk17 2023-08-11 18:08:47 -07:00
Paulo Gustavo Veiga 87712b2493 Fix public map access. 2023-08-10 23:18:59 -07:00
Paulo Gustavo Veiga c783feef65 Add flavicon on auth exclusion. 2023-08-10 22:46:48 -07:00
Paulo Gustavo Veiga ea12d0246c Revert pipeline changes. 2023-08-10 22:30:54 -07:00
Paulo Gustavo Veiga 4f94d7117a Update pipeline docker image. 2023-08-10 21:57:27 -07:00
Paulo Gustavo Veiga abcd0d8515 Add spring messages. 2023-08-10 21:42:03 -07:00
Paulo Gustavo Veiga 1742b268a9 Fix log level on docker image. 2023-08-10 21:34:11 -07:00
Paulo Gustavo Veiga aaa8d5f0f3 Update tomcat version. 2023-08-10 21:27:37 -07:00
Paulo Gustavo Veiga 553688b070 Refactor variable properties. 2023-08-06 21:57:26 -07:00
Paulo Gustavo Veiga d2788ae00e Fix logger 2023-08-06 21:51:07 -07:00
Paulo Gustavo Veiga d4840b9c20 Fix logger 2023-08-06 21:48:10 -07:00
Paulo Gustavo Veiga b8601d7029 Fix typo 2023-08-06 20:35:42 -07:00
Paulo Gustavo Veiga 86682ca7d8 Fix base closing tag. 2023-08-06 20:02:30 -07:00
Paulo Gustavo Veiga 762ebabe7e Define plugin version. 2023-08-06 17:34:27 -07:00
Paulo Gustavo Veiga 30b2e7e8eb Define compiler version. 2023-08-06 17:31:35 -07:00
Paulo Gustavo Veiga 5844663701 Merge branch 'develop' of bitbucket.org:wisemapping/wisemapping-open-source into develop 2023-08-01 22:17:15 -07:00
Paulo Gustavo Veiga 734ec3df67 Bump version. 2023-07-31 21:31:56 -07:00
Paulo Gustavo Veiga 40afd70780 Update to jslt 3.0.1 2023-07-31 21:08:56 -07:00
Paulo Gustavo Veiga 4ebef65728 Fix hibernate warning 2023-07-30 22:50:04 -07:00
Paulo Gustavo Veiga e55e7e8867 Remove Tiles !!!! 2023-07-30 22:34:31 -07:00
Paulo Gustavo Veiga 1340fff68a Move error page to react. 2023-07-30 22:31:24 -07:00
Paulo Gustavo Veiga 68aa7c20eb Fix java 17 migration warnings 2023-07-30 20:12:11 -07:00
Paulo Gustavo Veiga 963ed70d8d Fix failing tests. 2023-07-30 18:21:25 -07:00
Paulo Gustavo Veiga 0090464d88 Update to java 17 2023-07-30 18:04:45 -07:00
Paulo Gustavo Veiga 53173ec75d Fix test execution 2023-07-28 23:09:44 -07:00
Paulo Gustavo Veiga a66dff8ae4 Migrate authentication to beans. 2023-07-28 22:46:38 -07:00
59 changed files with 772 additions and 807 deletions

15
LICENSE.md Normal file
View File

@ -0,0 +1,15 @@
# WiseMapping Public License Version 1.0 (WPL)
WiseMapping open source edition is licensed under the WiseMapping Public License Version 1.0. It is basically Apache License Version 2.0 plus the "powered by wisemapping" text requirement on every single page (the "License") unless we authorize you to remove it.
The WiseMapping Public License Version 1.0 ("WPL") consists of the [APACHE LICENSE, VERSION 2.0](http://www.apache.org/licenses/LICENSE-2.0), modified to be specific to WiseMapping, with the Additional Terms in Exhibit B.
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.
## EXHIBIT B - WiseMapping Public License.
Additional Terms applicable to the WiseMapping Public License.
I. Effect.
These additional terms described in this wiseMapping Public License - Additional Terms shall apply to the Covered Code under this License.
II. WiseMapping and "powered by WiseMapping" text.
This License does not grant any rights to use the trademarks "WiseMapping" even if such marks are included in the Original Code or Modifications.
However, in addition to the other notice obligations, unless wisemapping founders authorize you by email not to do it, (1) all copies of the Original Code in Executable and Source Code form must, as a form of attribution of the original author, include on each user interface screen (i) the "powered by WiseMapping" text; and (2) all derivative works and copies of derivative works of the Covered Code in Executable and Source Code form must include on each user interface screen (i) the "powered by WiseMapping" text. In addition, the "powered by WiseMapping" text, as appropriate, must be visible to all users, must appear in each user interface screen, and must be in the same position. When users click on the "powered by WiseMapping" text it must direct them to http://www.wisemapping.com. This obligation shall also apply to any copies or derivative works which are distributed under the alternative terms of Section 3.6 and this obligation must be included in any such license

View File

@ -96,5 +96,5 @@ After credential was created, Google will show you the clientId and clientSecret
## License
The source code is Licensed under the WiseMapping Open License, Version 1.0 (the “License”);
You may obtain a copy of the License at: [https://wisemapping.atlassian.net/wiki/display/WS/License]
You may obtain a copy of the License at: [https://bitbucket.org/wisemapping/wisemapping-open-source/src/develop/license.md](https://bitbucket.org/wisemapping/wisemapping-open-source/src/develop/LICENSE.md)

View File

@ -20,7 +20,7 @@ pipelines:
# Compile sources ...
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.36.0/install.sh | bash
- . $HOME/.nvm/nvm.sh && nvm install node
- mvn -B verify --file pom.xml
- mvn clean install --file pom.xml -DskipTests
# Publish to docker repo ...
- docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD
- docker build -t wisemapping/wisemapping:latest -f distribution/Dockerfile wise-webapp/target/

45
config/README.md Normal file
View File

@ -0,0 +1,45 @@
# Database Configuration
## Overview
WiseMapping supports a wide variety of databases. However, we run intensively tests over HSQL and MySQL database.
* HyperSQL: Automatically configured when you compile WiseMapping and It's used primarily for testing. Additionally, the binary distribution already has an instance configured to provide a single click installation.
* MySQL: This version is the most tested database we support. MySQL is the database use in http://www.wisemapping.com and it's the suggested version for production environments.
* PostgreSQL: Scripts are distributed for the creation and configuration of the it. You will find them within "config/postgres" directory in the binary distribution. Additionally, JDBC driver need to be added to the container.
* Others: In spite of the fact that we don't provide yet initialization scripts for others databases, WiseMapping can be deployed in any relational database. Please, contact us if you have any particular question on this area.
* In the following section, you are going to find a detailed explanation how to configure you WiseMapping using MySQL 5.5.
## MySQL Installation
### Prerequisites
* Download and install MySQL. You can download it for free from: http://dev.mysql.com/downloads/
Running SQL Scripts
Inside the WiseMapping binary distribution, you will find a directory "config/mysql". It contains all the SQL script required to configure a new WiseMapping database instance.
You will find 4 scripts:
* create-database.sql: Create all wisemapping database and wisemapping user.
* create-schemas.sql: Create all database tables and index.
* apopulate-schemas.sql: Creates a mind map example and an a test user "test@wisemapping.org" with password "test".
* drop-schemas.sql: Drop all wisemapping tables in case you want to have a fresh installation.
There are a lot of good tools you can use to run this scripts (eg: MySQLWorkbench). However, the simples way is to use the command line tool that is distributed as part of the MySQL installation.
If you are one brave hearts that is not afraid of the command line tools, open a terminar and execute the following lines:
~~~~
cd <WISEMAPPING-DIR>/config/database/mysql
# Default MySQL installation creates a "root" user with empty password. You can connect to the database with this user if you are # logged in same machine where the database is installed and must be executed logged as "root"
#
# If you have changed the default database "root" password , you need to specify an additional -p parameter and provide the
# new password.
mysql -uroot < create-database.sql
# Create tables and default tests user
mysql -uwisemapping -Dwisemapping -ppassword < create-schemas.sql
mysql -uwisemapping -Dwisemapping -ppassword < apopulate-schemas.sql
~~~~
Great, you have configured you database !. Let's configure WiseMapping now.

View File

@ -21,7 +21,7 @@ RUN cd ${WEBAPP_TARGET_DIR} && jar -xvf /tmp/wisemapping.war
RUN rm /tmp/wisemapping.war
# Change logger to
RUN cp ${WEBAPP_TARGET_DIR}/WEB-INF/classes/log4j-stdout.xml ${WEBAPP_TARGET_DIR}/WEB-INF/classes/log4j.xml
RUN cp ${WEBAPP_TARGET_DIR}/WEB-INF/log4j2-stdout.xml ${WEBAPP_TARGET_DIR}/WEB-INF/classes/log4j2.xml
# Add support for proxy
RUN sed -i 's|\

View File

@ -1,15 +0,0 @@
Copyright [2014] [wisemapping]
Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
"powered by wisemapping" text requirement on every single page;
you may not use this file except in compliance with the License.
You may obtain a copy of the license at
http://www.wisemapping.org/license
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.

View File

@ -46,6 +46,11 @@
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>

View File

@ -29,11 +29,11 @@
<mkdir dir="target/wisemapping-mindplot"/>
<exec executable="npm" dir="target" failonerror="true">
<arg value="pack"/>
<arg value="@wisemapping/mindplot@5.1.1"/>
<arg value="@wisemapping/mindplot@5.1.2"/>
</exec>
<exec executable="tar" dir="target" failonerror="true">
<arg value="-xvzf"/>
<arg value="wisemapping-mindplot-5.1.1.tgz"/>
<arg value="wisemapping-mindplot-5.1.2.tgz"/>
<arg value="-C"/>
<arg value="wisemapping-mindplot"/>
</exec>
@ -42,11 +42,11 @@
<mkdir dir="target/wisemapping-webapp"/>
<exec executable="npm" dir="target" failonerror="true">
<arg value="pack"/>
<arg value="@wisemapping/webapp@5.1.1"/>
<arg value="@wisemapping/webapp@5.1.2"/>
</exec>
<exec executable="tar" dir="target" failonerror="true">
<arg value="-xvzf"/>
<arg value="wisemapping-webapp-5.1.1.tgz"/>
<arg value="wisemapping-webapp-5.1.2.tgz"/>
<arg value="-C"/>
<arg value="wisemapping-webapp"/>
</exec>

View File

@ -13,10 +13,8 @@
</parent>
<properties>
<org.springframework.version>6.0.10</org.springframework.version>
<org.springframework.addons>6.1.1</org.springframework.addons>
<hibernate.version>6.2.6.Final</hibernate.version>
<hibernate-validator.version>6.0.21.Final</hibernate-validator.version>
<org.springframework.version>6.0.14</org.springframework.version>
<org.springframework.addons>6.1.5</org.springframework.addons>
<spring-security-taglibs.version>6.0.2</spring-security-taglibs.version>
</properties>
@ -51,6 +49,16 @@
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
@ -76,8 +84,14 @@
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core-jakarta</artifactId>
<version>5.6.15.Final</version>
<artifactId>hibernate-core</artifactId>
<version>6.1.7.Final</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- Hibernate Validator -->
@ -120,12 +134,12 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.6.1</version>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.15</version>
<version>6.0.6</version>
<scope>test</scope>
</dependency>
@ -133,7 +147,6 @@
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
@ -165,26 +178,20 @@
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
<scope>runtime</scope>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.hibernate</groupId>-->
<!-- <artifactId>hibernate-ehcache</artifactId>-->
<!-- <version>5.6.15.Final</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>javax.cache</groupId>-->
<!-- <artifactId>cache-api</artifactId>-->
<!-- <version>1.1.1</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>jakarta.mail</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
@ -348,27 +355,6 @@
</profiles>
<build>
<plugins>
<!-- <plugin>-->
<!-- <groupId>org.hibernate.orm.tooling</groupId>-->
<!-- <artifactId>hibernate-enhance-maven-plugin</artifactId>-->
<!-- <version>${hibernate.version}</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <phase>compile</phase>-->
<!-- <configuration>-->
<!-- <failOnError>true</failOnError>-->
<!-- <enableLazyInitialization>true</enableLazyInitialization>-->
<!-- <enableDirtyTracking>true</enableDirtyTracking>-->
<!-- <enableAssociationManagement>true</enableAssociationManagement>-->
<!-- <enableExtendedEnhancement>false</enableExtendedEnhancement>-->
<!-- <enableExtendedEnhancement>false</enableExtendedEnhancement>-->
<!-- </configuration>-->
<!-- <goals>-->
<!-- <goal>enhance</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>

View File

@ -1,9 +1,12 @@
package com.wisemapping.config;
import com.wisemapping.exceptions.AccessDeniedSecurityException;
import com.wisemapping.exceptions.MapNotPublicSecurityException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@ -11,11 +14,15 @@ import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import java.util.Properties;
@EnableWebMvc
@Configuration
public class AppConfig {
@EnableTransactionManagement
@ComponentScan
@ImportResource("classpath:spring/wisemapping-common.xml")
public class Application {
@Autowired
TransactionManager txManager;
@Bean
HandlerExceptionResolver errorHandler() {

View File

@ -0,0 +1,34 @@
package com.wisemapping.config;
import com.wisemapping.security.MapAccessPermissionEvaluation;
import com.wisemapping.security.ReadSecurityAdvise;
import com.wisemapping.security.UpdateSecurityAdvise;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@Configuration
@EnableMethodSecurity(
securedEnabled = true,
jsr250Enabled = true)
public class MethodSecurityConfig {
@Autowired
private ReadSecurityAdvise readAdvice;
@Autowired
private UpdateSecurityAdvise updateAdvice;
@Bean
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
final MapAccessPermissionEvaluation permissionEvaluator = new MapAccessPermissionEvaluation(readAdvice, updateAdvice);
expressionHandler.setPermissionEvaluator(permissionEvaluator);
return expressionHandler;
}
}

View File

@ -34,6 +34,22 @@ public class SecurityConfig {
firewall.setAllowSemicolon(true);
return firewall;
}
@Bean
@Order(1)
public SecurityFilterChain embeddedDisabledXOrigin(@NotNull final HttpSecurity http, @NotNull final HandlerMappingIntrospector introspector) throws Exception {
final MvcRequestMatcher.Builder mvcMatcher = new MvcRequestMatcher.Builder(introspector).servletPath("/c");
http
.securityMatchers((matchers) ->
matchers.requestMatchers(mvcMatcher.pattern(("/maps/*/embed"))))
.authorizeHttpRequests(
(auth) -> auth.requestMatchers(mvcMatcher.pattern("/maps/*/embed")).permitAll())
.headers((header -> header.frameOptions()
.disable()
))
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
@Bean
@Order(2)
@ -44,13 +60,12 @@ public class SecurityConfig {
matchers.requestMatchers(serviceMapper.pattern(("/**"))))
.authorizeHttpRequests(auth ->
auth
.requestMatchers("/users/").permitAll()
.requestMatchers("/users/resetPassword").permitAll()
.requestMatchers("/oauth2/googlecallback").permitAll()
.requestMatchers("/oauth2/confirmaccountsync").permitAll()
.requestMatchers("/admin/**").hasAnyRole("ADMIN")
.requestMatchers("/**").hasAnyRole("USER", "ADMIN")
.requestMatchers(serviceMapper.pattern("/users/")).permitAll()
.requestMatchers(serviceMapper.pattern("/users/resetPassword")).permitAll()
.requestMatchers(serviceMapper.pattern("/oauth2/googlecallback")).permitAll()
.requestMatchers(serviceMapper.pattern("/oauth2/confirmaccountsync")).permitAll()
.requestMatchers(serviceMapper.pattern("/admin/**")).hasAnyRole("ADMIN")
.requestMatchers(serviceMapper.pattern("/**")).hasAnyRole("USER", "ADMIN")
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.httpBasic(httpBasic -> {
@ -60,7 +75,7 @@ public class SecurityConfig {
}
@Bean
@Order(1)
@Order(3)
public SecurityFilterChain mvcFilterChain(@NotNull final HttpSecurity http, @NotNull final HandlerMappingIntrospector introspector) throws Exception {
final AuthenticationSuccessHandler authenticationSuccessHandler = new AuthenticationSuccessHandler();
authenticationSuccessHandler.setAlwaysUseDefaultTargetUrl(false);
@ -76,12 +91,20 @@ public class SecurityConfig {
.authorizeHttpRequests(
(auth) ->
auth
.requestMatchers("/login", "logout").permitAll()
.requestMatchers("/registration", "registration-success", "/registration-google").permitAll()
.requestMatchers("/forgot-password", "/forgot-password-success").permitAll()
.requestMatchers("/maps/*/embed", "/maps/*/try", "/maps/*/public").permitAll()
.requestMatchers("/restful/maps/*/document/xml-pub").permitAll()
.requestMatchers("/**").hasAnyRole("USER", "ADMIN")
.requestMatchers(mvcMatcher.pattern("/login")).permitAll()
.requestMatchers(mvcMatcher.pattern("/logout")).permitAll()
.requestMatchers(mvcMatcher.pattern("/registration")).permitAll()
.requestMatchers(mvcMatcher.pattern("/registration-success")).permitAll()
.requestMatchers(mvcMatcher.pattern("/registration-google")).permitAll()
.requestMatchers(mvcMatcher.pattern("/forgot-password")).permitAll()
.requestMatchers(mvcMatcher.pattern("/forgot-password-success")).permitAll()
.requestMatchers(mvcMatcher.pattern("/maps/*/try")).permitAll()
.requestMatchers(mvcMatcher.pattern("/maps/*/public")).permitAll()
.requestMatchers(restfullMapper.pattern("/maps/*/document/xml-pub")).permitAll()
.requestMatchers(mvcMatcher.pattern("/**")).hasAnyRole("USER", "ADMIN")
.requestMatchers(restfullMapper.pattern("/**")).hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated())
.formLogin((loginForm) ->
loginForm.loginPage("/c/login")
@ -100,22 +123,32 @@ public class SecurityConfig {
.tokenValiditySeconds(2419200)
.rememberMeParameter("remember-me"
).authenticationSuccessHandler(authenticationSuccessHandler)
)
).headers((header -> header.frameOptions()
.disable()
))
.csrf((csrf) ->
csrf.ignoringRequestMatchers("/logout"));
csrf.ignoringRequestMatchers(mvcMatcher.pattern("/logout")));
return http.build();
}
@Bean
@Order(3)
@Order(4)
public SecurityFilterChain shareResourcesFilterChain(@NotNull final HttpSecurity http, @NotNull final HandlerMappingIntrospector introspector) throws Exception {
final MvcRequestMatcher.Builder restfullMapper = new MvcRequestMatcher.Builder(introspector);
return http.authorizeHttpRequests(
(auth) ->
auth.requestMatchers("/static/**", "/css/**", "/js/**", "/images/**", "/").permitAll()
auth.requestMatchers(restfullMapper.pattern("/static/**")).permitAll().
requestMatchers(restfullMapper.pattern("/css/**")).permitAll().
requestMatchers(restfullMapper.pattern("/js/**")).permitAll().
requestMatchers(restfullMapper.pattern("/images/**")).permitAll().
requestMatchers(restfullMapper.pattern("/*")).permitAll()
).build();
}
@Bean
public UserDetailsService userDetailsService() {
final UserDetailsService result = new UserDetailsService();

View File

@ -19,14 +19,21 @@ package com.wisemapping.dao;
import com.wisemapping.model.Label;
import com.wisemapping.model.User;
import jakarta.annotation.Resource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.SelectionQuery;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import java.util.List;
public class LabelManagerImpl extends HibernateDaoSupport
@Repository("labelManager")
public class LabelManagerImpl
implements LabelManager {
@Resource
private SessionFactory sessionFactory;
@Override
public void addLabel(@NotNull final Label label) {
@ -35,31 +42,37 @@ public class LabelManagerImpl extends HibernateDaoSupport
@Override
public void saveLabel(@NotNull final Label label) {
currentSession().save(label);
getSession().persist(label);
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
@NotNull
@Override
@SuppressWarnings("unchecked")
public List<Label> getAllLabels(@NotNull final User user) {
var query = currentSession().createQuery("from com.wisemapping.model.Label wisemapping where creator_id=:creatorId");
query.setParameter("creatorId", user.getId());
final SelectionQuery<Label> query = getSession().createSelectionQuery("from com.wisemapping.model.Label wisemapping where creator=:creatorId", Label.class);
query.setParameter("creatorId", user);
return query.list();
}
@Nullable
@Override
public Label getLabelById(int id, @NotNull final User user) {
var query = currentSession().createQuery("from com.wisemapping.model.Label wisemapping where id=:id and creator=:creator");
final Session session = getSession();
final SelectionQuery<Label> query = session.createSelectionQuery("from com.wisemapping.model.Label wisemapping where id=:id and creator=:creator", Label.class);
query.setParameter("id", id);
query.setParameter("creator", user);
return getFirst(query.list());
final List<Label> resultList = query.getResultList();
return getFirst(resultList);
}
@Nullable
@Override
public Label getLabelByTitle(@NotNull String title, @NotNull final User user) {
var query = currentSession().createQuery("from com.wisemapping.model.Label wisemapping where title=:title and creator=:creator");
final SelectionQuery<Label> query = getSession().createSelectionQuery("from com.wisemapping.model.Label wisemapping where title=:title and creator=:creator", Label.class);
query.setParameter("title", title);
query.setParameter("creator", user);
return getFirst(query.list());
@ -67,10 +80,11 @@ public class LabelManagerImpl extends HibernateDaoSupport
@Override
public void removeLabel(@NotNull Label label) {
getHibernateTemplate().delete(label);
getSession().remove(label);
}
@Nullable private Label getFirst(List<Label> labels) {
@Nullable
private Label getFirst(final List<Label> labels) {
Label result = null;
if (labels != null && !labels.isEmpty()) {
result = labels.get(0);

View File

@ -50,17 +50,11 @@ public interface MindmapManager {
void removeCollaboration(Collaboration collaboration);
List<Mindmap> search(MindMapCriteria criteria);
List<Mindmap> search(MindMapCriteria criteria, int maxResult);
List<MindMapHistory> getHistoryFrom(int mindmapId);
MindMapHistory getHistory(int historyId);
void updateCollaboration(@NotNull Collaboration collaboration);
void purgeHistory(int mapId) throws IOException;
List<Mindmap> findMindmapByUser(User user);
}

View File

@ -19,30 +19,31 @@
package com.wisemapping.dao;
import com.wisemapping.model.*;
import com.wisemapping.util.ZipUtils;
import jakarta.persistence.Query;
import org.hibernate.Criteria;
import org.hibernate.criterion.Junction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.SimpleExpression;
import jakarta.annotation.Resource;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.SelectionQuery;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
@Repository("mindmapManager")
public class MindmapManagerImpl
extends HibernateDaoSupport
implements MindmapManager {
@Resource
private SessionFactory sessionFactory;
@Override
public Collaborator findCollaborator(@NotNull final String email) {
final Collaborator collaborator;
Query query = currentSession().createQuery("from com.wisemapping.model.Collaborator collaborator where email=:email");
final SelectionQuery<Collaborator> query = getSession().createSelectionQuery("from com.wisemapping.model.Collaborator collaborator where email=:email", Collaborator.class);
query.setParameter("email", email);
final List<Collaborator> collaborators = query.getResultList();
@ -55,137 +56,87 @@ public class MindmapManagerImpl
return collaborator;
}
@Override
public List<Mindmap> search(MindMapCriteria criteria) {
return search(criteria, -1);
private Session getSession() {
return sessionFactory.getCurrentSession();
}
@Override
public List<MindMapHistory> getHistoryFrom(int mindmapId) {
final Criteria hibernateCriteria = currentSession().createCriteria(MindMapHistory.class);
hibernateCriteria.add(Restrictions.eq("mindmapId", mindmapId));
hibernateCriteria.addOrder(Order.desc("creationTime"));
final Session session = getSession();
final CriteriaBuilder cb = session.getCriteriaBuilder();
// This line throws errors in some environments, so getting all history and taking firsts 10 records
hibernateCriteria.setMaxResults(30);
return hibernateCriteria.list();
final CriteriaQuery<MindMapHistory> cr = cb.createQuery(MindMapHistory.class);
final Root<MindMapHistory> root = cr.from(MindMapHistory.class);
final CriteriaQuery<MindMapHistory> select = cr.select(root)
.where(cb.equal(root.get("mindmapId"), mindmapId))
.orderBy(cb.desc(root.get("creationTime")));
return session.
createQuery(select)
.setMaxResults(30)
.getResultList();
}
@Override
public MindMapHistory getHistory(int historyId) {
return getHibernateTemplate().get(MindMapHistory.class, historyId);
final Session session = getSession();
return session.find(MindMapHistory.class, historyId);
}
@Override
public void updateCollaboration(@NotNull Collaboration collaboration) {
getHibernateTemplate().save(collaboration);
}
@Override
public void purgeHistory(int mapId) throws IOException {
final Criteria hibernateCriteria = currentSession().createCriteria(MindMapHistory.class);
hibernateCriteria.add(Restrictions.eq("mindmapId", mapId));
hibernateCriteria.addOrder(Order.desc("creationTime"));
final List<MindMapHistory> historyList = hibernateCriteria.list();
final Mindmap mindmap = this.getMindmapById(mapId);
if (mindmap != null) {
final Calendar yearAgo = Calendar.getInstance();
yearAgo.add(Calendar.MONTH, -12);
// If the map has not been modified in the last months, it means that I don't need to keep all the history ...
int max = mindmap.getLastModificationTime().before(yearAgo) ? 10 : 25;
final HibernateTemplate hibernateTemplate = getHibernateTemplate();
for (MindMapHistory history : historyList) {
byte[] zippedXml = history.getZippedXml();
if (new String(zippedXml).startsWith("<map")) {
history.setZippedXml(ZipUtils.bytesToZip(zippedXml));
hibernateTemplate.update(history);
}
}
if (historyList.size() > max) {
for (int i = max; i < historyList.size(); i++) {
hibernateTemplate.delete(historyList.get(i));
}
}
}
final Session session = getSession();
session.persist(collaboration);
}
@Override
public List<Mindmap> findMindmapByUser(@NotNull User user) {
final Mindmap collaborator;
final Query query = currentSession()
.createQuery("from com.wisemapping.model.Mindmap m where m.id in (select c.mindMap.id from com.wisemapping.model.Collaboration as c where c.collaborator.id=:collabId )");
final SelectionQuery<Mindmap> query = getSession()
.createSelectionQuery("from com.wisemapping.model.Mindmap m where m.id in (select c.mindMap.id from com.wisemapping.model.Collaboration as c where c.collaborator.id=:collabId )", Mindmap.class);
query.setParameter("collabId", user.getId());
return query.getResultList();
}
@Override
public List<Mindmap> search(MindMapCriteria criteria, int maxResult) {
final Criteria hibernateCriteria = currentSession().createCriteria(Mindmap.class);
//always search public maps
hibernateCriteria.add(Restrictions.like("public", Boolean.TRUE));
if (criteria != null) {
final Junction junction;
if (criteria.isOrCriteria()) {
junction = Restrictions.disjunction();
} else {
junction = Restrictions.conjunction();
}
if (criteria.getTitle() != null && criteria.getTitle().length() > 0) {
final SimpleExpression titleRestriction = Restrictions.like("title", "%" + criteria.getTitle() + "%");
junction.add(titleRestriction);
}
if (criteria.getDescription() != null && criteria.getDescription().length() > 0) {
final SimpleExpression descriptionRestriction = Restrictions.like("description", "%" + criteria.getDescription() + "%");
junction.add(descriptionRestriction);
}
hibernateCriteria.add(junction);
}
return hibernateCriteria.list();
}
@Override
public List<Collaboration> findCollaboration(final int collaboratorId) {
Query query = currentSession().createQuery("from com.wisemapping.model.Collaboration c where c.collaborator.id=:collaboratorId");
final SelectionQuery<Collaboration> query = getSession().createSelectionQuery("from com.wisemapping.model.Collaboration c where c.collaborator.id=:collaboratorId", Collaboration.class);
query.setParameter("collaboratorId", collaboratorId);
return query.getResultList();
}
@Override
public void addCollaborator(@NotNull Collaborator collaborator) {
final Session session = getSession();
assert collaborator != null : "ADD MINDMAP COLLABORATOR: Collaborator is required!";
getHibernateTemplate().save(collaborator);
session.persist(collaborator);
}
@Override
public void removeCollaboration(Collaboration collaboration) {
getHibernateTemplate().delete(collaboration);
final Session session = getSession();
session.remove(collaboration);
}
@Override
public void removeCollaborator(@NotNull Collaborator collaborator) {
getHibernateTemplate().delete(collaborator);
final Session session = getSession();
session.remove(collaborator);
}
@Override
@Nullable
public Mindmap getMindmapById(int id) {
return getHibernateTemplate().get(Mindmap.class, id);
final Session session = getSession();
return session.get(Mindmap.class, id);
}
@Override
public Mindmap getMindmapByTitle(final String title, final User user) {
final Mindmap result;
Query query = currentSession().createQuery("from com.wisemapping.model.Mindmap wisemapping where title=:title and creator=:creator");
final SelectionQuery<Mindmap> query = getSession().createSelectionQuery("from com.wisemapping.model.Mindmap wisemapping where title=:title and creator=:creator", Mindmap.class);
query.setParameter("title", title);
query.setParameter("creator", user);
@ -207,13 +158,13 @@ public class MindmapManagerImpl
@Override
public void saveMindmap(Mindmap mindMap) {
assert mindMap != null : "Save Mindmap: Mindmap is required!";
currentSession().save(mindMap);
getSession().persist(mindMap);
}
@Override
public void updateMindmap(@NotNull Mindmap mindMap, boolean saveHistory) {
assert mindMap != null : "Save Mindmap: Mindmap is required!";
getHibernateTemplate().saveOrUpdate(mindMap);
getSession().merge(mindMap);
if (saveHistory) {
saveHistory(mindMap);
}
@ -222,16 +173,20 @@ public class MindmapManagerImpl
@Override
public void removeMindmap(@NotNull final Mindmap mindmap) {
// Delete history first ...
final Criteria hibernateCriteria = currentSession().createCriteria(MindMapHistory.class);
hibernateCriteria.add(Restrictions.eq("mindmapId", mindmap.getId()));
final List list = hibernateCriteria.list();
getHibernateTemplate().deleteAll(list);
final Session session = getSession();
final CriteriaBuilder cb = session.getCriteriaBuilder();
final CriteriaDelete<MindMapHistory> cr = cb.createCriteriaDelete(MindMapHistory.class);
final Root<MindMapHistory> root = cr.from(MindMapHistory.class);
final CriteriaDelete<MindMapHistory> deleteStatement = cr.where(cb.equal(root.get("mindmapId"), mindmap.getId()));
session.createMutationQuery(deleteStatement).executeUpdate();
// Remove collaborations ...
mindmap.removedCollaboration(mindmap.getCollaborations());
// Delete mindmap ....
getHibernateTemplate().delete(mindmap);
getSession().remove(mindmap);
}
private void saveHistory(@NotNull final Mindmap mindMap) {
@ -241,6 +196,6 @@ public class MindmapManagerImpl
history.setCreationTime(Calendar.getInstance());
history.setEditor(mindMap.getLastEditor());
history.setMindmapId(mindMap.getId());
getHibernateTemplate().saveOrUpdate(history);
getSession().merge(history);
}
}

View File

@ -18,37 +18,43 @@
package com.wisemapping.dao;
import com.wisemapping.model.AccessAuditory;
import com.wisemapping.model.AuthenticationType;
import com.wisemapping.model.Collaboration;
import com.wisemapping.model.Collaborator;
import com.wisemapping.model.User;
import com.wisemapping.model.*;
import com.wisemapping.security.DefaultPasswordEncoderFactories;
import com.wisemapping.security.LegacyPasswordEncoder;
import jakarta.annotation.Resource;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.SelectionQuery;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
@Repository
public class UserManagerImpl
extends HibernateDaoSupport
implements UserManager {
@Autowired
private SessionFactory sessionFactory;
@Autowired
private PasswordEncoder passwordEncoder;
public void setEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@SuppressWarnings("unchecked")
public List<User> getAllUsers() {
return currentSession().createQuery("from com.wisemapping.model.User user").list();
return getSession().createSelectionQuery("from com.wisemapping.model.User user", User.class).getResultList();
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
@ -57,10 +63,10 @@ public class UserManagerImpl
public User getUserBy(@NotNull final String email) {
User user = null;
var query = currentSession().createQuery("from com.wisemapping.model.User colaborator where email=:email");
SelectionQuery<User> query = getSession().createSelectionQuery("from com.wisemapping.model.User colaborator where email=:email",User.class);
query.setParameter("email", email);
final List<User> users = query.list();
final List<User> users = query.getResultList();
if (users != null && !users.isEmpty()) {
assert users.size() == 1 : "More than one user with the same email!";
user = users.get(0);
@ -71,19 +77,20 @@ public class UserManagerImpl
@Override
public Collaborator getCollaboratorBy(final String email) {
final Collaborator cola;
var query = currentSession().createQuery("from com.wisemapping.model.Collaborator colaborator where " +
"email=:email");
final Collaborator result;
Session session = getSession();
final SelectionQuery<Collaborator> query = session.createSelectionQuery("from com.wisemapping.model.Collaborator colaborator where " +
"email=:email", Collaborator.class);
query.setParameter("email", email);
final List<User> cols = query.list();
final List<Collaborator> cols = query.getResultList();
if (cols != null && !cols.isEmpty()) {
assert cols.size() == 1 : "More than one colaborator with the same email!";
cola = cols.get(0);
result = cols.get(0);
} else {
cola = null;
result = null;
}
return cola;
return result;
}
@Nullable
@ -91,7 +98,7 @@ public class UserManagerImpl
public User getUserBy(int id) {
User user = null;
try {
user = getHibernateTemplate().get(User.class, id);
user = getSession().get(User.class, id);
} catch (ObjectNotFoundException e) {
// Ignore ...
}
@ -106,7 +113,7 @@ public class UserManagerImpl
} else {
user.setPassword("");
}
getHibernateTemplate().saveOrUpdate(user);
getSession().persist(user);
}
@Override
@ -114,10 +121,10 @@ public class UserManagerImpl
assert user != null : "Trying to store a null user";
// Migrate from previous temporal collab to new user ...
final HibernateTemplate template = getHibernateTemplate();
final Session session = getSession();
collaborator.setEmail(collaborator.getEmail() + "_toRemove");
template.saveOrUpdate(collaborator);
template.flush();
session.merge(collaborator);
session.flush();
// Save all new...
this.createUser(user);
@ -129,18 +136,18 @@ public class UserManagerImpl
}
// Delete old user ...
template.delete(collaborator);
session.remove(collaborator);
return user;
}
@Override
public void removeUser(@NotNull final User user) {
getHibernateTemplate().delete(user);
getSession().remove(user);
}
public void auditLogin(@NotNull AccessAuditory accessAuditory) {
assert accessAuditory != null : "accessAuditory is null";
getHibernateTemplate().save(accessAuditory);
getSession().persist(accessAuditory);
}
public void updateUser(@NotNull User user) {
@ -152,21 +159,21 @@ public class UserManagerImpl
user.setPassword(passwordEncoder.encode(user.getPassword()));
}
getHibernateTemplate().update(user);
getSession().merge(user);
}
public User getUserByActivationCode(long code) {
final User user;
var query = currentSession().createQuery("from com.wisemapping.model.User user where " +
"activationCode=:activationCode");
final SelectionQuery<User> query = getSession().createSelectionQuery("from com.wisemapping.model.User user where " +
"activationCode=:activationCode", User.class);
query.setParameter("activationCode", code);
final List users = query.list();
final List<User> users = query.getResultList();
if (users != null && !users.isEmpty()) {
assert users.size() == 1 : "More than one user with the same username!";
user = (User) users.get(0);
user = users.get(0);
} else {
user = null;
}

View File

@ -21,11 +21,14 @@ import com.wisemapping.exceptions.ClientException;
import com.wisemapping.exceptions.OAuthAuthenticationException;
import com.wisemapping.exceptions.Severity;
import com.wisemapping.exceptions.ValidationException;
import com.wisemapping.mail.NotificationService;
import com.wisemapping.model.User;
import com.wisemapping.rest.model.RestErrors;
import com.wisemapping.security.Utils;
import com.wisemapping.service.NotificationService;
import com.wisemapping.service.RegistrationException;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
@ -38,9 +41,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Locale;
@ -62,25 +62,27 @@ public class BaseController {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public RestErrors handleClientErrors(@NotNull IllegalArgumentException ex) {
logger.error(ex.getMessage(), ex);
return new RestErrors(ex.getMessage(), Severity.WARNING);
}
@ExceptionHandler(ValidationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public RestErrors handleValidationErrors(@NotNull ValidationException ex) {
logger.error(ex.getMessage(), ex);
return new RestErrors(ex.getErrors(), messageSource);
}
@ExceptionHandler(JsonHttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public RestErrors handleJSONErrors(@NotNull JsonHttpMessageNotReadableException ex) {
logger.error(ex.getMessage(), ex);
return new RestErrors("Communication error", Severity.SEVERE);
}
@ExceptionHandler(java.lang.reflect.UndeclaredThrowableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public RestErrors handleSecurityErrors(@NotNull UndeclaredThrowableException ex) {
logger.error(ex.getMessage(), ex);
final Throwable cause = ex.getCause();
RestErrors result;
if (cause instanceof ClientException) {
@ -107,6 +109,7 @@ public class BaseController {
// "error_description": "Bad Request"
//}, status: 400
//
logger.error(ex.getMessage(), ex);
response.setStatus(response.getStatus());
return ex;
}
@ -115,17 +118,16 @@ public class BaseController {
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public RestErrors handleServerErrors(@NotNull Exception ex, @NotNull HttpServletRequest request) {
logger.error(ex.getMessage(), ex);
final User user = Utils.getUser(false);
notificationService.reportJavaException(ex, user, request);
logger.error(ex);
return new RestErrors(ex.getMessage(), Severity.SEVERE);
}
@ExceptionHandler(RegistrationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public RestErrors handleRegistrationErrors(@NotNull RegistrationException exception) {
return new RestErrors(exception, messageSource);
public RestErrors handleRegistrationErrors(@NotNull RegistrationException ex) {
return new RestErrors(ex, messageSource);
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.rest;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class DebugMappingJacksonHttpMessageConverter extends MappingJackson2HttpMessageConverter {
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws JsonHttpMessageNotReadableException {
try {
final byte[] bytes = IOUtils.toByteArray(inputMessage.getBody());
final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
final WrapHttpInputMessage wrap = new WrapHttpInputMessage(bais, inputMessage.getHeaders());
return super.readInternal(clazz, wrap);
} catch (HttpMessageNotReadableException | IOException e) {
throw new JsonHttpMessageNotReadableException("Request Body could not be read", e);
}
}
}
class WrapHttpInputMessage implements HttpInputMessage {
private final InputStream body;
private final HttpHeaders headers;
WrapHttpInputMessage(InputStream is, HttpHeaders headers) {
this.body = is;
this.headers = headers;
}
@Override
public InputStream getBody() {
return body;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
}

View File

@ -35,6 +35,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@ -47,6 +49,7 @@ import java.util.stream.Collectors;
@Controller
@Transactional(propagation = Propagation.REQUIRED)
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
public class MindmapController extends BaseController {
final Logger logger = LogManager.getLogger();
@ -84,8 +87,7 @@ public class MindmapController extends BaseController {
List<Mindmap> mindmaps = mindmapService.findMindmapsByUser(user);
mindmaps = mindmaps
.stream()
.filter(m -> filter.accept(m, user))
.collect(Collectors.toUnmodifiableList());
.filter(m -> filter.accept(m, user)).toList();
return new RestMindmapList(mindmaps, user);
}
@ -148,6 +150,7 @@ public class MindmapController extends BaseController {
saveMindmapDocument(minor, mindmap, user);
}
@PreAuthorize("permitAll()")
@RequestMapping(method = RequestMethod.GET, value = {"/maps/{id}/document/xml", "/maps/{id}/document/xml-pub"}, consumes = {"text/plain"}, produces = {"application/xml; charset=UTF-8"})
@ResponseBody
public byte[] retrieveDocument(@PathVariable int id, @NotNull HttpServletResponse response) throws WiseMappingException, IOException {

View File

@ -0,0 +1,6 @@
package com.wisemapping.security;
public enum MapAccessPermission {
READ,
WRITE
}

View File

@ -0,0 +1,91 @@
package com.wisemapping.security;
import com.wisemapping.model.Collaborator;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import jakarta.validation.constraints.NotNull;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import java.io.Serializable;
public class MapAccessPermissionEvaluation implements PermissionEvaluator {
final private static Logger logger = LogManager.getLogger();
private MapPermissionsSecurityAdvice readAdvice;
private MapPermissionsSecurityAdvice updateAdvice;
public MapAccessPermissionEvaluation(final @NotNull MapPermissionsSecurityAdvice readAdvice, final @NotNull MapPermissionsSecurityAdvice updateAdvice) {
this.readAdvice = readAdvice;
this.updateAdvice = updateAdvice;
}
@Override
public boolean hasPermission(
@NotNull Authentication auth, @NotNull Object targetDomainObject, @NotNull Object permission) {
logger.log(Level.DEBUG, "auth: " + auth + ",targetDomainObject:" + targetDomainObject + ",permission:" + permission);
if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)) {
logger.debug("Permissions could not be validated, illegal parameters.");
return false;
}
boolean result;
final User user = Utils.getUser();
final MapAccessPermission perm = MapAccessPermission.valueOf((permission.toString().toUpperCase()));
if (targetDomainObject instanceof Integer) {
// Checking permissions by mapId ...
final int mapId = (Integer) targetDomainObject;
result = hasPrivilege(mapId, perm);
} else if (targetDomainObject instanceof Mindmap) {
final Mindmap map = (Mindmap) targetDomainObject;
result = hasPrivilege(map, perm);
} else if (targetDomainObject instanceof Collaborator collab) {
// Read only operations checks ...
result = user.identityEquality(collab) || readAdvice.getMindmapService().isAdmin(user);
} else {
throw new IllegalArgumentException("Unsupported check control of permissions");
}
if (!result) {
logger.debug("User '" + (user != null ? user.getEmail() : "none") + "' not allowed to invoke");
}
return result;
}
@Override
public boolean hasPermission(
@NotNull Authentication auth, Serializable targetId, @NotNull String targetType, @NotNull Object
permission) {
logger.log(Level.FATAL, "Unsupported privilege: auth: " + auth + ",targetId:" + targetType + ",targetType:" + targetType + ", permission:" + permission);
return false;
}
private boolean hasPrivilege(@NotNull int mapId, @NotNull MapAccessPermission permission) {
boolean result;
final User user = Utils.getUser();
if (MapAccessPermission.READ == permission) {
result = readAdvice.isAllowed(user, mapId);
} else {
result = updateAdvice.isAllowed(user, mapId);
}
return result;
}
private boolean hasPrivilege(@NotNull Mindmap map, @NotNull MapAccessPermission permission) {
boolean result;
final User user = Utils.getUser();
if (MapAccessPermission.READ == permission) {
result = readAdvice.isAllowed(user, map);
} else {
result = updateAdvice.isAllowed(user, map);
}
return result;
}
}

View File

@ -1,38 +1,37 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.service;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
public class HibernateAppListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent ce) {
try {
Class.forName("tomcatJndi.HibernateUtil").newInstance();
} catch (Exception e) {}
}
/* Application Shutdown Event */
public void contextDestroyed(ServletContextEvent ce)
{ }
}
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.security;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import com.wisemapping.service.MindmapService;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class MapPermissionsSecurityAdvice {
@Autowired private MindmapService mindmapService;
protected abstract boolean isAllowed(@Nullable User user, Mindmap map);
protected abstract boolean isAllowed(@Nullable User user, int mapId);
protected MindmapService getMindmapService() {
return mindmapService;
}
}

View File

@ -16,32 +16,22 @@
* limitations under the License.
*/
package com.wisemapping.security.aop;
package com.wisemapping.security;
import com.wisemapping.model.CollaborationRole;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;
public class ViewBaseSecurityAdvise
extends BaseSecurityAdvice
implements MethodInterceptor {
@Component
public class ReadSecurityAdvise
extends MapPermissionsSecurityAdvice {
@Override
public Object invoke(@NotNull MethodInvocation methodInvocation) throws Throwable {
checkRole(methodInvocation);
return methodInvocation.proceed();
}
@Override
protected boolean isAllowed(@Nullable User user, Mindmap map) {
return getMindmapService().hasPermissions(user, map, CollaborationRole.VIEWER);
}
@Override
protected boolean isAllowed(@Nullable User user, int mapId) {
return getMindmapService().hasPermissions(user, mapId, CollaborationRole.VIEWER);
}

View File

@ -0,0 +1,48 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.security;
import com.wisemapping.model.CollaborationRole;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;
@Component
public class UpdateSecurityAdvise
extends MapPermissionsSecurityAdvice {
@Override
protected boolean isAllowed(@Nullable User user, @NotNull Mindmap map) {
boolean result;
if (map.getCreator() == null) {
// This means that the map is new and is an add operation.
result = true;
} else {
result = getMindmapService().hasPermissions(user, map, CollaborationRole.EDITOR);
}
return result;
}
@Override
protected boolean isAllowed(@Nullable User user, int mapId) {
return getMindmapService().hasPermissions(user, mapId, CollaborationRole.EDITOR);
}
}

View File

@ -23,13 +23,16 @@ import com.wisemapping.model.User;
import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class UserDetailsService
implements org.springframework.security.core.userdetails.UserDetailsService {
@Autowired
private UserService userService;
private String adminUser;

View File

@ -1,65 +0,0 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.security.aop;
import com.wisemapping.exceptions.AccessDeniedSecurityException;
import com.wisemapping.model.Collaborator;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import com.wisemapping.security.Utils;
import com.wisemapping.service.MindmapService;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.Nullable;
public abstract class BaseSecurityAdvice {
private MindmapService mindmapService = null;
public void checkRole(MethodInvocation methodInvocation) throws AccessDeniedSecurityException {
final User user = Utils.getUser();
final Object argument = methodInvocation.getArguments()[0];
boolean isAllowed;
if (argument instanceof Mindmap) {
isAllowed = isAllowed(user, (Mindmap) argument) || mindmapService.isAdmin(user);
} else if (argument instanceof Integer) {
isAllowed = isAllowed(user, ((Integer) argument)) || mindmapService.isAdmin(user);
} else if (argument instanceof Collaborator) {
// Read operation find on the user are allowed ...
isAllowed = user.identityEquality((Collaborator) argument) || mindmapService.isAdmin(user);
} else {
throw new IllegalArgumentException("Argument " + argument);
}
if (!isAllowed) {
throw new AccessDeniedSecurityException("User '" + (user != null ? user.getEmail() : "none") + "' not allowed to invoke:" + methodInvocation);
}
}
protected abstract boolean isAllowed(@Nullable User user, Mindmap map);
protected abstract boolean isAllowed(@Nullable User user, int mapId);
protected MindmapService getMindmapService() {
return mindmapService;
}
public void setMindmapService(MindmapService service) {
this.mindmapService = service;
}
}

View File

@ -1,55 +0,0 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.security.aop;
import com.wisemapping.model.CollaborationRole;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class UpdateSecurityAdvise
extends BaseSecurityAdvice
implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
checkRole(methodInvocation);
return methodInvocation.proceed();
}
@Override
protected boolean isAllowed(@Nullable User user, @NotNull Mindmap map) {
boolean result;
if (map.getCreator() == null) {
// This means that the map is new and is an add operation.
result = true;
} else {
result = getMindmapService().hasPermissions(user, map, CollaborationRole.EDITOR);
}
return result;
}
@Override
protected boolean isAllowed(@Nullable User user, int mapId) {
return getMindmapService().hasPermissions(user, mapId, CollaborationRole.EDITOR);
}
}

View File

@ -23,19 +23,24 @@ import com.wisemapping.model.Label;
import com.wisemapping.model.User;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service("labelService")
@Transactional(propagation = Propagation.REQUIRED)
public class LabelServiceImpl implements LabelService {
@Autowired
private LabelManager labelManager;
public void setLabelManager(LabelManager labelManager) {
this.labelManager = labelManager;
}
@Override
public void addLabel(@NotNull final Label label, @NotNull final User user) throws WiseMappingException {
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'WRITE')")
public void addLabel(@NotNull final Label label, @NotNull final User user) {
label.setCreator(user);
labelManager.addLabel(label);
@ -43,22 +48,26 @@ public class LabelServiceImpl implements LabelService {
@NotNull
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'READ')")
public List<Label> getAll(@NotNull final User user) {
return labelManager.getAllLabels(user);
}
@Override @Nullable
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'READ')")
public Label findLabelById(int id, @NotNull final User user) {
return labelManager.getLabelById(id, user);
}
@Nullable
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'READ')")
public Label getLabelByTitle(@NotNull String title, @NotNull final User user) {
return labelManager.getLabelByTitle(title, user);
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'WRITE')")
public void removeLabel(@NotNull Label label, @NotNull User user) throws WiseMappingException {
if (label.getCreator().equals(user)) {
labelManager.removeLabel(label);

View File

@ -17,36 +17,44 @@
*/
package com.wisemapping.mail;
package com.wisemapping.service;
import com.wisemapping.util.VelocityEngineUtils;
import com.wisemapping.util.VelocityEngineWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public final class Mailer {
@Service
public final class MailerService {
//~ Instance fields ......................................................................................
@Autowired
private JavaMailSender mailSender;
@Autowired
private VelocityEngineWrapper velocityEngineWrapper;
private final String serverFromEmail;
private final String supportEmail;
private final String errorReporterEmail;
@Value("${mail.serverSendEmail}")
private String serverFromEmail;
@Value("${mail.supportEmail}")
private String supportEmail;
@Value("${mail.errorReporterEmail}")
private String errorReporterEmail;
//~ Methods ..............................................................................................
public Mailer(@NotNull String siteEmail, @NotNull String supportEmail, @NotNull String errorReporterEmail) {
this.serverFromEmail = siteEmail;
this.supportEmail = supportEmail;
this.errorReporterEmail = errorReporterEmail;
}
public String getServerSenderEmail() {
return serverFromEmail;
}

View File

@ -49,8 +49,6 @@ public interface MindmapService {
void removeMindmap(@NotNull final Mindmap mindmap, @NotNull final User user) throws WiseMappingException;
List<Mindmap> search(MindMapCriteria criteria);
List<MindMapHistory> findMindmapHistory(int mindmapId);
boolean hasPermissions(@Nullable User user, Mindmap map, CollaborationRole allowedRole);

View File

@ -20,23 +20,28 @@ package com.wisemapping.service;
import com.wisemapping.dao.MindmapManager;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.mail.NotificationService;
import com.wisemapping.model.*;
import com.wisemapping.security.Utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@Service("mindmapService")
@Transactional(propagation = Propagation.REQUIRED)
public class MindmapServiceImpl
implements MindmapService {
@Autowired
@ -49,6 +54,8 @@ public class MindmapServiceImpl
@Autowired
private NotificationService notificationService;
@Value("${admin.user}")
private String adminUser;
final private LockManager lockManager;
@ -92,37 +99,42 @@ public class MindmapServiceImpl
}
@Override
@PreAuthorize("hasPermission(#user, 'READ')")
public Mindmap getMindmapByTitle(String title, User user) {
return mindmapManager.getMindmapByTitle(title, user);
}
@Override
@Nullable
public Mindmap findMindmapById(int id) {
return mindmapManager.getMindmapById(id);
@PreAuthorize("hasPermission(#mapId, 'READ')")
public Mindmap findMindmapById(int mapId) {
return mindmapManager.getMindmapById(mapId);
}
@NotNull
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'READ')")
public List<Mindmap> findMindmapsByUser(@NotNull User user) {
return mindmapManager.findMindmapByUser(user);
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#user, 'READ')")
public List<Collaboration> findCollaborations(@NotNull User user) {
return mindmapManager.findCollaboration(user.getId());
}
@Override
public void updateMindmap(@NotNull Mindmap mindMap, boolean saveHistory) throws WiseMappingException {
if (mindMap.getTitle() == null || mindMap.getTitle().length() == 0) {
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mindmap, 'WRITE')")
public void updateMindmap(@NotNull Mindmap mindmap, boolean saveHistory) throws WiseMappingException {
if (mindmap.getTitle() == null || mindmap.getTitle().length() == 0) {
throw new WiseMappingException("The title can not be empty");
}
// Check that what we received a valid mindmap...
final String xml;
try {
xml = mindMap.getXmlStr().trim();
xml = mindmap.getXmlStr().trim();
} catch (UnsupportedEncodingException e) {
throw new WiseMappingException("Could not be decoded.", e);
}
@ -131,15 +143,11 @@ public class MindmapServiceImpl
throw new WiseMappingException("Map seems not to be a valid mindmap: '" + xml + "'");
}
mindmapManager.updateMindmap(mindMap, saveHistory);
}
@Override
public List<Mindmap> search(MindMapCriteria criteria) {
return mindmapManager.search(criteria);
mindmapManager.updateMindmap(mindmap, saveHistory);
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mindmap, 'WRITE')")
public void removeCollaboration(@NotNull Mindmap mindmap, @NotNull Collaboration collaboration) throws CollaborationException {
// remove collaborator association
final Mindmap mindMap = collaboration.getMindMap();
@ -154,6 +162,7 @@ public class MindmapServiceImpl
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mindmap, 'READ')")
public void removeMindmap(@NotNull Mindmap mindmap, @NotNull User user) throws WiseMappingException {
if (mindmap.getCreator().identityEquality(user)) {
mindmapManager.removeMindmap(mindmap);
@ -166,9 +175,10 @@ public class MindmapServiceImpl
}
@Override
public void addMindmap(@NotNull Mindmap map, @NotNull User user) {
@PreAuthorize("hasPermission(#mindmap, 'WRITE')")
public void addMindmap(@NotNull Mindmap mindmap, @NotNull User user) {
final String title = map.getTitle();
final String title = mindmap.getTitle();
if (title == null || title.length() == 0) {
throw new IllegalArgumentException("The tile can not be empty");
@ -180,20 +190,21 @@ public class MindmapServiceImpl
}
final Calendar creationTime = Calendar.getInstance();
map.setLastEditor(user);
map.setCreationTime(creationTime);
map.setLastModificationTime(creationTime);
map.setCreator(user);
mindmap.setLastEditor(user);
mindmap.setCreationTime(creationTime);
mindmap.setLastModificationTime(creationTime);
mindmap.setCreator(user);
// Add map creator with owner permissions ...
final User dbUser = userService.getUserBy(user.getId());
final Collaboration collaboration = new Collaboration(CollaborationRole.OWNER, dbUser, map);
map.getCollaborations().add(collaboration);
final Collaboration collaboration = new Collaboration(CollaborationRole.OWNER, dbUser, mindmap);
mindmap.getCollaborations().add(collaboration);
mindmapManager.addMindmap(dbUser, map);
mindmapManager.addMindmap(dbUser, mindmap);
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mindmap, 'WRITE')")
public void addCollaboration(@NotNull Mindmap mindmap, @NotNull String email, @NotNull CollaborationRole role, @Nullable String message)
throws CollaborationException {
@ -227,7 +238,8 @@ public class MindmapServiceImpl
}
}
private Collaborator addCollaborator(String email) {
private Collaborator addCollaborator(@NotNull String email) {
// Add a new collaborator ...
Collaborator collaborator = mindmapManager.findCollaborator(email);
if (collaborator == null) {
@ -241,11 +253,13 @@ public class MindmapServiceImpl
@Override
public List<MindMapHistory> findMindmapHistory(int mindmapId) {
return mindmapManager.getHistoryFrom(mindmapId);
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mapId, 'READ')")
public List<MindMapHistory> findMindmapHistory(int mapId) {
return mindmapManager.getHistoryFrom(mapId);
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mindmap, 'WRITE')")
public void revertChange(@NotNull Mindmap mindmap, int historyId)
throws WiseMappingException {
final MindMapHistory history = mindmapManager.getHistory(historyId);
@ -254,8 +268,9 @@ public class MindmapServiceImpl
}
@Override
public MindMapHistory findMindmapHistory(int id, int hid) throws WiseMappingException {
final List<MindMapHistory> mindmapHistory = this.findMindmapHistory(id);
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#mapId, 'READ')")
public MindMapHistory findMindmapHistory(int mapId, int hid) throws WiseMappingException {
final List<MindMapHistory> mindmapHistory = this.findMindmapHistory(mapId);
MindMapHistory result = null;
for (MindMapHistory history : mindmapHistory) {
if (history.getId() == hid) {
@ -265,12 +280,13 @@ public class MindmapServiceImpl
}
if (result == null) {
throw new WiseMappingException("History could not be found for mapid=" + id + ",hid" + hid);
throw new WiseMappingException("History could not be found for mapid=" + mapId + ",hid" + hid);
}
return result;
}
@Override
@PreAuthorize("hasAnyRole('USER', 'ADMIN') && hasPermission(#collaborator, 'WRITE')")
public void updateCollaboration(@NotNull Collaborator collaborator, @NotNull Collaboration collaboration) throws WiseMappingException {
if (!collaborator.identityEquality(collaboration.getCollaborator())) {
throw new WiseMappingException("No enough permissions for this operation.");

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
package com.wisemapping.mail;
package com.wisemapping.service;
import com.wisemapping.filter.SupportedUserAgent;
import com.wisemapping.model.Collaboration;
@ -29,10 +29,13 @@ import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ResourceBundleMessageSource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@ -42,13 +45,16 @@ import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
@Service
final public class NotificationService {
final private static Logger logger = LogManager.getLogger();
@Autowired
private ResourceBundleMessageSource messageSource;
@Autowired
private Mailer mailer;
private MailerService mailerService;
@Value("${site.baseurl:http://localhost:8080/}")
private String baseUrl;
public void newCollaboration(@NotNull Collaboration collaboration, @NotNull Mindmap mindmap, @NotNull User user, @Nullable String message) {
@ -56,7 +62,7 @@ final public class NotificationService {
try {
// Sent collaboration email ...
final String formMail = mailer.getServerSenderEmail();
final String formMail = mailerService.getServerSenderEmail();
// Is the user already registered user ?.
final String collabEmail = collaboration.getCollaborator().getEmail();
@ -72,14 +78,14 @@ final public class NotificationService {
model.put("baseUrl", getBaseUrl());
model.put("senderMail", user.getEmail());
model.put("message", message);
model.put("doNotReplay", messageSource.getMessage("EMAIL.DO_NOT_REPLAY", new Object[]{mailer.getSupportEmail()}, locale));
model.put("doNotReplay", messageSource.getMessage("EMAIL.DO_NOT_REPLAY", new Object[]{mailerService.getSupportEmail()}, locale));
// To resolve resources on templates ...
model.put("noArg", new Object[]{});
model.put("messages", messageSource);
model.put("locale", locale);
mailer.sendEmail(formMail, collabEmail, subject, model, "newCollaboration.vm");
mailerService.sendEmail(formMail, collabEmail, subject, model, "newCollaboration.vm");
} catch (Exception e) {
handleException(e);
}
@ -125,8 +131,8 @@ final public class NotificationService {
model.put("messageTitle", messageTitle);
model.put("messageBody", messageBody);
model.put("baseUrl", getBaseUrl());
model.put("supportEmail", mailer.getSupportEmail());
model.put("doNotReplay", messageSource.getMessage("EMAIL.DO_NOT_REPLAY", new Object[]{mailer.getSupportEmail()}, locale));
model.put("supportEmail", mailerService.getSupportEmail());
model.put("doNotReplay", messageSource.getMessage("EMAIL.DO_NOT_REPLAY", new Object[]{mailerService.getSupportEmail()}, locale));
// To resolve resources on templates ...
model.put("noArg", new Object[]{});
@ -134,7 +140,7 @@ final public class NotificationService {
model.put("locale", locale);
logger.debug("Email properties->" + model);
mailer.sendEmail(mailer.getServerSenderEmail(), user.getEmail(), mailSubject, model, "baseLayout.vm");
mailerService.sendEmail(mailerService.getServerSenderEmail(), user.getEmail(), mailSubject, model, "baseLayout.vm");
} catch (Exception e) {
handleException(e);
}
@ -146,15 +152,15 @@ final public class NotificationService {
}
public void setMailer(Mailer mailer) {
this.mailer = mailer;
public void setMailer(MailerService mailerService) {
this.mailerService = mailerService;
}
public void activateAccount(@NotNull User user) {
final Map<String, Object> model = new HashMap<>();
model.put("user", user);
mailer.sendEmail(mailer.getServerSenderEmail(), user.getEmail(), "[WiseMapping] Active account", model, "activationAccountMail.vm");
mailerService.sendEmail(mailerService.getServerSenderEmail(), user.getEmail(), "[WiseMapping] Active account", model, "activationAccountMail.vm");
}
public void sendRegistrationEmail(@NotNull User user) {

View File

@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.mail;
package com.wisemapping.service;
import org.jetbrains.annotations.NotNull;
import org.springframework.util.DigestUtils;

View File

@ -29,21 +29,27 @@ import org.apache.http.client.fluent.Request;
import org.jetbrains.annotations.Nullable;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class RecaptchaService {
final private static Logger logger = LogManager.getLogger();
final private static String GOOGLE_RECAPTCHA_VERIFY_URL =
"https://www.google.com/recaptcha/api/siteverify";
private final static ObjectMapper objectMapper = new ObjectMapper();
public static final String CATCH_ERROR_CODE_TIMEOUT_OR_DUPLICATE = "timeout-or-duplicate";
public static final String CATCHA_ERROR_CODE_INPUT_RESPONSE = "invalid-input-response";
@Value("${google.recaptcha2.secretKey}")
private String recaptchaSecret;
@Nullable

View File

@ -22,7 +22,6 @@ import com.wisemapping.dao.UserManager;
import com.wisemapping.exceptions.InvalidMindmapException;
import com.wisemapping.exceptions.OAuthAuthenticationException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.mail.NotificationService;
import com.wisemapping.model.*;
import com.wisemapping.rest.model.RestResetPasswordAction;
import com.wisemapping.rest.model.RestResetPasswordResponse;
@ -33,18 +32,31 @@ import com.wisemapping.util.VelocityEngineUtils;
import com.wisemapping.util.VelocityEngineWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service("userService")
@Transactional(propagation = Propagation.REQUIRED)
public class UserServiceImpl
implements UserService {
@Autowired
private UserManager userManager;
@Autowired
private MindmapService mindmapService;
@Autowired
private NotificationService notificationService;
@Autowired
private MessageSource messageSource;
@Autowired
private VelocityEngineWrapper velocityEngineWrapper;
@Autowired
private GoogleService googleService;
@Override

View File

@ -20,6 +20,8 @@ package com.wisemapping.service.google;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
@ -30,11 +32,17 @@ import com.wisemapping.service.google.http.HttpInvokerException;
@Service
public class GoogleService {
@Autowired
private HttpInvoker httpInvoker;
@Value("${security.oauth2.google.confirmUrl}")
private String optinConfirmUrl;
@Value("${security.oauth2.google.userinfoUrl}")
private String accountBasicDataUrl;
@Value("${security.oauth2.google.clientId}")
private String clientId;
@Value("${security.oauth2.google.clientSecret}")
private String clientSecret;
@Value("${security.oauth2.google.callbackUrl}")
private String callbackUrl;
public void setHttpInvoker(HttpInvoker httpInvoker) {

View File

@ -21,7 +21,9 @@ import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
@Component
public class VelocityEngineWrapper {
private final VelocityEngine velocityEngine;

View File

@ -36,6 +36,8 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@ -46,6 +48,7 @@ import org.springframework.web.servlet.ModelAndView;
import java.util.Locale;
@Controller
@Transactional(propagation = Propagation.REQUIRED)
public class MvcMindmapController {
@Qualifier("mindmapService")
@ -58,6 +61,7 @@ public class MvcMindmapController {
final MindMapBean mindmap = findMindmapBean(id);
model.addAttribute("principal", Utils.getUser());
model.addAttribute("mindmap", mindmap);
model.addAttribute("creatorFullName", mindmap.getCreator().getFullName());
final Locale locale = LocaleContextHolder.getLocale();
model.addAttribute("locale", locale.toString().toLowerCase());
return "mindmapViewonly";

View File

@ -53,4 +53,16 @@ public class MvcUsersController {
return new ModelAndView("reactInclude");
}
@RequestMapping(value = "registration-success", method = RequestMethod.GET)
@PreAuthorize("permitAll()")
public ModelAndView showRegistrationSuccess() {
return new ModelAndView("reactInclude");
}
@RequestMapping(value = "forgot-password-success", method = RequestMethod.GET)
@PreAuthorize("permitAll()")
public ModelAndView showResetPasswordSuccess() {
return new ModelAndView("reactInclude");
}
}

View File

@ -4,20 +4,20 @@
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="LogToFile" fileName="wisemapping.log">
<File name="LogToFile" fileName="/var/log/wisemapping.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="com.wisemapping" level="warn">
<Logger name="com.wisemapping" level="trace">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Logger name="org.springframework" level="warn">
<Logger name="org.springframework" level="trace">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="warn">
<Root level="trace">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>

View File

@ -64,4 +64,7 @@ OWNER_ROLE_CAN_NOT_BE_CHANGED=Роль владельца изменить не
ZOOM_TO_FIT=Увеличить, чтобы соответствовать
ZOOM_OUT=Уменьшить
ZOOM_IN=Приблизить
PASSWORD_TOO_LONG=Password must be less than 40 characters.
PASSWORD_TOO_LONG=Password must be less than 40 characters.
CHANGE_PASSWORD.EMAIL_SUBJECT=Your password has been reset
CHANGE_PASSWORD.EMAIL_TITLE=A temporal password has been generated
CHANGE_PASSWORD.EMAIL_BODY=<p>Someone, most likely you, requested a new password for your WiseMapping account. </p><p><strong>Here is your new password: {0} </strong></p><p>You can login clicking <a href="{1}/c/login">here</a>. We strongly encourage you to change the password as soon as possible.</p>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">-->
<!-- <property name="defaultEncoding" value="UTF-8"/>-->
<!-- <property name="basenames">-->
<!-- <list>-->
<!-- <value>messages</value>-->
<!-- </list>-->
<!-- </property>-->
<!-- </bean>-->
<import resource="wisemapping-datasource.xml"/>
<import resource="wisemapping-dao.xml"/>
<import resource="wisemapping-service.xml"/>
<import resource="wisemapping-servlet.xml"/>
</beans>

View File

@ -23,7 +23,7 @@
<prop key="hibernate.dialect">${database.hibernate.dialect}</prop>
<!-- <prop key="hibernate.cache.use_second_level_cache">true</prop>-->
<!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>-->
<!-- <prop key="hibernate.default_batch_fetch_size">200</prop>-->
<prop key="hibernate.default_batch_fetch_size">200</prop>
<prop key="hibernate.nestedTransactionAllowed">true</prop>
<prop key="hibernate.auto_quote_keyword">true</prop>
</props>
@ -35,23 +35,4 @@
<property name="nestedTransactionAllowed" value="true"/>
</bean>
<!-- Hibernate Template Definition -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="mindmapSessionFactory"/>
</bean>
<bean id="txAttributes"
class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource" ref="txAttributes"/>
</bean>
</beans>

View File

@ -13,11 +13,10 @@
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.wisemapping.rest"/>
<context:annotation-config/>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.wisemapping.rest.DebugMappingJacksonHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="/WEB-INF/app.properties" ignore-unresolvable="true"/>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.smtp.host}"/>
<property name="port" value="${mail.smtp.port}"/>
<property name="protocol" value="smtp"/>
<property name="username" value="${mail.username}"/>
<property name="password" value="${mail.password}"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">${mail.smtp.auth:false}</prop>
<prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable:false}</prop>
<prop key="mail.smtp.quitwait">${mail.smtp.quitwait:true}</prop>
</props>
</property>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="defaultEncoding" value="UTF-8"/>
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
<import resource="wisemapping-security-${security.type:db}.xml"/>
</beans>

View File

@ -12,8 +12,6 @@
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.wisemapping"/>
<context:annotation-config/>
<mvc:annotation-driven/>
<context:property-placeholder location="/WEB-INF/app.properties" ignore-unresolvable="true"/>
<!-- Interceptors Registration -->

View File

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG">
<Configuration status="warn">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.wisemapping" level="debug">
<Logger name="com.wisemapping" level="warn">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Logger name="org.springframework" level="trace">
<Logger name="org.springframework" level="warn">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="trace">
<Root level="warn">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>

View File

@ -1,6 +1,5 @@
<%@ page import="com.wisemapping.security.Utils" %>
<%@ page import="com.wisemapping.model.User" %>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ include file="init.jsp" %>
<%--@elvariable id="mindmap" type="com.wisemapping.model.Mindmap"--%>
@ -8,12 +7,15 @@
<%--@elvariable id="editorTryMode" type="java.lang.String"--%>
<%--@elvariable id="lockInfo" type="com.wisemapping.service.LockInfo"--%>
<c:set var="baseUrl" value="${requestScope['site.baseurl']}" scope="request" />
<c:set var="baseJsUrl" value="${requestScope['site.static.js.url']}" scope="request" />
<!DOCTYPE html>
<html lang="${fn:substring(locale,0,2)}">
<head>
<base href="${baseUrl}/static/webapp/" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="utf-8" />
<base href="${requestScope['site.baseurl']}/static/webapp/">
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'" crossorigin>
<%@ include file="pageHeaders.jsf" %>
@ -45,9 +47,7 @@
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root" class="mindplot-div-container"></div>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/webapp/vendors.bundle.js" crossorigin="anonymous" defer></script>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/webapp/app.bundle.js" crossorigin="anonymous" defer></script>
<script type="text/javascript" src="${baseJsUrl}/webapp/vendors.bundle.js" crossorigin="anonymous" defer></script>
<script type="text/javascript" src="${baseJsUrl}/webapp/app.bundle.js" crossorigin="anonymous" defer></script>
</body>
</html>

View File

@ -1,5 +1,9 @@
<%@page pageEncoding="UTF-8" %>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@include file="init.jsp" %>
<c:set var="baseUrl" value="${requestScope['site.baseurl']}" scope="request" />
<c:set var="baseJsUrl" value="${requestScope['site.static.js.url']}" scope="request" />
<%--@elvariable id="mindmap" type="com.wisemapping.model.Mindmap"--%>
@ -7,9 +11,9 @@
<html lang="${fn:substring(locale,0,2)}">
<head>
<base href="${baseUrl}/static/mindplot/" />
<meta name="viewport" content="initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<base href="${requestScope['site.baseurl']}/static/mindplot/">
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'" crossorigin>
<link rel="preload" href="../../css/viewonly.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
@ -67,11 +71,11 @@
</a>
<div id="mapDetails">
<span class="title"><spring:message code="CREATOR"/>:</span><span>${mindmap.creator.fullName}</span>
<span class="title"><spring:message code="CREATOR"/>:</span><span>${creatorFullName}</span>
<span class="title"><spring:message code="DESCRIPTION"/>:</span><span>${mindmap.title}</span>
</div>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/mindplot/loader.js" crossorigin="anonymous" defer></script>
<script type="text/javascript" src="${baseJsUrl}/mindplot/loader.js" crossorigin="anonymous" defer></script>
<div id="floating-panel">
<div id="zoom-button">

View File

@ -1,12 +1,15 @@
<%@ taglib uri = "jakarta.tags.functions" prefix = "fn" %>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@taglib uri="jakarta.tags.functions" prefix="fn" %>
<%@taglib uri="jakarta.tags.core" prefix="c"%>
<c:set var="baseUrl" value="${requestScope['site.baseurl']}" scope="request" />
<c:set var="baseJsUrl" value="${requestScope['site.static.js.url']}" scope="request" />
<!DOCTYPE html>
<html lang="${fn:substring(locale,0,2)}">
<head>
<base href="${baseUrl}/static/webapp/" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="utf-8" />
<base href="${requestScope['site.baseurl']}/static/webapp/">
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'" crossorigin>
<%@ include file="pageHeaders.jsf" %>
@ -21,12 +24,15 @@
googleOauth2Url: '${requestScope['security.oauth2.google.url']}'
};
<!-- Hack to force view selection on react to move all the UI to react-->
<%-- Hack to force view selection on react to move all the UI to react --%>
window.errorMvcView = '${requestScope['exception']!=null?(fn:indexOf(requestScope['exception'],'SecurityException') gt 1?'securityError':'unexpectedError'):''}';
/*
${requestScope['exception']}
*/
</script>
<c:if test="${requestScope['google.analytics.enabled']}">
<!-- Google Ads Sense Config. Lazy loading optimization -->
<%-- Google Ads Sense Config. Lazy loading optimization --%>
<script type="text/javascript">
function downloadJsAtOnload() {
setTimeout(function downloadJs() {
@ -47,8 +53,8 @@
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/webapp/vendors.bundle.js" crossorigin="anonymous" async></script>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/webapp/app.bundle.js" crossorigin="anonymous" async></script>
<script type="text/javascript" src="${baseJsUrl}/webapp/vendors.bundle.js" crossorigin="anonymous" async></script>
<script type="text/javascript" src="${baseJsUrl}/webapp/app.bundle.js" crossorigin="anonymous" async></script>
</body>
</html>

View File

@ -24,12 +24,7 @@
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/wisemapping-aop.xml
/WEB-INF/wisemapping-datasource.xml
/WEB-INF/wisemapping-dao.xml
/WEB-INF/wisemapping-service.xml
/WEB-INF/wisemapping-model.xml
/WEB-INF/wisemapping-servlet.xml
classpath:spring/wisemapping-common.xml
</param-value>
</context-param>
@ -37,17 +32,13 @@
<param-name>contextInitializerClasses</param-name>
<param-value>com.wisemapping.webmvc.ApplicationContextInitializer</param-value>
</context-param>
<!--
- Loads the root application context of this web app at startup.
- The application context is then available via
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
-->
<listener>
<listener-class>com.wisemapping.service.HibernateAppListener</listener-class>
</listener>
<listener>
<listener-class>com.wisemapping.listener.UnlockOnExpireListener</listener-class>
</listener>
@ -96,7 +87,7 @@
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/wisemapping-servlet.xml
classpath:spring/wisemapping-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
@ -108,7 +99,7 @@
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/wisemapping-rest.xml
classpath:spring/wisemapping-rest.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="viewSecurityAdvisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="viewSecurityAdvice"/>
<property name="mappedNames">
<list>
<value>getMindmapUserBy</value>
<value>getMindmapById</value>
<value>linkLabel</value>
<value>find*</value>
<value>filter*</value>
<!-- Remove can be performed in view only maps -->
<value>removeMindmap</value>
</list>
</property>
</bean>
<bean id="updateSecurityAdvisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="updateSecurityAdvice"/>
<property name="mappedNames">
<list>
<value>save*</value>
<value>update*</value>
<value>add*</value>
<value>revert*</value>
<value>removeCollaboration</value>
</list>
</property>
</bean>
<bean id="viewSecurityAdvice" class="com.wisemapping.security.aop.ViewBaseSecurityAdvise">
<property name="mindmapService" ref="mindmapService"/>
</bean>
<bean id="updateSecurityAdvice" class="com.wisemapping.security.aop.UpdateSecurityAdvise">
<property name="mindmapService" ref="mindmapService"/>
</bean>
</beans>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans>
<bean id="userManager" class="com.wisemapping.dao.UserManagerImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
<property name="encoder" ref="passwordEncoder"/>
</bean>
<bean id="mindmapManager" class="com.wisemapping.dao.MindmapManagerImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
</bean>
<bean id="labelManager" class="com.wisemapping.dao.LabelManagerImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
</bean>
</beans>
</beans>

View File

@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="/WEB-INF/app.properties" ignore-unresolvable="true"/>
<bean id="mailer" class="com.wisemapping.mail.Mailer">
<constructor-arg index="0" value="${mail.serverSendEmail}"/>
<constructor-arg index="1" value="${mail.supportEmail}"/>
<constructor-arg index="2" value="${mail.errorReporterEmail}"/>
<property name="mailSender" ref="mailSender"/>
<property name="velocityEngineWrapper" ref="velocityEngineWrapper"/>
</bean>
<bean id="httpInvoker" class="com.wisemapping.service.google.http.HttpInvoker">
</bean>
<bean id="googleService" class="com.wisemapping.service.google.GoogleService">
<property name="httpInvoker" ref="httpInvoker"/>
<property name="optinConfirmUrl" value="${security.oauth2.google.confirmUrl}"/>
<property name="accountBasicDataUrl" value="${security.oauth2.google.userinfoUrl}"/>
<property name="clientId" value="${security.oauth2.google.clientId}"/>
<property name="clientSecret" value="${security.oauth2.google.clientSecret}"/>
<property name="callbackUrl" value="${security.oauth2.google.callbackUrl}"/>
</bean>
<bean id="userServiceTarget" class="com.wisemapping.service.UserServiceImpl">
<property name="userManager" ref="userManager"/>
<property name="mindmapService" ref="mindMapServiceTarget"/>
<property name="notificationService" ref="notificationService"/>
<property name="messageSource" ref="messageSource"/>
<property name="velocityEngineWrapper" ref="velocityEngineWrapper"/>
<property name="googleService" ref="googleService"/>
</bean>
<bean id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="userServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="mindMapServiceTarget" class="com.wisemapping.service.MindmapServiceImpl">
<property name="mindmapManager" ref="mindmapManager"/>
<property name="userService" ref="userService"/>
<property name="notificationService" ref="notificationService"/>
<property name="adminUser" value="${admin.user}"/>
</bean>
<bean id="recaptchaService" class="com.wisemapping.service.RecaptchaService">
<property name="recaptchaSecret" value="${google.recaptcha2.secretKey}"/>
</bean>
<bean id="mindmapService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.wisemapping.service.MindmapService"/>
<property name="interceptorNames">
<list>
<value>txInterceptor</value>
<value>viewSecurityAdvisor</value>
<value>updateSecurityAdvisor</value>
</list>
</property>
<property name="target" ref="mindMapServiceTarget"/>
</bean>
<bean id="labelServiceTarget" class="com.wisemapping.service.LabelServiceImpl">
<property name="labelManager" ref="labelManager"/>
</bean>
<bean id="labelService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="labelServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.smtp.host}"/>
<property name="port" value="${mail.smtp.port}"/>
<property name="protocol" value="smtp"/>
<property name="username" value="${mail.username}"/>
<property name="password" value="${mail.password}"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">${mail.smtp.auth:false}</prop>
<prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable:false}</prop>
<prop key="mail.smtp.quitwait">${mail.smtp.quitwait:true}</prop>
</props>
</property>
</bean>
<bean id="velocityEngineWrapper" class="com.wisemapping.util.VelocityEngineWrapper">
</bean>
<bean id="notificationService" class="com.wisemapping.mail.NotificationService">
<property name="baseUrl" value="${site.baseurl:http://localhost:8080/}"/>
<property name="mailer" ref="mailer"/>
<property name="messageSource" ref="messageSource"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="defaultEncoding" value="UTF-8"/>
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
<import resource="wisemapping-security-${security.type}.xml"/>
</beans>

View File

@ -4,4 +4,6 @@ User-agent: *
Allow: /
Disallow: /c/restful/maps/*/document/xml-pub
Disallow: /c/maps/*/edit
Disallow: /c/maps/*/public
Disallow: /c/maps/*/try