1
0
mirror of synced 2026-09-05 08:49:54 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Rob Winch 48f347c9d8 Update to Kotlin 2.2 2025-06-26 17:18:25 -05:00
5928 changed files with 51584 additions and 179813 deletions
+85 -134
View File
@@ -1,13 +1,11 @@
version: 2 version: 2
registries: registries:
shibboleth: spring-milestones:
type: maven-repository type: maven-repository
url: https://build.shibboleth.net/maven/releases url: https://repo.spring.io/milestone
updates: updates:
# 7.0.x
- package-ecosystem: gradle - package-ecosystem: gradle
target-branch: 7.0.x target-branch: 6.5.x
directory: / directory: /
schedule: schedule:
interval: daily interval: daily
@@ -15,61 +13,8 @@ updates:
timezone: Etc/UTC timezone: Etc/UTC
labels: labels:
- 'type: dependency-upgrade' - 'type: dependency-upgrade'
- 'in: build'
registries: registries:
- shibboleth - spring-milestones
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: io.spring.nullability:*
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: com.gradle.enterprise
update-types:
- version-update:semver-major
- version-update:semver-minor
- dependency-name: '*'
update-types:
- version-update:semver-major
- version-update:semver-minor
- package-ecosystem: npm
target-branch: 7.0.x
directory: /docs
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: 7.0.x
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
# 7.1.x
- package-ecosystem: gradle
target-branch: 7.1.x
directory: /
schedule:
interval: daily
time: '03:00'
timezone: Etc/UTC
labels:
- 'type: dependency-upgrade'
- 'in: build'
registries:
- shibboleth
ignore: ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt - dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython - dependency-name: org.python:jython
@@ -81,34 +26,62 @@ updates:
- dependency-name: org.mockito:mockito-bom - dependency-name: org.mockito:mockito-bom
update-types: update-types:
- version-update:semver-major - version-update:semver-major
- dependency-name: com.gradle.enterprise
update-types:
- version-update:semver-major
- version-update:semver-minor
- dependency-name: '*' - dependency-name: '*'
update-types: update-types:
- version-update:semver-major - version-update:semver-major
- version-update:semver-minor - version-update:semver-minor
- package-ecosystem: npm - package-ecosystem: gradle
target-branch: 7.1.x target-branch: 6.4.x
directory: /docs
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: 7.1.x
directory: / directory: /
schedule: schedule:
interval: weekly interval: daily
time: '03:00'
timezone: Etc/UTC
labels: labels:
- 'type: task'
- 'type: dependency-upgrade' - 'type: dependency-upgrade'
- 'in: build' registries:
- spring-milestones
# main ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: '*'
update-types:
- version-update:semver-major
- version-update:semver-minor
- package-ecosystem: gradle
target-branch: 6.3.x
directory: /
schedule:
interval: daily
time: '03:00'
timezone: Etc/UTC
labels:
- 'type: dependency-upgrade'
registries:
- spring-milestones
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: '*'
update-types:
- version-update:semver-major
- version-update:semver-minor
- package-ecosystem: gradle - package-ecosystem: gradle
target-branch: main target-branch: main
directory: / directory: /
@@ -118,9 +91,8 @@ updates:
timezone: Etc/UTC timezone: Etc/UTC
labels: labels:
- 'type: dependency-upgrade' - 'type: dependency-upgrade'
- 'in: build'
registries: registries:
- shibboleth - spring-milestones
ignore: ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt - dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython - dependency-name: org.python:jython
@@ -139,6 +111,36 @@ updates:
- dependency-name: '*' - dependency-name: '*'
update-types: update-types:
- version-update:semver-major - version-update:semver-major
- version-update:semver-minor
- package-ecosystem: github-actions
target-branch: 6.3.x
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'in: build'
ignore:
- dependency-name: sjohnr/*
- package-ecosystem: github-actions
target-branch: docs-build
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'in: build'
- package-ecosystem: npm
target-branch: docs-build
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'in: build'
- package-ecosystem: npm - package-ecosystem: npm
target-branch: main target-branch: main
directory: /docs directory: /docs
@@ -146,63 +148,12 @@ updates:
interval: weekly interval: weekly
labels: labels:
- 'type: task' - 'type: task'
- 'type: dependency-upgrade'
- 'in: build' - 'in: build'
- package-ecosystem: github-actions
target-branch: main
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
# docs-build
- package-ecosystem: gradle
target-branch: docs-build
directory: /
schedule:
interval: daily
time: '03:00'
timezone: Etc/UTC
labels:
- 'type: dependency-upgrade'
registries:
- shibboleth
ignore:
- dependency-name: com.nimbusds:nimbus-jose-jwt
- dependency-name: org.python:jython
- dependency-name: org.apache.directory.server:*
- dependency-name: org.apache.directory.shared:*
- dependency-name: org.junit:junit-bom
update-types:
- version-update:semver-major
- dependency-name: org.mockito:mockito-bom
update-types:
- version-update:semver-major
- dependency-name: com.gradle.enterprise
update-types:
- version-update:semver-major
- version-update:semver-minor
- dependency-name: '*'
update-types:
- version-update:semver-major
- package-ecosystem: npm - package-ecosystem: npm
target-branch: docs-build target-branch: 6.3.x
directory: / directory: /docs
schedule: schedule:
interval: weekly interval: weekly
labels: labels:
- 'type: task' - 'type: task'
- 'type: dependency-upgrade'
- 'in: build'
- package-ecosystem: github-actions
target-branch: docs-build
directory: /
schedule:
interval: weekly
labels:
- 'type: task'
- 'type: dependency-upgrade'
- 'in: build' - 'in: build'
@@ -1,16 +0,0 @@
name: Merge Dependabot PR
on:
pull_request:
branches:
- main
- 'docs-build'
run-name: Merge Dependabot PR ${{ github.ref_name }}
jobs:
merge-dependabot-pr:
permissions: write-all
uses: spring-io/spring-github-workflows/.github/workflows/spring-merge-dependabot-pr.yml@0d3f15bb384839966a1ff5c4383731a2b747f24b # v7
with:
mergeArguments: --auto --rebase
-36
View File
@@ -1,36 +0,0 @@
name: CI
on:
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
env:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
permissions:
contents: read
jobs:
snapshot-test:
name: Test Against Snapshots
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17
strategy:
matrix:
include:
- java-version: 25
toolchain: 25
with:
java-version: ${{ matrix.java-version }}
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.0.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ -PmicrometerVersion=1.+ --stacktrace
secrets: inherit
send-notification:
name: Send Notification
needs: [ snapshot-test ]
if: ${{ !success() }}
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
+1 -1
View File
@@ -14,4 +14,4 @@ jobs:
actions: read actions: read
contents: read contents: read
security-events: write security-events: write
uses: spring-io/github-actions/.github/workflows/codeql-analysis.yml@e415dadd0910c901e7a7fabd67bbb355b2324500 # 1 uses: spring-io/github-actions/.github/workflows/codeql-analysis.yml@1
@@ -17,40 +17,70 @@ permissions:
jobs: jobs:
build: build:
name: Build name: Build
uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17 uses: spring-io/spring-security-release-tools/.github/workflows/build.yml@v1
strategy: strategy:
matrix: matrix:
os: [ ubuntu-latest, windows-latest ] os: [ ubuntu-latest, windows-latest ]
jdk: [ 25 ] jdk: [ 17 ]
with: with:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
java-version: ${{ matrix.jdk }} java-version: ${{ matrix.jdk }}
distribution: temurin distribution: temurin
secrets: inherit secrets: inherit
test:
name: Test Against Snapshots
uses: spring-io/spring-security-release-tools/.github/workflows/test.yml@v1
strategy:
matrix:
include:
- java-version: 21-ea
toolchain: 21
- java-version: 17
toolchain: 17
with:
java-version: ${{ matrix.java-version }}
test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace
secrets: inherit
deploy-artifacts: deploy-artifacts:
name: Deploy Artifacts name: Deploy Artifacts
needs: [ build ] needs: [ build, test]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17 uses: spring-io/spring-security-release-tools/.github/workflows/deploy-artifacts.yml@v1
with: with:
should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }} should-deploy-artifacts: ${{ needs.build.outputs.should-deploy-artifacts }}
default-publish-milestones-central: true secrets: inherit
java-version: 25 deploy-docs:
name: Deploy Docs
needs: [ build, test ]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-docs.yml@v1
with:
should-deploy-docs: ${{ needs.build.outputs.should-deploy-artifacts }}
secrets: inherit secrets: inherit
deploy-schema: deploy-schema:
name: Deploy Schema name: Deploy Schema
needs: [ build ] needs: [ build, test ]
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17 uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@v1
with: with:
should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }} should-deploy-schema: ${{ needs.build.outputs.should-deploy-artifacts }}
java-version: 25 secrets: inherit
perform-release:
name: Perform Release
needs: [ deploy-artifacts, deploy-docs, deploy-schema ]
uses: spring-io/spring-security-release-tools/.github/workflows/perform-release.yml@v1
with:
should-perform-release: ${{ needs.deploy-artifacts.outputs.artifacts-deployed }}
project-version: ${{ needs.deploy-artifacts.outputs.project-version }}
milestone-repo-url: https://repo.spring.io/artifactory/milestone
release-repo-url: https://repo1.maven.org/maven2
artifact-path: org/springframework/security/spring-security-core
slack-announcing-id: spring-security-announcing
secrets: inherit secrets: inherit
send-notification: send-notification:
name: Send Notification name: Send Notification
needs: [ deploy-artifacts, deploy-schema ] needs: [ perform-release ]
if: ${{ !success() }} if: ${{ !success() }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Send Notification - name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17 uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
with: with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }} webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
-76
View File
@@ -1,76 +0,0 @@
name: Defer Issues
on:
workflow_dispatch:
permissions:
contents: read
jobs:
defer-issues:
name: Defer Issues
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects'
permissions:
issues: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Compute Version
id: compute-version
uses: spring-io/spring-release-actions/compute-version@1b8671612c3eb3d9b9763e2d7b66f1a80d00ee95 # 0.0.6
- name: Get Today's Release Version
id: todays-release
uses: spring-io/spring-release-actions/get-todays-release-version@1b8671612c3eb3d9b9763e2d7b66f1a80d00ee95 # 0.0.6
with:
snapshot-version: ${{ steps.compute-version.outputs.version }}
milestone-repository: ${{ github.repository }}
milestone-token: ${{ secrets.GITHUB_TOKEN }}
- name: Compute Next Version
id: next-version
uses: spring-io/spring-release-actions/compute-next-version@1b8671612c3eb3d9b9763e2d7b66f1a80d00ee95 # 0.0.6
with:
version: ${{ steps.todays-release.outputs.release-version }}
- name: Schedule Next Milestone
uses: spring-io/spring-release-actions/schedule-milestone@1b8671612c3eb3d9b9763e2d7b66f1a80d00ee95 # 0.0.6
with:
version: ${{ steps.next-version.outputs.version }}
version-date: ${{ steps.next-version.outputs.version-date }}
repository: ${{ github.repository }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Move Open Issues to Next Milestone
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CURRENT_MILESTONE: ${{ steps.todays-release.outputs.release-version }}
NEXT_MILESTONE: ${{ steps.next-version.outputs.version }}
run: |
current_milestone_number=$(gh api repos/${{ github.repository }}/milestones \
--jq ".[] | select(.title == \"$CURRENT_MILESTONE\") | .number")
if [ -z "$current_milestone_number" ]; then
echo "No milestone found for $CURRENT_MILESTONE"
exit 0
fi
next_milestone_number=$(gh api repos/${{ github.repository }}/milestones \
--jq ".[] | select(.title == \"$NEXT_MILESTONE\") | .number")
if [ -z "$next_milestone_number" ]; then
echo "No milestone found for $NEXT_MILESTONE"
exit 1
fi
echo "Moving open issues from milestone '$CURRENT_MILESTONE' (#$current_milestone_number) to '$NEXT_MILESTONE' (#$next_milestone_number)"
page=1
while true; do
issues=$(gh api "repos/${{ github.repository }}/issues?milestone=$current_milestone_number&state=open&per_page=100&page=$page" \
--jq '.[].number')
if [ -z "$issues" ]; then
break
fi
for issue in $issues; do
echo "Moving issue/PR #$issue to milestone $NEXT_MILESTONE"
gh api repos/${{ github.repository }}/issues/$issue \
--method PATCH \
--field milestone=$next_milestone_number \
--silent
done
page=$((page + 1))
done
echo "Done."
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
if: github.repository_owner == 'spring-projects' if: github.repository_owner == 'spring-projects'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@v4
with: with:
ref: docs-build ref: docs-build
fetch-depth: 1 fetch-depth: 1
@@ -9,7 +9,6 @@ permissions:
jobs: jobs:
upgrade_wrapper: upgrade_wrapper:
name: Execution name: Execution
if: ${{ github.repository == 'spring-projects/spring-security' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Git configuration - name: Set up Git configuration
@@ -20,14 +19,14 @@ jobs:
git config --global user.name 'github-actions[bot]' git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com' git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- name: Checkout - name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@v4
- name: Set up JDK 25 - name: Set up JDK 17
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0 uses: actions/setup-java@v4
with: with:
java-version: '25' java-version: '17'
distribution: 'temurin' distribution: 'temurin'
- name: Set up Gradle - name: Set up Gradle
uses: gradle/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # v5.0.1 uses: gradle/gradle-build-action@v2
- name: Upgrade Wrappers - name: Upgrade Wrappers
run: ./gradlew clean upgradeGradleWrapperAll --continue -Porg.gradle.java.installations.auto-download=false run: ./gradlew clean upgradeGradleWrapperAll --continue -Porg.gradle.java.installations.auto-download=false
env: env:
@@ -0,0 +1,35 @@
name: Check Milestone
on:
milestone:
types: [created, opened, edited]
env:
DUE_ON: ${{ github.event.milestone.due_on }}
TITLE: ${{ github.event.milestone.title }}
permissions:
contents: read
jobs:
spring-releasetrain-checks:
name: Check DueOn is on a Release Date
runs-on: ubuntu-latest
if: ${{ github.repository == 'spring-projects/spring-security' }}
permissions:
contents: none
steps:
- name: Print Milestone Being Checked
run: echo "Validating DueOn '$DUE_ON' for milestone '$TITLE'"
- name: Validate DueOn
if: env.DUE_ON != ''
run: |
export TOOL_VERSION=0.1.1
wget "https://repo.maven.apache.org/maven2/io/spring/releasetrain/spring-release-train-tools/$TOOL_VERSION/spring-release-train-tools-$TOOL_VERSION.jar"
java -cp "spring-release-train-tools-$TOOL_VERSION.jar" io.spring.releasetrain.CheckMilestoneDueOnMain --dueOn "$DUE_ON" --expectedDayOfWeek MONDAY --expectedMondayCount 3
send-notification:
name: Send Notification
needs: [ spring-releasetrain-checks ]
if: ${{ failure() || cancelled() }}
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
+8 -8
View File
@@ -11,11 +11,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.repository == 'spring-projects/spring-security' }} if: ${{ github.repository == 'spring-projects/spring-security' }}
steps: steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/checkout@v4
- name: Set up gradle - name: Set up gradle
uses: spring-io/spring-gradle-build-action@c8668747d7c264864c8c7f7026d0d277d14a78dc # v2.0.6 uses: spring-io/spring-gradle-build-action@v2
with: with:
java-version: '25' java-version: '17'
distribution: 'temurin' distribution: 'temurin'
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew clean build -PskipCheckExpectedBranchVersion --continue --scan run: ./gradlew clean build -PskipCheckExpectedBranchVersion --continue --scan
@@ -24,17 +24,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.repository == 'spring-projects/spring-security' }} if: ${{ github.repository == 'spring-projects/spring-security' }}
steps: steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/checkout@v4
- name: Set up gradle - name: Set up gradle
uses: spring-io/spring-gradle-build-action@c8668747d7c264864c8c7f7026d0d277d14a78dc # v2.0.6 uses: spring-io/spring-gradle-build-action@v2
with: with:
java-version: '25' java-version: '17'
distribution: 'temurin' distribution: 'temurin'
- name: Run Antora - name: Run Antora
run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora
- name: Upload Docs - name: Upload Docs
id: upload id: upload
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@v4
with: with:
name: docs name: docs
path: docs/build/site path: docs/build/site
@@ -46,6 +46,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Send Notification - name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17 uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
with: with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }} webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
@@ -1,30 +0,0 @@
name: Release Announcements - Publish
on:
workflow_dispatch:
inputs:
version:
description: The version to publish
required: true
type: string
permissions:
actions: write
contents: read
issues: write
jobs:
deploy-schema:
name: Deploy Schema
uses: spring-io/spring-security-release-tools/.github/workflows/deploy-schema.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17
with:
should-deploy-schema: true
secrets: inherit
publish-release-announcements:
name: Publish Release Announcements
needs: [ deploy-schema ]
if: ${{ !github.event.repository.fork }}
uses: spring-io/spring-security-release-tools/.github/workflows/release-announcements-publish.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17
with:
version: ${{ inputs.version }}
secrets: inherit
@@ -1,24 +0,0 @@
name: Release Announcements - Stage
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
workflow_dispatch:
inputs:
version:
description: The version to stage
required: true
type: string
permissions:
contents: read
jobs:
stage-release-announcements:
name: Stage Release Announcements
if: ${{ !github.event.repository.fork }}
uses: spring-io/spring-security-release-tools/.github/workflows/release-announcements-stage.yml@3f6cc7ffc137ca160061749d5f34dc30d5f36986 # v1.0.17
with:
version: ${{ inputs.version || github.ref_name }}
secrets: inherit
+24
View File
@@ -0,0 +1,24 @@
name: Release Scheduler
on:
schedule:
- cron: '15 15 * * MON' # Every Monday at 3:15pm UTC
workflow_dispatch:
permissions: read-all
jobs:
dispatch_scheduled_releases:
name: Dispatch scheduled releases
if: github.repository_owner == 'spring-projects'
strategy:
matrix:
# List of active maintenance branches.
branch: [ main, 6.5.x, 6.4.x, 6.3.x ]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Dispatch
env:
GH_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
run: gh workflow run update-scheduled-release-version.yml -r ${{ matrix.branch }}
@@ -12,25 +12,23 @@ permissions:
jobs: jobs:
update-antora-ui-spring: update-antora-ui-spring:
name: Update on Supported Branches
if: ${{ github.repository == 'spring-projects/spring-security' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Update on Supported Branches
strategy: strategy:
matrix: matrix:
branch: [ '6.5.x', '7.0.x', '7.1.x', 'main' ] branch: [ '5.8.x', '6.2.x', '6.3.x', 'main' ]
steps: steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf # v0.0.22 - uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
name: Update name: Update
with: with:
docs-branch: ${{ matrix.branch }} docs-branch: ${{ matrix.branch }}
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
antora-file-path: 'docs/antora-playbook.yml' antora-file-path: 'docs/antora-playbook.yml'
update-antora-ui-spring-docs-build: update-antora-ui-spring-docs-build:
name: Update on docs-build
if: ${{ github.repository == 'spring-projects/spring-security' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Update on docs-build
steps: steps:
- uses: spring-io/spring-doc-actions/update-antora-spring-ui@415e2b11a766ba64799fffb5c97a4f7e17f677cf # v0.0.22 - uses: spring-io/spring-doc-actions/update-antora-spring-ui@e28269199d1d27975cf7f65e16d6095c555b3cd0
name: Update name: Update
with: with:
docs-branch: 'docs-build' docs-branch: 'docs-build'
@@ -0,0 +1,23 @@
name: Update Scheduled Release Version
on:
workflow_dispatch: # Manual trigger only. Triggered by release-scheduler.yml on main.
permissions:
contents: read
jobs:
update-scheduled-release-version:
name: Update Scheduled Release Version
uses: spring-io/spring-security-release-tools/.github/workflows/update-scheduled-release-version.yml@v1
secrets: inherit
send-notification:
name: Send Notification
needs: [ update-scheduled-release-version ]
if: ${{ failure() || cancelled() }}
runs-on: ubuntu-latest
steps:
- name: Send Notification
uses: spring-io/spring-security-release-tools/.github/actions/send-notification@v1
with:
webhook-url: ${{ secrets.SPRING_SECURITY_CI_GCHAT_WEBHOOK_URL }}
-1
View File
@@ -25,7 +25,6 @@ atlassian-ide-plugin.xml
s101plugin.state s101plugin.state
.attach_pid* .attach_pid*
.~lock.*# .~lock.*#
.kotlin/
!.idea/checkstyle-idea.xml !.idea/checkstyle-idea.xml
!.idea/externalDependencies.xml !.idea/externalDependencies.xml
+1 -1
View File
@@ -3,4 +3,4 @@
# See https://sdkman.io/usage#config # See https://sdkman.io/usage#config
# A summary is to add the following to ~/.sdkman/etc/config # A summary is to add the following to ~/.sdkman/etc/config
# sdkman_auto_env=true # sdkman_auto_env=true
java=25-librca java=17.0.3-tem
+1 -1
View File
@@ -1,3 +1,3 @@
{ {
"java.gradle.buildServer.enabled": "off" "java.import.gradle.enabled": false
} }
+2 -2
View File
@@ -31,7 +31,7 @@ If you have a question, check Stack Overflow using
https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags]. https://stackoverflow.com/questions/tagged/spring-security+or+spring-ldap+or+spring-authorization-server+or+spring-session?tab=Newest[this list of tags].
Find an existing discussion, or start a new one if necessary. Find an existing discussion, or start a new one if necessary.
If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue. If you believe there is an issue, search through https://github.com/spring-projects/spring-security/issues[existing issues] trying a few different ways to find discussions, past or current, that are related to the issue.
Reading those discussions helps you to learn about the issue, and helps us to make a decision. Reading those discussions helps you to learn about the issue, and helps us to make a decision.
[[find-an-issue]] [[find-an-issue]]
@@ -94,7 +94,7 @@ Don't worry if you don't get them all correct the first time, we will help you.
1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin. 1. [[sign-cla]] All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin.
For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring]. For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring].
2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier to discuss with the team first to determine the right fix or enhancement. 2. [[create-an-issue-list]] Must you https://github.com/spring-projects/spring-security/issues/new/choose[create an issue] first? No, but it is recommended for features and larger bug fixes. It's easier discuss with the team first to determine the right fix or enhancement.
For typos and straightforward bug fixes, starting with a pull request is encouraged. For typos and straightforward bug fixes, starting with a pull request is encouraged.
Please include a description for context and motivation. Please include a description for context and motivation.
Note that the team may close your pull request if it's not a fit for the project. Note that the team may close your pull request if it's not a fit for the project.
-21
View File
@@ -68,27 +68,6 @@ The https://github.com/spring-projects/spring-security/tree/docs-build[playbook
Discover more commands with `./gradlew tasks`. Discover more commands with `./gradlew tasks`.
=== IDE setup (IntelliJ)
No special steps are needed to open Spring Security in IntelliJ.
=== IDE setup (Eclipse and VS Code)
To work in Eclipse or VS Code, first generate Eclipse metadata so you can import the project into Eclipse or VS Code:
[indent=0]
----
./gradlew cleanEclipse eclipse
----
If you have not built the project yet, run `./gradlew publishToMavenLocal` first so dependencies are resolved.
*VS Code:* Open the repository root as a folder. The repository includes `.vscode/settings.json` which disables automatic Gradle import so that the generated Eclipse metadata (`.classpath`, `.project`) is used. Do not use the Gradle for Java extension to import the project.
*Eclipse:* File → Import → General → Existing Projects into Workspace, then select the repository root.
The build uses a custom Eclipse plugin to work around Gradle dependency cycles that confuse IDE metadata generation. You may see Eclipse warnings about `xml-apis` from some test dependencies; those are excluded in the build and can be ignored.
== Getting Support == Getting Support
Check out the https://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow]. Check out the https://stackoverflow.com/questions/tagged/spring-security[Spring Security tags on Stack Overflow].
https://spring.io/support[Commercial support] is available too. https://spring.io/support[Commercial support] is available too.
-54
View File
@@ -1,54 +0,0 @@
plugins {
id 'compile-warnings-error'
id 'javadoc-warnings-error'
}
apply plugin: 'io.spring.convention.spring-module'
dependencies {
management platform(project(":spring-security-dependencies"))
api project(':spring-security-crypto')
api project(':spring-security-core')
api 'org.springframework:spring-aop'
api 'org.springframework:spring-beans'
api 'org.springframework:spring-context'
api 'org.springframework:spring-core'
api 'org.springframework:spring-expression'
api 'io.micrometer:micrometer-observation'
optional project(':spring-security-acl')
optional project(':spring-security-messaging')
optional project(':spring-security-web')
optional 'org.springframework:spring-websocket'
optional 'com.fasterxml.jackson.core:jackson-databind'
optional 'io.micrometer:context-propagation'
optional 'io.projectreactor:reactor-core'
optional 'jakarta.annotation:jakarta.annotation-api'
optional 'org.aspectj:aspectjrt'
optional 'org.springframework:spring-jdbc'
optional 'org.springframework:spring-tx'
optional 'org.jetbrains.kotlinx:kotlinx-coroutines-reactor'
provided 'jakarta.servlet:jakarta.servlet-api'
testImplementation project(path : ':spring-security-web', configuration : 'tests')
testImplementation 'commons-collections:commons-collections'
testImplementation 'io.projectreactor:reactor-test'
testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
testImplementation "org.mockito:mockito-core"
testImplementation "org.mockito:mockito-junit-jupiter"
testImplementation "org.springframework:spring-core-test"
testImplementation "org.springframework:spring-test"
testImplementation 'org.skyscreamer:jsonassert'
testImplementation 'org.springframework:spring-test'
testImplementation 'org.jetbrains.kotlin:kotlin-reflect'
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation 'io.mockk:mockk'
testRuntimeOnly 'org.hsqldb:hsqldb'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
@@ -1,36 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.security.access;
/**
* Represents the interface of a secured object.
*
* @author Ben Alex
*/
public interface ITargetObject {
Integer computeHashCode(String input);
int countLength(String input);
String makeLowerCase(String input);
String makeUpperCase(String input);
String publicMakeLowerCase(String input);
}
@@ -1,53 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.security.access;
/**
* Simply extends {@link TargetObject} so we have a different object to put configuration
* attributes against.
* <P>
* There is no different behaviour. We have to define each method so that
* <code>Class.getMethod(methodName, args)</code> returns a <code>Method</code>
* referencing this class rather than the parent class.
* </p>
* <P>
* We need to implement <code>ITargetObject</code> again because the
* <code>MethodDefinitionAttributes</code> only locates attributes on interfaces
* explicitly defined by the intercepted class (not the interfaces defined by its parent
* class or classes).
* </p>
*
* @author Ben Alex
*/
public class OtherTargetObject extends TargetObject implements ITargetObject {
@Override
public String makeLowerCase(String input) {
return super.makeLowerCase(input);
}
@Override
public String makeUpperCase(String input) {
return super.makeUpperCase(input);
}
@Override
public String publicMakeLowerCase(String input) {
return super.publicMakeLowerCase(input);
}
}
@@ -1,81 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.security.access;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Represents a secured object.
*
* @author Ben Alex
*/
public class TargetObject implements ITargetObject {
@Override
public Integer computeHashCode(String input) {
return input.hashCode();
}
@Override
public int countLength(String input) {
return input.length();
}
/**
* Returns the lowercase string, followed by security environment information.
* @param input the message to make lowercase
* @return the lowercase message, a space, the <code>Authentication</code> class that
* was on the <code>SecurityContext</code> at the time of method invocation, and a
* boolean indicating if the <code>Authentication</code> object is authenticated or
* not
*/
@Override
public String makeLowerCase(String input) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null) {
return input.toLowerCase() + " Authentication empty";
}
else {
return input.toLowerCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated();
}
}
/**
* Returns the uppercase string, followed by security environment information.
* @param input the message to make uppercase
* @return the uppercase message, a space, the <code>Authentication</code> class that
* was on the <code>SecurityContext</code> at the time of method invocation, and a
* boolean indicating if the <code>Authentication</code> object is authenticated or
* not
*/
@Override
public String makeUpperCase(String input) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return input.toUpperCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated();
}
/**
* Delegates through to the {@link #makeLowerCase(String)} method.
* @param input the message to be made lower-case
*/
@Override
public String publicMakeLowerCase(String input) {
return this.makeLowerCase(input);
}
}
-6
View File
@@ -1,9 +1,3 @@
plugins {
id 'compile-warnings-error'
id 'javadoc-warnings-error'
id 'security-nullability'
}
apply plugin: 'io.spring.convention.spring-module' apply plugin: 'io.spring.convention.spring-module'
dependencies { dependencies {
@@ -71,7 +71,7 @@ import org.springframework.util.StringUtils;
* <tt>AclEntryVoter</tt>: * <tt>AclEntryVoter</tt>:
* <ul> * <ul>
* <li>Process domain object class <code>BankAccount</code>, configuration attribute * <li>Process domain object class <code>BankAccount</code>, configuration attribute
* <code>VOTE_ACL_BANK_ACCOUNT_READ</code>, require permission * <code>VOTE_ACL_BANK_ACCONT_READ</code>, require permission
* <code>BasePermission.READ</code></li> * <code>BasePermission.READ</code></li>
* <li>Process domain object class <code>BankAccount</code>, configuration attribute * <li>Process domain object class <code>BankAccount</code>, configuration attribute
* <code>VOTE_ACL_BANK_ACCOUNT_WRITE</code>, require permission list * <code>VOTE_ACL_BANK_ACCOUNT_WRITE</code>, require permission list
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@ import java.util.Locale;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage; import org.springframework.core.log.LogMessage;
import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.access.PermissionEvaluator;
@@ -45,7 +44,7 @@ import org.springframework.security.core.Authentication;
/** /**
* Used by Spring Security's expression-based access control implementation to evaluate * Used by Spring Security's expression-based access control implementation to evaluate
* permissions for a particular object using the ACL module. Similar in behaviour to * permissions for a particular object using the ACL module. Similar in behaviour to
* <code> org.springframework.security.acls.AclEntryVoter AclEntryVoter </code> * {@link org.springframework.security.acls.AclEntryVoter AclEntryVoter}.
* *
* @author Luke Taylor * @author Luke Taylor
* @since 3.0 * @since 3.0
@@ -74,7 +73,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
* be overridden using a null check in the expression itself). * be overridden using a null check in the expression itself).
*/ */
@Override @Override
public boolean hasPermission(Authentication authentication, @Nullable Object domainObject, Object permission) { public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
if (domainObject == null) { if (domainObject == null) {
return false; return false;
} }
@@ -111,7 +111,6 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends Abstract
return returnedObject; return returnedObject;
} }
@SuppressWarnings({ "unchecked", "rawtypes" })
private Filterer getFilterer(Object returnedObject) { private Filterer getFilterer(Object returnedObject) {
if (returnedObject instanceof Collection) { if (returnedObject instanceof Collection) {
return new CollectionFilterer((Collection) returnedObject); return new CollectionFilterer((Collection) returnedObject);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,79 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.springframework.security.acls.aot.hint;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.acls.domain.AclImpl;
import org.springframework.security.acls.domain.AuditLogger;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AuditableAccessControlEntry;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;
/**
* {@link RuntimeHintsRegistrar} for ACL (Access Control List) classes.
*
* @author Josh Long
*/
class AclRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
registerAclDomainHints(hints);
registerJdbcSchemaHints(hints);
}
private void registerAclDomainHints(RuntimeHints hints) {
// Register core ACL domain types
Stream
.of(Acl.class, AccessControlEntry.class, AuditableAccessControlEntry.class, ObjectIdentity.class, Sid.class,
AclImpl.class, AccessControlEntry.class, AuditLogger.class, ObjectIdentityImpl.class,
PrincipalSid.class, GrantedAuthoritySid.class, BasePermission.class)
.forEach((c) -> hints.reflection()
.registerType(TypeReference.of(c),
(builder) -> builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.ACCESS_DECLARED_FIELDS)));
}
private void registerJdbcSchemaHints(RuntimeHints hints) {
String[] sqlFiles = new String[] { "createAclSchema.sql", "createAclSchemaMySQL.sql",
"createAclSchemaOracle.sql", "createAclSchemaPostgres.sql", "createAclSchemaSqlServer.sql",
"createAclSchemaWithAclClassIdType.sql", "select.sql" };
for (String sqlFile : sqlFiles) {
Resource sqlResource = new ClassPathResource(sqlFile);
if (sqlResource.exists()) {
hints.resources().registerResource(sqlResource);
}
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright 2004-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
/**
* AOT and native image hint support for ACLs.
*/
@NullMarked
package org.springframework.security.acls.aot.hint;
import org.jspecify.annotations.NullMarked;
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.Permission; import org.springframework.security.acls.model.Permission;
/** /**
@@ -54,7 +52,7 @@ public abstract class AbstractPermission implements Permission {
} }
@Override @Override
public final boolean equals(@Nullable Object obj) { public final boolean equals(Object obj) {
if (obj == null) { if (obj == null) {
return false; return false;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,8 +18,6 @@ package org.springframework.security.acls.domain;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.AccessControlEntry; import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl; import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AuditableAccessControlEntry; import org.springframework.security.acls.model.AuditableAccessControlEntry;
@@ -38,7 +36,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
private Permission permission; private Permission permission;
private final @Nullable Serializable id; private final Serializable id;
private final Sid sid; private final Sid sid;
@@ -48,7 +46,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
private final boolean granting; private final boolean granting;
public AccessControlEntryImpl(@Nullable Serializable id, Acl acl, Sid sid, Permission permission, boolean granting, public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
boolean auditSuccess, boolean auditFailure) { boolean auditSuccess, boolean auditFailure) {
Assert.notNull(acl, "Acl required"); Assert.notNull(acl, "Acl required");
Assert.notNull(sid, "Sid required"); Assert.notNull(sid, "Sid required");
@@ -63,7 +61,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
} }
@Override @Override
public boolean equals(@Nullable Object arg0) { public boolean equals(Object arg0) {
if (!(arg0 instanceof AccessControlEntryImpl)) { if (!(arg0 instanceof AccessControlEntryImpl)) {
return false; return false;
} }
@@ -135,7 +133,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, AuditableAcce
} }
@Override @Override
public @Nullable Serializable getId() { public Serializable getId() {
return this.id; return this.id;
} }
@@ -20,7 +20,7 @@ import org.springframework.security.acls.model.Acl;
/** /**
* Strategy used by {@link AclImpl} to determine whether a principal is permitted to call * Strategy used by {@link AclImpl} to determine whether a principal is permitted to call
* administrative methods on the <code>AclImpl</code>. * adminstrative methods on the <code>AclImpl</code>.
* *
* @author Ben Alex * @author Ben Alex
*/ */
@@ -99,8 +99,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
Authentication authentication = context.getAuthentication(); Authentication authentication = context.getAuthentication();
// Check if authorized by virtue of ACL ownership // Check if authorized by virtue of ACL ownership
Sid currentUser = createCurrentUser(authentication); Sid currentUser = createCurrentUser(authentication);
Sid owner = acl.getOwner(); if (currentUser.equals(acl.getOwner())
if (owner != null && currentUser.equals(owner)
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) { && ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
return; return;
} }
@@ -109,8 +108,8 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
Collection<? extends GrantedAuthority> reachableGrantedAuthorities = this.roleHierarchy Collection<? extends GrantedAuthority> reachableGrantedAuthorities = this.roleHierarchy
.getReachableGrantedAuthorities(authentication.getAuthorities()); .getReachableGrantedAuthorities(authentication.getAuthorities());
Set<String> authorities = AuthorityUtils.authorityListToSet(reachableGrantedAuthorities); Set<String> authorities = AuthorityUtils.authorityListToSet(reachableGrantedAuthorities);
if (owner instanceof GrantedAuthoritySid if (acl.getOwner() instanceof GrantedAuthoritySid
&& authorities.contains(((GrantedAuthoritySid) owner).getGrantedAuthority())) { && authorities.contains(((GrantedAuthoritySid) acl.getOwner()).getGrantedAuthority())) {
return; return;
} }
@@ -20,8 +20,6 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.AccessControlEntry; import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl; import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.AuditableAcl; import org.springframework.security.acls.model.AuditableAcl;
@@ -43,7 +41,7 @@ import org.springframework.util.ObjectUtils;
*/ */
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
private @Nullable Acl parentAcl; private Acl parentAcl;
private transient AclAuthorizationStrategy aclAuthorizationStrategy; private transient AclAuthorizationStrategy aclAuthorizationStrategy;
@@ -56,10 +54,10 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
private Serializable id; private Serializable id;
// OwnershipAcl // OwnershipAcl
private @Nullable Sid owner; private Sid owner;
// includes all SIDs the WHERE clause covered, even if there was no ACE for a SID // includes all SIDs the WHERE clause covered, even if there was no ACE for a SID
private @Nullable List<Sid> loadedSids = null; private List<Sid> loadedSids = null;
private boolean entriesInheriting = true; private boolean entriesInheriting = true;
@@ -99,8 +97,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* @param owner the owner (required) * @param owner the owner (required)
*/ */
public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
PermissionGrantingStrategy grantingStrategy, @Nullable Acl parentAcl, @Nullable List<Sid> loadedSids, PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting,
boolean entriesInheriting, Sid owner) { Sid owner) {
Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required"); Assert.notNull(id, "Id required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
@@ -119,7 +117,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* Private no-argument constructor for use by reflection-based persistence tools along * Private no-argument constructor for use by reflection-based persistence tools along
* with field-level access. * with field-level access.
*/ */
@SuppressWarnings({ "unused", "NullAway.Init" }) @SuppressWarnings("unused")
private AclImpl() { private AclImpl() {
} }
@@ -201,7 +199,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
@Override @Override
public boolean isSidLoaded(@Nullable List<Sid> sids) { public boolean isSidLoaded(List<Sid> sids) {
// If loadedSides is null, this indicates all SIDs were loaded // If loadedSides is null, this indicates all SIDs were loaded
// Also return true if the caller didn't specify a SID to find // Also return true if the caller didn't specify a SID to find
if ((this.loadedSids == null) || (sids == null) || sids.isEmpty()) { if ((this.loadedSids == null) || (sids == null) || sids.isEmpty()) {
@@ -240,19 +238,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
@Override @Override
public @Nullable Sid getOwner() { public Sid getOwner() {
return this.owner; return this.owner;
} }
@Override @Override
public void setParent(@Nullable Acl newParent) { public void setParent(Acl newParent) {
this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); this.aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself"); Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
this.parentAcl = newParent; this.parentAcl = newParent;
} }
@Override @Override
public @Nullable Acl getParentAcl() { public Acl getParentAcl() {
return this.parentAcl; return this.parentAcl;
} }
@@ -278,7 +276,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(Object obj) {
if (obj == this) { if (obj == this) {
return true; return true;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.Sid; import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@@ -44,12 +42,12 @@ public class GrantedAuthoritySid implements Sid {
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
Assert.notNull(grantedAuthority, "GrantedAuthority required"); Assert.notNull(grantedAuthority, "GrantedAuthority required");
Assert.notNull(grantedAuthority.getAuthority(), Assert.notNull(grantedAuthority.getAuthority(),
"This Sid is only compatible with GrantedAuthority that provide a non-null getAuthority()"); "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
this.grantedAuthority = grantedAuthority.getAuthority(); this.grantedAuthority = grantedAuthority.getAuthority();
} }
@Override @Override
public boolean equals(@Nullable Object object) { public boolean equals(Object object) {
if ((object == null) || !(object instanceof GrantedAuthoritySid)) { if ((object == null) || !(object instanceof GrantedAuthoritySid)) {
return false; return false;
} }
@@ -19,8 +19,6 @@ package org.springframework.security.acls.domain;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@@ -99,7 +97,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
* @return <code>true</code> if the presented object matches this object * @return <code>true</code> if the presented object matches this object
*/ */
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(Object obj) {
if (obj == null || !(obj instanceof ObjectIdentityImpl)) { if (obj == null || !(obj instanceof ObjectIdentityImpl)) {
return false; return false;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.Sid; import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@@ -48,7 +46,7 @@ public class PrincipalSid implements Sid {
} }
@Override @Override
public boolean equals(@Nullable Object object) { public boolean equals(Object object) {
if ((object == null) || !(object instanceof PrincipalSid)) { if ((object == null) || !(object instanceof PrincipalSid)) {
return false; return false;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,8 +18,6 @@ package org.springframework.security.acls.domain;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.security.acls.model.AclCache; import org.springframework.security.acls.model.AclCache;
import org.springframework.security.acls.model.MutableAcl; import org.springframework.security.acls.model.MutableAcl;
@@ -80,13 +78,13 @@ public class SpringCacheBasedAclCache implements AclCache {
} }
@Override @Override
public @Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity) { public MutableAcl getFromCache(ObjectIdentity objectIdentity) {
Assert.notNull(objectIdentity, "ObjectIdentity required"); Assert.notNull(objectIdentity, "ObjectIdentity required");
return getFromCache((Object) objectIdentity); return getFromCache((Object) objectIdentity);
} }
@Override @Override
public @Nullable MutableAcl getFromCache(Serializable pk) { public MutableAcl getFromCache(Serializable pk) {
Assert.notNull(pk, "Primary key (identifier) required"); Assert.notNull(pk, "Primary key (identifier) required");
return getFromCache((Object) pk); return getFromCache((Object) pk);
} }
@@ -103,16 +101,12 @@ public class SpringCacheBasedAclCache implements AclCache {
this.cache.put(acl.getId(), acl); this.cache.put(acl.getId(), acl);
} }
private @Nullable MutableAcl getFromCache(Object key) { private MutableAcl getFromCache(Object key) {
Cache.ValueWrapper element = this.cache.get(key); Cache.ValueWrapper element = this.cache.get(key);
if (element == null) { if (element == null) {
return null; return null;
} }
Object value = element.get(); return initializeTransientFields((MutableAcl) element.get());
if (value == null) {
return null;
}
return initializeTransientFields((MutableAcl) value);
} }
private MutableAcl initializeTransientFields(MutableAcl value) { private MutableAcl initializeTransientFields(MutableAcl value) {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,4 @@
/** /**
* Basic implementation of access control lists (ACLs) interfaces. * Basic implementation of access control lists (ACLs) interfaces.
*/ */
@NullMarked
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import org.jspecify.annotations.NullMarked;
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@ import java.util.UUID;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
@@ -68,10 +67,10 @@ class AclClassIdUtils {
* @return The identifier in the appropriate target Java type. Typically Long or UUID. * @return The identifier in the appropriate target Java type. Typically Long or UUID.
* @throws SQLException * @throws SQLException
*/ */
@Nullable Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException { Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
Class<? extends Serializable> classIdType = classIdTypeFrom(resultSet); if (isString(identifier) && hasValidClassIdType(resultSet)
if (isString(identifier) && classIdType != null && canConvertFromStringTo(classIdType)) { && canConvertFromStringTo(classIdTypeFrom(resultSet))) {
return convertFromStringTo((String) identifier, classIdType); return convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
} }
// Assume it should be a Long type // Assume it should be a Long type
return convertToLong(identifier); return convertToLong(identifier);
@@ -87,38 +86,28 @@ class AclClassIdUtils {
} }
} }
private @Nullable Class<? extends Serializable> classIdTypeFrom(ResultSet resultSet) throws SQLException { private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
try { return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
}
catch (SQLException ex) {
log.debug("Unable to obtain the class id type", ex);
return null;
}
} }
private @Nullable Class<? extends Serializable> classIdTypeFrom(String className) { private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
if (className == null) { if (className == null) {
return null; return null;
} }
try { try {
return Class.forName(className).asSubclass(Serializable.class); return (Class) Class.forName(className);
} }
catch (ClassNotFoundException ex) { catch (ClassNotFoundException ex) {
log.debug("Unable to find class id type on classpath", ex); log.debug("Unable to find class id type on classpath", ex);
return null; return null;
} }
catch (ClassCastException ex) {
log.debug("Class id type is not a Serializable type", ex);
return null;
}
} }
private <T> boolean canConvertFromStringTo(Class<T> targetType) { private <T> boolean canConvertFromStringTo(Class<T> targetType) {
return this.conversionService.canConvert(String.class, targetType); return this.conversionService.canConvert(String.class, targetType);
} }
private <T extends Serializable> @Nullable T convertFromStringTo(String identifier, Class<T> targetType) { private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
return this.conversionService.convert(identifier, targetType); return this.conversionService.convert(identifier, targetType);
} }
@@ -132,7 +121,7 @@ class AclClassIdUtils {
* exception occurred * exception occurred
* @throws IllegalArgumentException if targetType is null * @throws IllegalArgumentException if targetType is null
*/ */
private @Nullable Long convertToLong(Serializable identifier) { private Long convertToLong(Serializable identifier) {
if (this.conversionService.canConvert(identifier.getClass(), Long.class)) { if (this.conversionService.canConvert(identifier.getClass(), Long.class)) {
return this.conversionService.convert(identifier, Long.class); return this.conversionService.convert(identifier, Long.class);
} }
@@ -151,10 +140,10 @@ class AclClassIdUtils {
private static class StringToLongConverter implements Converter<String, Long> { private static class StringToLongConverter implements Converter<String, Long> {
@Override @Override
public Long convert(@Nullable String identifierAsString) { public Long convert(String identifierAsString) {
if (identifierAsString == null) { if (identifierAsString == null) {
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class), throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
TypeDescriptor.valueOf(Long.class), identifierAsString, new NullPointerException()); TypeDescriptor.valueOf(Long.class), null, null);
} }
return Long.parseLong(identifierAsString); return Long.parseLong(identifierAsString);
@@ -165,10 +154,10 @@ class AclClassIdUtils {
private static class StringToUUIDConverter implements Converter<String, UUID> { private static class StringToUUIDConverter implements Converter<String, UUID> {
@Override @Override
public UUID convert(@Nullable String identifierAsString) { public UUID convert(String identifierAsString) {
if (identifierAsString == null) { if (identifierAsString == null) {
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class), throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
TypeDescriptor.valueOf(UUID.class), identifierAsString, new NullPointerException()); TypeDescriptor.valueOf(UUID.class), null, null);
} }
return UUID.fromString(identifierAsString); return UUID.fromString(identifierAsString);
@@ -31,8 +31,6 @@ import java.util.Set;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
@@ -67,11 +65,10 @@ import org.springframework.util.Assert;
* NB: This implementation does attempt to provide reasonably optimised lookups - within * NB: This implementation does attempt to provide reasonably optimised lookups - within
* the constraints of a normalised database and standard ANSI SQL features. If you are * the constraints of a normalised database and standard ANSI SQL features. If you are
* willing to sacrifice either of these constraints (e.g. use a particular database * willing to sacrifice either of these constraints (e.g. use a particular database
* feature such as hierarchical queries or materialized views, or reduce normalisation) * feature such as hierarchical queries or materalized views, or reduce normalisation) you
* you are likely to achieve better performance. In such situations you will need to * are likely to achieve better performance. In such situations you will need to provide
* provide your own custom <code>LookupStrategy</code>. This class does not support * your own custom <code>LookupStrategy</code>. This class does not support subclassing,
* subclassing, as it is likely to change in future releases and therefore subclassing is * as it is likely to change in future releases and therefore subclassing is unsupported.
* unsupported.
* <p> * <p>
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and * There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order * one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order
@@ -226,8 +223,7 @@ public class BasicLookupStrategy implements LookupStrategy {
* @param findNow Long-based primary keys to retrieve * @param findNow Long-based primary keys to retrieve
* @param sids * @param sids
*/ */
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow, private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow, final List<Sid> sids) {
final @Nullable List<Sid> sids) {
Assert.notNull(acls, "ACLs are required"); Assert.notNull(acls, "ACLs are required");
Assert.notEmpty(findNow, "Items to find now required"); Assert.notEmpty(findNow, "Items to find now required");
String sql = computeRepeatingSql(this.lookupPrimaryKeysWhereClause, findNow.size()); String sql = computeRepeatingSql(this.lookupPrimaryKeysWhereClause, findNow.size());
@@ -267,7 +263,7 @@ public class BasicLookupStrategy implements LookupStrategy {
* automatically create entries if required) * automatically create entries if required)
*/ */
@Override @Override
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids) { public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
Assert.isTrue(this.batchSize >= 1, "BatchSize must be >= 1"); Assert.isTrue(this.batchSize >= 1, "BatchSize must be >= 1");
Assert.notEmpty(objects, "Objects to lookup required"); Assert.notEmpty(objects, "Objects to lookup required");
// Map<ObjectIdentity,Acl> // Map<ObjectIdentity,Acl>
@@ -326,7 +322,7 @@ public class BasicLookupStrategy implements LookupStrategy {
* properly-configured parent ACLs. * properly-configured parent ACLs.
*/ */
private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities, private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities,
@Nullable List<Sid> sids) { List<Sid> sids) {
Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
// contains Acls with StubAclParents // contains Acls with StubAclParents
@@ -402,10 +398,8 @@ public class BasicLookupStrategy implements LookupStrategy {
} }
// Now we have the parent (if there is one), create the true AclImpl // Now we have the parent (if there is one), create the true AclImpl
Sid owner = inputAcl.getOwner();
Assert.isTrue(owner != null, "Owner is required");
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), this.aclAuthorizationStrategy, AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), this.aclAuthorizationStrategy,
this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), owner); this.grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
// Copy the "aces" from the input to the destination // Copy the "aces" from the input to the destination
@@ -511,9 +505,9 @@ public class BasicLookupStrategy implements LookupStrategy {
private final Map<Serializable, Acl> acls; private final Map<Serializable, Acl> acls;
private final @Nullable List<Sid> sids; private final List<Sid> sids;
ProcessResultSet(Map<Serializable, Acl> acls, @Nullable List<Sid> sids) { ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
Assert.notNull(acls, "ACLs cannot be null"); Assert.notNull(acls, "ACLs cannot be null");
this.acls = acls; this.acls = acls;
this.sids = sids; // can be null this.sids = sids; // can be null
@@ -584,9 +578,6 @@ public class BasicLookupStrategy implements LookupStrategy {
// target id type, e.g. UUID. // target id type, e.g. UUID.
Serializable identifier = (Serializable) rs.getObject("object_id_identity"); Serializable identifier = (Serializable) rs.getObject("object_id_identity");
identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs); identifier = BasicLookupStrategy.this.aclClassIdUtils.identifierFrom(identifier, rs);
if (identifier == null) {
throw new IllegalStateException("Identifier cannot be null");
}
ObjectIdentity objectIdentity = BasicLookupStrategy.this.objectIdentityGenerator ObjectIdentity objectIdentity = BasicLookupStrategy.this.objectIdentityGenerator
.createObjectIdentity(identifier, rs.getString("class")); .createObjectIdentity(identifier, rs.getString("class"));
@@ -678,7 +669,7 @@ public class BasicLookupStrategy implements LookupStrategy {
} }
@Override @Override
public boolean isSidLoaded(@Nullable List<Sid> sids) { public boolean isSidLoaded(List<Sid> sids) {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
@@ -27,7 +27,6 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcOperations;
@@ -99,7 +98,7 @@ public class JdbcAclService implements AclService {
} }
@Override @Override
public @Nullable List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) { public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() }; Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql, List<ObjectIdentity> objects = this.jdbcOperations.query(this.findChildrenSql,
(rs, rowNum) -> mapObjectIdentityRow(rs), args); (rs, rowNum) -> mapObjectIdentityRow(rs), args);
@@ -110,14 +109,11 @@ public class JdbcAclService implements AclService {
String javaType = rs.getString("class"); String javaType = rs.getString("class");
Serializable identifier = (Serializable) rs.getObject("obj_id"); Serializable identifier = (Serializable) rs.getObject("obj_id");
identifier = this.aclClassIdUtils.identifierFrom(identifier, rs); identifier = this.aclClassIdUtils.identifierFrom(identifier, rs);
if (identifier == null) {
throw new IllegalStateException("Identifier cannot be null");
}
return this.objectIdentityGenerator.createObjectIdentity(identifier, javaType); return this.objectIdentityGenerator.createObjectIdentity(identifier, javaType);
} }
@Override @Override
public Acl readAclById(ObjectIdentity object, @Nullable List<Sid> sids) throws NotFoundException { public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids); Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
Assert.isTrue(map.containsKey(object), Assert.isTrue(map.containsKey(object),
() -> "There should have been an Acl entry for ObjectIdentity " + object); () -> "There should have been an Acl entry for ObjectIdentity " + object);
@@ -135,7 +131,7 @@ public class JdbcAclService implements AclService {
} }
@Override @Override
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids) public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
throws NotFoundException { throws NotFoundException {
Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids); Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids);
// Check every requested object identity was found (throw NotFoundException if // Check every requested object identity was found (throw NotFoundException if
@@ -164,7 +160,7 @@ public class JdbcAclService implements AclService {
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE; this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
} }
else { else {
log.debug("Find children statement has already been overridden, so not overriding the default"); log.debug("Find children statement has already been overridden, so not overridding the default");
} }
} }
} }
@@ -22,8 +22,6 @@ import java.util.List;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.security.acls.domain.AccessControlEntryImpl; import org.springframework.security.acls.domain.AccessControlEntryImpl;
@@ -52,7 +50,7 @@ import org.springframework.util.Assert;
* The default settings are for HSQLDB. If you are using a different database you will * The default settings are for HSQLDB. If you are using a different database you will
* probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and * probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and
* {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The * {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The
* other queries, SQL inserts and updates can also be customized to accommodate schema * other queries, SQL inserts and updates can also be customized to accomodate schema
* variations, but must produce results consistent with those expected by the defaults. * variations, but must produce results consistent with those expected by the defaults.
* <p> * <p>
* See the appendix of the Spring Security reference manual for more information on the * See the appendix of the Spring Security reference manual for more information on the
@@ -122,7 +120,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
// Need to retrieve the current principal, in order to know who "owns" this ACL // Need to retrieve the current principal, in order to know who "owns" this ACL
// (can be changed later on) // (can be changed later on)
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication(); Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
Assert.isTrue(auth != null, "Authentication required");
PrincipalSid sid = new PrincipalSid(auth); PrincipalSid sid = new PrincipalSid(auth);
// Create the acl_object_identity row // Create the acl_object_identity row
@@ -158,12 +155,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class"); Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
Assert.state(acl.getId() != null, "ACL ID cannot be null");
stmt.setLong(1, (Long) acl.getId()); stmt.setLong(1, (Long) acl.getId());
stmt.setInt(2, i); stmt.setInt(2, i);
Long sidPrimaryKey = createOrRetrieveSidPrimaryKey(entry.getSid(), true); stmt.setLong(3, createOrRetrieveSidPrimaryKey(entry.getSid(), true));
Assert.state(sidPrimaryKey != null, "SID primary key cannot be null");
stmt.setLong(3, sidPrimaryKey);
stmt.setInt(4, entry.getPermission().getMask()); stmt.setInt(4, entry.getPermission().getMask());
stmt.setBoolean(5, entry.isGranting()); stmt.setBoolean(5, entry.isGranting());
stmt.setBoolean(6, entry.isAuditSuccess()); stmt.setBoolean(6, entry.isAuditSuccess());
@@ -195,14 +189,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param allowCreate true if creation is permitted if not found * @param allowCreate true if creation is permitted if not found
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected @Nullable Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) { protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
List<@Nullable Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type); List<Long> classIds = this.jdbcOperations.queryForList(this.selectClassPrimaryKey, Long.class, type);
if (!classIds.isEmpty()) { if (!classIds.isEmpty()) {
Long result = classIds.get(0); return classIds.get(0);
if (result != null) {
return result;
}
} }
if (allowCreate) { if (allowCreate) {
@@ -213,9 +204,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
this.jdbcOperations.update(this.insertClass, type, idType.getCanonicalName()); this.jdbcOperations.update(this.insertClass, type, idType.getCanonicalName());
} }
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
Long result = this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class); return this.jdbcOperations.queryForObject(this.classIdentityQuery, Long.class);
Assert.state(result != null, "Failed to retrieve class primary key");
return result;
} }
return null; return null;
@@ -230,7 +219,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized * @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
* implementation. * implementation.
*/ */
protected @Nullable Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) { protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
Assert.notNull(sid, "Sid required"); Assert.notNull(sid, "Sid required");
if (sid instanceof PrincipalSid) { if (sid instanceof PrincipalSid) {
String sidName = ((PrincipalSid) sid).getPrincipal(); String sidName = ((PrincipalSid) sid).getPrincipal();
@@ -251,22 +240,16 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param allowCreate true if creation is permitted if not found * @param allowCreate true if creation is permitted if not found
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected @Nullable Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
boolean allowCreate) { List<Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class, sidIsPrincipal,
List<@Nullable Long> sidIds = this.jdbcOperations.queryForList(this.selectSidPrimaryKey, Long.class, sidName);
sidIsPrincipal, sidName);
if (!sidIds.isEmpty()) { if (!sidIds.isEmpty()) {
Long result = sidIds.get(0); return sidIds.get(0);
if (result != null) {
return result;
}
} }
if (allowCreate) { if (allowCreate) {
this.jdbcOperations.update(this.insertSid, sidIsPrincipal, sidName); this.jdbcOperations.update(this.insertSid, sidIsPrincipal, sidName);
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
Long result = this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class); return this.jdbcOperations.queryForObject(this.sidIdentityQuery, Long.class);
Assert.state(result != null, "Failed to retrieve sid primary key");
return result;
} }
return null; return null;
} }
@@ -296,9 +279,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
} }
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity); Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
if (oidPrimaryKey == null) {
throw new NotFoundException("Object identity not found: " + objectIdentity);
}
// Delete this ACL's ACEs in the acl_entry table // Delete this ACL's ACEs in the acl_entry table
deleteEntries(oidPrimaryKey); deleteEntries(oidPrimaryKey);
@@ -339,11 +319,10 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param oid to find * @param oid to find
* @return the object identity or null if not found * @return the object identity or null if not found
*/ */
protected @Nullable Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
try { try {
Long result = this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, return this.jdbcOperations.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, oid.getType(),
oid.getType(), oid.getIdentifier().toString()); oid.getIdentifier().toString());
return result;
} }
catch (DataAccessException notFound) { catch (DataAccessException notFound) {
return null; return null;
@@ -361,11 +340,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier"); Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
// Delete this ACL's ACEs in the acl_entry table // Delete this ACL's ACEs in the acl_entry table
Long oidPrimaryKey = retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()); deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()));
if (oidPrimaryKey == null) {
throw new NotFoundException("Object identity not found for ACL: " + acl.getObjectIdentity());
}
deleteEntries(oidPrimaryKey);
// Create this ACL's ACEs in the acl_entry table // Create this ACL's ACEs in the acl_entry table
createEntries(acl); createEntries(acl);
@@ -496,7 +471,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID; this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
} }
else { else {
log.debug("Insert class statement has already been overridden, so not overriding the default"); log.debug("Insert class statement has already been overridden, so not overridding the default");
} }
} }
} }
@@ -19,8 +19,6 @@ package org.springframework.security.acls.jdbc;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.model.Acl; import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.NotFoundException; import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.security.acls.model.ObjectIdentity;
@@ -44,6 +42,6 @@ public interface LookupStrategy {
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to * {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
* automatically create entries if required) * automatically create entries if required)
*/ */
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids); Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,7 +17,4 @@
/** /**
* JDBC-based persistence of ACL information * JDBC-based persistence of ACL information
*/ */
@NullMarked
package org.springframework.security.acls.jdbc; package org.springframework.security.acls.jdbc;
import org.jspecify.annotations.NullMarked;
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.Nullable;
/** /**
* Represents an individual permission assignment within an {@link Acl}. * Represents an individual permission assignment within an {@link Acl}.
* *
@@ -38,7 +36,7 @@ public interface AccessControlEntry extends Serializable {
* Obtains an identifier that represents this ACE. * Obtains an identifier that represents this ACE.
* @return the identifier, or <code>null</code> if unsaved * @return the identifier, or <code>null</code> if unsaved
*/ */
@Nullable Serializable getId(); Serializable getId();
Permission getPermission(); Permission getPermission();
@@ -19,8 +19,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import org.jspecify.annotations.Nullable;
/** /**
* Represents an access control list (ACL) for a domain object. * Represents an access control list (ACL) for a domain object.
* *
@@ -84,7 +82,7 @@ public interface Acl extends Serializable {
* @return the owner (may be <tt>null</tt> if the implementation does not use * @return the owner (may be <tt>null</tt> if the implementation does not use
* ownership concepts) * ownership concepts)
*/ */
@Nullable Sid getOwner(); Sid getOwner();
/** /**
* A domain object may have a parent for the purpose of ACL inheritance. If there is a * A domain object may have a parent for the purpose of ACL inheritance. If there is a
@@ -105,7 +103,7 @@ public interface Acl extends Serializable {
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not * @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
* have a parent) * have a parent)
*/ */
@Nullable Acl getParentAcl(); Acl getParentAcl();
/** /**
* Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down * Indicates whether the ACL entries from the {@link #getParentAcl()} should flow down
@@ -191,6 +189,6 @@ public interface Acl extends Serializable {
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this * @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
* <tt>Acl</tt> instance * <tt>Acl</tt> instance
*/ */
boolean isSidLoaded(@Nullable List<Sid> sids); boolean isSidLoaded(List<Sid> sids);
} }
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import org.springframework.security.acls.jdbc.JdbcAclService; import org.springframework.security.acls.jdbc.JdbcAclService;
/** /**
@@ -33,9 +31,9 @@ public interface AclCache {
void evictFromCache(ObjectIdentity objectIdentity); void evictFromCache(ObjectIdentity objectIdentity);
@Nullable MutableAcl getFromCache(ObjectIdentity objectIdentity); MutableAcl getFromCache(ObjectIdentity objectIdentity);
@Nullable MutableAcl getFromCache(Serializable pk); MutableAcl getFromCache(Serializable pk);
void putInCache(MutableAcl acl); void putInCache(MutableAcl acl);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,8 +19,6 @@ package org.springframework.security.acls.model;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
/** /**
* Provides retrieval of {@link Acl} instances. * Provides retrieval of {@link Acl} instances.
* *
@@ -34,7 +32,7 @@ public interface AclService {
* @param parentIdentity to locate children of * @param parentIdentity to locate children of
* @return the children (or <tt>null</tt> if none were found) * @return the children (or <tt>null</tt> if none were found)
*/ */
@Nullable List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity); List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
/** /**
* Same as {@link #readAclsById(List)} except it returns only a single Acl. * Same as {@link #readAclsById(List)} except it returns only a single Acl.
@@ -61,7 +59,7 @@ public interface AclService {
* @throws NotFoundException if an {@link Acl} was not found for the requested * @throws NotFoundException if an {@link Acl} was not found for the requested
* {@link ObjectIdentity} * {@link ObjectIdentity}
*/ */
Acl readAclById(ObjectIdentity object, @Nullable List<Sid> sids) throws NotFoundException; Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException;
/** /**
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s. * Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s.
@@ -100,7 +98,6 @@ public interface AclService {
* @throws NotFoundException if an {@link Acl} was not found for each requested * @throws NotFoundException if an {@link Acl} was not found for each requested
* {@link ObjectIdentity} * {@link ObjectIdentity}
*/ */
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, @Nullable List<Sid> sids) Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException;
throws NotFoundException;
} }
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.Nullable;
/** /**
* Represents the identity of an individual domain object instance. * Represents the identity of an individual domain object instance.
* *
@@ -42,7 +40,7 @@ public interface ObjectIdentity extends Serializable {
* @see Object#equals(Object) * @see Object#equals(Object)
*/ */
@Override @Override
boolean equals(@Nullable Object obj); boolean equals(Object obj);
/** /**
* Obtains the actual identifier. This identifier must not be reused to represent * Obtains the actual identifier. This identifier must not be reused to represent
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,8 +18,6 @@ package org.springframework.security.acls.model;
import java.io.Serializable; import java.io.Serializable;
import org.jspecify.annotations.Nullable;
/** /**
* A security identity recognised by the ACL system. * A security identity recognised by the ACL system.
* *
@@ -42,7 +40,7 @@ public interface Sid extends Serializable {
* @return <code>true</code> if the objects are equal, <code>false</code> otherwise * @return <code>true</code> if the objects are equal, <code>false</code> otherwise
*/ */
@Override @Override
boolean equals(@Nullable Object obj); boolean equals(Object obj);
/** /**
* Refer to the <code>java.lang.Object</code> documentation for the interface * Refer to the <code>java.lang.Object</code> documentation for the interface
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,7 +18,4 @@
* Interfaces and shared classes to manage access control lists (ACLs) for domain object * Interfaces and shared classes to manage access control lists (ACLs) for domain object
* instances. * instances.
*/ */
@NullMarked
package org.springframework.security.acls.model; package org.springframework.security.acls.model;
import org.jspecify.annotations.NullMarked;
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,7 +24,4 @@
* older and more verbose attribute/voter/after-invocation approach from versions before * older and more verbose attribute/voter/after-invocation approach from versions before
* Spring Security 3.0. * Spring Security 3.0.
*/ */
@NullMarked
package org.springframework.security.acls; package org.springframework.security.acls;
import org.jspecify.annotations.NullMarked;
@@ -1,2 +0,0 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.security.acls.aot.hint.AclRuntimeHints
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ import static org.mockito.Mockito.verify;
/** /**
* @author Luke Taylor * @author Luke Taylor
*/ */
@SuppressWarnings({ "unchecked", "deprecation" }) @SuppressWarnings({ "unchecked" })
public class AclEntryAfterInvocationCollectionFilteringProviderTests { public class AclEntryAfterInvocationCollectionFilteringProviderTests {
@Test @Test
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ import static org.mockito.Mockito.verify;
/** /**
* @author Luke Taylor * @author Luke Taylor
*/ */
@SuppressWarnings({ "unchecked", "deprecation" }) @SuppressWarnings({ "unchecked" })
public class AclEntryAfterInvocationProviderTests { public class AclEntryAfterInvocationProviderTests {
@Test @Test
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -478,7 +478,6 @@ public class AclImplTests {
} }
@Test @Test
@SuppressWarnings("unchecked")
public void hashCodeWithoutStackOverFlow() throws Exception { public void hashCodeWithoutStackOverFlow() throws Exception {
Sid sid = new PrincipalSid("pSid"); Sid sid = new PrincipalSid("pSid");
ObjectIdentity oid = new ObjectIdentityImpl("type", 1); ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@@ -47,6 +46,7 @@ import org.springframework.security.acls.model.Sid;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@@ -109,8 +109,7 @@ public class JdbcAclServiceTests {
List<ObjectIdentity> result = new ArrayList<>(); List<ObjectIdentity> result = new ArrayList<>();
result.add(new ObjectIdentityImpl(Object.class, "5577")); result.add(new ObjectIdentityImpl(Object.class, "5577"));
Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" }; Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
given(this.jdbcOperations.query(anyString(), ArgumentMatchers.<RowMapper<ObjectIdentity>>any(), eq(args))) given(this.jdbcOperations.query(anyString(), any(RowMapper.class), eq(args))).willReturn(result);
.willReturn(result);
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L); ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity); List<ObjectIdentity> objectIdentities = this.aclService.findChildren(objectIdentity);
assertThat(objectIdentities).hasSize(1); assertThat(objectIdentities).hasSize(1);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -80,10 +80,11 @@ public class SpringCacheBasedAclCacheTests {
assertThatIllegalArgumentException().isThrownBy(() -> new SpringCacheBasedAclCache(null, null, null)); assertThatIllegalArgumentException().isThrownBy(() -> new SpringCacheBasedAclCache(null, null, null));
} }
@SuppressWarnings("rawtypes")
@Test @Test
public void cacheOperationsAclWithoutParent() { public void cacheOperationsAclWithoutParent() {
Cache cache = getCache(); Cache cache = getCache();
Map<?, ?> realCache = (Map<?, ?>) cache.getNativeCache(); Map realCache = (Map) cache.getNativeCache();
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
@@ -115,10 +116,11 @@ public class SpringCacheBasedAclCacheTests {
assertThat(realCache).isEmpty(); assertThat(realCache).isEmpty();
} }
@SuppressWarnings("rawtypes")
@Test @Test
public void cacheOperationsAclWithParent() throws Exception { public void cacheOperationsAclWithParent() throws Exception {
Cache cache = getCache(); Cache cache = getCache();
Map<?, ?> realCache = (Map<?, ?>) cache.getNativeCache(); Map realCache = (Map) cache.getNativeCache();
Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+4 -10
View File
@@ -1,17 +1,13 @@
apply plugin: 'io.spring.convention.spring-module' apply plugin: 'io.spring.convention.spring-module'
apply plugin: 'io.freefair.aspectj' apply plugin: 'io.freefair.aspectj'
apply plugin: 'javadoc-warnings-error'
apply plugin: 'compile-warnings-error'
compileAspectj { compileAspectj {
sourceCompatibility = "17" sourceCompatibility "17"
targetCompatibility = "17" targetCompatibility "17"
ajcOptions.compilerArgs += ['-Xlint:ignore']
} }
compileTestAspectj { compileTestAspectj {
sourceCompatibility = "17" sourceCompatibility "17"
targetCompatibility = "17" targetCompatibility "17"
ajcOptions.compilerArgs += ['-Xlint:ignore']
} }
dependencies { dependencies {
@@ -22,8 +18,6 @@ dependencies {
api 'org.springframework:spring-context' api 'org.springframework:spring-context'
api 'org.springframework:spring-core' api 'org.springframework:spring-core'
optional project(':spring-security-access')
testImplementation 'org.springframework:spring-aop' testImplementation 'org.springframework:spring-aop'
testImplementation "org.assertj:assertj-core" testImplementation "org.assertj:assertj-core"
testImplementation "org.junit.jupiter:junit-jupiter-api" testImplementation "org.junit.jupiter:junit-jupiter-api"
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-present the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

Some files were not shown because too many files have changed in this diff Show More