1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 module hunt.shiro.subject.Subject;
20 
21 import hunt.shiro.subject.PrincipalCollection;
22 import hunt.shiro.subject.SubjectContext;
23 
24 import hunt.shiro.SecurityUtils;
25 import hunt.shiro.Exceptions;
26 import hunt.shiro.authc.AuthenticationToken;
27 import hunt.shiro.authz.permission.Permission;
28 import hunt.shiro.mgt.SecurityManager;
29 import hunt.shiro.mgt.SubjectFactory;
30 import hunt.shiro.session.Session;
31 import hunt.shiro.subject.support.DefaultSubjectContext;
32 // import hunt.shiro.util.StringUtils;
33 
34 import hunt.collection;
35 import hunt.Exceptions;
36 import hunt.util.Common;
37 import hunt.util.Runnable;
38 
39 import std.array;
40 import std.range;
41 import std.traits;
42 
43 /**
44  * A {@code Subject} represents state and security operations for a <em>single</em> application user.
45  * These operations include authentication (login/logout), authorization (access control), and
46  * session access. It is Shiro's primary mechanism for single-user security functionality.
47  * <h3>Acquiring a Subject</h3>
48  * To acquire the currently-executing {@code Subject}, application developers will almost always use
49  * {@code SecurityUtils}:
50  * <pre>
51  * {@link SecurityUtils SecurityUtils}.{@link hunt.shiro.SecurityUtils#getSubject() getSubject()}</pre>
52  * Almost all security operations should be performed with the {@code Subject} returned from this method.
53  * <h3>Permission methods</h3>
54  * Note that there are many *Permission methods in this interface overloaded to accept string arguments instead of
55  * {@link Permission Permission} instances. They are a convenience allowing the caller to use a string representation of
56  * a {@link Permission Permission} if desired.  The underlying Authorization subsystem implementations will usually
57  * simply convert these string values to {@link Permission Permission} instances and then just call the corresponding
58  * type-safe method.  (Shiro's default implementations do string-to-Permission conversion for these methods using
59  * {@link hunt.shiro.authz.permission.PermissionResolver PermissionResolver}s.)
60  * <p/>
61  * These overloaded *Permission methods forgo type-safety for the benefit of convenience and simplicity,
62  * so you should choose which ones to use based on your preferences and needs.
63  *
64  */
65 interface Subject {
66 
67     enum string DEFAULT_NAME = fullyQualifiedName!Subject;
68 
69     /**
70      * Returns this Subject's application-wide uniquely identifying principal, or {@code null} if this
71      * Subject is anonymous because it doesn't yet have any associated account data (for example,
72      * if they haven't logged in).
73      * <p/>
74      * The term <em>principal</em> is just a fancy security term for any identifying attribute(s) of an application
75      * user, such as a username, or user id, or public key, or anything else you might use in your application to
76      * identify a user.
77      * <h4>Uniqueness</h4>
78      * Although given names and family names (first/last) are technically considered principals as well,
79      * Shiro expects the object returned from this method to be an identifying attribute unique across
80      * your entire application.
81      * <p/>
82      * This implies that things like given names and family names are usually poor
83      * candidates as return values since they are rarely guaranteed to be unique;  Things often used for this value:
84      * <ul>
85      * <li>A {@code long} RDBMS surrogate primary key</li>
86      * <li>An application-unique username</li>
87      * <li>A {@link java.util.UUID UUID}</li>
88      * <li>An LDAP Unique ID</li>
89      * </ul>
90      * or any other similar suitable unique mechanism valuable to your application.
91      * <p/>
92      * Most implementations will simply return
93      * <code>{@link #getPrincipals()}.{@link hunt.shiro.subject.PrincipalCollection#getPrimaryPrincipal() getPrimaryPrincipal()}</code>
94      *
95      * @return this Subject's application-specific unique identity.
96      * @see hunt.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
97      */
98     Object getPrincipal();
99 
100     /**
101      * Returns this Subject's principals (identifying attributes) in the form of a {@code PrincipalCollection} or
102      * {@code null} if this Subject is anonymous because it doesn't yet have any associated account data (for example,
103      * if they haven't logged in).
104      * <p/>
105      * The word &quot;principals&quot; is nothing more than a fancy security term for identifying attributes associated
106      * with a Subject, aka, application user.  For example, user id, a surname (family/last name), given (first) name,
107      * social security number, nickname, username, etc, are all examples of a principal.
108      *
109      * @return all of this Subject's principals (identifying attributes).
110      * @see #getPrincipal()
111      * @see hunt.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
112      */
113     PrincipalCollection getPrincipals();
114 
115     /**
116      * Returns {@code true} if this Subject is permitted to perform an action or access a resource summarized by the
117      * specified permission string.
118      * <p/>
119      * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
120      * Please see the class-level JavaDoc for more information on these string-based permission methods.
121      *
122      * @param permission the string representation of a Permission that is being checked.
123      * @return true if this Subject is permitted, false otherwise.
124      * @see #isPermitted(Permission permission)
125      */
126     bool isPermitted(string permission);
127 
128     /**
129      * Returns {@code true} if this Subject is permitted to perform an action or access a resource summarized by the
130      * specified permission.
131      * <p/>
132      * More specifically, this method determines if any {@code Permission}s associated
133      * with the subject {@link Permission#implies(Permission) imply} the specified permission.
134      *
135      * @param permission the permission that is being checked.
136      * @return true if this Subject is permitted, false otherwise.
137      */
138     bool isPermitted(Permission permission);
139 
140     /**
141      * Checks if this Subject implies the given permission strings and returns a bool array indicating which
142      * permissions are implied.
143      * <p/>
144      * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
145      * Please see the class-level JavaDoc for more information on these string-based permission methods.
146      *
147      * @param permissions the string representations of the Permissions that are being checked.
148      * @return a bool array where indices correspond to the index of the
149      *         permissions in the given list.  A true value at an index indicates this Subject is permitted for
150      *         for the associated {@code Permission} string in the list.  A false value at an index
151      *         indicates otherwise.
152      */
153     bool[] isPermitted(string[] permissions...);
154 
155     /**
156      * Checks if this Subject implies the given Permissions and returns a bool array indicating which permissions
157      * are implied.
158      * <p/>
159      * More specifically, this method should determine if each {@code Permission} in
160      * the array is {@link Permission#implies(Permission) implied} by permissions
161      * already associated with the subject.
162      * <p/>
163      * This is primarily a performance-enhancing method to help reduce the number of
164      * {@link #isPermitted} invocations over the wire in client/server systems.
165      *
166      * @param permissions the permissions that are being checked.
167      * @return a bool array where indices correspond to the index of the
168      *         permissions in the given list.  A true value at an index indicates this Subject is permitted for
169      *         for the associated {@code Permission} object in the list.  A false value at an index
170      *         indicates otherwise.
171      */
172     bool[] isPermitted(List!(Permission) permissions);
173 
174     /**
175      * Returns {@code true} if this Subject implies all of the specified permission strings, {@code false} otherwise.
176      * <p/>
177      * This is an overloaded method for the corresponding type-safe {@link hunt.shiro.authz.Permission Permission}
178      * variant.  Please see the class-level JavaDoc for more information on these string-based permission methods.
179      *
180      * @param permissions the string representations of the Permissions that are being checked.
181      * @return true if this Subject has all of the specified permissions, false otherwise.
182      * @see #isPermittedAll(Collection)
183      */
184     bool isPermittedAll(string[] permissions...);
185 
186     /**
187      * Returns {@code true} if this Subject implies all of the specified permissions, {@code false} otherwise.
188      * <p/>
189      * More specifically, this method determines if all of the given {@code Permission}s are
190      * {@link Permission#implies(Permission) implied by} permissions already associated with this Subject.
191      *
192      * @param permissions the permissions to check.
193      * @return true if this Subject has all of the specified permissions, false otherwise.
194      */
195     bool isPermittedAll(Collection!(Permission) permissions);
196 
197     /**
198      * Ensures this Subject implies the specified permission string.
199      * <p/>
200      * If this subject's existing associated permissions do not {@link Permission#implies(Permission)} imply}
201      * the given permission, an {@link hunt.shiro.authz.AuthorizationException} will be thrown.
202      * <p/>
203      * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
204      * Please see the class-level JavaDoc for more information on these string-based permission methods.
205      *
206      * @param permission the string representation of the Permission to check.
207      * @throws hunt.shiro.authz.AuthorizationException
208      *          if the user does not have the permission.
209      */
210     void checkPermission(string permission);
211 
212     /**
213      * Ensures this Subject {@link Permission#implies(Permission) implies} the specified {@code Permission}.
214      * <p/>
215      * If this subject's existing associated permissions do not {@link Permission#implies(Permission) imply}
216      * the given permission, an {@link hunt.shiro.authz.AuthorizationException} will be thrown.
217      *
218      * @param permission the Permission to check.
219      * @throws hunt.shiro.authz.AuthorizationException
220      *          if this Subject does not have the permission.
221      */
222     void checkPermission(Permission permission);
223 
224     /**
225      * Ensures this Subject
226      * {@link hunt.shiro.authz.Permission#implies(hunt.shiro.authz.Permission) implies} all of the
227      * specified permission strings.
228      * <p/>
229      * If this subject's existing associated permissions do not
230      * {@link hunt.shiro.authz.Permission#implies(hunt.shiro.authz.Permission) imply} all of the given permissions,
231      * an {@link hunt.shiro.authz.AuthorizationException} will be thrown.
232      * <p/>
233      * This is an overloaded method for the corresponding type-safe {@link Permission Permission} variant.
234      * Please see the class-level JavaDoc for more information on these string-based permission methods.
235      *
236      * @param permissions the string representations of Permissions to check.
237      * @throws AuthorizationException if this Subject does not have all of the given permissions.
238      */
239     void checkPermissions(string[] permissions...);
240 
241     /**
242      * Ensures this Subject
243      * {@link hunt.shiro.authz.Permission#implies(hunt.shiro.authz.Permission) implies} all of the
244      * specified permission strings.
245      * <p/>
246      * If this subject's existing associated permissions do not
247      * {@link hunt.shiro.authz.Permission#implies(hunt.shiro.authz.Permission) imply} all of the given permissions,
248      * an {@link hunt.shiro.authz.AuthorizationException} will be thrown.
249      *
250      * @param permissions the Permissions to check.
251      * @throws AuthorizationException if this Subject does not have all of the given permissions.
252      */
253     void checkPermissions(Collection!(Permission) permissions);
254 
255     /**
256      * Returns {@code true} if this Subject has the specified role, {@code false} otherwise.
257      *
258      * @param roleIdentifier the application-specific role identifier (usually a role id or role name).
259      * @return {@code true} if this Subject has the specified role, {@code false} otherwise.
260      */
261     bool hasRole(string roleIdentifier);
262 
263     /**
264      * Checks if this Subject has the specified roles, returning a bool array indicating
265      * which roles are associated.
266      * <p/>
267      * This is primarily a performance-enhancing method to help reduce the number of
268      * {@link #hasRole} invocations over the wire in client/server systems.
269      *
270      * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
271      * @return a bool array where indices correspond to the index of the
272      *         roles in the given identifiers.  A true value indicates this Subject has the
273      *         role at that index.  False indicates this Subject does not have the role at that index.
274      */
275     bool[] hasRoles(List!(string) roleIdentifiers);
276 
277     bool[] hasRoles(string[] roleIdentifiers...);
278 
279     /**
280      * Returns {@code true} if this Subject has all of the specified roles, {@code false} otherwise.
281      *
282      * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
283      * @return true if this Subject has all the roles, false otherwise.
284      */
285     bool hasAllRoles(Collection!(string) roleIdentifiers);
286 
287     bool hasAllRoles(string[] roleIdentifiers);
288 
289     /**
290      * Asserts this Subject has the specified role by returning quietly if they do or throwing an
291      * {@link hunt.shiro.authz.AuthorizationException} if they do not.
292      *
293      * @param roleIdentifier the application-specific role identifier (usually a role id or role name ).
294      * @throws hunt.shiro.authz.AuthorizationException
295      *          if this Subject does not have the role.
296      */
297     void checkRole(string roleIdentifier);
298 
299     /**
300      * Asserts this Subject has all of the specified roles by returning quietly if they do or throwing an
301      * {@link hunt.shiro.authz.AuthorizationException} if they do not.
302      *
303      * @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
304      * @throws hunt.shiro.authz.AuthorizationException
305      *          if this Subject does not have all of the specified roles.
306      */
307     void checkRoles(Collection!(string) roleIdentifiers);
308 
309     /**
310      * Same as {@link #checkRoles(Collection!(string) roleIdentifiers) checkRoles(Collection!(string) roleIdentifiers)} but
311      * doesn't require a collection as a an argument.
312      * Asserts this Subject has all of the specified roles by returning quietly if they do or throwing an
313      * {@link hunt.shiro.authz.AuthorizationException} if they do not.
314      *
315      * @param roleIdentifiers roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
316      * @throws AuthorizationException hunt.shiro.authz.AuthorizationException
317      *          if this Subject does not have all of the specified roles.
318      */
319     void checkRoles(string[] roleIdentifiers...);
320 
321     /**
322      * Performs a login attempt for this Subject/user.  If unsuccessful,
323      * an {@link AuthenticationException} is thrown, the subclass of which identifies why the attempt failed.
324      * If successful, the account data associated with the submitted principals/credentials will be
325      * associated with this {@code Subject} and the method will return quietly.
326      * <p/>
327      * Upon returning quietly, this {@code Subject} instance can be considered
328      * authenticated and {@link #getPrincipal() getPrincipal()} will be non-null and
329      * {@link #isAuthenticated() isAuthenticated()} will be {@code true}.
330      *
331      * @param token the token encapsulating the subject's principals and credentials to be passed to the
332      *              Authentication subsystem for verification.
333      * @throws hunt.shiro.authc.AuthenticationException
334      *          if the authentication attempt fails.
335      */
336     void login(AuthenticationToken token);
337 
338     /**
339      * Returns {@code true} if this Subject/user proved their identity <em>during their current session</em>
340      * by providing valid credentials matching those known to the system, {@code false} otherwise.
341      * <p/>
342      * Note that even if this Subject's identity has been remembered via 'remember me' services, this method will
343      * still return {@code false} unless the user has actually logged in with proper credentials <em>during their
344      * current session</em>.  See the {@link #isRemembered() isRemembered()} method JavaDoc for more.
345      *
346      * @return {@code true} if this Subject proved their identity during their current session
347      *         by providing valid credentials matching those known to the system, {@code false} otherwise.
348      */
349     bool isAuthenticated();
350 
351 
352     /**
353      * Returns {@code true} if this {@code Subject} has an identity (it is not anonymous) and the identity
354      * (aka {@link #getPrincipals() principals}) is remembered from a successful authentication during a previous
355      * session.
356      * <p/>
357      * Although the underlying implementation determines exactly how this method functions, most implementations have
358      * this method act as the logical equivalent to this code:
359      * <pre>
360      * {@link #getPrincipal() getPrincipal()} !is null && !{@link #isAuthenticated() isAuthenticated()}</pre>
361      * <p/>
362      * Note as indicated by the above code example, if a {@code Subject} is remembered, they are
363      * <em>NOT</em> considered authenticated.  A check against {@link #isAuthenticated() isAuthenticated()} is a more
364      * strict check than that reflected by this method.  For example, a check to see if a subject can access financial
365      * information should almost always depend on {@link #isAuthenticated() isAuthenticated()} to <em>guarantee</em> a
366      * verified identity, and not this method.
367      * <p/>
368      * Once the subject is authenticated, they are no longer considered only remembered because their identity would
369      * have been verified during the current session.
370      * <h4>Remembered vs Authenticated</h4>
371      * Authentication is the process of <em>proving</em> you are who you say you are.  When a user is only remembered,
372      * the remembered identity gives the system an idea who that user probably is, but in reality, has no way of
373      * absolutely <em>guaranteeing</em> if the remembered {@code Subject} represents the user currently
374      * using the application.
375      * <p/>
376      * So although many parts of the application can still perform user-specific logic based on the remembered
377      * {@link #getPrincipals() principals}, such as customized views, it should never perform highly-sensitive
378      * operations until the user has legitimately verified their identity by executing a successful authentication
379      * attempt.
380      * <p/>
381      * We see this paradigm all over the web, and we will use <a href="http://www.amazon.com">Amazon.com</a> as an
382      * example:
383      * <p/>
384      * When you visit Amazon.com and perform a login and ask it to 'remember me', it will set a cookie with your
385      * identity.  If you don't log out and your session expires, and you come back, say the next day, Amazon still knows
386      * who you <em>probably</em> are: you still see all of your book and movie recommendations and similar user-specific
387      * features since these are based on your (remembered) user id.
388      * <p/>
389      * BUT, if you try to do something sensitive, such as access your account's billing data, Amazon forces you
390      * to do an actual log-in, requiring your username and password.
391      * <p/>
392      * This is because although amazon.com assumed your identity from 'remember me', it recognized that you were not
393      * actually authenticated.  The only way to really guarantee you are who you say you are, and therefore allow you
394      * access to sensitive account data, is to force you to perform an actual successful authentication.  You can
395      * check this guarantee via the {@link #isAuthenticated() isAuthenticated()} method and not via this method.
396      *
397      * @return {@code true} if this {@code Subject}'s identity (aka {@link #getPrincipals() principals}) is
398      *         remembered from a successful authentication during a previous session, {@code false} otherwise.
399      */
400     bool isRemembered();
401 
402     /**
403      * Returns the application {@code Session} associated with this Subject.  If no session exists when this
404      * method is called, a new session will be created, associated with this Subject, and then returned.
405      *
406      * @return the application {@code Session} associated with this Subject.
407      * @see #getSession(bool)
408      */
409     Session getSession();
410 
411     /**
412      * Returns the application {@code Session} associated with this Subject.  Based on the bool argument,
413      * this method functions as follows:
414      * <ul>
415      * <li>If there is already an existing session associated with this {@code Subject}, it is returned and
416      * the {@code create} argument is ignored.</li>
417      * <li>If no session exists and {@code create} is {@code true}, a new session will be created, associated with
418      * this {@code Subject} and then returned.</li>
419      * <li>If no session exists and {@code create} is {@code false}, {@code null} is returned.</li>
420      * </ul>
421      *
422      * @param create bool argument determining if a new session should be created or not if there is no existing session.
423      * @return the application {@code Session} associated with this {@code Subject} or {@code null} based
424      *         on the above described logic.
425      */
426     Session getSession(bool create);
427 
428     /**
429      * Logs out this Subject and invalidates and/or removes any associated entities,
430      * such as a {@link Session Session} and authorization data.  After this method is called, the Subject is
431      * considered 'anonymous' and may continue to be used for another log-in if desired.
432      * <h3>Web Environment Warning</h3>
433      * Calling this method in web environments will usually remove any associated session cookie as part of
434      * session invalidation.  Because cookies are part of the HTTP header, and headers can only be set before the
435      * response body (html, image, etc) is sent, this method in web environments must be called before <em>any</em>
436      * content has been rendered.
437      * <p/>
438      * The typical approach most applications use in this scenario is to redirect the user to a different
439      * location (e.g. home page) immediately after calling this method.  This is an effect of the HTTP protocol
440      * itself and not a reflection of Shiro's implementation.
441      * <p/>
442      * Non-HTTP environments may of course use a logged-out subject for login again if desired.
443      */
444     void logout();
445 
446     /**
447      * Associates the specified {@code Callable} with this {@code Subject} instance and then executes it on the
448      * currently running thread.  If you want to execute the {@code Callable} on a different thread, it is better to
449      * use the {@link #associateWith(Callable)} method instead.
450      *
451      * @param callable the Callable to associate with this subject and then execute.
452      * @param <V>      the type of return value the {@code Callable} will return
453      * @return the resulting object returned by the {@code Callable}'s execution.
454      * @throws ExecutionException if the {@code Callable}'s {@link Callable#call call} method.
455      */
456     // V execute(V)(Callable!(V) callable);
457 
458     /**
459      * Associates the specified {@code Runnable} with this {@code Subject} instance and then executes it on the
460      * currently running thread.  If you want to execute the {@code Runnable} on a different thread, it is better to
461      * use the {@link #associateWith(Runnable)} method instead.
462      * <p/>
463      * <b>Note</b>: This method is primarily provided to execute existing/legacy Runnable implementations.  It is better
464      * for new code to use {@link #execute(Callable)} since that supports the ability to return values and catch
465      * exceptions.
466      *
467      * @param runnable the {@code Runnable} to associate with this {@code Subject} and then execute.
468      */
469     void execute(Runnable runnable);
470 
471     /**
472      * Returns a {@code Callable} instance matching the given argument while additionally ensuring that it will
473      * retain and execute under this Subject's identity.  The returned object can be used with an
474      * {@link java.util.concurrent.ExecutorService ExecutorService} to execute as this Subject.
475      * <p/>
476      * This will effectively ensure that any calls to
477      * {@code SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()} and related functionality will continue
478      * to function properly on any thread that executes the returned {@code Callable} instance.
479      *
480      * @param callable the callable to execute as this {@code Subject}
481      * @param <V>      the {@code Callable}s return value type
482      * @return a {@code Callable} that can be run as this {@code Subject}.
483      */
484     // Callable!(V) associateWith(V)(Callable!(V) callable);
485 
486     /**
487      * Returns a {@code Runnable} instance matching the given argument while additionally ensuring that it will
488      * retain and execute under this Subject's identity.  The returned object can be used with an
489      * {@link java.util.concurrent.Executor Executor} or another thread to execute as this Subject.
490      * <p/>
491      * This will effectively ensure that any calls to
492      * {@code SecurityUtils}.{@link SecurityUtils#getSubject() getSubject()} and related functionality will continue
493      * to function properly on any thread that executes the returned {@code Runnable} instance.
494      * <p/>
495      * *Note that if you need a return value to be returned as a result of the runnable's execution or if you need to
496      * react to any Exceptions, it is highly recommended to use the
497      * {@link #associateWith(java.util.concurrent.Callable) createCallable} method instead of this one.
498      *
499      * @param runnable the runnable to execute as this {@code Subject}
500      * @return a {@code Runnable} that can be run as this {@code Subject} on another thread.
501      * @see #associateWith (java.util.concurrent.Callable)
502      */
503     Runnable associateWith(Runnable runnable);
504 
505     /**
506      * Allows this subject to 'run as' or 'assume' another identity indefinitely.  This can only be
507      * called when the {@code Subject} instance already has an identity (i.e. they are remembered from a previous
508      * log-in or they have authenticated during their current session).
509      * <p/>
510      * Some notes about {@code runAs}:
511      * <ul>
512      * <li>You can tell if a {@code Subject} is 'running as' another identity by calling the
513      * {@link #isRunAs() isRunAs()} method.</li>
514      * <li>If running as another identity, you can determine what the previous 'pre run as' identity
515      * was by calling the {@link #getPreviousPrincipals() getPreviousPrincipals()} method.</li>
516      * <li>When you want a {@code Subject} to stop running as another identity, you can return to its previous
517      * 'pre run as' identity by calling the {@link #releaseRunAs() releaseRunAs()} method.</li>
518      * </ul>
519      *
520      * @param principals the identity to 'run as', aka the identity to <em>assume</em> indefinitely.
521      * @throws NullPointerException  if the specified principals collection is {@code null} or empty.
522      * @throws IllegalStateException if this {@code Subject} does not yet have an identity of its own.
523      */
524     void runAs(PrincipalCollection principals);
525 
526     /**
527      * Returns {@code true} if this {@code Subject} is 'running as' another identity other than its original one or
528      * {@code false} otherwise (normal {@code Subject} state).  See the {@link #runAs runAs} method for more
529      * information.
530      *
531      * @return {@code true} if this {@code Subject} is 'running as' another identity other than its original one or
532      *         {@code false} otherwise (normal {@code Subject} state).
533      * @see #runAs
534      */
535     bool isRunAs();
536 
537     /**
538      * Returns the previous 'pre run as' identity of this {@code Subject} before assuming the current
539      * {@link #runAs runAs} identity, or {@code null} if this {@code Subject} is not operating under an assumed
540      * identity (normal state). See the {@link #runAs runAs} method for more information.
541      *
542      * @return the previous 'pre run as' identity of this {@code Subject} before assuming the current
543      *         {@link #runAs runAs} identity, or {@code null} if this {@code Subject} is not operating under an assumed
544      *         identity (normal state).
545      * @see #runAs
546      */
547     PrincipalCollection getPreviousPrincipals();
548 
549     /**
550      * Releases the current 'run as' (assumed) identity and reverts back to the previous 'pre run as'
551      * identity that existed before {@code #runAs runAs} was called.
552      * <p/>
553      * This method returns 'run as' (assumed) identity being released or {@code null} if this {@code Subject} is not
554      * operating under an assumed identity.
555      *
556      * @return the 'run as' (assumed) identity being released or {@code null} if this {@code Subject} is not operating
557      *         under an assumed identity.
558      * @see #runAs
559      */
560     PrincipalCollection releaseRunAs();
561 
562 }
563 
564 
565 /**
566  * Builder design pattern implementation for creating {@link Subject} instances in a simplified way without
567  * requiring knowledge of Shiro's construction techniques.
568  * <p/>
569  * <b>NOTE</b>: This is provided for framework development support only and should typically never be used by
570  * application developers.  {@code Subject} instances should generally be acquired by using
571  * <code>SecurityUtils.{@link SecurityUtils#getSubject() getSubject()}</code>
572  * <h4>Usage</h4>
573  * The simplest usage of this builder is to construct an anonymous, session-less {@code Subject} instance:
574  * <pre>
575  * Subject subject = new Subject.{@link #Builder() Builder}().{@link #buildSubject() buildSubject()};</pre>
576  * The default, no-arg {@code Subject.Builder()} constructor shown above will use the application's
577  * currently accessible {@code SecurityManager} via
578  * <code>SecurityUtils.{@link SecurityUtils#getSecurityManager() getSecurityManager()}</code>.  You may also
579  * specify the exact {@code SecurityManager} instance to be used by the additional
580  * <code>Subject.{@link #Builder(hunt.shiro.mgt.SecurityManager) Builder(securityManager)}</code>
581  * constructor if desired.
582  * <p/>
583  * All other methods may be called before the {@link #buildSubject() buildSubject()} method to
584  * provide context on how to construct the {@code Subject} instance.  For example, if you have a session id and
585  * want to acquire the {@code Subject} that 'owns' that session (assuming the session exists and is not expired):
586  * <pre>
587  * Subject subject = new Subject.Builder().sessionId(sessionId).buildSubject();</pre>
588  * <p/>
589  * Similarly, if you want a {@code Subject} instance reflecting a certain identity:
590  * <pre>
591  * PrincipalCollection principals = new SimplePrincipalCollection("username", <em>yourRealmName</em>);
592  * Subject subject = new Subject.Builder().principals(principals).build();</pre>
593  * <p/>
594  * <b>Note*</b> that the returned {@code Subject} instance is <b>not</b> automatically bound to the application (thread)
595  * for further use.  That is,
596  * {@link hunt.shiro.SecurityUtils SecurityUtils}.{@link hunt.shiro.SecurityUtils#getSubject() getSubject()}
597  * will not automatically return the same instance as what is returned by the builder.  It is up to the framework
598  * developer to bind the built {@code Subject} for continued use if desired.
599  *
600  */
601 class SubjectBuilder {
602 
603     /**
604      * Hold all contextual data via the Builder instance's method invocations to be sent to the
605      * {@code SecurityManager} during the {@link #buildSubject} call.
606      */
607     private SubjectContext subjectContext;
608 
609     /**
610      * The SecurityManager to invoke during the {@link #buildSubject} call.
611      */
612     private SecurityManager securityManager;
613 
614     /**
615      * Constructs a new {@link Subject.Builder} instance, using the {@code SecurityManager} instance available
616      * to the calling code as determined by a call to {@link hunt.shiro.SecurityUtils#getSecurityManager()}
617      * to build the {@code Subject} instance.
618      */
619     // this() {
620     //     this(SecurityUtils.getSecurityManager());
621     // }
622 
623     /**
624      * Constructs a new {@link Subject.Builder} instance which will use the specified {@code SecurityManager} when
625      * building the {@code Subject} instance.
626      *
627      * @param securityManager the {@code SecurityManager} to use when building the {@code Subject} instance.
628      */
629     this(SecurityManager securityManager) {
630         if (securityManager  is null) {
631             throw new NullPointerException("SecurityManager method argument cannot be null.");
632         }
633         this.securityManager = securityManager;
634         this.subjectContext = newSubjectContextInstance();
635         if (this.subjectContext  is null) {
636             throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' " ~
637                     "cannot be null.");
638         }
639         this.subjectContext.setSecurityManager(securityManager);
640     }
641 
642     /**
643      * Creates a new {@code SubjectContext} instance to be used to populate with subject contextual data that
644      * will then be sent to the {@code SecurityManager} to create a new {@code Subject} instance.
645      *
646      * @return a new {@code SubjectContext} instance
647      */
648     protected SubjectContext newSubjectContextInstance() {
649         return new DefaultSubjectContext();
650     }
651 
652     /**
653      * Returns the backing context used to build the {@code Subject} instance, available to subclasses
654      * since the {@code context} class attribute is marked as {@code private}.
655      *
656      * @return the backing context used to build the {@code Subject} instance, available to subclasses.
657      */
658     protected SubjectContext getSubjectContext() {
659         return this.subjectContext;
660     }
661 
662     /**
663      * Enables building a {@link Subject Subject} instance that owns the {@link Session Session} with the
664      * specified {@code sessionId}.
665      * <p/>
666      * Usually when specifying a {@code sessionId}, no other {@code Builder} methods would be specified because
667      * everything else (principals, inet address, etc) can usually be reconstructed based on the referenced
668      * session alone.  In other words, this is almost always sufficient:
669      * <pre>
670      * new Subject.Builder().sessionId(sessionId).buildSubject();</pre>
671      * <p/>
672      * <b>Although simple in concept, this method provides very powerful functionality previously absent in almost
673      * all Java environments:</b>
674      * <p/>
675      * The ability to reference a {@code Subject} and their server-side session
676      * <em>across clients of different mediums</em> such as web applications, Java applets,
677      * standalone C# clients over XML-RPC and/or SOAP, and many others. This is a <em>huge</em>
678      * benefit in heterogeneous enterprise applications.
679      * <p/>
680      * To maintain session integrity across client mediums, the {@code sessionId} <b>must</b> be transmitted
681      * to all client mediums securely (e.g. over SSL) to prevent man-in-the-middle attacks.  This
682      * is nothing new - all web applications are susceptible to the same problem when transmitting
683      * {@code Cookie}s or when using URL rewriting.  As long as the
684      * {@code sessionId} is transmitted securely, session integrity can be maintained.
685      *
686      * @param sessionId the id of the session that backs the desired Subject being acquired.
687      * @return this {@code Builder} instance for method chaining.
688      */
689     SubjectBuilder sessionId(string sessionId) {
690         if (!sessionId.empty()) {
691             this.subjectContext.setSessionId(sessionId);
692         }
693         return this;
694     }
695 
696     /**
697      * Ensures the {@code Subject} being built will reflect the specified host name or IP as its originating
698      * location.
699      *
700      * @param host the host name or IP address to use as the {@code Subject}'s originating location.
701      * @return this {@code Builder} instance for method chaining.
702      */
703     SubjectBuilder host(string host) {
704         if (!host.empty()) {
705             this.subjectContext.setHost(host);
706         }
707         return this;
708     }
709 
710     /**
711      * Ensures the {@code Subject} being built will use the specified {@link Session} instance.  Note that it is
712      * more common to use the {@link #sessionId sessionId} builder method rather than having to construct a
713      * {@code Session} instance for this method.
714      *
715      * @param session the session to use as the {@code Subject}'s {@link Session}
716      * @return this {@code Builder} instance for method chaining.
717      */
718     SubjectBuilder session(Session session) {
719         if (session !is null) {
720             this.subjectContext.setSession(session);
721         }
722         return this;
723     }
724 
725     /**
726      * Ensures the {@code Subject} being built will reflect the specified principals (aka identity).
727      * <p/>
728      * For example, if your application's unique identifier for users is a {@code string} username, and you wanted
729      * to create a {@code Subject} instance that reflected a user whose username is
730      * '{@code jsmith}', and you knew the Realm that could acquire {@code jsmith}'s principals based on the username
731      * was named &quot;{@code myRealm}&quot;, you might create the '{@code jsmith} {@code Subject} instance this
732      * way:
733      * <pre>
734      * PrincipalCollection identity = new {@link hunt.shiro.subject.SimplePrincipalCollection#SimplePrincipalCollection(Object, string) SimplePrincipalCollection}(&quot;jsmith&quot;, &quot;myRealm&quot;);
735      * Subject jsmith = new Subject.Builder().principals(identity).buildSubject();</pre>
736      * <p/>
737      * Similarly, if your application's unique identifier for users is a {@code long} value (such as might be used
738      * as a primary key in a relational database) and you were using a {@code JDBC}
739      * {@code Realm} named, (unimaginatively) &quot;jdbcRealm&quot;, you might create the Subject
740      * instance this way:
741      * <pre>
742      * long userId = //get user ID from somewhere
743      * PrincipalCollection userIdentity = new {@link hunt.shiro.subject.SimplePrincipalCollection#SimplePrincipalCollection(Object, string) SimplePrincipalCollection}(<em>userId</em>, &quot;jdbcRealm&quot;);
744      * Subject user = new Subject.Builder().principals(identity).buildSubject();</pre>
745      *
746      * @param principals the principals to use as the {@code Subject}'s identity.
747      * @return this {@code Builder} instance for method chaining.
748      */
749     SubjectBuilder principals(PrincipalCollection principals) {
750         if (principals !is null && !principals.isEmpty()) {
751             this.subjectContext.setPrincipals(principals);
752         }
753         return this;
754     }
755 
756     /**
757      * Configures whether or not the created Subject instance can create a new {@code Session} if one does not
758      * already exist.  If set to {@code false}, any application calls to
759      * {@code subject.getSession()} or {@code subject.getSession(true))} will result in a SessionException.
760      * <p/>
761      * This setting is {@code true} by default, as most applications find value in sessions.
762      *
763      * @param enabled whether or not the created Subject instance can create a new {@code Session} if one does not
764      *                already exist.
765      * @return this {@code Builder} instance for method chaining.
766      */
767     SubjectBuilder sessionCreationEnabled(bool enabled) {
768         this.subjectContext.setSessionCreationEnabled(enabled);
769         return this;
770     }
771 
772     /**
773      * Ensures the {@code Subject} being built will be considered
774      * {@link hunt.shiro.subject.Subject#isAuthenticated() authenticated}.  Per the
775      * {@link hunt.shiro.subject.Subject#isAuthenticated() isAuthenticated()} JavaDoc, be careful
776      * when specifying {@code true} - you should know what you are doing and have a good reason for ignoring Shiro's
777      * default authentication state mechanisms.
778      *
779      * @param authenticated whether or not the built {@code Subject} will be considered authenticated.
780      * @return this {@code Builder} instance for method chaining.
781      * @see hunt.shiro.subject.Subject#isAuthenticated()
782      */
783     SubjectBuilder authenticated(bool authenticated) {
784         this.subjectContext.setAuthenticated(authenticated);
785         return this;
786     }
787 
788     /**
789      * Allows custom attributes to be added to the underlying context {@code Map} used to construct the
790      * {@link Subject} instance.
791      * <p/>
792      * A {@code null} key{@link IllegalArgumentException}. A {@code null} value effectively removes
793      * any previously stored attribute under the given key from the context map.
794      * <p/>
795      * <b>*NOTE*:</b> This method is only useful when configuring Shiro with a custom {@link SubjectFactory}
796      * implementation.  This method allows end-users to append additional data to the context map which the
797      * {@code SubjectFactory} implementation can use when building custom Subject instances. As such, this method
798      * is only useful when a custom {@code SubjectFactory} implementation has been configured.
799      *
800      * @param attributeKey   the key under which the corresponding value will be stored in the context {@code Map}.
801      * @param attributeValue the value to store in the context map under the specified {@code attributeKey}.
802      * @return this {@code Builder} instance for method chaining.
803      * @throws IllegalArgumentException if the {@code attributeKey} is {@code null}.
804      * @see SubjectFactory#createSubject(SubjectContext)
805      */
806     SubjectBuilder contextAttribute(string attributeKey, Object attributeValue) {
807         if (attributeKey.empty) {
808             string msg = "Subject context map key cannot be null.";
809             throw new IllegalArgumentException(msg);
810         }
811 
812         Map!(string, Object) contextMap = cast(Map!(string, Object))subjectContext;
813         if (attributeValue is null) {
814             contextMap.remove(attributeKey);
815         } else {
816             contextMap.put(attributeKey, attributeValue);
817         }
818         return this;
819     }
820 
821     /**
822      * Creates and returns a new {@code Subject} instance reflecting the cumulative state acquired by the
823      * other methods in this class.
824      * <p/>
825      * This {@code Builder} instance will still retain the underlying state after this method is called - it
826      * will not clear it; repeated calls to this method will return multiple {@link Subject} instances, all
827      * reflecting the exact same state.  If a new (different) {@code Subject} is to be constructed, a new
828      * {@code Builder} instance must be created.
829      * <p/>
830      * <b>Note</b> that the returned {@code Subject} instance is <b>not</b> automatically bound to the application
831      * (thread) for further use.  That is,
832      * {@link hunt.shiro.SecurityUtils SecurityUtils}.{@link hunt.shiro.SecurityUtils#getSubject() getSubject()}
833      * will not automatically return the same instance as what is returned by the builder.  It is up to the
834      * framework developer to bind the returned {@code Subject} for continued use if desired.
835      *
836      * @return a new {@code Subject} instance reflecting the cumulative state acquired by the
837      *         other methods in this class.
838      */
839     Subject buildSubject() {
840         return this.securityManager.createSubject(this.subjectContext);
841     }
842 
843 }