Merge "Fix same-origin check for link rewrites"
diff --git a/Documentation/backend_licenses.txt b/Documentation/backend_licenses.txt
index 1ab3119..dbea391 100755
--- a/Documentation/backend_licenses.txt
+++ b/Documentation/backend_licenses.txt
@@ -69,9 +69,11 @@
* jetty:http
* jetty:io
* jetty:jmx
+* jetty:nested
* jetty:security
* jetty:server
* jetty:servlet
+* jetty:session
* jetty:util
* jetty:util-ajax
* log:log4j
diff --git a/Documentation/licenses.txt b/Documentation/licenses.txt
index 23cbaed..7a3c608 100644
--- a/Documentation/licenses.txt
+++ b/Documentation/licenses.txt
@@ -71,9 +71,11 @@
* jetty:http
* jetty:io
* jetty:jmx
+* jetty:nested
* jetty:security
* jetty:server
* jetty:servlet
+* jetty:session
* jetty:util
* jetty:util-ajax
* log:log4j
diff --git a/Documentation/release_war_jars.txt b/Documentation/release_war_jars.txt
index 76927bf..953e2dc 100644
--- a/Documentation/release_war_jars.txt
+++ b/Documentation/release_war_jars.txt
@@ -48,12 +48,16 @@
javax.inject
javax.servlet-api
jcl-over-slf4j
+jetty-ee8-nested
+jetty-ee8-security
+jetty-ee8-servlet
jetty-http
jetty-io
jetty-jmx
jetty-security
jetty-server
-jetty-servlet
+jetty-servlet-api
+jetty-session
jetty-util
jetty-util-ajax
jgit
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index f66f25c..824a757 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -4297,7 +4297,7 @@
.Request
----
- POST /projects/testproj/migrate-labels HTTP/1.0
+ POST /projects/testproj/migrate-labels:review HTTP/1.0
Content-Type: application/json; charset=UTF-8
----
diff --git a/configs/skills/gerrit_hygiene_operations/SKILL.md b/configs/skills/gerrit_hygiene_operations/SKILL.md
index d267731..095cfe4 100644
--- a/configs/skills/gerrit_hygiene_operations/SKILL.md
+++ b/configs/skills/gerrit_hygiene_operations/SKILL.md
@@ -43,10 +43,9 @@
: Syntax Normalization** : linting mandates for frontend :
: : TypeScript components. Strict :
: : enforcement of formatting rules, such :
-: : as whitespace removal and line-length :
-: : constraints, ensures optimal diff :
-: : readability and prevents automated CI :
-: : pipeline failures. :
+: : as line-length constraints, ensures :
+: : optimal diff readability and prevents :
+: : automated CI pipeline failures. :
| **Proprietary Infrastructure | Establishes strict boundaries for |
: Encapsulation** : documenting public APIs by forbidding :
: : the leakage of proprietary backend :
@@ -145,43 +144,40 @@
**Context:** This section defines the structural code style and linting mandates
for frontend TypeScript components. Strict enforcement of formatting rules, such
-as whitespace removal and line-length constraints, ensures optimal diff
-readability and prevents automated CI pipeline failures.
+as line-length constraints, ensures optimal diff readability and prevents
+automated CI pipeline failures.
### Summary
| Rule ID | Principle / Constraint | Priority | Primary Symptom / Trap |
| :-------- | :--------------------- | :------- | :------------------------ |
-| **T2-01** | Strict Trailing | Medium | Chaining long promise |
-: : Whitespace and Line : : callbacks or variable :
-: : Length Formatting : : assignments on a single :
-: : : : line, or leaving trailing :
-: : : : spaces on empty lines. :
+| **T2-01** | Strict Line Length | Medium | Chaining long promise |
+: : Formatting : : callbacks or variable :
+: : : : assignments on a single :
+: : : : line. :
--------------------------------------------------------------------------------
### Rules
-#### T2-01: Strict Trailing Whitespace and Line Length Formatting
+#### T2-01: Strict Line Length Formatting
> **Rule:** Always format TypeScript files to strictly adhere to linting limits
-> by wrapping long chained expressions and stripping trailing whitespace from
-> empty lines. Never commit code that triggers structural style violations.
+> by wrapping long chained expressions. Never commit code that triggers structural
+> style violations.
>
> **What:** TypeScript frontend files must strictly adhere to linting standards
-> by removing trailing whitespaces on empty lines and properly wrapping long
-> chained expressions.
+> by properly wrapping long chained expressions.
>
> **Applies To:** TypeScript UI components (e.g., Lit elements like
> `gr-reply-dialog.ts`).
>
-> **Why:** Inconsistent formatting, trailing whitespaces, and over-extended
-> lines caused unnecessary diff noise and failed automated linting checks in the
-> frontend CI pipeline. Failing to adhere to this typically results in **Linting
-> Pipeline Failure**.
+> **Why:** Inconsistent formatting and over-extended lines caused unnecessary diff
+> noise and failed automated linting checks in the frontend CI pipeline. Failing
+> to adhere to this typically results in **Linting Pipeline Failure**.
**Trap 1: Chaining long promise callbacks or variable assignments on a single
-line, or leaving trailing spaces on empty lines.**
+line.**
**Don't:**
diff --git a/external_deps.lock.json b/external_deps.lock.json
index 00a1a49..c556eb5 100644
--- a/external_deps.lock.json
+++ b/external_deps.lock.json
@@ -168,18 +168,17 @@
"org.commonmark:commonmark-ext-autolink": -1853742120,
"org.commonmark:commonmark-ext-gfm-strikethrough": 350394231,
"org.commonmark:commonmark-ext-gfm-tables": 1881582931,
- "org.eclipse.jetty.ee8:jetty-ee8-nested": -1812530566,
- "org.eclipse.jetty.ee8:jetty-ee8-security": 925022545,
- "org.eclipse.jetty.ee8:jetty-ee8-servlet": 1799016170,
- "org.eclipse.jetty:jetty-http": 1984891007,
- "org.eclipse.jetty:jetty-io": 1765684893,
- "org.eclipse.jetty:jetty-jmx": -1704061949,
- "org.eclipse.jetty:jetty-security": 1160320567,
- "org.eclipse.jetty:jetty-server": 280305722,
- "org.eclipse.jetty:jetty-servlet": 697742931,
- "org.eclipse.jetty:jetty-session": -834663410,
- "org.eclipse.jetty:jetty-util": -1520256775,
- "org.eclipse.jetty:jetty-util-ajax": -726746674,
+ "org.eclipse.jetty.ee8:jetty-ee8-nested": -1627496831,
+ "org.eclipse.jetty.ee8:jetty-ee8-security": 1632270986,
+ "org.eclipse.jetty.ee8:jetty-ee8-servlet": -1338697711,
+ "org.eclipse.jetty:jetty-http": -235909997,
+ "org.eclipse.jetty:jetty-io": -44878927,
+ "org.eclipse.jetty:jetty-jmx": 1781043564,
+ "org.eclipse.jetty:jetty-security": -1819173301,
+ "org.eclipse.jetty:jetty-server": -130172210,
+ "org.eclipse.jetty:jetty-session": -1378386067,
+ "org.eclipse.jetty:jetty-util": -444622835,
+ "org.eclipse.jetty:jetty-util-ajax": -622085534,
"org.hamcrest:hamcrest": 1547523135,
"org.jruby:jruby-complete": -2103568068,
"org.json:json": -811907600,
@@ -202,7 +201,7 @@
"org.slf4j:slf4j-ext": -916772347,
"org.slf4j:slf4j-log4j12": -630224096,
"org.slf4j:slf4j-reload4j": 1021466445,
- "org.slf4j:slf4j-simple": -487947767,
+ "org.slf4j:slf4j-simple": 1999565066,
"org.tukaani:xz": -1743168321,
"repositories": 2019057769,
"xerces:xercesImpl": -1165914651,
@@ -429,32 +428,30 @@
"org.commonmark:commonmark-ext-gfm-tables": -1205584749,
"org.commonmark:commonmark-ext-gfm-tables:jar:sources": 1341057091,
"org.commonmark:commonmark:jar:sources": -1511261547,
- "org.eclipse.jetty.ee8:jetty-ee8-nested": -581707497,
- "org.eclipse.jetty.ee8:jetty-ee8-nested:jar:sources": 1832439134,
- "org.eclipse.jetty.ee8:jetty-ee8-security": -216309662,
- "org.eclipse.jetty.ee8:jetty-ee8-security:jar:sources": 1985769014,
- "org.eclipse.jetty.ee8:jetty-ee8-servlet": -1110646724,
- "org.eclipse.jetty.ee8:jetty-ee8-servlet:jar:sources": 1045866630,
+ "org.eclipse.jetty.ee8:jetty-ee8-nested": -1480285467,
+ "org.eclipse.jetty.ee8:jetty-ee8-nested:jar:sources": -2141029892,
+ "org.eclipse.jetty.ee8:jetty-ee8-security": -1089777429,
+ "org.eclipse.jetty.ee8:jetty-ee8-security:jar:sources": -374234244,
+ "org.eclipse.jetty.ee8:jetty-ee8-servlet": 709534403,
+ "org.eclipse.jetty.ee8:jetty-ee8-servlet:jar:sources": 1796299448,
"org.eclipse.jetty.toolchain:jetty-servlet-api": 1364182673,
"org.eclipse.jetty.toolchain:jetty-servlet-api:jar:sources": 736604807,
- "org.eclipse.jetty:jetty-http": -293230884,
- "org.eclipse.jetty:jetty-http:jar:sources": -1107669868,
- "org.eclipse.jetty:jetty-io": -783344138,
- "org.eclipse.jetty:jetty-io:jar:sources": 1011133100,
- "org.eclipse.jetty:jetty-jmx": 359701595,
- "org.eclipse.jetty:jetty-jmx:jar:sources": -1366075600,
- "org.eclipse.jetty:jetty-security": -109984940,
- "org.eclipse.jetty:jetty-security:jar:sources": -256108816,
- "org.eclipse.jetty:jetty-server": -1931992277,
- "org.eclipse.jetty:jetty-server:jar:sources": 887545786,
- "org.eclipse.jetty:jetty-servlet": -2029359212,
- "org.eclipse.jetty:jetty-servlet:jar:sources": 607287657,
- "org.eclipse.jetty:jetty-session": 1317046857,
- "org.eclipse.jetty:jetty-session:jar:sources": -1905516033,
- "org.eclipse.jetty:jetty-util": 2108090903,
- "org.eclipse.jetty:jetty-util-ajax": -1216843848,
- "org.eclipse.jetty:jetty-util-ajax:jar:sources": 884169258,
- "org.eclipse.jetty:jetty-util:jar:sources": -1854246232,
+ "org.eclipse.jetty:jetty-http": -1578822522,
+ "org.eclipse.jetty:jetty-http:jar:sources": -1317713476,
+ "org.eclipse.jetty:jetty-io": -225847225,
+ "org.eclipse.jetty:jetty-io:jar:sources": 116677681,
+ "org.eclipse.jetty:jetty-jmx": 1202016563,
+ "org.eclipse.jetty:jetty-jmx:jar:sources": -1552312519,
+ "org.eclipse.jetty:jetty-security": 501899561,
+ "org.eclipse.jetty:jetty-security:jar:sources": 1985223928,
+ "org.eclipse.jetty:jetty-server": -963731471,
+ "org.eclipse.jetty:jetty-server:jar:sources": -466994191,
+ "org.eclipse.jetty:jetty-session": 1869188771,
+ "org.eclipse.jetty:jetty-session:jar:sources": -1630590830,
+ "org.eclipse.jetty:jetty-util": -1027747345,
+ "org.eclipse.jetty:jetty-util-ajax": 573093314,
+ "org.eclipse.jetty:jetty-util-ajax:jar:sources": 455294676,
+ "org.eclipse.jetty:jetty-util:jar:sources": -280937557,
"org.hamcrest:hamcrest": 1282317766,
"org.hamcrest:hamcrest-core": 649657847,
"org.hamcrest:hamcrest-core:jar:sources": -1646511374,
@@ -499,8 +496,8 @@
"org.slf4j:slf4j-ext:jar:sources": 194861628,
"org.slf4j:slf4j-reload4j": -1779685465,
"org.slf4j:slf4j-reload4j:jar:sources": -1558574593,
- "org.slf4j:slf4j-simple": -444090931,
- "org.slf4j:slf4j-simple:jar:sources": 1767487902,
+ "org.slf4j:slf4j-simple": -1055624668,
+ "org.slf4j:slf4j-simple:jar:sources": 751828941,
"org.tukaani:xz": -321288404,
"org.tukaani:xz:jar:sources": -893332662,
"xerces:xercesImpl": -1852819301,
@@ -1289,24 +1286,24 @@
},
"org.eclipse.jetty.ee8:jetty-ee8-nested": {
"shasums": {
- "jar": "876fd83d52002d26ecb1a145ed7ae2397742a77c5e8ea9c6d309071b41cbb59c",
- "sources": "c4f2633f8501679b59a0156cd64a6b49f34c27abf9896b6113f45fa7f6ae7d4a"
+ "jar": "240df6fb5bb28545183cbac87f191c0d21074b17a2c9d4562581a68a8d79c347",
+ "sources": "45b7a070430ced248fab480132c2a02c98b64181b619f11fdc27291fc60cdefc"
},
- "version": "12.1.8"
+ "version": "12.1.10"
},
"org.eclipse.jetty.ee8:jetty-ee8-security": {
"shasums": {
- "jar": "5643ebb9781e97b4ebc5096bea9533fefdeef535b1afa8b8f2c7524901a26dbe",
- "sources": "e29ee9d16fcbaa271c12bb43ee39b29b2c04e1af5087aabf8d1cd18754175eef"
+ "jar": "85351106e71c1036256488bbd2c84879d6316c67cdce3b44dda7835daf82e3c9",
+ "sources": "d5e6227dfbde0e6beb3cf2976cc64049a85b828143bb328f3de3ef06e5a4803f"
},
- "version": "12.1.8"
+ "version": "12.1.10"
},
"org.eclipse.jetty.ee8:jetty-ee8-servlet": {
"shasums": {
- "jar": "183551aaff43938c5fc0fa649b62521b279eacbd53b3e5ee692cb1a3c08a6f8e",
- "sources": "c0bb488146c42812a19c6f8e4c9f43aa55c5cf1c700bfcd2400c0493279159c5"
+ "jar": "f593838935e9c15b9cd6bbe8707af6f5e8204f2732c88c84b654962bac660dbe",
+ "sources": "53b2477db964532be722a1ff8f53ab4d7f88b87012f4e2b4e3360c5ecd08aff0"
},
- "version": "12.1.8"
+ "version": "12.1.10"
},
"org.eclipse.jetty.toolchain:jetty-servlet-api": {
"shasums": {
@@ -1317,66 +1314,59 @@
},
"org.eclipse.jetty:jetty-http": {
"shasums": {
- "jar": "02c6514977f0051dfdecf8d0799acf7a88fd8008a5fd9320a92f2e5db45d297b",
- "sources": "1851f55b408241a6ae692730dd9bda9d1ecf7f0be6a9ccc471affa5bf8d07b9c"
+ "jar": "090f276739fd9bf8c30511007caec669ea3804b1df1061c37f44467474bee71d",
+ "sources": "4d416e2686881085327d3a28e349029d4ae9fc9b44db831291633f18bbf01625"
},
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-io": {
"shasums": {
- "jar": "f6246a2cf0abcee7f0971217c0ce4cd30d8ce15a91530363457113907ab38690",
- "sources": "f21960b5fe18c1fa4281aa0ba1ce8f2f7d4d8f00e64e08d536b6d6577ca92489"
+ "jar": "448fc0f8f6f5f7251fc46de8e3aae7da14bd7c571a8043dac3dc381d08228fa0",
+ "sources": "bf40abffd40e759b16b642e12dfacb7bca1d0c937f5456b62506cc78169f6b56"
},
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-jmx": {
"shasums": {
- "jar": "24b24e205b7f1a7812c781e95ac6154b044e09abf0d13432777fc0e7fbd2f4ac",
- "sources": "5627d14d6d36d68f14a2765adfafe18852099e19821fe73a68adb93ed8819eb5"
+ "jar": "baaaf76b139335125bfa51109c80d271de73f40ee8b5270674f56e90a66e9d81",
+ "sources": "b45a4c63d7b7ea44ca6eb9b9c5fbf1d100069bec66942c83ee553d05335a1fcb"
},
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-security": {
"shasums": {
- "jar": "af923d4f395a73bf8ddcb754f42d7617c6b7055e37e5a6b625ed894f73107ae9",
- "sources": "0f8718fe938f0c8a5c3098129b67d13381c1fef0d56765627ccc2e017fc2654b"
+ "jar": "2f34b7895cec4e3547a1b52e12e7e92b3f3a110bf3c17637f8743ca3f4e42f0c",
+ "sources": "9e55b7f04431d4cc723a85a18ddc910e71f5b1a284c28b059d297d07509b4ff8"
},
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-server": {
"shasums": {
- "jar": "ba957ae07da647023cfa52c923732aea1c67f5273a594cee1863365dfebb9a02",
- "sources": "089098dce0a947401a52bd00056427e1a2e348a71340a00e496c3139c14bafcb"
+ "jar": "4b0108e87abada7027123deca17186249413232dad0a2bd58a4e70a987b5354a",
+ "sources": "5e7693e35285d286dcd0bfdc73d74e6824027eeaaa0a9b4c70c0080475c22f71"
},
- "version": "9.4.57.v20241219"
- },
- "org.eclipse.jetty:jetty-servlet": {
- "shasums": {
- "jar": "c5e9517974dec9e4606b2d810f4995ea81091b1e24bd9640cb45d8b2aefd722c",
- "sources": "d3214106ebbfa9034aa041ea26caa080a99c494ae6275f88c95bc63796bc0367"
- },
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-session": {
"shasums": {
- "jar": "ebe84dd41942d7adda5f7d1304095d274e7915999451d848e887cbd409f947ea",
- "sources": "3741c771d7204c47d8e72ae5b6e834ab4710c9fe6118d4777bfd910a17bb847f"
+ "jar": "164649123d15a3f2be5c196e82aa652dff05c75362db71b0f4ab6bb35165020a",
+ "sources": "b11e8cfb2db04ac2d1633bccfd47ba9e1b3afca0b75d4354a38140ba3e94c83e"
},
- "version": "12.1.8"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-util": {
"shasums": {
- "jar": "6ccbf678716778e316cc097d8aada4fe2a2e16c0bbfd8a1763204d6724b423f4",
- "sources": "77d5935c637276d08da2e1141a7fe4d9db4a2d072b6b418b625b261009d0cb4c"
+ "jar": "c52b4ff62cdacca8a399c611231129e6bd1074db7e3892e78cd106725cdd0ef1",
+ "sources": "209630667d8e042f187bed4e754c3f8af7c5247888fc83b8dc97b5bb2134d435"
},
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.eclipse.jetty:jetty-util-ajax": {
"shasums": {
- "jar": "67af50dd7714803b1bcdfabac181dd8b279d0ba6ba7fd27ea80c5b2099016542",
- "sources": "19888b386e9d4e81c81ce94465e8263680e1abcd83f324ba1992d7ded099abad"
+ "jar": "73dfbf388b46c9e2afbc78823ea556f8d25cf851902f99873d03df90becc2b97",
+ "sources": "4617309092393ed2f6ed76d915f24b518ccbff8c8731124bf109e346607e86b3"
},
- "version": "9.4.57.v20241219"
+ "version": "12.1.10"
},
"org.hamcrest:hamcrest": {
"shasums": {
@@ -1534,10 +1524,10 @@
},
"org.slf4j:slf4j-simple": {
"shasums": {
- "jar": "ddfea59ac074c6d3e24ac2c38622d2d963895e17f70b38ed4bdae4d780be6964",
- "sources": "30b660e79419bfcebd678e75bdfe3644eaf325f50253a68395d93634da5953df"
+ "jar": "8268bd018a5709b07209e0d8ca6221a37584ba1bc12ba985b8335a82c648bdd0",
+ "sources": "977f636bc90dc879c56cd6b6158abf0ee77a6f4619ab23342781a273b743786b"
},
- "version": "2.0.17"
+ "version": "2.0.18"
},
"org.tukaani:xz": {
"shasums": {
@@ -1824,32 +1814,36 @@
],
"org.eclipse.jetty:jetty-http": [
"org.eclipse.jetty:jetty-io",
- "org.eclipse.jetty:jetty-util"
+ "org.eclipse.jetty:jetty-util",
+ "org.slf4j:slf4j-api"
],
"org.eclipse.jetty:jetty-io": [
- "org.eclipse.jetty:jetty-util"
+ "org.eclipse.jetty:jetty-util",
+ "org.slf4j:slf4j-api"
],
"org.eclipse.jetty:jetty-jmx": [
- "org.eclipse.jetty:jetty-util"
+ "org.eclipse.jetty:jetty-util",
+ "org.slf4j:slf4j-api"
],
"org.eclipse.jetty:jetty-security": [
- "org.eclipse.jetty:jetty-server"
+ "org.eclipse.jetty:jetty-server",
+ "org.slf4j:slf4j-api"
],
"org.eclipse.jetty:jetty-server": [
- "javax.servlet:javax.servlet-api",
"org.eclipse.jetty:jetty-http",
- "org.eclipse.jetty:jetty-io"
- ],
- "org.eclipse.jetty:jetty-servlet": [
- "org.eclipse.jetty:jetty-security",
- "org.eclipse.jetty:jetty-util-ajax"
+ "org.eclipse.jetty:jetty-io",
+ "org.slf4j:slf4j-api"
],
"org.eclipse.jetty:jetty-session": [
"org.eclipse.jetty:jetty-server",
"org.slf4j:slf4j-api"
],
+ "org.eclipse.jetty:jetty-util": [
+ "org.slf4j:slf4j-api"
+ ],
"org.eclipse.jetty:jetty-util-ajax": [
- "org.eclipse.jetty:jetty-util"
+ "org.eclipse.jetty:jetty-util",
+ "org.slf4j:slf4j-api"
],
"org.mockito:mockito-core": [
"net.bytebuddy:byte-buddy",
@@ -3778,35 +3772,34 @@
"org.eclipse.jetty:jetty-http": [
"org.eclipse.jetty.http",
"org.eclipse.jetty.http.compression",
+ "org.eclipse.jetty.http.content",
"org.eclipse.jetty.http.pathmap"
],
"org.eclipse.jetty:jetty-io": [
"org.eclipse.jetty.io",
+ "org.eclipse.jetty.io.content",
+ "org.eclipse.jetty.io.internal",
"org.eclipse.jetty.io.jmx",
"org.eclipse.jetty.io.ssl"
],
"org.eclipse.jetty:jetty-jmx": [
- "org.eclipse.jetty.jmx",
- "org.eclipse.jetty.util.log.jmx"
+ "org.eclipse.jetty.jmx"
],
"org.eclipse.jetty:jetty-security": [
"org.eclipse.jetty.security",
- "org.eclipse.jetty.security.authentication"
+ "org.eclipse.jetty.security.authentication",
+ "org.eclipse.jetty.security.internal",
+ "org.eclipse.jetty.security.jaas",
+ "org.eclipse.jetty.security.jaas.callback",
+ "org.eclipse.jetty.security.jaas.spi"
],
"org.eclipse.jetty:jetty-server": [
"org.eclipse.jetty.server",
"org.eclipse.jetty.server.handler",
"org.eclipse.jetty.server.handler.gzip",
"org.eclipse.jetty.server.handler.jmx",
- "org.eclipse.jetty.server.jmx",
- "org.eclipse.jetty.server.nio",
- "org.eclipse.jetty.server.resource",
- "org.eclipse.jetty.server.session"
- ],
- "org.eclipse.jetty:jetty-servlet": [
- "org.eclipse.jetty.servlet",
- "org.eclipse.jetty.servlet.jmx",
- "org.eclipse.jetty.servlet.listener"
+ "org.eclipse.jetty.server.internal",
+ "org.eclipse.jetty.server.jmx"
],
"org.eclipse.jetty:jetty-session": [
"org.eclipse.jetty.session"
@@ -3816,7 +3809,7 @@
"org.eclipse.jetty.util.annotation",
"org.eclipse.jetty.util.component",
"org.eclipse.jetty.util.compression",
- "org.eclipse.jetty.util.log",
+ "org.eclipse.jetty.util.jndi",
"org.eclipse.jetty.util.preventers",
"org.eclipse.jetty.util.resource",
"org.eclipse.jetty.util.security",
@@ -4537,8 +4530,6 @@
"org.eclipse.jetty:jetty-security:jar:sources",
"org.eclipse.jetty:jetty-server",
"org.eclipse.jetty:jetty-server:jar:sources",
- "org.eclipse.jetty:jetty-servlet",
- "org.eclipse.jetty:jetty-servlet:jar:sources",
"org.eclipse.jetty:jetty-session",
"org.eclipse.jetty:jetty-session:jar:sources",
"org.eclipse.jetty:jetty-util",
@@ -4835,8 +4826,6 @@
"org.eclipse.jetty:jetty-security:jar:sources",
"org.eclipse.jetty:jetty-server",
"org.eclipse.jetty:jetty-server:jar:sources",
- "org.eclipse.jetty:jetty-servlet",
- "org.eclipse.jetty:jetty-servlet:jar:sources",
"org.eclipse.jetty:jetty-session",
"org.eclipse.jetty:jetty-session:jar:sources",
"org.eclipse.jetty:jetty-util",
@@ -5215,12 +5204,14 @@
},
"org.eclipse.jetty:jetty-http": {
"org.eclipse.jetty.http.HttpFieldPreEncoder": [
- "org.eclipse.jetty.http.Http1FieldPreEncoder"
+ "org.eclipse.jetty.http.Http10FieldPreEncoder",
+ "org.eclipse.jetty.http.Http11FieldPreEncoder"
]
},
"org.eclipse.jetty:jetty-http:jar:sources": {
"org.eclipse.jetty.http.HttpFieldPreEncoder": [
- "org.eclipse.jetty.http.Http1FieldPreEncoder"
+ "org.eclipse.jetty.http.Http10FieldPreEncoder",
+ "org.eclipse.jetty.http.Http11FieldPreEncoder"
]
},
"org.jruby:jruby-complete": {
diff --git a/java/com/google/gerrit/pgm/http/jetty/BUILD b/java/com/google/gerrit/pgm/http/jetty/BUILD
index e006c91..f6416fb 100644
--- a/java/com/google/gerrit/pgm/http/jetty/BUILD
+++ b/java/com/google/gerrit/pgm/http/jetty/BUILD
@@ -24,6 +24,7 @@
"//lib/guice:guice-assistedinject",
"//lib/guice:guice-servlet",
"//lib/jetty:jmx",
+ "//lib/jetty:nested",
"//lib/jetty:server",
"//lib/jetty:servlet",
"//lib/log:log4j",
diff --git a/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java b/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
index 1c43240..ff8b1e5 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
@@ -20,14 +20,14 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.util.http.CacheHeaders;
import java.io.IOException;
+import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.ee8.nested.ErrorHandler;
+import org.eclipse.jetty.ee8.nested.Request;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.server.HttpConnection;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.ErrorHandler;
class HiddenErrorHandler extends ErrorHandler {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -35,18 +35,17 @@
@Override
public void handle(
String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res)
- throws IOException {
- HttpConnection conn = HttpConnection.getCurrentConnection();
+ throws IOException, ServletException {
baseRequest.setHandled(true);
try {
log(req);
} finally {
- reply(conn, res);
+ reply(baseRequest, res);
}
}
- private void reply(HttpConnection conn, HttpServletResponse res) throws IOException {
- byte[] msg = message(conn);
+ private void reply(Request baseRequest, HttpServletResponse res) throws IOException {
+ byte[] msg = message(baseRequest);
res.setHeader(HttpHeader.CONTENT_TYPE.asString(), "text/plain; charset=ISO-8859-1");
res.setContentLength(msg.length);
try {
@@ -58,15 +57,12 @@
}
}
- private static byte[] message(HttpConnection conn) {
- String msg;
- if (conn == null) {
- msg = "";
- } else {
- msg = conn.getHttpChannel().getResponse().getReason();
- if (msg == null) {
- msg = HttpStatus.getMessage(conn.getHttpChannel().getResponse().getStatus());
- }
+ private static byte[] message(Request baseRequest) {
+ // Preserve a custom reason phrase (e.g. from sendError(int, String)) when
+ // present, falling back to the standard HTTP status phrase otherwise.
+ String msg = baseRequest.getResponse().getReason();
+ if (msg == null) {
+ msg = Strings.nullToEmpty(HttpStatus.getMessage(baseRequest.getResponse().getStatus()));
}
return msg.getBytes(ISO_8859_1);
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
index 8ad89b2..f279150 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
@@ -100,26 +100,27 @@
null // MDC properties
);
- String uri = req.getRequestURI();
- if (!Strings.isNullOrEmpty(req.getQueryString())) {
- uri += "?" + LogRedactUtil.redactQueryString(req.getQueryString());
- }
+ String path = req.getHttpURI().getPath();
+ String query = req.getHttpURI().getQuery();
+ String uri =
+ Strings.isNullOrEmpty(query) ? path : path + "?" + LogRedactUtil.redactQueryString(query);
+
String user = (String) req.getAttribute(GetUserFilter.USER_ATTR_KEY);
if (user != null) {
event.setProperty(P_USER, user);
}
- set(event, P_HOST, req.getRemoteAddr());
+ set(event, P_HOST, Request.getRemoteAddr(req));
set(event, P_METHOD, req.getMethod());
set(event, P_RESOURCE, uri);
- set(event, P_PROTOCOL, req.getProtocol());
+ set(event, P_PROTOCOL, req.getConnectionMetaData().getProtocol());
set(event, P_STATUS, rsp.getStatus());
- set(event, P_CONTENT_LENGTH, rsp.getContentCount());
- set(event, P_LATENCY, System.currentTimeMillis() - req.getTimeStamp());
- set(event, P_REFERER, req.getHeader("Referer"));
- set(event, P_USER_AGENT, req.getHeader("User-Agent"));
- set(event, P_COMMAND_STATUS, rsp.getHeader(GIT_COMMAND_STATUS_HEADER));
- String traceId = rsp.getHeader(RestApiServlet.X_GERRIT_TRACE);
+ set(event, P_CONTENT_LENGTH, Response.getContentBytesWritten(rsp));
+ set(event, P_LATENCY, System.currentTimeMillis() - Request.getTimeStamp(req));
+ set(event, P_REFERER, req.getHeaders().get("Referer"));
+ set(event, P_USER_AGENT, req.getHeaders().get("User-Agent"));
+ set(event, P_COMMAND_STATUS, rsp.getHeaders().get(GIT_COMMAND_STATUS_HEADER));
+ String traceId = rsp.getHeaders().get(RestApiServlet.X_GERRIT_TRACE);
if (traceId != null) {
set(event, P_TRACE_ID, traceId);
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
index 65eb405..7cde777 100644
--- a/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
+++ b/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -52,7 +52,14 @@
import javax.servlet.Filter;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
+import org.eclipse.jetty.ee8.nested.SessionHandler;
+import org.eclipse.jetty.ee8.servlet.DefaultServlet;
+import org.eclipse.jetty.ee8.servlet.FilterHolder;
+import org.eclipse.jetty.ee8.servlet.ServletContextHandler;
+import org.eclipse.jetty.ee8.servlet.ServletHolder;
import org.eclipse.jetty.http.HttpScheme;
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.io.ConnectionStatistics;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Connector;
@@ -60,21 +67,14 @@
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.BlockingArrayQueue;
-import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jgit.lib.Config;
@@ -259,15 +259,11 @@
Handler app = makeContext(env, cfg, sessionHandler);
if (cfg.getBoolean("httpd", "requestLog", !reverseProxy)) {
- RequestLogHandler handler = new RequestLogHandler();
- handler.setRequestLog(httpLogFactory.get());
- handler.setHandler(app);
- app = handler;
+ httpd.setRequestLog(httpLogFactory.get());
}
if (cfg.getBoolean("httpd", "registerMBeans", false)) {
MBeanContainer mbean = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
httpd.addEventListener(mbean);
- httpd.addBean(Log.getRootLogger());
httpd.addBean(mbean);
}
@@ -313,6 +309,24 @@
final ServerConnector c;
HttpConfiguration config = defaultConfig(requestHeaderSize);
+ // Jetty 12 changed the default UriCompliance to RFC3986 (strict),
+ // which rejects two URI shapes Gerrit's REST API depends on:
+ // - AMBIGUOUS_PATH_SEPARATOR: encoded '/' (%2F) inside a path
+ // segment, used for project/branch names (e.g.
+ // DELETE /projects/foo%2Fbar/branches/refs%2Fheads%2Ftest);
+ // - AMBIGUOUS_PATH_ENCODING: an encoded character that itself
+ // decodes to a reserved one (e.g. %25 decoding to '%'),
+ // hit by /changes/%3C%25%3DFOO%25%3E~1/detail where the
+ // decoded identifier '<%=FOO%>' contains a literal '%'.
+ // Allow exactly these two violations; broader presets like LEGACY
+ // also permit suspicious characters, USER_INFO, FRAGMENT etc. that
+ // Gerrit's REST surface does not need.
+ config.setUriCompliance(
+ UriCompliance.from(
+ EnumSet.of(
+ UriCompliance.Violation.AMBIGUOUS_PATH_SEPARATOR,
+ UriCompliance.Violation.AMBIGUOUS_PATH_ENCODING)));
+
if (AuthType.CLIENT_SSL_CERT_LDAP.equals(authType) && !"https".equals(u.getScheme())) {
throw new IllegalArgumentException(
"Protocol '"
@@ -373,11 +387,27 @@
} else if ("proxy-https".equals(u.getScheme())) {
defaultPort = 8080;
config.addCustomizer(new ForwardedRequestCustomizer());
+ // For a proxy that terminates TLS, mark every request as HTTPS
+ // unconditionally. ForwardedRequestCustomizer alone only sets
+ // isSecure() when the proxy sends X-Forwarded-Proto=https or
+ // X-Proxied-Https=on; this wrapper covers proxies that don't.
+ // Jetty 12's HttpConfiguration.Customizer returns a (possibly
+ // wrapped) Request, so wrap the URI's scheme and override isSecure().
config.addCustomizer(
- (connector, channelConfig, request) -> {
- request.setScheme(HttpScheme.HTTPS.asString());
- request.setSecure(true);
- });
+ (request, responseHeaders) ->
+ new Request.Wrapper(request) {
+ @Override
+ public HttpURI getHttpURI() {
+ return HttpURI.build(super.getHttpURI())
+ .scheme(HttpScheme.HTTPS.asString())
+ .asImmutable();
+ }
+
+ @Override
+ public boolean isSecure() {
+ return true;
+ }
+ });
c = newServerConnector(server, acceptors, config);
} else {
@@ -428,9 +458,21 @@
private HttpConfiguration defaultConfig(int requestHeaderSize) {
HttpConfiguration config = new HttpConfiguration();
config.setRequestHeaderSize(requestHeaderSize);
+ // Jetty 12 changed the default for relativeRedirectAllowed from false to
+ // true (https://github.com/jetty/jetty.project/issues/11947); restore the
+ // pre-Jetty-12 behaviour Gerrit's redirect handling expects.
+ config.setRelativeRedirectAllowed(false);
config.setSendServerVersion(false);
config.setSendDateHeader(true);
- config.setBlockingTimeout(0);
+ // TODO(davido): consider configuring HttpConfiguration.setMinResponseDataRate
+ // and setMinRequestDataRate. Jetty 12 removed setBlockingTimeout (deprecated
+ // in Jetty 9) in favour of these minimum bytes/sec knobs. Gerrit's previous
+ // setBlockingTimeout(0) was an explicit opt-in to Jetty 9's special
+ // "0 == use idle timeout" semantic (the Jetty 9 default was -1, i.e.
+ // blocking-timeout disabled). In Jetty 12 the blocking-timeout knob no
+ // longer exists; the connector's idle timeout governs all stalled IO.
+ // Revisit if slow-client mitigation becomes desirable.
+
return config;
}
@@ -469,6 +511,13 @@
return site.resolve(path);
}
+ // BlockingArrayQueue's 3-arg constructor is deprecated for removal in
+ // Jetty 12.1.2+ -- the public API no longer offers a bounded-but-growable
+ // queue matching Gerrit's historical (initial = minThreads, grow up to
+ // maxCapacity) semantics. Revisit when Jetty 12.2 drops it: either switch
+ // to the unbounded constructor (Jetty's own recommendation) or to the
+ // fixed-size 1-arg one.
+ @SuppressWarnings("removal")
private QueuedThreadPool threadPool(Config cfg, ThreadSettingsConfig threadSettingsConfig) {
int maxThreads = threadSettingsConfig.getHttpdMaxThreads();
int minThreads = cfg.getInt("httpd", null, "minthreads", 5);
@@ -502,7 +551,7 @@
paths.add(p);
}
- final List<ContextHandler> all = new ArrayList<>();
+ final List<Handler> all = new ArrayList<>();
for (String path : paths) {
all.add(makeContext(path, env, cfg, sessionHandler));
}
@@ -522,7 +571,7 @@
return r;
}
- private ContextHandler makeContext(
+ private Handler makeContext(
final String contextPath, JettyEnv env, Config cfg, SessionHandler sessionHandler) {
final ServletContextHandler app = new ServletContextHandler();
@@ -601,6 +650,8 @@
ds.setInitParameter("gzip", "true");
app.setWelcomeFiles(new String[0]);
- return app;
+ // ee8 ContextHandler implements Supplier<org.eclipse.jetty.server.Handler>;
+ // unwrap to the core Handler for installation into the server's handler tree.
+ return app.get();
}
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/SameSiteFilter.java b/java/com/google/gerrit/pgm/http/jetty/SameSiteFilter.java
index ae30cd2..9e8f2d6 100644
--- a/java/com/google/gerrit/pgm/http/jetty/SameSiteFilter.java
+++ b/java/com/google/gerrit/pgm/http/jetty/SameSiteFilter.java
@@ -28,13 +28,23 @@
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
-import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jgit.lib.Config;
@Singleton
public class SameSiteFilter implements Filter {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+ // Magic strings inherited from Jetty 9's HttpCookie.SAME_SITE_*_COMMENT
+ // public constants. In Jetty 12 these constants moved to
+ // org.eclipse.jetty.ee{8,9}.nested.Response as protected fields, so they are
+ // no longer accessible from application code -- but the underlying mechanism
+ // is preserved: the ee8 nested Response inspects a Cookie's comment for
+ // these markers and emits a proper SameSite attribute on the wire.
+ // See org.eclipse.jetty.ee8.nested.Response (the values are kept verbatim).
+ private static final String SAME_SITE_LAX_COMMENT = "__SAME_SITE_LAX__";
+ private static final String SAME_SITE_STRICT_COMMENT = "__SAME_SITE_STRICT__";
+ private static final String SAME_SITE_NONE_COMMENT = "__SAME_SITE_NONE__";
+
private final String sameSite;
@Inject
@@ -55,9 +65,9 @@
}
String sameSiteComment =
switch (sameSite.toLowerCase()) {
- case "lax" -> HttpCookie.SAME_SITE_LAX_COMMENT;
- case "strict" -> HttpCookie.SAME_SITE_STRICT_COMMENT;
- case "none" -> HttpCookie.SAME_SITE_NONE_COMMENT;
+ case "lax" -> SAME_SITE_LAX_COMMENT;
+ case "strict" -> SAME_SITE_STRICT_COMMENT;
+ case "none" -> SAME_SITE_NONE_COMMENT;
default ->
throw new ServletException(String.format("Invalid sameSite value: %s", sameSite));
};
diff --git a/java/com/google/gerrit/server/account/AccountManager.java b/java/com/google/gerrit/server/account/AccountManager.java
index 62981a2..c017765 100644
--- a/java/com/google/gerrit/server/account/AccountManager.java
+++ b/java/com/google/gerrit/server/account/AccountManager.java
@@ -298,28 +298,49 @@
accountUpdates.add(a -> a.setFullName(who.getDisplayName()));
}
- if (!realm.allowsEdit(AccountFieldName.USER_NAME)
- && who.getUserName().isPresent()
- && !who.getUserName().equals(user.getUserName())) {
+ String backfilledUsername = null;
+ if (who.getUserName().isPresent() && !who.getUserName().equals(user.getUserName())) {
if (user.getUserName().isPresent()) {
- logger.atWarning().log(
- "Not changing already set username %s to %s",
- user.getUserName().get(), who.getUserName().get());
+ // Username renames on login are intentionally not supported; use PutUsername instead.
+ // Only warn when the realm owns usernames and would prevent an explicit rename anyway.
+ if (!realm.allowsEdit(AccountFieldName.USER_NAME)) {
+ logger.atWarning().log(
+ "Not changing already set username %s to %s",
+ user.getUserName().get(), who.getUserName().get());
+ }
} else {
- logger.atWarning().log("Not setting username to %s", who.getUserName().get());
+ backfilledUsername = who.getUserName().get();
+ ExternalId userNameExtId = createUsername(user.getAccountId(), backfilledUsername);
+ accountUpdates.add(u -> u.addExternalId(userNameExtId));
}
}
if (!accountUpdates.isEmpty()) {
- Optional<AccountState> updatedAccount =
- accountsUpdateProvider
- .get()
- .update(
- "Update Account on Login",
- user.getAccountId(),
- AccountsUpdate.joinDeltaConfigures(accountUpdates));
- if (!updatedAccount.isPresent()) {
- throw new StorageException("Account " + user.getAccountId() + " has been deleted");
+ try {
+ Optional<AccountState> updatedAccount =
+ accountsUpdateProvider
+ .get()
+ .update(
+ "Update Account on Login",
+ user.getAccountId(),
+ AccountsUpdate.joinDeltaConfigures(accountUpdates));
+ if (!updatedAccount.isPresent()) {
+ throw new StorageException("Account " + user.getAccountId() + " has been deleted");
+ }
+ } catch (DuplicateExternalIdKeyException e) {
+ throw new AccountException(
+ "Cannot assign external ID \""
+ + e.getDuplicateKey().get()
+ + "\" to account "
+ + user.getAccountId()
+ + "; external ID already in use.",
+ e);
+ }
+ if (backfilledUsername != null) {
+ sshKeyCache.evict(backfilledUsername);
+ logger.atInfo().log(
+ "Backfilled missing username external ID %s for account %s",
+ backfilledUsername, user.getAccountId());
}
}
}
diff --git a/java/com/google/gerrit/server/restapi/group/DeleteMembers.java b/java/com/google/gerrit/server/restapi/group/DeleteMembers.java
index a4d28c2..b30ed8f 100644
--- a/java/com/google/gerrit/server/restapi/group/DeleteMembers.java
+++ b/java/com/google/gerrit/server/restapi/group/DeleteMembers.java
@@ -76,7 +76,8 @@
if (Strings.isNullOrEmpty(nameOrEmail)) {
continue;
}
- membersToRemove.add(accountResolver.resolve(nameOrEmail).asUnique().account().id());
+ membersToRemove.add(
+ accountResolver.resolveIncludeInactive(nameOrEmail).asUnique().account().id());
}
AccountGroup.UUID groupUuid = internalGroup.getGroupUUID();
try {
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AbstractAccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AbstractAccountIT.java
index 75c92b1..7b2e2dc 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AbstractAccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AbstractAccountIT.java
@@ -179,7 +179,6 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpResponse;
@@ -3115,7 +3114,8 @@
GroupMembership testGroupMembership =
new GroupMembership() {
@Override
- public ImmutableSet<AccountGroup.UUID> intersection(Iterable<AccountGroup.UUID> groupUuids) {
+ public ImmutableSet<AccountGroup.UUID> intersection(
+ Iterable<AccountGroup.UUID> groupUuids) {
return StreamSupport.stream(groupUuids.spliterator(), /* parallel= */ false)
.filter(this::contains)
.collect(toImmutableSet());
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java
index 1db2414..8d3bb85 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java
@@ -188,6 +188,53 @@
}
@Test
+ public void authenticateBackfillsMissingUsernameExternalId() throws Exception {
+ String username = "foo";
+ Account.Id accountId = Account.id(seq.nextAccountId());
+ ExternalId.Key gerritExtIdKey = externalIdKeyFactory.create(ExternalId.SCHEME_GERRIT, username);
+ ExternalId.Key usernameExtIdKey =
+ externalIdKeyFactory.create(ExternalId.SCHEME_USERNAME, username);
+ accountsUpdate.insert(
+ "Create Test Account",
+ accountId,
+ u -> u.addExternalId(externalIdFactory.create(gerritExtIdKey, accountId)));
+ assertNoSuchExternalIds(usernameExtIdKey);
+
+ AuthRequest who = authRequestFactory.createForUser(username);
+ AuthResult authResult = accountManager.authenticate(who);
+
+ assertAuthResultForExistingAccount(authResult, accountId, gerritExtIdKey);
+ assertExternalId(usernameExtIdKey, accountId, null);
+ }
+
+ @Test
+ public void authenticateDoesNotRenameExistingUsername() throws Exception {
+ String existingUsername = "foo";
+ String renamedUsername = "bar";
+ Account.Id accountId = Account.id(seq.nextAccountId());
+ ExternalId.Key gerritExtIdKey =
+ externalIdKeyFactory.create(ExternalId.SCHEME_GERRIT, existingUsername);
+ ExternalId.Key existingUsernameExtIdKey =
+ externalIdKeyFactory.create(ExternalId.SCHEME_USERNAME, existingUsername);
+ ExternalId.Key renamedUsernameExtIdKey =
+ externalIdKeyFactory.create(ExternalId.SCHEME_USERNAME, renamedUsername);
+ accountsUpdate.insert(
+ "Create Test Account",
+ accountId,
+ u ->
+ u.addExternalId(externalIdFactory.create(gerritExtIdKey, accountId))
+ .addExternalId(externalIdFactory.create(existingUsernameExtIdKey, accountId)));
+
+ AuthRequest who = authRequestFactory.createForUser(existingUsername);
+ who.setUserName(renamedUsername);
+ AuthResult authResult = accountManager.authenticate(who);
+
+ assertAuthResultForExistingAccount(authResult, accountId, gerritExtIdKey);
+ assertExternalId(existingUsernameExtIdKey, accountId, null);
+ assertNoSuchExternalIds(renamedUsernameExtIdKey);
+ }
+
+ @Test
public void authenticateWithExternalUser() throws Exception {
String username = "foo";
Account.Id accountId = Account.id(seq.nextAccountId());
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index d7007b4..48e4939 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -218,6 +218,37 @@
}
@Test
+ public void removeInactiveMemberByUserName() throws Exception {
+ String inactiveMemberUserName = name("inactiveUser");
+ Account.Id inactiveAccountId =
+ accountOperations.newAccount().username(inactiveMemberUserName).inactive().create();
+ AccountGroup.UUID group = groupOperations.newGroup().addMember(inactiveAccountId).create();
+
+ gApi.groups().id(group.get()).removeMembers(inactiveMemberUserName);
+
+ ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
+ assertThat(members).isEmpty();
+ }
+
+ @Test
+ public void removeInactiveMemberByEmail() throws Exception {
+ String inactiveMemberEmail = "inactiveUser@example.com";
+ Account.Id inactiveAccountId =
+ accountOperations
+ .newAccount()
+ .username(name("inactiveUser"))
+ .inactive()
+ .preferredEmail(inactiveMemberEmail)
+ .create();
+ AccountGroup.UUID group = groupOperations.newGroup().addMember(inactiveAccountId).create();
+
+ gApi.groups().id(group.get()).removeMembers(inactiveMemberEmail);
+
+ ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
+ assertThat(members).isEmpty();
+ }
+
+ @Test
public void addExternalGroups() throws Exception {
AccountGroup.UUID group1 = groupOperations.newGroup().create();
AccountGroup.UUID group2 = groupOperations.newGroup().create();
diff --git a/javatests/com/google/gerrit/pgm/BUILD b/javatests/com/google/gerrit/pgm/BUILD
index d30e7ee..34cce11 100644
--- a/javatests/com/google/gerrit/pgm/BUILD
+++ b/javatests/com/google/gerrit/pgm/BUILD
@@ -10,6 +10,7 @@
"//java/com/google/gerrit/pgm/util",
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server/securestore/testing",
+ "//javatests/com/google/gerrit/util/http/testutil",
"//lib:guava",
"//lib:jgit",
"//lib:jgit-junit",
diff --git a/javatests/com/google/gerrit/pgm/http/jetty/ProjectQoSFilterTest.java b/javatests/com/google/gerrit/pgm/http/jetty/ProjectQoSFilterTest.java
index 23c9724..8253b90 100644
--- a/javatests/com/google/gerrit/pgm/http/jetty/ProjectQoSFilterTest.java
+++ b/javatests/com/google/gerrit/pgm/http/jetty/ProjectQoSFilterTest.java
@@ -30,8 +30,6 @@
import javax.servlet.AsyncEvent;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import org.eclipse.jetty.server.Request;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -163,12 +161,8 @@
}
}
- private static final class FakeHttpServletRequest extends HttpServletRequestWrapper {
-
- FakeHttpServletRequest() {
- super(new Request(null, null));
- }
-
+ private static final class FakeHttpServletRequest
+ extends com.google.gerrit.util.http.testutil.FakeHttpServletRequest {
@Override
public String getRemoteHost() {
return "1.2.3.4";
diff --git a/lib/jetty/BUILD b/lib/jetty/BUILD
index fc029ed..10bcc82 100644
--- a/lib/jetty/BUILD
+++ b/lib/jetty/BUILD
@@ -6,16 +6,29 @@
visibility = ["//visibility:public"],
exports = [
":util-ajax",
- "@external_deps//:org_eclipse_jetty_jetty_servlet",
+ "@external_deps//:org_eclipse_jetty_ee8_jetty_ee8_servlet",
],
- runtime_deps = [":security"],
+ runtime_deps = [
+ ":nested",
+ ":security",
+ ],
+)
+
+java_library(
+ name = "nested",
+ data = ["//lib:LICENSE-Apache2.0"],
+ visibility = ["//visibility:public"],
+ exports = ["@external_deps//:org_eclipse_jetty_ee8_jetty_ee8_nested"],
)
java_library(
name = "security",
data = ["//lib:LICENSE-Apache2.0"],
visibility = ["//visibility:public"],
- exports = ["@external_deps//:org_eclipse_jetty_jetty_security"],
+ exports = [
+ "@external_deps//:org_eclipse_jetty_ee8_jetty_ee8_security",
+ "@external_deps//:org_eclipse_jetty_jetty_security",
+ ],
runtime_deps = [":server"],
)
@@ -25,6 +38,7 @@
visibility = ["//visibility:public"],
exports = [
":http",
+ ":session",
"@external_deps//:org_eclipse_jetty_jetty_server",
],
)
@@ -65,6 +79,12 @@
)
java_library(
+ name = "session",
+ data = ["//lib:LICENSE-Apache2.0"],
+ exports = ["@external_deps//:org_eclipse_jetty_jetty_session"],
+)
+
+java_library(
name = "util-ajax",
data = ["//lib:LICENSE-Apache2.0"],
exports = ["@external_deps//:org_eclipse_jetty_jetty_util_ajax"],
diff --git a/modules/jgit b/modules/jgit
index 0675211..c46df0c 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 067521170e2a7308c6a1292a99900eadcee0b790
+Subproject commit c46df0c50f75b68430dcb12a200ee2cbdd7e50e1
diff --git a/plugins/commit-message-length-validator b/plugins/commit-message-length-validator
index 1e08c1e..275c528 160000
--- a/plugins/commit-message-length-validator
+++ b/plugins/commit-message-length-validator
@@ -1 +1 @@
-Subproject commit 1e08c1ef59b4c812ee046746869e0debc7569d9e
+Subproject commit 275c528d58a12d8c90cd9755240be06844fdea07
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 7d5c0df..caa60af 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -1320,7 +1320,7 @@
{
label: 'URL and title',
shortcut: 'r',
- value: `${changeURL}: ${this.change?.subject}`,
+ value: `${changeURL} - ${this.change?.subject}`,
},
{
label: 'Markdown',
diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
index 9e538f6..ff1d059 100644
--- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
+++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
@@ -26,12 +26,12 @@
['application/xquery', 'xquery'],
['application/x-epp', 'epp'],
['application/x-erb', 'erb'],
- ['text/ada', 'ada'],
['text/css', 'css'],
['text/html', 'html'],
['text/javascript', 'js'],
['text/jsx', 'jsx'],
['text/tsx', 'jsx'],
+ ['text/x-ada', 'ada'],
['text/x-c', 'cpp'],
['text/x-c++src', 'cpp'],
['text/x-clojure', 'clojure'],
diff --git a/tools/deps.toml b/tools/deps.toml
index 3b4b7af..75ffd76 100644
--- a/tools/deps.toml
+++ b/tools/deps.toml
@@ -8,7 +8,7 @@
gitiles = "1.6.0"
greenmail = "1.5.5"
httpcomp = "4.5.14"
-jetty = "9.4.57.v20241219"
+jetty = "12.1.10"
mail = "1.6.0"
mime4j = "0.8.1"
ow2 = "9.9.1"
@@ -73,12 +73,15 @@
javax-inject = { module = "javax.inject:javax.inject", version = "1" }
javax-mail = { module = "com.sun.mail:javax.mail", version.ref = "mail" }
javax-servlet-api = { module = "javax.servlet:javax.servlet-api", version = "4.0.1" }
+jetty-ee8-nested = { module = "org.eclipse.jetty.ee8:jetty-ee8-nested", version.ref = "jetty" }
+jetty-ee8-security = { module = "org.eclipse.jetty.ee8:jetty-ee8-security", version.ref = "jetty" }
+jetty-ee8-servlet = { module = "org.eclipse.jetty.ee8:jetty-ee8-servlet", version.ref = "jetty" }
jetty-http = { module = "org.eclipse.jetty:jetty-http", version.ref = "jetty" }
jetty-io = { module = "org.eclipse.jetty:jetty-io", version.ref = "jetty" }
jetty-jmx = { module = "org.eclipse.jetty:jetty-jmx", version.ref = "jetty" }
jetty-security = { module = "org.eclipse.jetty:jetty-security", version.ref = "jetty" }
jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "jetty" }
-jetty-servlet = { module = "org.eclipse.jetty:jetty-servlet", version.ref = "jetty" }
+jetty-session = { module = "org.eclipse.jetty:jetty-session", version.ref = "jetty" }
jetty-util = { module = "org.eclipse.jetty:jetty-util", version.ref = "jetty" }
jetty-util-ajax = { module = "org.eclipse.jetty:jetty-util-ajax", version.ref = "jetty" }
json-smart = { module = "net.minidev:json-smart", version = "1.1.1" }
diff --git a/tools/java_deps.MODULE.bazel b/tools/java_deps.MODULE.bazel
index d456542..a899132 100644
--- a/tools/java_deps.MODULE.bazel
+++ b/tools/java_deps.MODULE.bazel
@@ -126,12 +126,6 @@
"com.googlecode.javaewah:JavaEWAH",
"commons-codec:commons-codec",
"org.apache.commons:commons-lang3",
- "org.eclipse.jetty:jetty-http",
- "org.eclipse.jetty:jetty-io",
- "org.eclipse.jetty:jetty-security",
- "org.eclipse.jetty:jetty-server",
- "org.eclipse.jetty:jetty-util",
- "org.eclipse.jetty:jetty-util-ajax",
]
[