You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/04/17 15:46:15 UTC
[isis] branch 2.0.0-M5 updated (4c16248 -> 901938b)
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a change to branch 2.0.0-M5
in repository https://gitbox.apache.org/repos/asf/isis.git.
from 4c16248 ISIS-2484: minor tweaks
new 6975c7d ISIS-2484: adds some sketchy notes on jaxrsclient and restclient
new 901938b ISIS-2484: adds docs for secman
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../adoc/modules/model-annotation/pages/about.adoc | 2 +
.../secman/images/secman-domain-model.drawio.svg | 1 +
.../images/secman-shiro-architecture.drawio.svg | 1 +
.../secman-shiro-delegate-architecture.drawio.svg | 1 +
...s-security-module-realm-with-delegate-realm.PNG | Bin 45089 -> 0 bytes
...iro-to-use-isisaddons-security-module-realm.PNG | Bin 38713 -> 0 bytes
.../secman/adoc/modules/secman/pages/about.adoc | 218 +++++++++++++++-
.../secman/adoc/modules/secman/pages/api.adoc | 7 -
.../modules/secman/pages/jbcrypt-encryption.adoc | 7 -
.../adoc/modules/secman/pages/jdo-persistence.adoc | 7 -
.../adoc/modules/secman/pages/jpa-persistence.adoc | 8 -
.../secman/adoc/modules/secman/pages/model.adoc | 7 -
.../adoc/modules/secman/pages/setting-up.adoc | 288 +++++++++++++++++++++
.../adoc/modules/secman/pages/shiro-realm.adoc | 34 ---
.../adoc/modules/secman/partials/module-nav.adoc | 11 +-
.../api/tenancy/ApplicationTenancyEvaluator.java | 35 ++-
.../secman/api/user/ApplicationUser.java | 27 ++
.../secman/shiro/PrincipalForApplicationUser.java | 33 +--
.../adoc/modules/jaxrsclient/pages/about.adoc | 8 +-
.../impl/client/JaxRsClientDefault.java | 7 +-
.../adoc/modules/restclient/pages/about.adoc | 5 +-
.../isis/extensions/restclient/RestfulClient.java | 5 +
22 files changed, 605 insertions(+), 107 deletions(-)
create mode 100644 extensions/security/secman/adoc/modules/secman/images/secman-domain-model.drawio.svg
create mode 100644 extensions/security/secman/adoc/modules/secman/images/secman-shiro-architecture.drawio.svg
create mode 100644 extensions/security/secman/adoc/modules/secman/images/secman-shiro-delegate-architecture.drawio.svg
delete mode 100644 extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm-with-delegate-realm.PNG
delete mode 100644 extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm.PNG
delete mode 100644 extensions/security/secman/adoc/modules/secman/pages/api.adoc
delete mode 100644 extensions/security/secman/adoc/modules/secman/pages/jbcrypt-encryption.adoc
delete mode 100644 extensions/security/secman/adoc/modules/secman/pages/jdo-persistence.adoc
delete mode 100644 extensions/security/secman/adoc/modules/secman/pages/jpa-persistence.adoc
delete mode 100644 extensions/security/secman/adoc/modules/secman/pages/model.adoc
create mode 100644 extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc
delete mode 100644 extensions/security/secman/adoc/modules/secman/pages/shiro-realm.adoc
[isis] 01/02: ISIS-2484: adds some sketchy notes on jaxrsclient and
restclient
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch 2.0.0-M5
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 6975c7d76f87a7034b2510f4b0017c377e238c66
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Apr 16 11:23:59 2021 +0100
ISIS-2484: adds some sketchy notes on jaxrsclient and restclient
---
mappings/jaxrsclient/adoc/modules/jaxrsclient/pages/about.adoc | 8 +++++++-
.../extensions/jaxrsclient/impl/client/JaxRsClientDefault.java | 7 +++++--
mappings/restclient/adoc/modules/restclient/pages/about.adoc | 5 ++++-
.../java/org/apache/isis/extensions/restclient/RestfulClient.java | 5 +++++
4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/mappings/jaxrsclient/adoc/modules/jaxrsclient/pages/about.adoc b/mappings/jaxrsclient/adoc/modules/jaxrsclient/pages/about.adoc
index 4c58125..891ea36 100644
--- a/mappings/jaxrsclient/adoc/modules/jaxrsclient/pages/about.adoc
+++ b/mappings/jaxrsclient/adoc/modules/jaxrsclient/pages/about.adoc
@@ -2,4 +2,10 @@
:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-WARNING: TODO
+
+Consider the use case where an Apache Isis app emits "thin" events to an ESB, for example using the xref:mappings:outbox-publisher:about.adoc[Outbox Publisher].
+The ESB then queries back to the Apache Isis app to get extra info in a canonical DTO form in order to continue processing.
+
+TIP: for more on this use case, try searching on "link:https://www.google.com/search?q=fat+vs+thin+events[fat vs thin events]".
+
+This library, then, provides a bit of code to construct the correct `Accept-Type` headers, in a format that is then interpreted by an application-specific implementation of xref:refguide:applib:index/services/conmap/ContentMappingService.adoc[ContentMappingService].
diff --git a/mappings/jaxrsclient/impl/src/main/java/org/apache/isis/extensions/jaxrsclient/impl/client/JaxRsClientDefault.java b/mappings/jaxrsclient/impl/src/main/java/org/apache/isis/extensions/jaxrsclient/impl/client/JaxRsClientDefault.java
index 548dee1..1c41e67 100644
--- a/mappings/jaxrsclient/impl/src/main/java/org/apache/isis/extensions/jaxrsclient/impl/client/JaxRsClientDefault.java
+++ b/mappings/jaxrsclient/impl/src/main/java/org/apache/isis/extensions/jaxrsclient/impl/client/JaxRsClientDefault.java
@@ -108,6 +108,9 @@ public class JaxRsClientDefault implements JaxRsClient {
/**
* Optional hook, eg allow timeouts to be set:
*
+ * <p>
+ * for example:
+ * </p>
* <pre>
* HTTPConduit conduit = WebClient.getConfig(webTarget).getHttpConduit();
* conduit.getClient().setConnectionTimeout(1000 * 3);
@@ -123,12 +126,12 @@ public class JaxRsClientDefault implements JaxRsClient {
}
private MediaType mediaTypeFor(final Class<?> dtoClass, final String reprType) {
-
+
// application/xml;profile="urn~org.restfulobjects~repr-types/action-result";x-ro-domain-type="org.apache.isis.schema.cmd.v1.CommandsDto"
val parameters = new HashMap<String,String>();
parameters.put("profile", "urn:org.restfulobjects:repr-types/" + reprType);
parameters.put("x-ro-domain-type", dtoClass.getName());
-
+
return new MediaType("application", "xml", parameters);
}
diff --git a/mappings/restclient/adoc/modules/restclient/pages/about.adoc b/mappings/restclient/adoc/modules/restclient/pages/about.adoc
index 845cfc1..7d54c6a 100644
--- a/mappings/restclient/adoc/modules/restclient/pages/about.adoc
+++ b/mappings/restclient/adoc/modules/restclient/pages/about.adoc
@@ -2,4 +2,7 @@
:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-WARNING: TODO
+This library is for integration scenario to programmatically invoke the xref:vro::about.adoc[REST API (Restful Objects Viewer)] of an Apache Isis application, using the link:http://restfulobjects.org[restfulobjects protocol].
+
+A common use case would be to consume information from some external system, for example uploading a scanned PDF or a representation of an incoming invoice.
+
diff --git a/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/RestfulClient.java b/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/RestfulClient.java
index 4db0af5..3043e0e 100644
--- a/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/RestfulClient.java
+++ b/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/RestfulClient.java
@@ -44,6 +44,11 @@ import lombok.extern.log4j.Log4j2;
/**
* Setup the Restful Client with Basic-Auth:
+ *
+ * <p>
+ * For example:
+ * </p>
+ *
* <blockquote><pre>
RestfulClientConfig clientConfig = new RestfulClientConfig();
clientConfig.setRestfulBase("http://localhost:8080/helloworld/restful/");
[isis] 02/02: ISIS-2484: adds docs for secman
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch 2.0.0-M5
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 901938bee873e46c2420c09f1e7683e88b15975c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Sat Apr 17 16:45:54 2021 +0100
ISIS-2484: adds docs for secman
---
.../adoc/modules/model-annotation/pages/about.adoc | 2 +
.../secman/images/secman-domain-model.drawio.svg | 1 +
.../images/secman-shiro-architecture.drawio.svg | 1 +
.../secman-shiro-delegate-architecture.drawio.svg | 1 +
...s-security-module-realm-with-delegate-realm.PNG | Bin 45089 -> 0 bytes
...iro-to-use-isisaddons-security-module-realm.PNG | Bin 38713 -> 0 bytes
.../secman/adoc/modules/secman/pages/about.adoc | 218 +++++++++++++++-
.../secman/adoc/modules/secman/pages/api.adoc | 7 -
.../modules/secman/pages/jbcrypt-encryption.adoc | 7 -
.../adoc/modules/secman/pages/jdo-persistence.adoc | 7 -
.../adoc/modules/secman/pages/jpa-persistence.adoc | 8 -
.../secman/adoc/modules/secman/pages/model.adoc | 7 -
.../adoc/modules/secman/pages/setting-up.adoc | 288 +++++++++++++++++++++
.../adoc/modules/secman/pages/shiro-realm.adoc | 34 ---
.../adoc/modules/secman/partials/module-nav.adoc | 11 +-
.../api/tenancy/ApplicationTenancyEvaluator.java | 35 ++-
.../secman/api/user/ApplicationUser.java | 27 ++
.../secman/shiro/PrincipalForApplicationUser.java | 33 +--
18 files changed, 584 insertions(+), 103 deletions(-)
diff --git a/extensions/core/model-annotation/adoc/modules/model-annotation/pages/about.adoc b/extensions/core/model-annotation/adoc/modules/model-annotation/pages/about.adoc
index d47f854..09d1dfa 100644
--- a/extensions/core/model-annotation/adoc/modules/model-annotation/pages/about.adoc
+++ b/extensions/core/model-annotation/adoc/modules/model-annotation/pages/about.adoc
@@ -5,3 +5,5 @@
WARNING: TODO: v2 - to document
+
+See xref:refguide:extensions:index/modelannotation/applib/annotation/Model.adoc[]
diff --git a/extensions/security/secman/adoc/modules/secman/images/secman-domain-model.drawio.svg b/extensions/security/secman/adoc/modules/secman/images/secman-domain-model.drawio.svg
new file mode 100644
index 0000000..48933bb
--- /dev/null
+++ b/extensions/security/secman/adoc/modules/secman/images/secman-domain-model.drawio.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="851px" height="1097px" viewBox="-0.5 -0.5 851 1097" content="<mxfile host="drawio-plugin" modified="2021-04-17T11:26:56.237Z" agent="5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" version="13.7.9" etag="xhDWezcWVjG4hn-7gP9F" type="embed"><diagram id="or [...]
\ No newline at end of file
diff --git a/extensions/security/secman/adoc/modules/secman/images/secman-shiro-architecture.drawio.svg b/extensions/security/secman/adoc/modules/secman/images/secman-shiro-architecture.drawio.svg
new file mode 100644
index 0000000..1f39a15
--- /dev/null
+++ b/extensions/security/secman/adoc/modules/secman/images/secman-shiro-architecture.drawio.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="561px" height="501px" viewBox="-0.5 -0.5 561 501" content="<mxfile host="drawio-plugin" modified="2021-04-17T14:58:13.625Z" agent="5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" version="13.7.9" etag="mLaIqad2fvYvt_aNfytd" type="embed"><diagram id="Y7dH [...]
\ No newline at end of file
diff --git a/extensions/security/secman/adoc/modules/secman/images/secman-shiro-delegate-architecture.drawio.svg b/extensions/security/secman/adoc/modules/secman/images/secman-shiro-delegate-architecture.drawio.svg
new file mode 100644
index 0000000..6bef6c5
--- /dev/null
+++ b/extensions/security/secman/adoc/modules/secman/images/secman-shiro-delegate-architecture.drawio.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="626px" height="301px" viewBox="-0.5 -0.5 626 301" content="<mxfile host="drawio-plugin" modified="2021-04-17T15:19:10.006Z" agent="5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" etag="nwql6B5-Cr2bjjWmf_Z0" version="13.7.9" type="embed"><diagram id="Y7dH [...]
\ No newline at end of file
diff --git a/extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm-with-delegate-realm.PNG b/extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm-with-delegate-realm.PNG
deleted file mode 100644
index 14af8c0..0000000
Binary files a/extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm-with-delegate-realm.PNG and /dev/null differ
diff --git a/extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm.PNG b/extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm.PNG
deleted file mode 100644
index 59780f4..0000000
Binary files a/extensions/security/secman/adoc/modules/secman/images/shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm.PNG and /dev/null differ
diff --git a/extensions/security/secman/adoc/modules/secman/pages/about.adoc b/extensions/security/secman/adoc/modules/secman/pages/about.adoc
index b43f248..a2b3c9b 100644
--- a/extensions/security/secman/adoc/modules/secman/pages/about.adoc
+++ b/extensions/security/secman/adoc/modules/secman/pages/about.adoc
@@ -2,10 +2,222 @@
:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-WARNING: TODO: this content has not yet been reviewed/updated for v2.0
-This SecMan module provides a complete security subdomain for users, roles, permissions; all are persisted as domain entities.
+The primary purpose of SecMan is provide an implementation of the xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] SPI, to determine whether the currently logged-in user has access to a given object member
-What that means, of course, that they can also be administered through your Apache Isis application.
+This authorization is implemented using domain entities, whch means that authorizations/permissions can theybe administered from within your Apache Isis application.
Moreover, the set of permissions (to features) is derived completely from your application's metamodel; in essence the permissions are "type-safe".
+The domain model is explained in more detail <<domain-model,below>>.
+
+SecMan can be used just for authorization, or it can be used in conjunction with Apache Isis' xref:security:shiro:about.adoc[Shiro security] implementation to perform authentication, where a password is held for each application user.
+This integration is discussed in more detail <<shiro-integration,below>>.
+
+This guide explains these concepts in more detail, and describes how to configure secman for use.
+
+
+== Users, Roles and Permissions
+
+As described in the introduction, the primary purpose of SecMan is provide an implementation of the xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] SPI, to determine whether the currently logged-in user has access to a given object member:
+
+* the logged-in user is represented as an xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication]
+
+* by "object member" we mean either an action, property or collection,as represented by an xref:refguide:applib:index/Identifier.adoc[Identifier]
+
+* by "access", we mean whether the object member is xref:refguide:core:index/security/authorization/Authorizor.adoc#isVisible__Authentication_Identifier[visible] to the user, and if so whether it is xref:refguide:core:index/security/authorization/Authorizor.adoc#isUsable__Authentication_Identifier[usable] (not disabled) by the user.
+
+SecMan's xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] implementation uses domain entities to model users, roles and permissions.
+Each permission relates to an "object feature".
+Object features themselves come in three varieties:
+
+* the most fine-grained object feature is an object member
++
+for example `myapp.customer.CustomerAddress#zipCode`
+
+* next up is an object feature representing an entire type
++
+for example `myapp.customer.CustomerAddress`.
+This is usually specified using xref:refguide:applib:index/annotation/DomainObject.adoc#objectType[@DomainObject#objectType()]
+
+* most general is an object feature representing a namespace
++
+These consist of the portion of the xref:refguide:applib:index/annotation/DomainObject.adoc#objectType[object type] up to but excluding the local type name, for example `myapp.customer`.
+
+Permissions are inferred: a permission granted at the type level implies a permission for all of the object members of the type, and a permission granted to a namespace implies a permission for all of the object members of all of the object types within that namespace.
+
+Multipart namespaces also imply a hierarchy and permissions can be inferred through that hierarchy.
+For example the `myapp.customer` namespace has a parent `myapp` namespace.
+Permissions granted to the `myapp` namespace will be inferred by types in the child `myapp.customer` namespace.
+
+Permissions are also either additive or subtractive: they can indicate the user has been ``ALLOW``ed access to an object member, or they have been ``VETO``ed access.
+
+Because of permission inference, there could be more than one permission that applies to an object member, where one permission is an `ALLOW` and another permission is a `VETO`.
+SecMan uses the most specific permission to determine whether access should be granted or not.
+For example:
+
+* if there is an ``VETO`` on `mycompany.customer`, but an ``ADDRESS`` on `mycompany.customer.CustomerProfile`, then access will be given to the object members in ``mycompany.customer.CustomerProfile`` because the type-level `ALLOW` takes precedence over the namespace-level ``VETO``.
+
+* if there is an ``ALLOW`` on `mycompany.customer.CustomerAddress`, but a ``VETO`` on ``mycompany.customer.CustomerAddress#zipCode``, then access will be given to all the object members of `CustomerAddress` _except for_ `zipCode`.
+
+
+
+[#domain-model]
+== Domain Model
+
+The diagram below shows the domain model for SecMan, and how it relates to the features obtained from the core metamodel:
+
+.SecMan domain model
+image:secman-domain-model.drawio.svg[]
+
+SecMan's users, roles and permissions are entities, but application features are serializable value types that are derived from the Apache Isis metamodel.
+
+Thus:
+
+* a user (represented by xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser]) can belong to many roles (xref:refguide:extensions:index/secman/api/role/ApplicationRole.adoc[ApplicationRole])
+* a role in turn holds a set of permissions (xref:refguide:extensions:index/secman/api/permission/ApplicationPermission.adoc[ApplicationPermission]).
+Each such permission is either an ``ALLOW`` or a ``VETO`` to an application feature, represented by a fully qualified name
+* this resolves to an xref:refguide:applib:index/services/appfeat/ApplicationFeatureId.adoc[ApplicationFeatureId] (from the core metamodel).
+That feature will be either a namespace, a type or a member.
++
+The core metamodel also provides xref:refguide:applib:index/services/appfeat/ApplicationFeature.adoc[ApplicationFeature] (each being identified with an xref:refguide:applib:index/services/appfeat/ApplicationFeatureId.adoc[ApplicationFeatureId] that makes it easier to navigate around the application feature hierarchy.
+
+The domain model also shows the xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancyEvaluator.adoc[ApplicationTenancyEvaluator] interface and xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancy.adoc[ApplicationTenancy] entity.
+These are to support multitenancy, discussed in the section <<Multitenancy,below>>.
+
+
+== Multitenancy
+
+In addition to users, roles and permissions, SecMan also supports link:https://en.wikipedia.org/wiki/Multitenancy[multitenancy].
+The idea is that the ownership of domain objects is logically partitioned into tenants; one tenant cannot see or access the data owned by another tenant.
+
+Implementing multitenancy requires that both data and the user is "tagged" in some way, and that these tags are compared against each other to determine if the user has access to the tagged data.
+This is represented in the domain model through the xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancyEvaluator.adoc[ApplicationTenancyEvaluator] SPI interface.
+The idea is that the application provides its own implementation of this interface, that performs the evaluation of whether the current user can view the domain object or not (and if they can, whether the domain object members are disabled/read-only).
+
+One simple implementation is to tag domain objects with a "path", and similarly to store a "path" for each application user.
+The idea behind the xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancy.adoc[ApplicationTenancy] is simply to name these tenancies; its `atPath` property is intended to be a primary key.
+The xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser] entity also has an `atPath` property.
+We could therefore use this "atPath" to represent a country, eg "/GBR", "/ITA", "/FRA", "/BEL" and so on.
+
+For example, the example below uses implements the rule that a user can always view an object within (above or below) their place in the path "hierarchy", and can edit any object "under" them in the hierarchy:
+
+[source,java]
+.ApplicationTenancyEvaluatorUsingAtPath.java
+----
+@Service
+public class ApplicationTenancyEvaluatorUsingAtPath implements ApplicationTenancyEvaluator {
+
+ @Override
+ public boolean handles(Class<?> cls) {
+ return HasAtPath.class.isAssignableFrom(cls); // <.>
+ }
+ @Override
+ public String hides(Object domainObject, ApplicationUser applicationUser) {
+ final String objAtPath = ((HasAtPath) domainObject).getAtPath();
+ if(objAtPath == null) { return null; } // show
+ final String userAtPath = applicationUser.getAtPath();
+ if(userAtPath == null) { return "user does not have atPath"; } // hide
+ return objAtPath.startsWith(userAtPath) || userAtPath.startsWith(objAtPath) // <.>
+ ? null
+ : "object not visible within user's tenancy";
+ }
+ @Override
+ public String disables(Object domainObject, ApplicationUser applicationUser) {
+ final String objAtPath = ((HasAtPath) domainObject).getAtPath();
+ if(objAtPath == null) { return null; } // enable
+ final String userAtPath = applicationUser.getAtPath();
+ if(userAtPath == null) { return "user does not have atPath"; } // disable
+ return objAtPath.startsWith(userAtPath) // <.>
+ ? null
+ : "object not enabled within user's tenancy";
+ }
+}
+----
+<.> SecMan provides the xref:refguide:extensions:index/secman/api/tenancy/HasAtPath.adoc[HasAtPath] interface to standardize the way in which domain objects expose their "tag" (atPath) to the evaluator.
+<.> can view all objects (above and below) within the user's hierarchy
++
+for example:
++
+* obj = '/', user = '/ITA' : visible
+* obj = '/ITA', user = '/ITA' : visible
+* obj = '/ITA/MIL', user = '/ITA' : visible
+* obj = '/FRA', user = '/ITA' : not visible
+
+<.> can edit only objects at or below the user's hierarchy
++
+for example:
++
+* obj = '/', user = '/ITA' : not editable
+* obj = '/ITA', user = '/ITA' : editable
+* obj = '/ITA/MIL', user = '/ITA' : editable
+* obj = '/FRA', user = '/ITA' : not editable
+
+More complex implementations are possible: ultimately the "atPath" properties are just strings and so can be interpreted in whatever way makes sense.
+For example, to allow a user to be able to access objects from multiple countries, we could use a format such as "/ITA;/BEL".
+The implementation would parse the string and allow access for any country.
+
+For this reason, the xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser]'s `atPath` property is _not_ a foreign key to the xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancy.adoc[ApplicationTenancy] entity.
+
+TIP: Another implementation of xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancyEvaluator.adoc[ApplicationTenancyEvaluator] can be found in the xref:docs:demo:about.adoc[Demo App]..
+
+
+[#shiro-integration]
+== Shiro Integration
+
+While SecMan is primarily designed for authorization (as per the xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] SPI), it is necessary when running an Apache Isis application to specify an authenticator.
+SecMan provides specific support so that Apache Isis' xref:security:shiro:about.adoc[Shiro security] integration can be used for authentication.
+
+This is implemented through the SecMan's shiro realm submodule, which provides an implementation of Apache Shiro's `Realm` interface that then calls back into SecMan.
+
+The diagram below sketches the high-level architecture:
+
+.SecMan's Shiro architecture
+image:secman-shiro-architecture.drawio.svg[]
+
+Thus:
+
+* Apache Isis' xref:security:shiro:about.adoc[Shiro security] integration sets up Shiro web filters to intercept every http request, as well as the xref:refguide:security:index/shiro/authentication/AuthenticatorShiro.adoc[AuthenticatorShiro] implementation.
+* The `AuthenticatorShiro` calls to the Shiro Security Manager to obtain the authenticated principal.
+* The Shiro Security Manager uses the `shiro.ini` configuration file to look up the realm to perform the authentication; in this case we configure it to use Secman's realm (xref:refguide:extensions:index/secman/shiro/IsisModuleExtSecmanShiroRealm.adoc[IsisModuleExtSecmanShiroRealm]).
+* Secman's realm implementation queries the database and uses this to create an instance of `PrincipalForApplicationUser`, where the `Principal` interface is Shiro's representation of an authenticated user.
+The `PrincipalForApplicationUser` is backed by xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser], which all of the permissions to object members for this particular user.
+* to render a page, the Apache Isis viewer uses configured `Authorizor`, in this case
+Secman's own xref:refguide:extensions:index/secman/api/authorizor/AuthorizorSecman.adoc[AuthorizorSecman].
+This looks up the current xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser] (which will already reside in-memory) and renders the page according to which object members are visible or not.
+
+
+The above configuration allows Secman to be used to authenticate users; the password is stored as an (typically) encrypted property of the xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser].
+These are called "local" users, as per the xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser]'s `accountType` property.
+
+Secman's xref:refguide:extensions:index/secman/shiro/IsisModuleExtSecmanShiroRealm.adoc[Realm implementation] also allows a "delegate" realm to be configured.
+In such cases the authentication of "delegated" users is performed by the delegate realm rather than locally.
+
+The diagram below shows where this delegation occurs:
+
+.SecMan's Shiro delegate architecture
+image:secman-shiro-delegate-architecture.drawio.svg[]
+
+Configuring the delegate realm is performed using Shiro's "poor man's dependency injection" syntax in its `shiro.ini` file.
+
+== Password encryption
+
+Secman provides the xref:refguide:extensions:index/secman/api/encryption/PasswordEncryptionService.adoc[PasswordEncryptionService] SPI to allow different algorithms to encrypt the user's password.
+
+The `encryption-jbcrypt` module provides an implementation using the link:https://www.mindrot.org/projects/jBCrypt/[jBCrypt] library.
+
+
+== SecMan's structure
+
+SecMan consists of a number of Maven submodules:
+
+* the API module (`isis-extensions-secman-api`) defines a set of interfaces for the xref:refguide:extensions:index/secman/api/user/ApplicationUser.adoc[ApplicationUser], xref:refguide:extensions:index/secman/api/role/ApplicationRole.adoc[ApplicationRole],
+xref:refguide:extensions:index/secman/api/permission/ApplicationPermission.adoc[ApplicationPermission] and xref:refguide:extensions:index/secman/api/tenancy/ApplicationTenancy.adoc[ApplicationTenancy] entities.
+
+* the two persistence modules (`isis-extensions-secman-persistence-jpa` and `isis-extensions-secman-persistence-jdo`) provide concrete implementations of the APIs for JPA and JDO respectively.
+As you might expect, they are intended for use with xref:pjpa:ROOT:about.adoc[JPA/Eclipselink] and xref:pjdo:ROOT:about.adoc[JDO/DataNucleus] persistence mechanisms respectively; use one or the other.
+
+* the Model module (`isis-extensions-secman-model`) defines view models to represent the feature application features, and also contains business logic as mixins to the API (and therefore contributed to the appropriate concrete entity).
+
+* the Shiro realm module (`isis-extensions-secman-shiro-realm`) provides the Shiro realm interface that delegates to the Secman database (see discussion <<shiro-integration,above>>)
+
+* the jbcrypt encryption module (`isis-extensions-secman-encryption-jbcrypt`) provides an implementation of Secman's xref:refguide:extensions:index/secman/api/encryption/PasswordEncryptionService.adoc[PasswordEncryptionService] so that passwords are persisted securely using link:https://www.mindrot.org/projects/jBCrypt/[jBCrypt].
diff --git a/extensions/security/secman/adoc/modules/secman/pages/api.adoc b/extensions/security/secman/adoc/modules/secman/pages/api.adoc
deleted file mode 100644
index 944a91b..0000000
--- a/extensions/security/secman/adoc/modules/secman/pages/api.adoc
+++ /dev/null
@@ -1,7 +0,0 @@
-= API
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-:page-partial:
-
-
-TODO: to document
diff --git a/extensions/security/secman/adoc/modules/secman/pages/jbcrypt-encryption.adoc b/extensions/security/secman/adoc/modules/secman/pages/jbcrypt-encryption.adoc
deleted file mode 100644
index a56168c..0000000
--- a/extensions/security/secman/adoc/modules/secman/pages/jbcrypt-encryption.adoc
+++ /dev/null
@@ -1,7 +0,0 @@
-= JBCrypt Encryption
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-:page-partial:
-
-
-TODO: to document
diff --git a/extensions/security/secman/adoc/modules/secman/pages/jdo-persistence.adoc b/extensions/security/secman/adoc/modules/secman/pages/jdo-persistence.adoc
deleted file mode 100644
index 4e0f61f..0000000
--- a/extensions/security/secman/adoc/modules/secman/pages/jdo-persistence.adoc
+++ /dev/null
@@ -1,7 +0,0 @@
-= JDO Persistence
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-:page-partial:
-
-
-CAUTION: TODO: to document (see also xref:jpa-persistence.adoc[])
diff --git a/extensions/security/secman/adoc/modules/secman/pages/jpa-persistence.adoc b/extensions/security/secman/adoc/modules/secman/pages/jpa-persistence.adoc
deleted file mode 100644
index 9a26f35..0000000
--- a/extensions/security/secman/adoc/modules/secman/pages/jpa-persistence.adoc
+++ /dev/null
@@ -1,8 +0,0 @@
-= JPA Persistence
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-:page-partial:
-
-
-CAUTION: TODO: to document (see also xref:jdo-persistence.adoc[])
-
diff --git a/extensions/security/secman/adoc/modules/secman/pages/model.adoc b/extensions/security/secman/adoc/modules/secman/pages/model.adoc
deleted file mode 100644
index 1671359..0000000
--- a/extensions/security/secman/adoc/modules/secman/pages/model.adoc
+++ /dev/null
@@ -1,7 +0,0 @@
-= Model
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-:page-partial:
-
-
-TODO: to document
diff --git a/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc b/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc
new file mode 100644
index 0000000..8226fa1
--- /dev/null
+++ b/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc
@@ -0,0 +1,288 @@
+= Setting up
+
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+:page-partial:
+
+This section describes how to setup and configure SecMan for use in your Apache Isis application.
+
+include::docs:mavendeps:partial$setup-and-configure-dependencyManagement.adoc[leveloffset=+1]
+
+In addition, add a section for secman's own BOM:
+
+[source,xml,subs="attributes+"]
+.pom.xml
+----
+<dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.isis.extensions</groupId>
+ <artifactId>isis-extensions-secman</artifactId>
+ <scope>import</scope>
+ <type>pom</type>
+ <version>{page-isisrel}</version>
+ </dependency>
+ </dependencies>
+</dependencyManagement>
+----
+
+== Dependencies
+
+In the webapp module of your application, add the following dependency:
+
+[source,xml]
+.pom.xml
+----
+<dependencies>
+ <dependency>
+ <groupId>org.apache.isis.extensions</groupId>
+ <artifactId>isis-extensions-secman-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.extensions</groupId>
+ <artifactId>isis-extensions-secman-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.extensions</groupId>
+ <artifactId>isis-extensions-secman-persistence-XXX</artifactId> <!--.-->
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.extensions</groupId>
+ <artifactId>isis-extensions-secman-encryption-jbcrypt</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.extensions</groupId>
+ <artifactId>isis-extensions-secman-shiro-realm</artifactId>
+ </dependency>
+</dependencies>
+----
+<.> specify either `isis-extensions-secman-persistence-jpa` or `isis-extensions-secman-persistence-jdo`, as required
+
+
+[[_update-appmanifest]]
+== Update AppManifest
+
+=== Import modules
+
+In your application's `AppManifest` (top-level Spring `@Configuration` used to bootstrap the app), import the SecMan modules.
+You will also need to import the fixture module; SecMan uses fixture scripts to seed its entities:
+
+[source,java]
+.AppManifest.java
+----
+@Configuration
+@Import({
+ ...
+ IsisModuleSecurityShiro.class, // <.>
+ ...
+ IsisModuleExtSecmanApi.class, // <.>
+ IsisModuleExtSecmanModel.class,
+ IsisModuleExtSecmanPersistenceJpa.class,
+ IsisModuleExtSecmanRealmShiro.class,
+ IsisModuleExtSecmanEncryptionJbcrypt.class,
+
+ IsisModuleTestingFixturesApplib.class, // <.>
+ ...
+})
+public class AppManifest {
+}
+----
+<.> enable Shiro for security.
++
+Ensure that no other `IsisModuleSecurityXxx` module is imported.
+<.> SecMan dependencies
+<.> fixture script support
+
+
+[#configure-services]
+=== Configure Services
+
+It is also necessary to configure some aspects of SecMan.
+This is most easily done using `Bean` definitions within the `AppManifest`:
+
+[source,java]
+.AppManifest.java
+----
+//...
+public class AppManifest {
+
+ @Bean
+ public SecmanConfiguration secmanConfiguration() {
+ return SecmanConfiguration.builder()
+ .adminUserName("sven").adminPassword("pass") // <.>
+ .adminRoleName("isis-ext-secman-admin-role") // <.>
+ .regularUserRoleName("isis-ext-secman-user-role") // <.>
+ .build();
+ }
+
+ @Bean
+ public PermissionsEvaluationService permissionsEvaluationService() {
+ return new PermissionsEvaluationServiceAllowBeatsVeto(); // <.>
+ }
+
+ @Bean
+ public SecurityRealmService securityRealmService() {
+ return new SecurityRealmService() {
+ @Override
+ public SecurityRealm getCurrentRealm() {
+ return () ->
+ EnumSet.noneOf(SecurityRealmCharacteristic.class); // <.>
+ }
+ };
+ }
+}
+----
+<.> indicates the security super-user and password
+<.> indicates the name of the role granted to this security super-user.
+This can be any name.
+<.> indicates the name of the role that should be granted to regular users of the application.
++
+IMPORTANT: This role grants regular users the ability to logout (among other things).
+<.> indicates that only local users are supported (no delegate realm is in used).
++
+See <<delegate-realms,below>> to configure for a delegate realm.
+
+
+
+== Shiro Realm
+
+SecMan's Shiro realm is configured using the `shiro.ini` file:
+
+[source,ini]
+.shiro.ini
+----
+[main]
+
+authenticationStrategy=org.apache.isis.extensions.secman.shiro.AuthenticationStrategyForIsisModuleSecurityRealm
+isisModuleSecurityRealm=org.apache.isis.extensions.secman.shiro.IsisModuleExtSecmanShiroRealm
+
+securityManager.authenticator.authenticationStrategy = $authenticationStrategy
+securityManager.realms = $isisModuleSecurityRealm
+
+[users]
+[roles]
+----
+
+The `[users]` and `[roles]` sections are required but are unused.
+
+
+[#delegate-realms]
+== Delegate Realms
+
+If a delegate realm is to be used, then there are two changes required.
+
+* first, in the `AppManifest`:
++
+[source,java]
+.AppManifest.java
+----
+@Bean
+public SecurityRealmService securityRealmService() {
+ return new SecurityRealmService() {
+ @Override
+ public SecurityRealm getCurrentRealm() {
+ return () -> EnumSet.of(SecurityRealmCharacteristic.DELEGATING);
+ }
+ };
+}
+----
+
+* second, specify the delegate realm implementation in the `shiro.ini` file, and "inject" it into the semcan realm.
++
+For example, to use xref:shiro-realm-ldap:about.adoc[LDAP Realm for Shiro] as a delegate:
++
+[source,ini]
+.shiro.ini
+----
+[main]
+
+...
+ldapRealm=org.apache.isis.extensions.shirorealmldap.realm.impl.IsisLdapRealm #<.>
+ldapRealm.xxx=... #<.>
+ldapRealm.yyy=...
+
+isisModuleSecurityRealm.delegateAuthenticationRealm=$ldapRealm #<.>
+
+...
+----
+<.> instantiate the LDAP realm
+<.> configure the LDAP realm as required
+<.> specify the LDAP realm as the delegate realm for SecMan's own realm.
+
+
+
+
+== Seed Users and Roles
+
+With SecMan enabled, it will automatically set up a security super-user (as described <<configure-services,above>>) and a regular role.
+
+Creating regular applications users thereafter can be done manually, but if prototyping with an in-memory database then you will most likely want to set up some fixure scripts to automatically set up application users.
+
+SecMan provides a number of convenience fixture scripts to inherit from.
+For example, these scripts can be used to set up access to the domain objects in the xref:docs:starters:helloworld.adoc[HelloWorld] starter app:
+
+* to set up a "user-rw" role with access to everything under the "hello" namespace:
++
+[source,java]
+.RoleAndPerms__UserRw.java
+----
+public class RoleAndPerms__UserRw extends AbstractRoleAndPermissionsFixtureScript {
+
+ public static final String ROLE_NAME = "user-rw";
+
+ public RoleAndPerms__UserRw() {
+ super(ROLE_NAME, "Read-write access to entire application");
+ }
+
+ @Override
+ protected void execute(ExecutionContext ec) {
+ newPermissions(
+ ApplicationPermissionRule.ALLOW,
+ ApplicationPermissionMode.CHANGING,
+ Can.of(ApplicationFeatureId.newNamespace("hello"))
+ );
+ }
+}
+----
+
+* to set up a "no-delete" role that vetoes the ability to delete objects:
++
+[source,java]
+.RoleAndPerms__UserRw.java
+----
+public class RoleAndPerms__NoDelete extends AbstractRoleAndPermissionsFixtureScript {
+
+ public static final String ROLE_NAME = "no-delete";
+
+ public RoleAndPerms__NoDelete() {
+ super(ROLE_NAME, "Veto access to deleting HelloWorld objects");
+ }
+
+ @Override
+ protected void execute(ExecutionContext ec) {
+ newPermissions(
+ ApplicationPermissionRule.VETO,
+ ApplicationPermissionMode.VIEWING,
+ Can.of(ApplicationFeatureId.newFeature(ApplicationFeatureSort.MEMBER, "hello.HelloWorldObject#delete"))
+ );
+ }
+}
+----
+
+* to set up a user "joe" with the "user-rw" and "no-delete" role:
++
+[source,java]
+.UserToRole__bob_UserRw.java
+----
+public class UserToRole__bob_UserRw extends AbstractUserAndRolesFixtureScript {
+
+ public UserToRole__bob_UserRw() {
+ super("joe", "pass", "bob@world.com",
+ "/ITA",
+ AccountType.LOCAL,
+ Can.of(
+ RoleAndPerms__UserRw.ROLE_NAME,
+ RoleAndPerms__NoDelete.ROLE_NAME
+ ));
+ }
+}
+----
diff --git a/extensions/security/secman/adoc/modules/secman/pages/shiro-realm.adoc b/extensions/security/secman/adoc/modules/secman/pages/shiro-realm.adoc
deleted file mode 100644
index 6d9d623..0000000
--- a/extensions/security/secman/adoc/modules/secman/pages/shiro-realm.adoc
+++ /dev/null
@@ -1,34 +0,0 @@
-= Shiro Realm
-
-:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
-:page-partial:
-
-
-WARNING: TODO - not yet reviewed for v2.
-
-Because each user to be authorised must exist in the SecMan database, this means that it can also act as a secondary authenticator.
-It does this by providing an implementation of the Shiro `Realm` API, which fits in as follows:
-
-image::shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm.PNG[width="600px"]
-
-where the `IsisModuleSecurityRealm` realm is the implementation provided by the module.
-
-Using this design the password management can be handled to a subsidiary (delegate) Shiro realm (for example, using the xref:shiro-realm-ldap:about.adoc[]).
-
-In the configuration above user passwords are stored in the database. The module uses link:http://www.mindrot.org/projects/jBCrypt/[jBCrypt] so that passwords are only stored in a (one-way) encrypted form in the database.
-
-
-
-The xref:security:ROOT:about.adoc[SecMan extension] also supports a slightly more sophisticated configuration.
-Most organizations use LDAP for user credentials, and maintaining two separate user accounts would be less than ideal.
-The `IsisModuleSecurityRealm` can therefore be configured with a subsidiary "delegate" realm that is responsible for performing the primary authentication of the user; if that passes then a user is created (as a domain entity) automatically.
-In most cases this delegate realm will be the LDAP realm, and so the architecture becomes:
-
-image::shiro-realm/configure-shiro-to-use-isisaddons-security-module-realm-with-delegate-realm.PNG[width="600px"]
-
-
-The xref:security:ROOT:about.adoc[SecMan extension] has many more features than are described here, all of which are described in the module's README.
-The README also explains in detail how to configure an existing app to use this module.
-
-//You can also look at the Isisaddons https://github.com/apache/isis-app-todoapp[TodoApp example] (not ASF), which is preconfigured to use the security module.
-
diff --git a/extensions/security/secman/adoc/modules/secman/partials/module-nav.adoc b/extensions/security/secman/adoc/modules/secman/partials/module-nav.adoc
index 91417aa..4caf43b 100644
--- a/extensions/security/secman/adoc/modules/secman/partials/module-nav.adoc
+++ b/extensions/security/secman/adoc/modules/secman/partials/module-nav.adoc
@@ -1,10 +1,3 @@
-
-
-** xref:security:secman:about.adoc[Secman]
-*** xref:security:secman:api.adoc[API]
-*** xref:security:secman:model.adoc[Model]
-*** xref:security:secman:jbcrypt-encryption.adoc[JBCrypt Encryption]
-*** xref:security:secman:jdo-persistence.adoc[JDO Persistence]
-*** xref:security:secman:jpa-persistence.adoc[JPA Persistence]
-*** xref:security:secman:shiro-realm.adoc[Realm (for Shiro)]
+** xref:security:secman:about.adoc[Overview and Design]
+*** xref:security:secman:setting-up.adoc[Setting up]
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancyEvaluator.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancyEvaluator.java
index 01128cd..f859a00 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancyEvaluator.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/tenancy/ApplicationTenancyEvaluator.java
@@ -45,9 +45,42 @@ public interface ApplicationTenancyEvaluator {
*/
boolean handles(Class<?> cls);
+ /**
+ * Whether this domain object should not be visible to the specified
+ * {@link ApplicationUser user}.
+ *
+ * <p>
+ * The domain object will be one that is handled by this evaluator,
+ * in other words that {@link #handles(Class)} was previously called
+ * and the evaluator returned <code>true</code>.
+ * </p>
+ * <p>
+ * A non-null return value means that the object should be hidden.
+ * </p>
+ */
String hides(Object domainObject, ApplicationUser applicationUser);
+ /**
+ * Whether the object members of this domain object should be
+ * disabled/read-only for the specified {@link ApplicationUser user}.
+ *
+ * <p>
+ * The domain object will be one that is handled by this evaluator,
+ * in other words that {@link #handles(Class)} was previously called
+ * and the evaluator returned <code>true</code>.
+ * </p>
+ *
+ * <p>
+ * This method is only called after
+ * {@link #hides(Object, ApplicationUser)} and only if that method
+ * returned <code>false</code>.
+ * </p>
+ *
+ * <p>
+ * A non-null return value means that the object should be disabled,
+ * and is used as the reason why the object member is disabled.
+ * </p>
+ */
String disables(Object domainObject, ApplicationUser applicationUser);
-
}
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java
index 279a432..5562353 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/user/ApplicationUser.java
@@ -80,8 +80,35 @@ public interface ApplicationUser extends HasUsername, HasAtPath {
String getName();
+ /**
+ * Only used for {@link #getAccountType() local} users, stores the
+ * password in encrypted form.
+ *
+ * <p>
+ * The password will have been encrypted by the configured
+ * {@link org.apache.isis.extensions.secman.api.encryption.PasswordEncryptionService}.
+ * </p>
+ *
+ * @see org.apache.isis.extensions.secman.api.encryption.PasswordEncryptionService
+ */
String getEncryptedPassword();
+ /**
+ * Determines how to authenticate this user.
+ *
+ * <p>
+ * {@link AccountType#LOCAL local} users are authenticated directly
+ * against the {@link #getEncryptedPassword() password}.
+ * </p>
+ *
+ * <p>
+ * {@link AccountType#DELEGATED delegated} users are authenticated by
+ * some other authentication mechanism. For example, Secman's
+ * Shiro realm allows a delegate realm to be configured, and will
+ * call that delegate realm for delegated users rather than
+ * authenticating locally.
+ * </p>
+ */
AccountType getAccountType();
void setAccountType(AccountType accountType);
diff --git a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java
index 2cd62a9..c2ceb65 100644
--- a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java
+++ b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/PrincipalForApplicationUser.java
@@ -54,9 +54,6 @@ import lombok.val;
* creating an adapter object for the appropriate Shiro API.
* </p>
*
- * TODO: this should probably implement java.security.Principal so that it doesn't get wrapped in a
- * ShiroHttpServletRequest.ObjectPrincipal.
- * Such a change would need some testing to avoid regressions, though.
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
class PrincipalForApplicationUser implements AuthorizationInfo {
@@ -75,8 +72,8 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
.map(ApplicationRole::getName)
.collect(Collectors.toCollection(TreeSet::new));
val permissionSet = applicationUser.getPermissionSet();
-
- return new PrincipalForApplicationUser(username, encryptedPassword, accountType,
+
+ return new PrincipalForApplicationUser(username, encryptedPassword, accountType,
applicationUser.getStatus(), roles, permissionSet);
}
@@ -86,7 +83,7 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
@Getter(value = AccessLevel.PACKAGE) private final ApplicationUserStatus status;
@Getter(value = AccessLevel.PUBLIC) private final Set<String> roles;
@Getter(value = AccessLevel.PACKAGE) private final ApplicationPermissionValueSet permissionSet;
-
+
public boolean isDisabled() {
return getStatus() == ApplicationUserStatus.DISABLED;
}
@@ -95,7 +92,7 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
public Collection<String> getStringPermissions() {
return Collections.emptyList();
}
-
+
@Override
public Collection<Permission> getObjectPermissions() {
return objectPermissions.get();
@@ -103,31 +100,27 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
/**
* When wrapped by ShiroHttpServletRequest.ObjectPrincipal, the principal's name is derived by calling toString().
- *
- * TODO: this should probably implement java.security.Principal so that it doesn't get wrapped in a
- * ShiroHttpServletRequest.ObjectPrincipal. Such a change would need some testing to avoid regressions, though.
- *
*/
@Override
public String toString() {
return getUsername();
}
-
+
// -- HELPER
-
- private final transient _Lazy<Collection<Permission>> objectPermissions =
+
+ private final transient _Lazy<Collection<Permission>> objectPermissions =
_Lazy.threadSafe(this::createObjectPermissions);
-
+
private Collection<Permission> createObjectPermissions() {
val permission = Permission_backedByPermissionSet.of(getPermissionSet());
return Collections.singleton(permission);
}
-
+
@RequiredArgsConstructor(staticName = "of")
private static class Permission_backedByPermissionSet implements Permission {
-
+
@NonNull private final ApplicationPermissionValueSet permissionSet;
-
+
@Override
public boolean implies(Permission p) {
if (!(p instanceof PermissionForMember)) {
@@ -135,9 +128,9 @@ class PrincipalForApplicationUser implements AuthorizationInfo {
}
val permissionForMember = (PermissionForMember) p;
return permissionSet.grants(
- permissionForMember.getFeatureId(),
+ permissionForMember.getFeatureId(),
permissionForMember.getMode());
}
}
-
+
}