Skip to content

Commit

Permalink
Merge pull request #260 from micromata/Release-8.1-SNAPSHOT
Browse files Browse the repository at this point in the history
Release 8.1 snapshot
CorsPreflightFilter for development, BaseDao/KundeDao.isNew(data)
  • Loading branch information
kreinhard authored Jan 17, 2025
2 parents 7a15cec + 9a0941e commit f12fc11
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.wicket.spring.SpringWebApplicationFactory;
import org.projectforge.business.user.filter.WicketUserFilter;
import org.projectforge.carddav.CardDavInit;
import org.projectforge.framework.configuration.PFSpringConfiguration;
import org.projectforge.model.rest.RestPaths;
import org.projectforge.rest.config.LocaleFilter;
import org.projectforge.rest.config.Rest;
Expand Down Expand Up @@ -63,12 +64,21 @@ public class WebXMLInitializer implements ServletContextInitializer {
@Autowired
private CardDavInit cardDavInit;

@Autowired
private PFSpringConfiguration pfSpringConfiguration;

@Override
public void onStartup(ServletContext sc) throws ServletException {
final FilterRegistration securityHeaderFilter = sc.addFilter("SecurityHeaderFilter", SecurityHeaderFilter.class);
securityHeaderFilter.addMappingForUrlPatterns(null, false, "/*");
securityHeaderFilter.setInitParameter(SecurityHeaderFilter.PARAM_CSP_HEADER_VALUE, cspHeaderValue);

if (pfSpringConfiguration.getCorsFilterEnabled()) {
log.warn("************* Enabling CorsPreflightFilter for development. *************");
FilterRegistration.Dynamic corsPreflightFilter = sc.addFilter("CorsPreflightFilter", CorsPreflightFilter.class);
corsPreflightFilter.addMappingForUrlPatterns(null, false, "/*");
}

/*
* Redirect orphaned links from former versions of ProjectForge (e. g. if link in e-mails were changed due to migrations or refactoring.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2025 Micromata GmbH, Germany (www.micromata.com)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.config

import jakarta.servlet.Filter
import jakarta.servlet.FilterChain
import jakarta.servlet.ServletException
import jakarta.servlet.ServletRequest
import jakarta.servlet.ServletResponse
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.stereotype.Component
import java.io.IOException


@Component
class CorsPreflightFilter : Filter {
@Throws(IOException::class, ServletException::class)
override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
val httpRequest = request as HttpServletRequest
val httpResponse = response as HttpServletResponse

// Überprüfe den Origin-Header der Anfrage
val origin = httpRequest.getHeader("Origin")

// Nur Anfragen mit einem Origin behandeln
if (origin != null) {
httpResponse.setHeader("Access-Control-Allow-Origin", origin) // Setze den Origin der Anfrage
httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
httpResponse.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With")
httpResponse.setHeader("Access-Control-Allow-Credentials", "true") // Erlaubt Credentials
httpResponse.setHeader("Access-Control-Max-Age", "3600")
}

// Preflight-Request (OPTIONS) direkt beantworten
if ("OPTIONS".equals(httpRequest.method, ignoreCase = true)) {
httpResponse.status = HttpServletResponse.SC_OK
} else {
// Andere Anfragen weiterleiten
chain.doFilter(request, response)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

package org.projectforge.business.fibu;

import org.jetbrains.annotations.NotNull;
import org.projectforge.business.user.ProjectForgeGroup;
import org.projectforge.common.i18n.UserException;
import org.projectforge.framework.access.OperationType;
Expand Down Expand Up @@ -105,6 +106,11 @@ public KundeDO newInstance() {
return new KundeDO();
}

@Override
public boolean isNew(@NotNull KundeDO obj) {
return obj.getCreated() == null; // id isn't null while inserting new customers
}

@Override
public void onInsert(KundeDO obj) {
if (doesNumberAlreadyExist(obj)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ class OrderbookSnapshotsService {
readSnapshot(incrementalBasedOn, orderbook)
}
val serialized = entry.serializedOrderBook ?: return
if (serialized.isEmpty()) {
return
}
readSnapshot(serialized, orderbook)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,18 @@ protected constructor(open var doClass: Class<O>) : IDao<O>, BaseDaoPersistenceL
@JvmOverloads
open fun insertOrUpdate(obj: O, checkAccess: Boolean = true): Serializable? {
var id: Serializable? = null
if (obj.id != null && obj.created != null) { // obj.created is needed for KundeDO (id isn't null for inserting new customers).
if (!isNew(obj)) {
update(obj, checkAccess = checkAccess)
} else {
id = insert(obj, checkAccess = checkAccess)
}
return id
}

open fun isNew(obj: O): Boolean {
return obj.id == null
}

/**
* Call save(O) for every object in the given list.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import mu.KotlinLogging
import org.projectforge.business.user.UserTokenType
import org.projectforge.login.LoginService
import org.projectforge.rest.Authentication
import org.projectforge.rest.utils.RequestLog
import org.projectforge.security.SecurityLogging
import org.springframework.beans.factory.annotation.Autowired

Expand Down Expand Up @@ -55,7 +56,7 @@ class RestUserFilter : AbstractRestUserFilter(UserTokenType.REST_CLIENT) {
// Don't log error for userStatus (used by React client for checking weather the user is logged in or not).
if (requestURI == null || requestURI != "/rs/userStatus") {
val msg =
"Neither ${Authentication.AUTHENTICATION_USER_ID} nor ${Authentication.AUTHENTICATION_USERNAME}/${Authentication.AUTHENTICATION_TOKEN} is given for rest call: $requestURI. Rest call forbidden."
"Neither valid session-credentials (request.sessionId=${RequestLog.getTruncatedSessionId(authInfo.request)}), ${Authentication.AUTHENTICATION_USER_ID} nor ${Authentication.AUTHENTICATION_USERNAME}/${Authentication.AUTHENTICATION_TOKEN} is given for rest call: $requestURI. Rest call forbidden."
log.error(msg)
SecurityLogging.logSecurityWarn(authInfo.request, this::class.java, "REST AUTHENTICATION FAILED", msg)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void create() {
log.info("Double click detection in " + editPage.getClass() + " create method. Do nothing.");
} else {
editPage.setAlreadySubmitted(true);
if (editPage.getData().getId() != null) { // && editPage.getData() instanceof IManualIndex == false) {
if (!getBaseDao().isNew(editPage.getData())) { // && editPage.getData() instanceof IManualIndex == false) {
// User has used the back button?
log.info("User has used the back button in "
+ editPage.getClass()
Expand Down

0 comments on commit f12fc11

Please sign in to comment.