1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.security;
35
36 import static info.magnolia.cms.util.FilteredEventListener.JCR_SYSTEM_EXCLUDING_PREDICATE;
37
38 import info.magnolia.cms.security.auth.ACL;
39 import info.magnolia.cms.security.auth.PrincipalCollection;
40 import info.magnolia.cms.security.auth.PrincipalCollectionImpl;
41 import info.magnolia.cms.util.FilteredEventListener;
42 import info.magnolia.context.MgnlContext;
43 import info.magnolia.jcr.util.NodeTypes;
44 import info.magnolia.observation.WorkspaceEventListenerRegistration;
45 import info.magnolia.repository.RepositoryConstants;
46
47 import java.security.Principal;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.Collections;
51
52 import javax.jcr.Node;
53 import javax.jcr.RepositoryException;
54 import javax.jcr.Session;
55 import javax.jcr.observation.EventIterator;
56 import javax.jcr.observation.EventListener;
57 import javax.security.auth.Subject;
58
59 import org.apache.commons.lang3.StringUtils;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63
64
65
66
67 public class SystemUserManager extends MgnlUserManager {
68
69 private static final Logger log = LoggerFactory.getLogger(SystemUserManager.class);
70
71
72
73
74
75 private User anonymousUser;
76
77
78
79
80
81 private PrincipalCollection anonymousPermissions;
82
83 private final EventListener anonymousListener = new EventListener() {
84
85 @Override
86 public void onEvent(EventIterator events) {
87 anonymousUser = null;
88 anonymousPermissions = null;
89 log.debug("Anonymous user reloaded");
90 }
91 };
92
93 public SystemUserManager() {
94 final String anonymousUserPath = "/" + Realm.REALM_SYSTEM.getName() + "/" + UserManager.ANONYMOUS_USER;
95 try {
96 WorkspaceEventListenerRegistration.observe(RepositoryConstants.USERS, anonymousUserPath, anonymousListener)
97 .withSubNodes(true)
98 .withNodeTypes(NodeTypes.User.NAME)
99 .register();
100
101 WorkspaceEventListenerRegistration.observe(RepositoryConstants.USER_GROUPS, "/", new FilteredEventListener(anonymousListener, JCR_SYSTEM_EXCLUDING_PREDICATE))
102 .withSubNodes(true)
103 .withNodeTypes(NodeTypes.Group.NAME)
104 .register();
105
106 WorkspaceEventListenerRegistration.observe(RepositoryConstants.USER_ROLES, "/", new FilteredEventListener(anonymousListener, JCR_SYSTEM_EXCLUDING_PREDICATE))
107 .withSubNodes(true)
108 .withNodeTypes(NodeTypes.Role.NAME, NodeTypes.ContentNode.NAME)
109 .withDelay(1000L, 5000L)
110 .register();
111 } catch (RepositoryException e) {
112 log.error("An error occurred while registering event listeners for SystemUserManager", e);
113 }
114 }
115
116 @Override
117 public String getRealmName() {
118 String name = super.getRealmName();
119
120 if (StringUtils.isEmpty(name)) {
121 log.error("realm of system user manager is not set!");
122 return Realm.REALM_SYSTEM.getName();
123 }
124 return name;
125 }
126
127 @Override
128 public User getSystemUser() {
129 return getOrCreateUser(UserManager.SYSTEM_USER, UserManager.SYSTEM_PSWD);
130 }
131
132 @Override
133 public User getAnonymousUser() {
134 if (anonymousUser == null) {
135
136 anonymousUser = getRequiredSystemUser(UserManager.ANONYMOUS_USER, UserManager.ANONYMOUS_USER);
137 }
138 return anonymousUser;
139 }
140
141 public Subject getAnonymousSubject() {
142 if (anonymousPermissions == null) {
143 Subject subject = SecurityUtil.createSubjectAndPopulate(getAnonymousUser());
144 anonymousPermissions = PrincipalUtil.findPrincipal(subject, PrincipalCollection.class);
145 return subject;
146 }
147 Subject subject = new Subject();
148 subject.getPrincipals().add(getAnonymousUser());
149
150
151 Collection<Principal> permissions = new ArrayList<>();
152 for (Principal principal : anonymousPermissions.getCollection()) {
153 ACLhref="../../../../info/magnolia/cms/security/auth/ACL.html#ACL">ACL acl = (ACL) principal;
154
155 permissions.add(new ACLImpl(acl.getName(), new ArrayList<>(acl.getList())));
156 }
157 subject.getPrincipals().add(new PrincipalCollectionImpl(Collections.unmodifiableCollection(permissions)));
158 return subject;
159 }
160
161
162
163
164 private User getRequiredSystemUser(final String username, String password) {
165 return MgnlContext.doInSystemContext(new SilentSessionOp<User>(getRepositoryName()) {
166
167 @Override
168 public User doExec(Session session) throws RepositoryException {
169 User user;
170 Node node;
171 try {
172 node = session.getNode("/" + Realm.REALM_SYSTEM.getName() + "/" + username);
173 } catch (RepositoryException e) {
174 log.error("Error caught while loading the system user {}: {}: {}", username, e.getClass().getName(), e.getMessage(), e);
175 return null;
176 }
177 if (node == null) {
178 log.error("User not found: {}.", username);
179 return null;
180 }
181
182 user = newUserInstance(node);
183 return user;
184 }
185 });
186 }
187
188 protected User getOrCreateUser(String userName, String password) {
189 User user = getUser(userName);
190 if (user == null) {
191 log.error(
192 "Failed to get system user [{}], will try to create new system user with default password",
193 userName);
194 user = this.createUser(userName, password);
195 }
196 return user;
197 }
198 }