APMT (AEM Permission Matrix Tester) is a new library built on top of JUnit5, which allows to cover big part of permission test cases with little effort. Ease of use and readability, which are the main goals of the tool, are achieved through the use of DSL written in Kotlin.
Introduction
Permission tests are an inseparable part of the development of many web applications. This is especially true for AEM-based applications where the existence of multiple roles such as authors, reviewers, publishers, or super authors, is standard. Nevertheless, these tests are often performed manually and any attempt to automate them is abandoned. And here is where APMT comes to the rescue. APMT provides a suite of tests that checks permissions to perform read and write operations on resources. The only thing to configure is to provide the paths and users for which they will be run. Little effort, huge benefits.
Let's start
At the beginning, we need to create a file with general settings. It's called apmt.yaml
, and contains credentials of
apmt user and the addresses of author and publish instances. The APMT user is a special user, which should be able to
perform all actions on tested paths: creating, updating, reading and deleting resources. It's required because it
prepares environment for tests, and cleans it up when tests are done. AEM instances have to be accessible from the
machine where test are being executed. APMT connects to them, and performs CRUD operations on given paths, using HTTP
requests.
apmt-user:
username: apmt-user
password: p@SSWoRd
instances:
author:
name: author@local
url: http://localhost:4502
publish:
name: publish@local
url: http://localhost:4503
Currently there is no different way to provide password for the APMT user. But you may get around the problem using resource filtering mechanism available in many build tools like gradle or maven. Resource filtering would be a great choice also for handling different sets of environments. You may find simple configuration in example project.
In the second step we need to define test users. Let's put them into an enum class. As you can see below, it's written in Kotlin. We strongly recommend using Kotlin, because the whole code of APMT is written in this language, and we use cool features of that language like lambdas with receivers, and extension functions. That simplifies tests, and increases readability. Of course there is still possibility to use plain Java.
import com.cognifide.apmt.User
const val PASSWORD = "p@SSWoRd"
enum class Users (
override val username: String,
override val password: String
) : User {
GLOBAL_AUTHOR("global-test-author", PASSWORD),
LOCAL_AUTHOR("en_us-test-author", PASSWORD),
GLOBAL_SUPER_AUTHOR("global-test-super-author", PASSWORD),
LOCAL_SUPER_AUTHOR("en_us-test-super-author", PASSWORD)
}
Because users are defined in enum class, you may use different ways to store passwords than directly in code. For example you may fetch passwords from environment variable. Here is an example how it may look like:
import com.cognifide.apmt.User
import java.lang.RuntimeException
val PASSWORD = loadPassword()
fun loadPassword() : String = System.getenv("TEST_USER_PASSWORD") ?: throw RuntimeException("Cannot find environment variable with password")
Configuring permission test
And now we can go to tests. Let's start with a test checking the permissions to create a page. We need to create a class
that extends CreatePageTest
, and provide configuration using super class constructor. The first argument of all tests
is the same, it is a vararg of type TestCase
. TestCase
is just an interface, so in the example below, we are using
its implementation BasicTestCase
. The second argument is specific to this test, it defines structure of the created
page, like title or template, or any other property (or even child node).
import com.cognifide.apmt.BasicTestCase
import com.cognifide.apmt.tests.page.CreatePageTest
class CustomCreatePageTest : CreatePageTest(
BasicTestCase {
paths(
"/content/we-retail/us/es/apt-test-page"
)
allowedUsers(
Users.GLOBAL_AUTHOR,
Users.GLOBAL_SUPER_AUTHOR
)
allUsers(Users.values())
},
pageContent = {
jcrTitle = "APMT"
cqTemplate = "/conf/we-retail/settings/wcm/templates/content-page"
}
)
As you probably noticed, the BasicTestCase
doesn't simply define users
, but there are allowedUsers
and allUsers
methods instead. Actually, there is also deniedUsers
method. It makes no sense to use all of them at once. Methods
allowedUsers
and deniedUsers
directly indicate which users can create pages and which cannot. Using one of these
methods together with allUsers
causes the second group of users to be computed, as shown in the table:
allowedUsers | deniedUsers | allUsers | Allowed users | Denied users |
---|---|---|---|---|
defined | - | - | allowedUser | - |
defined | - | defined | allowedUser | allUsers - allowedUsers |
defined | defined | - | allowedUser | deniedUsers |
- | defined | - | - | deniedUsers |
- | defined | defined | allUsers - deniedUsers | deniedUsers |
It's very useful when list of users is long, or you are adding new users to it (they will be automatically used during next test's execution).
Execution
And that's it. You can now execute your test.
$ sh gradlew test
> Task :test
Check user permissions to create pages > User LOCAL_AUTHOR cannot create page /content/we-retail/us/es/apt-test-page PASSED
Check user permissions to create pages > User LOCAL_SUPER_AUTHOR cannot create page /content/we-retail/us/es/apt-test-page PASSED
Check user permissions to create pages > User GLOBAL_AUTHOR can create page /content/we-retail/us/es/apt-test-page PASSED
Check user permissions to create pages > User GLOBAL_SUPER_AUTHOR can create page /content/we-retail/us/es/apt-test-page PASSED
BUILD SUCCESSFUL in 4s
3 actionable tasks: 1 executed, 2 up-to-date
Next steps
At this point, you are familiar with main concepts of APMT library, so you may proceed to cover next test cases. Below is a list of tests currently provided by APMT. They check CRUD operations on assets, pages, and resources.
-
com.cognifide.apmt.tests.asset
CreateAssetTest
EditAssetTest
RemoveAssetTest
-
CreatePageTest
EditPagePropertiesTest
EditPageTest
OpenPageTest
RemovePageTest
ReplicatePageTest
-
com.cognifide.apmt.tests.resource
CreateResourceTest
EditResourceTest
ReadResourceTest
RemoveResourceTest
Summary
APMT comes with several tests for CRUD operations on pages, resources, and assets. They should be enough to cover big part of permission tests scope. If you've any questions, or are interested in details, please visit project's repo: https://github.com/wttech/apmt. You may also check out example project.