From a7195331a3b5d8cb4836062f99430b4f5f6e44c3 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Fri, 10 Jan 2020 17:10:57 +0100 Subject: [PATCH 01/10] Fix text colors for warning button --- .../src/__snapshots__/storyshots.test.ts.snap | 148 ++++++++++++++++++ .../src/buttons/index.stories.tsx | 9 ++ scm-ui/ui-styles/src/scm.scss | 5 + 3 files changed, 162 insertions(+) diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index c7ab6a81b6..819d1a4558 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -161,6 +161,154 @@ exports[`Storyshots Buttons|Button Colors 1`] = ` `; +exports[`Storyshots Buttons|Button Disabled 1`] = ` +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+`; + exports[`Storyshots Buttons|Button Loading 1`] = `
+ )) + .add("Disabled", () => ( +
+ {colors.map(color => ( + +
)); const buttonStory = (name: string, storyFn: () => ReactElement) => { diff --git a/scm-ui/ui-styles/src/scm.scss b/scm-ui/ui-styles/src/scm.scss index bcb1fd4aa4..adb3c0b774 100644 --- a/scm-ui/ui-styles/src/scm.scss +++ b/scm-ui/ui-styles/src/scm.scss @@ -303,6 +303,10 @@ $danger-25: scale-color($danger, $lightness: 75%); } } + &.is-warning { + color: #88550D; + } + &.is-primary:hover, &.is-primary.is-hovered { background-color: scale-color($primary, $lightness: -10%); @@ -371,6 +375,7 @@ $danger-25: scale-color($danger, $lightness: 75%); &.is-warning[disabled] { background-color: scale-color($warning, $lightness: 75%); + color: #e1d4c2; } &.is-danger:hover, From b6590673c0c8aa78f527656280b4e27220f36d76 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Mon, 13 Jan 2020 10:56:47 +0100 Subject: [PATCH 02/10] Create mock subject to satisfy legman The posted restart event will trigger legman to request the current subject so that it can be passed over. This will lead to an exception if no subject is registered. The subject itself is of no importance here. Reported here: https://groups.google.com/d/msg/scmmanager/m4CfDE2n4h8/Yn6fddaYBgAJ --- .../main/java/sonia/scm/update/MigrationWizardServlet.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scm-webapp/src/main/java/sonia/scm/update/MigrationWizardServlet.java b/scm-webapp/src/main/java/sonia/scm/update/MigrationWizardServlet.java index 173dcb0638..b0ee63c0e8 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/MigrationWizardServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/update/MigrationWizardServlet.java @@ -5,6 +5,9 @@ import com.github.mustachejava.Mustache; import com.github.mustachejava.MustacheFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; +import org.apache.shiro.mgt.DefaultSecurityManager; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.util.ThreadContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.event.ScmEventBus; @@ -116,6 +119,8 @@ class MigrationWizardServlet extends HttpServlet { respondWithTemplate(resp, model, "templates/repository-migration-restart.mustache"); + ThreadContext.bind(new Subject.Builder(new DefaultSecurityManager()).authenticated(false).buildSubject()); + ScmEventBus.getInstance().post(new RestartEvent(MigrationWizardServlet.class, "wrote migration data")); } From 772e16d943cf2faba1baa765a6f2ef6849216a66 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 13 Jan 2020 10:05:07 +0000 Subject: [PATCH 03/10] Close branch bugfix/warning_button_color From 2f9347a5ef24c61e6efa27801884026da6dd0474 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 13 Jan 2020 13:57:09 +0100 Subject: [PATCH 04/10] update smp-maven-plugin to 1.0.0-rc2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 918d43439a..7e009650c7 100644 --- a/pom.xml +++ b/pom.xml @@ -456,7 +456,7 @@ sonia.scm.maven smp-maven-plugin - 1.0.0-rc1 + 1.0.0-rc2 From b64860770e15f159acb080a09861b9f3fd71f4b3 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 13 Jan 2020 13:16:02 +0000 Subject: [PATCH 05/10] Close branch bugfix/restart_after_migration From 98febefa649fbd157a2da4f2b00206cb9faec929 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 13 Jan 2020 15:56:28 +0100 Subject: [PATCH 06/10] fix sonarqube code coverage --- Jenkinsfile | 2 +- pom.xml | 55 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 37cbdb4064..d89a945e6e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -33,7 +33,7 @@ node('docker') { } stage('Unit Test') { - mvn 'test -Dsonia.scm.test.skip.hg=true -Dmaven.test.failure.ignore=true' + mvn 'test -Pcoverage -Dsonia.scm.test.skip.hg=true -Dmaven.test.failure.ignore=true' } stage('Integration Test') { diff --git a/pom.xml b/pom.xml index 7e009650c7..a9e43c9015 100644 --- a/pom.xml +++ b/pom.xml @@ -685,28 +685,6 @@ 2.6 - - - - org.jacoco - jacoco-maven-plugin - 0.8.1 - - - - prepare-agent - - - - report - prepare-package - - report - - - - - @@ -787,6 +765,39 @@ + + coverage + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.5 + + + + prepare-agent + + + + report + test + + report + + + + + + + + + + APIviz From 2f48087f1390d7ca2e674a113797f7f2fd48013c Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 13 Jan 2020 21:38:28 +0100 Subject: [PATCH 07/10] enable react fast refresh for core ui --- package.json | 2 +- scm-ui/babel-preset/index.js | 23 +++++++------- scm-ui/ui-scripts/package.json | 8 +++-- scm-ui/ui-scripts/src/webpack.config.js | 10 ++++-- scm-ui/ui-styles/package.json | 4 +-- yarn.lock | 41 +++++++++++++++++++++---- 6 files changed, 62 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index c50258f18d..758ecdf611 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build:dev": "webpack --mode=development --config=scm-ui/ui-scripts/src/webpack.config.js", "test": "lerna run --scope '@scm-manager/ui-*' test", "typecheck": "lerna run --scope '@scm-manager/ui-*' typecheck", - "serve": "webpack-dev-server --mode=development --config=scm-ui/ui-scripts/src/webpack.config.js", + "serve": "NODE_ENV=development webpack-dev-server --hot --mode=development --config=scm-ui/ui-scripts/src/webpack.config.js", "deploy": "ui-scripts publish", "set-version": "ui-scripts version" }, diff --git a/scm-ui/babel-preset/index.js b/scm-ui/babel-preset/index.js index 54c71e3741..940dd71ff6 100644 --- a/scm-ui/babel-preset/index.js +++ b/scm-ui/babel-preset/index.js @@ -1,12 +1,11 @@ -module.exports = () => ({ - presets: [ - require("@babel/preset-env"), - require("@babel/preset-flow"), - require("@babel/preset-react"), - require("@babel/preset-typescript") - ], - plugins: [ - require("@babel/plugin-proposal-class-properties"), - require("@babel/plugin-proposal-optional-chaining") - ] -}); +module.exports = api => { + return { + presets: [ + require("@babel/preset-env"), + require("@babel/preset-flow"), + require("@babel/preset-react"), + require("@babel/preset-typescript") + ], + plugins: [require("@babel/plugin-proposal-class-properties"), require("@babel/plugin-proposal-optional-chaining")] + }; +}; diff --git a/scm-ui/ui-scripts/package.json b/scm-ui/ui-scripts/package.json index 7ef5d2819c..4b2564b419 100644 --- a/scm-ui/ui-scripts/package.json +++ b/scm-ui/ui-scripts/package.json @@ -10,6 +10,7 @@ "ui-scripts": "./bin/ui-scripts.js" }, "dependencies": { + "@pmmmwh/react-refresh-webpack-plugin": "^0.1.3", "babel-loader": "^8.0.6", "cache-loader": "^4.1.0", "css-loader": "^3.2.0", @@ -18,13 +19,14 @@ "mustache": "^3.1.0", "node-sass": "^4.12.0", "optimize-css-assets-webpack-plugin": "^5.0.3", + "react-refresh": "^0.7.2", "sass-loader": "^8.0.0", "script-loader": "^0.7.2", "style-loader": "^1.0.0", "thread-loader": "^2.1.3", - "webpack": "^4.41.1", - "webpack-cli": "^3.3.9", - "webpack-dev-server": "^3.8.2" + "webpack": "^4.41.5", + "webpack-cli": "^3.3.10", + "webpack-dev-server": "^3.10.1" }, "eslintConfig": { "extends": "@scm-manager/eslint-config", diff --git a/scm-ui/ui-scripts/src/webpack.config.js b/scm-ui/ui-scripts/src/webpack.config.js index 2dd5b4c470..30d7b159a3 100644 --- a/scm-ui/ui-scripts/src/webpack.config.js +++ b/scm-ui/ui-scripts/src/webpack.config.js @@ -3,11 +3,15 @@ const createIndexMiddleware = require("./middleware/IndexMiddleware"); const createContextPathMiddleware = require("./middleware/ContextPathMiddleware"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin"); + +const isDevelopment = process.env.NODE_ENV !== "production"; const root = path.resolve(process.cwd(), "scm-ui"); module.exports = [ { + mode: isDevelopment ? "development" : "production", context: root, entry: { webapp: [path.resolve(__dirname, "webpack-public-path.js"), "./ui-webapp/src/index.tsx"] @@ -41,7 +45,8 @@ module.exports = [ loader: "babel-loader", options: { cacheDirectory: true, - presets: ["@scm-manager/babel-preset"] + presets: ["@scm-manager/babel-preset"], + plugins: [isDevelopment && require.resolve("react-refresh/babel")].filter(Boolean) } } ] @@ -105,7 +110,8 @@ module.exports = [ } } } - } + }, + plugins: [isDevelopment && new ReactRefreshWebpackPlugin()].filter(Boolean) }, { context: root, diff --git a/scm-ui/ui-styles/package.json b/scm-ui/ui-styles/package.json index f5f984be08..d4f160f2d7 100644 --- a/scm-ui/ui-styles/package.json +++ b/scm-ui/ui-styles/package.json @@ -20,8 +20,8 @@ "node-sass": "^4.12.0", "sass-loader": "^8.0.0", "style-loader": "^1.0.0", - "webpack": "^4.41.0", - "webpack-dev-server": "^3.8.2" + "webpack": "^4.41.5", + "webpack-dev-server": "^3.10.1" }, "prettier": "@scm-manager/prettier-config" } diff --git a/yarn.lock b/yarn.lock index f75ea838fe..ef120d73f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2136,6 +2136,18 @@ dependencies: "@types/node" ">= 8" +"@pmmmwh/react-refresh-webpack-plugin@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.1.3.tgz#bb6815315028087e6af4f96d063376880caf9c82" + integrity sha512-FJ8WzpGrao8Gz8KNAeU9dcTYr1RjbAGnXJMKKXTp4oAw494SqQK4HyGT8HMmIQt0ayukuP+A71w1oV8/5xSAWQ== + dependencies: + ansi-html "^0.0.7" + error-stack-parser "^2.0.4" + html-entities "^1.2.1" + lodash.debounce "^4.0.8" + react-dev-utils "^9.1.0" + sockjs-client "^1.4.0" + "@reach/router@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.2.1.tgz#34ae3541a5ac44fa7796e5506a5d7274a162be4e" @@ -3309,7 +3321,7 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.8.1" -ansi-html@0.0.7: +ansi-html@0.0.7, ansi-html@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= @@ -6265,6 +6277,13 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + es-abstract@^1.13.0, es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1: version "1.17.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" @@ -11937,7 +11956,7 @@ react-clientside-effect@^1.2.0: dependencies: "@babel/runtime" "^7.0.0" -react-dev-utils@^9.0.0: +react-dev-utils@^9.0.0, react-dev-utils@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.1.0.tgz#3ad2bb8848a32319d760d0a84c56c14bdaae5e81" integrity sha512-X2KYF/lIGyGwP/F/oXgGDF24nxDA2KC4b7AFto+eqzc/t838gpSGiaU8trTqHXOohuLxxc5qi1eDzsl9ucPDpg== @@ -12130,6 +12149,11 @@ react-redux@^5.0.7: react-is "^16.6.0" react-lifecycles-compat "^3.0.0" +react-refresh@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.7.2.tgz#f30978d21eb8cac6e2f2fde056a7d04f6844dd50" + integrity sha512-u5l7fhAJXecWUJzVxzMRU2Zvw8m4QmDNHlTrT5uo3KBlYBhmChd7syAakBoay1yIiVhx/8Fi7a6v6kQZfsw81Q== + react-router-dom@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" @@ -13292,7 +13316,7 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.4.0: +sockjs-client@1.4.0, sockjs-client@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== @@ -13505,6 +13529,11 @@ stack-utils@^1.0.1: resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== +stackframe@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71" + integrity sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ== + state-toggle@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.2.tgz#75e93a61944116b4959d665c8db2d243631d6ddc" @@ -14717,7 +14746,7 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-cli@^3.3.9: +webpack-cli@^3.3.10: version "3.3.10" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== @@ -14745,7 +14774,7 @@ webpack-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.8.2: +webpack-dev-server@^3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.1.tgz#1ff3e5cccf8e0897aa3f5909c654e623f69b1c0e" integrity sha512-AGG4+XrrXn4rbZUueyNrQgO4KGnol+0wm3MPdqGLmmA+NofZl3blZQKxZ9BND6RDNuvAK9OMYClhjOSnxpWRoA== @@ -14810,7 +14839,7 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.33.0, webpack@^4.38.0, webpack@^4.41.0, webpack@^4.41.1: +webpack@^4.33.0, webpack@^4.38.0, webpack@^4.41.5: version "4.41.5" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== From 6c84b0ede4e73a6ce3bfc9cd5de2f70dd74a11c5 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Tue, 14 Jan 2020 11:00:47 +0000 Subject: [PATCH 08/10] Close branch bugfix/module_code_coverage From 1cade825afae7bdc8df1eabc0af6889173839822 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 14 Jan 2020 13:28:17 +0100 Subject: [PATCH 09/10] enable xrfs protection only on write request This change is required in order to fix the image viewer and download of editor plugin --- .../security/XsrfAccessTokenValidator.java | 15 +- .../XsrfAccessTokenValidatorTest.java | 158 +++++++++++------- 2 files changed, 110 insertions(+), 63 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/security/XsrfAccessTokenValidator.java b/scm-webapp/src/main/java/sonia/scm/security/XsrfAccessTokenValidator.java index 437174f57e..241b0ac001 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/XsrfAccessTokenValidator.java +++ b/scm-webapp/src/main/java/sonia/scm/security/XsrfAccessTokenValidator.java @@ -30,12 +30,15 @@ */ package sonia.scm.security; +import com.google.common.collect.ImmutableSet; import sonia.scm.plugin.Extension; import javax.inject.Inject; import javax.inject.Provider; import javax.servlet.http.HttpServletRequest; +import java.util.Locale; import java.util.Optional; +import java.util.Set; /** * Validates xsrf protected access tokens. The validator check if the current request contains an xsrf key which is @@ -47,7 +50,11 @@ import java.util.Optional; */ @Extension public class XsrfAccessTokenValidator implements AccessTokenValidator { - + + private static final Set ALLOWED_METHOD = ImmutableSet.of( + "GET", "HEAD", "OPTIONS" + ); + private final Provider requestProvider; @@ -65,8 +72,10 @@ public class XsrfAccessTokenValidator implements AccessTokenValidator { public boolean validate(AccessToken accessToken) { Optional xsrfClaim = accessToken.getCustom(Xsrf.TOKEN_KEY); if (xsrfClaim.isPresent()) { - String xsrfHeaderValue = requestProvider.get().getHeader(Xsrf.HEADER_KEY); - return xsrfClaim.get().equals(xsrfHeaderValue); + HttpServletRequest request = requestProvider.get(); + String xsrfHeaderValue = request.getHeader(Xsrf.HEADER_KEY); + return ALLOWED_METHOD.contains(request.getMethod().toUpperCase(Locale.ENGLISH)) + || xsrfClaim.get().equals(xsrfHeaderValue); } return true; } diff --git a/scm-webapp/src/test/java/sonia/scm/security/XsrfAccessTokenValidatorTest.java b/scm-webapp/src/test/java/sonia/scm/security/XsrfAccessTokenValidatorTest.java index a89744cd6e..0692a76bd2 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/XsrfAccessTokenValidatorTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/XsrfAccessTokenValidatorTest.java @@ -1,19 +1,19 @@ /** * Copyright (c) 2014, Sebastian Sdorra * All rights reserved. - * + *

* Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + *

* 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,33 +24,39 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + *

* http://bitbucket.org/sdorra/scm-manager - * */ package sonia.scm.security; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.EnumSource; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; import java.util.Optional; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; /** * Tests {@link XsrfAccessTokenValidator}. - * + * * @author Sebastian Sdorra */ -@RunWith(MockitoJUnitRunner.class) -public class XsrfAccessTokenValidatorTest { +@ExtendWith(MockitoExtension.class) +class XsrfAccessTokenValidatorTest { @Mock private HttpServletRequest request; @@ -59,62 +65,94 @@ public class XsrfAccessTokenValidatorTest { private AccessToken accessToken; private XsrfAccessTokenValidator validator; - + /** * Prepare object under test. */ - @Before - public void prepareObjectUnderTest() { + @BeforeEach + void prepareObjectUnderTest() { validator = new XsrfAccessTokenValidator(() -> request); } - - /** - * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)}. - */ - @Test - public void testValidate() { + + @Nested + class RequestMethodPost { + + @BeforeEach + void setRequestMethod() { + lenient().when(request.getMethod()).thenReturn("POST"); + } + + /** + * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)}. + */ + @Test + void testValidate() { + // prepare + when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.of("abc")); + when(request.getHeader(Xsrf.HEADER_KEY)).thenReturn("abc"); + + // execute and assert + assertTrue(validator.validate(accessToken)); + } + + /** + * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)} with wrong header. + */ + @Test + void testValidateWithWrongHeader() { + // prepare + when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.of("abc")); + when(request.getHeader(Xsrf.HEADER_KEY)).thenReturn("123"); + + // execute and assert + assertFalse(validator.validate(accessToken)); + } + + /** + * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)} without header. + */ + @Test + void testValidateWithoutHeader() { + // prepare + when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.of("abc")); + + // execute and assert + assertFalse(validator.validate(accessToken)); + } + + /** + * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)} without claims key. + */ + @Test + void testValidateWithoutClaimsKey() { + // prepare + when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.empty()); + + // execute and assert + assertTrue(validator.validate(accessToken)); + } + + } + + @ParameterizedTest + @CsvSource({"GET", "HEAD", "OPTIONS"}) + void shouldNotValidateReadRequests(String method) { // prepare + when(request.getMethod()).thenReturn(method); when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.of("abc")); - when(request.getHeader(Xsrf.HEADER_KEY)).thenReturn("abc"); - + // execute and assert assertTrue(validator.validate(accessToken)); } - - /** - * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)} with wrong header. - */ - @Test - public void testValidateWithWrongHeader() { + + @ParameterizedTest + @CsvSource({"POST", "PUT", "DELETE", "PATCH"}) + void shouldFailValidationOfWriteRequests(String method) { // prepare + when(request.getMethod()).thenReturn(method); when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.of("abc")); - when(request.getHeader(Xsrf.HEADER_KEY)).thenReturn("123"); - + // execute and assert assertFalse(validator.validate(accessToken)); } - - /** - * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)} without header. - */ - @Test - public void testValidateWithoutHeader() { - // prepare - when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.of("abc")); - - // execute and assert - assertFalse(validator.validate(accessToken)); - } - - /** - * Tests {@link XsrfAccessTokenValidator#validate(AccessToken)} without claims key. - */ - @Test - public void testValidateWithoutClaimsKey() { - // prepare - when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(Optional.empty()); - - // execute and assert - assertTrue(validator.validate(accessToken)); - } } From 4ff38777242eaa1b56121201c8121f1eca4da72c Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 15 Jan 2020 07:48:39 +0000 Subject: [PATCH 10/10] Close branch feature/react_fast_refresh