Skip to content

Commit

Permalink
Grails 7: (grails#46) Update documentation with updated links and add @p
Browse files Browse the repository at this point in the history
 annotation to examples
  • Loading branch information
bkoehm committed Dec 4, 2024
1 parent 8d81f9a commit ce29a75
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 28 deletions.
19 changes: 15 additions & 4 deletions docs/src/docs/installing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,25 @@ dependencies {

Different Branches are built for different versions of Grails

* master: Grails 4
* 3.3.x: Grails 3.3+
* 5.0.x: Grails 7
* 4.0: Grails 4 through Grails 6
* 3.3.x: Grails 3.3
* grails_32: Grails 3.2
* 2.x: Grails 2


Current version (master) is for Grails 4 only.
Previous version (3.3.x) is only compatible with Grails 3.3.x or higher.
Current version (5.0.x) is for Grails 7 only.

For Grails 3.3.x use:

[source, groovy]
.build.gradle
----
dependencies {
...
compile 'org.grails.plugins:spring-security-acl:3.2.1'
...
----

For previous Grails 3 versions ( 3.0.x, 3.1.x and 3.2.x ) use:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/installing/distribution.adoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[[Distribution]]
=== Distribution

Grails Spring Security ACL plugin is https://bintray.com/grails/plugins/spring-security-acl[distributed in bintray].
Grails Spring Security ACL plugin is https://repo.grails.org/ui/native/core/org/grails/plugins/spring-security-acl/[distributed in repo.grails.org].

4 changes: 2 additions & 2 deletions docs/src/docs/installing/snapshots.adoc
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[[Snapshots]]
=== Snapshots

Snapshots are published automatically to https://oss.jfrog.org/[Artifactory OSS] on every successful build.
Snapshots are published automatically to https://repo.grails.org/ui/native/core/org/grails/plugins/spring-security-acl/[repo.grails.org] on every successful build.
You can use them by defining this Maven repository inside
the `repositories` block in your `build.gradle`:

[source, groovy]
----
maven { url "https://oss.jfrog.org/artifactory/oss-snapshot-local" }
maven { url "https://repo.grails.org/grails/core" }
----
4 changes: 2 additions & 2 deletions docs/src/docs/introduction.adoc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[[introduction]]
== Introduction to the Spring Security ACL Plugin

The ACL plugin adds Domain Object Security support to a Grails application that uses Spring Security. It depends on the http://grails.org/plugin/spring-security-core[Spring Security Core plugin].
The ACL plugin adds Domain Object Security support to a Grails application that uses Spring Security. It depends on the https://github.com/grails/grails-spring-security-core[Spring Security Core plugin].

The core plugin and other extension plugins support restricting access to URLs via rules that include checking a user's authentication status, roles, etc. and the ACL plugin extends this by adding support for restricting access to individual domain class instances. The access can be very fine-grained and can define which actions can be taken on an object - these typically include Read, Create, Write, Delete, and Administer but you're free to define whatever actions you like.

To learn about using ACLs in Grails, you can follow the <<tutorial>> and in addition you can download and run a complete Grails application that uses the plugin. Installing and running the application are described in <<sampleApp>>.

In addition to this document, you should read the http://docs.spring.io/spring-security/site/docs/5.0.x/reference/htmlsingle/#domain-acls[Spring Security documentation].
In addition to this document, you should read the https://docs.spring.io/spring-security/reference/servlet/authorization/acls.html[Spring Security documentation].
13 changes: 7 additions & 6 deletions docs/src/docs/tutorial.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ and run the `compile` command to resolve the dependencies:
$ grails compile
....

This will transitively install the http://grails.org/plugin/spring-security-core[Spring Security Core] plugin, so you'll need to configure that by running the `s2-quickstart` script:
This will transitively install the https://github.com/grails/grails-spring-security-core[Spring Security Core] plugin, so you'll need to configure that by running the `s2-quickstart` script:

....
$ grails s2-quickstart com.testacl User Role
Expand Down Expand Up @@ -76,6 +76,7 @@ import org.springframework.security.acls.model.AccessControlEntry
import org.springframework.security.acls.model.MutableAcl
import org.springframework.security.acls.model.Permission
import org.springframework.security.acls.model.Sid
import org.springframework.security.core.parameters.P
import grails.compiler.GrailsCompileStatic
import grails.plugin.springsecurity.SpringSecurityService
Expand All @@ -97,7 +98,7 @@ class ReportService {
@PreAuthorize('hasPermission(#report, admin)')
@Transactional
void addPermission(Report report, String username, Permission permission) {
void addPermission(@P("report") Report report, String username, Permission permission) {
aclUtilService.addPermission report, username, permission
}
Expand All @@ -113,7 +114,7 @@ class ReportService {
}
@PreAuthorize('hasPermission(#id, "com.testacl.Report", read) or hasPermission(#id, "com.testacl.Report", admin)')
Report get(long id) {
Report get(@P("id") long id) {
Report.get id
}
Expand All @@ -129,13 +130,13 @@ class ReportService {
@Transactional
@PreAuthorize('hasPermission(#report, write) or hasPermission(#report, admin)')
void update(Report report, String name) {
void update(@P("report") Report report, String name) {
report.name = name
}
@Transactional
@PreAuthorize('hasPermission(#report, delete) or hasPermission(#report, admin)')
void delete(Report report) {
void delete(@P("report") Report report) {
report.delete()
// Delete the ACL information as well
Expand All @@ -144,7 +145,7 @@ class ReportService {
@Transactional
@PreAuthorize('hasPermission(#report, admin)')
void deletePermission(Report report, Sid recipient, Permission permission) {
void deletePermission(@P("report") Report report, Sid recipient, Permission permission) {
MutableAcl acl = (MutableAcl)aclUtilService.readAcl(report)
// Remove all permissions associated with this particular
Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/usage/acls.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

==== Suggested application changes

To properly display access denied exceptions (e.g. when a user tries to perform an action but doesn't have a grant authorizing it), you should create a mapping in `grails-app/controllers/UrlMappings.groovy` for error code 403. In addition, it's possible to trigger a http://docs.spring.io/spring-security/site/docs/5.0.x/apidocs/org/springframework/security/acls/model/NotFoundException.html[NotFoundException] which will create an error 500, but should be treated like a 403 error, so you should add mappings for these conditions:
To properly display access denied exceptions (e.g. when a user tries to perform an action but doesn't have a grant authorizing it), you should create a mapping in `grails-app/controllers/UrlMappings.groovy` for error code 403. In addition, it's possible to trigger a https://docs.spring.io/spring-security/site/docs/6.4.1/api/org/springframework/security/acls/model/NotFoundException.html[NotFoundException] which will create an error 500, but should be treated like a 403 error, so you should add mappings for these conditions:

[source,java]
----
Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/usage/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ grails.plugin.springsecurity.acl.authority.

==== Run-As Authentication Replacement

There are also two options to configure http://docs.spring.io/spring-security/site/docs/5.0.x/reference/htmlsingle/#runas[Run-As Authentication Replacement]:
There are also two options to configure https://docs.spring.io/spring-security/reference/servlet/authentication/runas.html[Run-As Authentication Replacement]:

[width="100%",options="header"]
|====================
Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/usage/customPermissions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Once this is done you can use the permission like any other, specifying its quot
[source,java]
----
@PreAuthorize("hasPermission(#id, 'com.testacl.Report', 'approve')")
Report get(long id) {
Report get(@P("id") long id) {
Report.get id
}
----
2 changes: 1 addition & 1 deletion docs/src/docs/usage/domainClasses.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ By default it's assumed that domain classes have a numeric primary key, but that

Finally, the `AclEntry` domain class contains entries representing grants (or denials) of a permission on an object instance to a recipient. The `aclObjectIdentity` field references the domain class instance (since an instance can have many granted permissions). The `sid` field references the recipient. The `granting` field determines whether the entry grants the permission (`true`) or denies it (`false`). The `aceOrder` field specifies the position of the entry, which is important because the entries are evaluated in order and the first matching entry determines whether access is allowed. `auditSuccess` and `auditFailure` determine whether to log success and/or failure events (these both default to `false`).

The `mask` field holds the permission. This can be a source of confusion because the name (and the Spring Security documentation) indicates that it's a bit mask. A value of 1 indicates permission A, a value of 2 indicates permission B, a value of 4 indicates permission C, a value of 8 indicates permission D, etc. So you would think that a value of 5 would indicate a grant of both permission A and C. Unfortunately this is not the case. There is a http://docs.spring.io/spring-security/site/docs/5.0.x/apidocs/org/springframework/security/acls/domain/CumulativePermission.html[CumulativePermission] class that supports this, but the standard classes don't support it (`AclImpl.isGranted()` checks for == rather than using | (bitwise or) so a combined entry would never match). So rather than grouping all permissions for one recipient on one instances into a bit mask, you must create individual records for each.
The `mask` field holds the permission. This can be a source of confusion because the name (and the Spring Security documentation) indicates that it's a bit mask. A value of 1 indicates permission A, a value of 2 indicates permission B, a value of 4 indicates permission C, a value of 8 indicates permission D, etc. So you would think that a value of 5 would indicate a grant of both permission A and C. Unfortunately this is not the case. There is a https://docs.spring.io/spring-security/site/docs/6.4.1/api/org/springframework/security/acls/domain/CumulativePermission.html[CumulativePermission] class that supports this, but the standard classes don't support it (`AclImpl.isGranted()` checks for == rather than using | (bitwise or) so a combined entry would never match). So rather than grouping all permissions for one recipient on one instances into a bit mask, you must create individual records for each.

[source,groovy]
----
Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/usage/runAs.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[[runAs]]
=== Run-As Authentication Replacement

Although not strictly related to ACLs, the plugin implements http://docs.spring.io/spring-security/site/docs/5.0.x/reference/htmlsingle/#runas[Run-As Authentication Replacement] since it's related to method security in general. This feature is similar to the Switch User feature of the Spring Security Core plugin, but instead of running as another user until you choose to revert to your original `Authentication`, the temporary authentication switch only lasts for one method invocation.
Although not strictly related to ACLs, the plugin implements https://docs.spring.io/spring-security/reference/servlet/authentication/runas.html[Run-As Authentication Replacement] since it's related to method security in general. This feature is similar to the Switch User feature of the Spring Security Core plugin, but instead of running as another user until you choose to revert to your original `Authentication`, the temporary authentication switch only lasts for one method invocation.

For example, in this service `someMethod()` requires that the authenticated user have `ROLE_ADMIN` and will also be granted `ROLE_RUN_AS_SUPERUSER` for the duration of the method only:

Expand Down
17 changes: 9 additions & 8 deletions docs/src/docs/usage/serviceMethods.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ There are two primary use cases for ACL security: determining whether a user is

There are four annotations:

* http://docs.spring.io/spring-security/site/docs/5.0.x/apidocs/org/springframework/security/access/prepost/PreAuthorize.html[@PreAuthorize]
* http://docs.spring.io/spring-security/site/docs/5.0.x/apidocs/org/springframework/security/access/prepost/PreFilter.html[@PreFilter]
* http://docs.spring.io/spring-security/site/docs/5.0.x/apidocs/org/springframework/security/access/prepost/PostAuthorize.html[@PostAuthorize]
* http://docs.spring.io/spring-security/site/docs/5.0.x/apidocs/org/springframework/security/access/prepost/PostFilter.html[@PostFilter]
* https://docs.spring.io/spring-security/site/docs/6.4.1/api/org/springframework/security/access/prepost/PreAuthorize.html[@PreAuthorize]
* https://docs.spring.io/spring-security/site/docs/6.4.1/api/org/springframework/security/access/prepost/PreFilter.html[@PreFilter]
* https://docs.spring.io/spring-security/site/docs/6.4.1/api/org/springframework/security/access/prepost/PostAuthorize.html[@PostAuthorize]
* https://docs.spring.io/spring-security/site/docs/6.4.1/api/org/springframework/security/access/prepost/PostFilter.html[@PostFilter]

The annotations use security-specific Spring expression language (SpEL) expressions - see http://docs.spring.io/spring-security/site/docs/5.0.x/reference/htmlsingle/#el-access[the documentation] for the available standard and method expressions.
The annotations use security-specific Spring expression language (SpEL) expressions - see https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html#authorization-expressions[the documentation] for the available standard and method expressions.

Here's an example service that manages a `Report` domain class and uses these annotations and expressions:

[source,java]
----
import org.springframework.security.access.prepost.PostFilter
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.parameters.P
import grails.gorm.transactions.Transactional
import com.yourapp.Report
Expand All @@ -26,7 +27,7 @@ class ReportService {
@PreAuthorize("hasPermission(#id, 'com.yourapp.Report', read) or " +
"hasPermission(#id, 'com.yourapp.Report', admin)")
Report getReport(long id) {
Report getReport(@P("id") long id) {
Report.get(id)
}
Expand All @@ -53,7 +54,7 @@ class ReportService {
@Transactional
@PreAuthorize("hasPermission(#report, write) or " +
"hasPermission(#report, admin)")
Report updateReport(Report report, params) {
Report updateReport(@P("report") Report report, params) {
report.properties = params
report.save()
report
Expand All @@ -62,7 +63,7 @@ class ReportService {
@Transactional
@PreAuthorize("hasPermission(#report, delete) or " +
"hasPermission(#report, admin)")
void deleteReport(Report report) {
void deleteReport(@P("report") Report report) {
report.delete()
}
}
Expand Down

0 comments on commit ce29a75

Please sign in to comment.