Authorized album is now working fully.
[photos] / src / main / java / org / wamblee / photos / model / plumbing / Producer.java
1 /*
2  * Copyright 2005-2013 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.photos.model.plumbing;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.security.Principal;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.logging.Logger;
24
25 import javax.enterprise.context.ApplicationScoped;
26 import javax.enterprise.context.SessionScoped;
27 import javax.enterprise.inject.Produces;
28 import javax.inject.Inject;
29 import javax.persistence.EntityManager;
30 import javax.persistence.PersistenceContext;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpSession;
33
34 import org.wamblee.cache.Cache;
35 import org.wamblee.cache.EhCache;
36 import org.wamblee.io.ClassPathResource;
37 import org.wamblee.io.InputResource;
38 import org.wamblee.photos.concurrent.ConcurrentAlbum;
39 import org.wamblee.photos.model.Album;
40 import org.wamblee.photos.model.PhotoEntry;
41 import org.wamblee.photos.model.filesystem.FileSystemAlbum;
42 import org.wamblee.photos.security.PageAuthorizationRule;
43 import org.wamblee.photos.security.PhotoAuthorizationRule;
44 import org.wamblee.photos.wicket.HomePage;
45 import org.wamblee.security.authentication.GroupSet;
46 import org.wamblee.security.authentication.Md5HexMessageDigester;
47 import org.wamblee.security.authentication.MessageDigester;
48 import org.wamblee.security.authentication.NameValidator;
49 import org.wamblee.security.authentication.RegexpNameValidator;
50 import org.wamblee.security.authentication.User;
51 import org.wamblee.security.authentication.UserAccessor;
52 import org.wamblee.security.authentication.UserAdminInitializer;
53 import org.wamblee.security.authentication.UserAdministration;
54 import org.wamblee.security.authentication.UserAdministrationImpl;
55 import org.wamblee.security.authentication.UserSet;
56 import org.wamblee.security.authentication.jpa.JpaGroupSet;
57 import org.wamblee.security.authentication.jpa.JpaUserSet;
58 import org.wamblee.security.authorization.AbstractAuthorizationRule;
59 import org.wamblee.security.authorization.AllOperation;
60 import org.wamblee.security.authorization.AnyUserCondition;
61 import org.wamblee.security.authorization.AuthorizationInitializer;
62 import org.wamblee.security.authorization.AuthorizationResult;
63 import org.wamblee.security.authorization.AuthorizationService;
64 import org.wamblee.security.authorization.CreateOperation;
65 import org.wamblee.security.authorization.DefaultOperationRegistry;
66 import org.wamblee.security.authorization.DeleteOperation;
67 import org.wamblee.security.authorization.GroupUserCondition;
68 import org.wamblee.security.authorization.Operation;
69 import org.wamblee.security.authorization.OperationRegistry;
70 import org.wamblee.security.authorization.ReadOperation;
71 import org.wamblee.security.authorization.WriteOperation;
72 import org.wamblee.security.authorization.jpa.JpaAuthorizationService;
73
74 /**
75  * @author Erik Brakkee
76  * 
77  */
78 public class Producer {
79
80     private static final Logger LOGGER = Logger.getLogger(Producer.class
81         .getName());
82
83     private static final String APP_CONFIG_RESOURCE = "META-INF/org.wamblee.photos.properties";
84
85     @Inject
86     private HttpServletRequest request;
87
88     @Inject
89     private HttpSession session;
90
91     @PersistenceContext
92     private EntityManager entityManager;
93
94     // Created by this producer.
95
96     @Inject
97     private UserAdministration userAdmin;
98
99     @Inject
100     private AuthorizationService authorizationService;
101
102     @Inject
103     @AllPhotos
104     private Album allPhotos;
105
106     @Inject
107     @UserCache
108     private Cache<String, User> userCache;
109
110     @Inject
111     @PhotoCache
112     private Cache<String, ArrayList<PhotoEntry>> photoCache;
113
114     private Configuration getCOnfiguration() {
115         LOGGER.info("Initializing configuration");
116         Configuration config;
117         try {
118             config = new Configuration(new ClassPathResource(
119                 APP_CONFIG_RESOURCE).getInputStream());
120         } catch (IOException e) {
121             throw new RuntimeException(
122                 "Could not read application configuration property classpath resource " +
123                     APP_CONFIG_RESOURCE, e);
124         }
125         return config;
126     }
127
128     @Produces
129     @ApplicationScoped
130     public UserAdministration getUserAdmin() {
131         LOGGER.info("Initializing user administration");
132         NameValidator passwordvalidator = new RegexpNameValidator(".{5,}",
133             "INVALID_PASSWORD", "Password must have at least 5 characters");
134         MessageDigester passwordEncoder = new Md5HexMessageDigester();
135         UserSet userset = new JpaUserSet(userCache, passwordvalidator,
136             passwordEncoder, entityManager);
137         GroupSet groupset = new JpaGroupSet(entityManager);
138         NameValidator uservalidator = new RegexpNameValidator(
139             "[a-zA-Z]+[a-zA-Z0-9]*", "INVALID_USERNAME",
140             "User name must consist of alphanumeric characters only");
141         NameValidator groupvalidator = new RegexpNameValidator(
142             "[a-zA-Z]+[a-zA-Z0-9]*", "INVALID_GROUPNAME",
143             "Group name must consist of alphanumeric characters only");
144
145         UserAdministration admin = new UserAdministrationImpl(userset,
146             groupset, uservalidator, groupvalidator);
147         UserAdminInitializer initializer = new UserAdminInitializer(admin,
148             new String[] { "erik", "admin" }, new String[] { "users",
149                 "administrators" }, new String[] { "abc123", "abc123" });
150         return admin;
151     }
152
153     @Produces
154     @ApplicationScoped
155     @UserCache
156     public Cache<String, User> getUserCache() {
157         try {
158             InputResource cacheConfig = new ClassPathResource(
159                 "META-INF/ehcache.xml");
160             return new EhCache(cacheConfig, "users");
161         } catch (IOException e) {
162             throw new RuntimeException("Could not create user cache", e);
163         }
164     }
165
166     @Produces
167     @ApplicationScoped
168     @PhotoCache
169     public Cache<String, ArrayList<PhotoEntry>> getPhotoCache() {
170         try {
171             InputResource cacheConfig = new ClassPathResource(
172                 "META-INF/ehcache.xml");
173             return new EhCache<String, ArrayList<PhotoEntry>>(cacheConfig,
174                 "photos");
175         } catch (IOException e) {
176             throw new RuntimeException("Could not create photo cache", e);
177         }
178     }
179
180     @Produces
181     @ApplicationScoped
182     public AuthorizationService getAuthorizationService() {
183         OperationRegistry registry = new DefaultOperationRegistry(
184             new Operation[] { new AllOperation(), new CreateOperation(),
185                 new DeleteOperation(), new ReadOperation(),
186                 new WriteOperation() });
187         UserAccessor userAccessor = new UserAccessor() {
188
189             @Override
190             public String getCurrentUser() {
191                 Principal principal = request.getUserPrincipal();
192                 if (principal == null) {
193                     return null;
194                 }
195                 return principal.getName();
196             }
197         };
198         AuthorizationService service = new JpaAuthorizationService("DEFAULT",
199             entityManager, userAccessor, userAdmin, 10000);
200
201         AnyUserCondition anyUserCondition = new AnyUserCondition();
202         GroupUserCondition adminUserCondition = new GroupUserCondition(
203             "administrators");
204
205         PhotoAuthorizationRule photoEntryRule = new PhotoAuthorizationRule();
206
207         // Pages that allow access by any authenticated user
208         PageAuthorizationRule anyUserPageRule = new PageAuthorizationRule(
209             AuthorizationResult.GRANTED, anyUserCondition, HomePage.class);
210
211         PageAuthorizationRule adminPageRule = new PageAuthorizationRule(
212             AuthorizationResult.GRANTED, adminUserCondition);
213
214         AuthorizationInitializer initializer = new AuthorizationInitializer(
215             service, new AbstractAuthorizationRule[] { photoEntryRule,
216                 anyUserPageRule, adminPageRule });
217
218         return service;
219     }
220
221     @Produces
222     @ApplicationScoped
223     @AllPhotos
224     public Album getAllPhotos() {
225         LOGGER.info("Initializing photo album");
226
227         try {
228             File dir = new File(getCOnfiguration().getPath());
229             Album fileSystemAlbum = new FileSystemAlbum(dir, "/", photoCache);
230             Album concurrentAlbum = new ConcurrentAlbum(fileSystemAlbum);
231
232             return concurrentAlbum;
233         } catch (IOException e) {
234             throw new RuntimeException("Could not initialize photo album", e);
235         }
236     }
237
238     @Produces
239     @SessionScoped
240     public User getUser() {
241         LOGGER.info("Initializing user object for current session");
242
243         Principal userPrincipal = request.getUserPrincipal();
244         if (userPrincipal == null) {
245             // CDI: cannot return null from this method.
246             throw new RuntimeException("No authenticated user");
247         }
248         String username = userPrincipal.getName();
249         List<User> users = entityManager
250             .createNamedQuery(User.QUERY_FIND_BY_NAME)
251             .setParameter(User.NAME_PARAM, username).getResultList();
252         if (users.size() > 1) {
253             throw new RuntimeException("More than one user found for '" +
254                 username + "'");
255         }
256         if (users.isEmpty()) {
257             throw new RuntimeException("No authenticated user");
258         }
259         return users.get(0);
260     }
261
262 }