]> git.argeo.org Git - lgpl/argeo-commons.git/blob - CmsSessionImpl.java
2e074e7781e57c5438272a6fc11221164512994f
[lgpl/argeo-commons.git] / CmsSessionImpl.java
1 package org.argeo.cms.internal.auth;
2
3 import java.io.Serializable;
4 import java.security.AccessControlContext;
5 import java.security.AccessController;
6 import java.security.PrivilegedAction;
7 import java.time.ZonedDateTime;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.List;
12 import java.util.Locale;
13 import java.util.Map;
14 import java.util.Objects;
15 import java.util.Set;
16 import java.util.UUID;
17 import java.util.function.Consumer;
18
19 import javax.crypto.SecretKey;
20 import javax.security.auth.Subject;
21 import javax.security.auth.login.LoginContext;
22 import javax.security.auth.login.LoginException;
23 import javax.security.auth.x500.X500Principal;
24
25 import org.argeo.api.cms.CmsAuth;
26 import org.argeo.api.cms.CmsConstants;
27 import org.argeo.api.cms.CmsLog;
28 import org.argeo.api.cms.CmsSession;
29 import org.argeo.cms.internal.runtime.CmsContextImpl;
30 import org.osgi.framework.ServiceRegistration;
31 import org.osgi.service.useradmin.Authorization;
32
33 /** Default CMS session implementation. */
34 public class CmsSessionImpl implements CmsSession, Serializable {
35 private static final long serialVersionUID = 1867719354246307225L;
36 // private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionImpl.class).getBundleContext();
37 private final static CmsLog log = CmsLog.getLog(CmsSessionImpl.class);
38
39 // private final Subject initialSubject;
40 private transient AccessControlContext accessControlContext;
41 private final UUID uuid;
42 private final String localSessionId;
43 private Authorization authorization;
44 // private final LdapName userDn;
45 private final String userDn;
46 private final boolean anonymous;
47
48 private final ZonedDateTime creationTime;
49 private ZonedDateTime end;
50 private final Locale locale;
51
52 private ServiceRegistration<CmsSession> serviceRegistration;
53
54 private Map<String, Object> views = new HashMap<>();
55
56 private List<Consumer<CmsSession>> onCloseCallbacks = Collections.synchronizedList(new ArrayList<>());
57
58 public CmsSessionImpl(UUID uuid, Subject initialSubject, Authorization authorization, Locale locale,
59 String localSessionId) {
60 Objects.requireNonNull(uuid);
61
62 this.creationTime = ZonedDateTime.now();
63 this.locale = locale;
64 this.accessControlContext = Subject.doAs(initialSubject, new PrivilegedAction<AccessControlContext>() {
65
66 @Override
67 public AccessControlContext run() {
68 return AccessController.getContext();
69 }
70
71 });
72 // this.initialSubject = initialSubject;
73 this.localSessionId = localSessionId;
74 this.authorization = authorization;
75 if (authorization.getName() != null) {
76 this.userDn = authorization.getName();
77 this.anonymous = false;
78 } else {
79 this.userDn = CmsConstants.ROLE_ANONYMOUS;
80 this.anonymous = true;
81 }
82 this.uuid = uuid;
83 }
84
85 public void close() {
86 end = ZonedDateTime.now();
87 CmsContextImpl.getCmsContext().unregisterCmsSession(this);
88 // serviceRegistration.unregister();
89
90 for (Consumer<CmsSession> onClose : onCloseCallbacks) {
91 onClose.accept(this);
92 }
93
94 try {
95 LoginContext lc;
96 if (isAnonymous()) {
97 lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_ANONYMOUS, getSubject());
98 } else {
99 lc = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, getSubject());
100 }
101 lc.logout();
102 } catch (LoginException e) {
103 log.warn("Could not logout " + getSubject() + ": " + e);
104 } finally {
105 accessControlContext = null;
106 }
107 log.debug("Closed " + this);
108 }
109
110 @Override
111 public void addOnCloseCallback(Consumer<CmsSession> onClose) {
112 onCloseCallbacks.add(onClose);
113 }
114
115 public Subject getSubject() {
116 return Subject.getSubject(accessControlContext);
117 }
118
119 public Set<SecretKey> getSecretKeys() {
120 checkValid();
121 return getSubject().getPrivateCredentials(SecretKey.class);
122 }
123
124 @Override
125 public boolean isValid() {
126 return !isClosed();
127 }
128
129 private void checkValid() {
130 if (!isValid())
131 throw new IllegalStateException("CMS session " + uuid + " is not valid since " + end);
132 }
133
134 final protected boolean isClosed() {
135 return getEnd() != null;
136 }
137
138 public Authorization getAuthorization() {
139 checkValid();
140 return authorization;
141 }
142
143 @Override
144 public String getDisplayName() {
145 return authorization.toString();
146 }
147
148 @Override
149 public UUID getUuid() {
150 return uuid;
151 }
152
153 @Override
154 public String getUserDn() {
155 return userDn;
156 }
157
158 @Override
159 public String getUserRole() {
160 return new X500Principal(authorization.getName()).getName();
161 }
162
163 @Override
164 public String getLocalId() {
165 return localSessionId;
166 }
167
168 @Override
169 public boolean isAnonymous() {
170 return anonymous;
171 }
172
173 @Override
174 public Locale getLocale() {
175 return locale;
176 }
177
178 @Override
179 public ZonedDateTime getCreationTime() {
180 return creationTime;
181 }
182
183 @Override
184 public ZonedDateTime getEnd() {
185 return end;
186 }
187
188 @Override
189 public void registerView(String uid, Object view) {
190 checkValid();
191 if (views.containsKey(uid))
192 throw new IllegalArgumentException("View " + uid + " is already registered.");
193 views.put(uid, view);
194 }
195
196 public String toString() {
197 return "CMS Session " + userDn + " localId=" + localSessionId + ", uuid=" + uuid;
198 }
199 }