]> git.argeo.org Git - lgpl/argeo-commons.git/blob - argeo/cms/auth/CurrentUser.java
Prepare next development cycle
[lgpl/argeo-commons.git] / argeo / cms / auth / CurrentUser.java
1 package org.argeo.cms.auth;
2
3 import java.security.Principal;
4 import java.security.PrivilegedAction;
5 import java.security.PrivilegedActionException;
6 import java.security.PrivilegedExceptionAction;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.Locale;
10 import java.util.Set;
11 import java.util.UUID;
12
13 import javax.security.auth.Subject;
14 import javax.security.auth.x500.X500Principal;
15
16 import org.argeo.api.cms.CmsConstants;
17 import org.argeo.api.cms.CmsSession;
18 import org.argeo.api.cms.CmsSessionId;
19 import org.argeo.cms.internal.auth.CmsSessionImpl;
20 import org.argeo.cms.internal.auth.ImpliedByPrincipal;
21 import org.argeo.cms.internal.runtime.CmsContextImpl;
22 import org.argeo.util.CurrentSubject;
23 import org.osgi.service.useradmin.Authorization;
24
25 /**
26 * Programmatic access to the currently authenticated user, within a CMS
27 * context.
28 */
29 public final class CurrentUser {
30 /*
31 * CURRENT USER API
32 */
33
34 /**
35 * Technical username of the currently authenticated user.
36 *
37 * @return the authenticated username or null if not authenticated / anonymous
38 */
39 public static String getUsername() {
40 return getUsername(currentSubject());
41 }
42
43 /**
44 * Human readable name of the currently authenticated user (typically first name
45 * and last name).
46 */
47 public static String getDisplayName() {
48 return getDisplayName(currentSubject());
49 }
50
51 /** Whether a user is currently authenticated. */
52 public static boolean isAnonymous() {
53 return isAnonymous(currentSubject());
54 }
55
56 /** Locale of the current user */
57 public final static Locale locale() {
58 return locale(currentSubject());
59 }
60
61 /** Roles of the currently logged-in user */
62 public final static Set<String> roles() {
63 return roles(currentSubject());
64 }
65
66 /** Returns true if the current user is in the specified role */
67 public static boolean isInRole(String role) {
68 Set<String> roles = roles();
69 return roles.contains(role);
70 }
71
72 /** Implies this {@link SystemRole} in this context. */
73 public final static boolean implies(SystemRole role, String context) {
74 return role.implied(currentSubject(), context);
75 }
76
77 /** Executes as the current user */
78 public final static <T> T doAs(PrivilegedAction<T> action) {
79 return Subject.doAs(currentSubject(), action);
80 }
81
82 /** Executes as the current user */
83 public final static <T> T tryAs(PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
84 return Subject.doAs(currentSubject(), action);
85 }
86
87 /*
88 * WRAPPERS
89 */
90
91 public final static String getUsername(Subject subject) {
92 if (subject == null)
93 throw new IllegalArgumentException("Subject cannot be null");
94 if (subject.getPrincipals(X500Principal.class).size() != 1)
95 return CmsConstants.ROLE_ANONYMOUS;
96 Principal principal = subject.getPrincipals(X500Principal.class).iterator().next();
97 return principal.getName();
98 }
99
100 public final static String getDisplayName(Subject subject) {
101 return getAuthorization(subject).toString();
102 }
103
104 public final static Set<String> roles(Subject subject) {
105 Set<String> roles = new HashSet<String>();
106 roles.add(getUsername(subject));
107 for (Principal group : subject.getPrincipals(ImpliedByPrincipal.class)) {
108 roles.add(group.getName());
109 }
110 return roles;
111 }
112
113 public final static Locale locale(Subject subject) {
114 Set<Locale> locales = subject.getPublicCredentials(Locale.class);
115 if (locales.isEmpty()) {
116 Locale defaultLocale = CmsContextImpl.getCmsContext().getDefaultLocale();
117 return defaultLocale;
118 } else
119 return locales.iterator().next();
120 }
121
122 /** Whether this user is currently authenticated. */
123 public static boolean isAnonymous(Subject subject) {
124 if (subject == null)
125 return true;
126 String username = getUsername(subject);
127 return username == null || username.equalsIgnoreCase(CmsConstants.ROLE_ANONYMOUS);
128 }
129
130 public static CmsSession getCmsSession() {
131 Subject subject = currentSubject();
132 Iterator<CmsSessionId> it = subject.getPrivateCredentials(CmsSessionId.class).iterator();
133 if (!it.hasNext())
134 throw new IllegalStateException("No CMS session id available for " + subject);
135 CmsSessionId cmsSessionId = it.next();
136 if (it.hasNext())
137 throw new IllegalStateException("More than one CMS session id available for " + subject);
138 return CmsContextImpl.getCmsContext().getCmsSessionByUuid(cmsSessionId.getUuid());
139 }
140
141 public static boolean isAvailable() {
142 return CurrentSubject.current() != null;
143 }
144
145 /*
146 * HELPERS
147 */
148 private static Subject currentSubject() {
149 Subject subject = CurrentSubject.current();
150 if (subject == null)
151 throw new IllegalStateException("Cannot find related subject");
152 return subject;
153 }
154
155 private static Authorization getAuthorization(Subject subject) {
156 return subject.getPrivateCredentials(Authorization.class).iterator().next();
157 }
158
159 public static boolean logoutCmsSession(Subject subject) {
160 UUID nodeSessionId;
161 if (subject.getPrivateCredentials(CmsSessionId.class).size() == 1)
162 nodeSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next().getUuid();
163 else
164 return false;
165 CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByUuid(nodeSessionId);
166
167 // FIXME logout all views
168 // TODO check why it is sometimes null
169 if (cmsSession != null)
170 cmsSession.close();
171 // if (log.isDebugEnabled())
172 // log.debug("Logged out CMS session " + cmsSession.getUuid());
173 return true;
174 }
175
176 /** singleton */
177 private CurrentUser() {
178 }
179 }