From 06bf9182a5cd8b626d8e66c1fde4e8e6c722a0b5 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Sun, 15 Sep 2013 00:45:19 +0200 Subject: [PATCH] dde authorization rules and authorized album. Not working yet because authorized album is not serializable. --- src/main/java/META-INF/persistence.xml | 1 + .../model/authorization/AuthorizedAlbum.java | 38 ++++---- .../photos/model/plumbing/Producer.java | 94 ++++++++++++++++++- .../security/PageAuthorizationRule.java | 88 +++++++++++++++++ .../org/wamblee/photos/wicket/HomePage.java | 13 +++ 5 files changed, 212 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/wamblee/photos/security/PageAuthorizationRule.java diff --git a/src/main/java/META-INF/persistence.xml b/src/main/java/META-INF/persistence.xml index df1adab..1686251 100644 --- a/src/main/java/META-INF/persistence.xml +++ b/src/main/java/META-INF/persistence.xml @@ -22,6 +22,7 @@ org.wamblee.security.authorization.AbstractAuthorizationRule org.wamblee.security.authorization.UrlAuthorizationRule org.wamblee.photos.security.PhotoAuthorizationRule + org.wamblee.photos.security.PageAuthorizationRule org.wamblee.security.authorization.AbstractAuthorizationService diff --git a/src/main/java/org/wamblee/photos/model/authorization/AuthorizedAlbum.java b/src/main/java/org/wamblee/photos/model/authorization/AuthorizedAlbum.java index 7406d99..96610a6 100644 --- a/src/main/java/org/wamblee/photos/model/authorization/AuthorizedAlbum.java +++ b/src/main/java/org/wamblee/photos/model/authorization/AuthorizedAlbum.java @@ -19,8 +19,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.logging.Logger; -import org.apache.log4j.Logger; import org.wamblee.cache.Cache; import org.wamblee.cache.CachedObject; import org.wamblee.photos.model.Album; @@ -39,8 +39,8 @@ import org.wamblee.security.authorization.WriteOperation; */ public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album { - private static final Logger LOGGER = Logger - .getLogger(AuthorizedAlbum.class); + private static final Logger LOGGER = Logger.getLogger(AuthorizedAlbum.class + .getName()); private AuthorizationService _authorizer; @@ -55,16 +55,16 @@ public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album { * Album to decorate. */ public AuthorizedAlbum(Album aAlbum, AuthorizationService aService, - Cache aCache, String aSessionId) { + Cache aCache, String aSessionId) { super(aAlbum); _authorizer = aService; _authorizedEntries = new CachedObject>( - aCache, aSessionId + "/" + aAlbum.getPath(), - new CachedObject.Computation>() { - public ArrayList getObject(String aObjectKey) { - return AuthorizedAlbum.this.compute(); - } - }); + aCache, aSessionId + "/" + aAlbum.getPath(), + new CachedObject.Computation>() { + public ArrayList getObject(String aObjectKey) { + return AuthorizedAlbum.this.compute(); + } + }); _sessionId = aSessionId; } @@ -105,10 +105,10 @@ public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album { return (T) new AuthorizedPhoto((Photo) aEntry); } else if (aEntry instanceof Album) { return (T) new AuthorizedAlbum((Album) aEntry, _authorizer, - _authorizedEntries.getCache(), _sessionId); + _authorizedEntries.getCache(), _sessionId); } else { throw new IllegalArgumentException( - "Entry is neither a photo nor an album: " + aEntry); + "Entry is neither a photo nor an album: " + aEntry); } } @@ -139,8 +139,8 @@ public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album { return entry; } else { if (!(entry instanceof Album)) { - throw new IllegalArgumentException(getPath() + " " - + aPath); + throw new IllegalArgumentException(getPath() + " " + + aPath); } return ((Album) entry).getEntry(remainder); } @@ -198,15 +198,15 @@ public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album { public void removeEntry(String aId) throws IOException { // Check whether deletion is allowed. PhotoEntry entry = _authorizer.check(decorated().getEntry("/" + aId), - new DeleteOperation()); + new DeleteOperation()); _authorizedEntries.invalidate(); decorated().removeEntry(aId); } public Photo findPhotoBefore(String aId) { Photo entry = decorated().findPhotoBefore(aId); - while (entry != null - && !_authorizer.isAllowed(entry, new AllOperation())) { + while (entry != null && + !_authorizer.isAllowed(entry, new AllOperation())) { entry = decorated().findPhotoBefore(entry.getId()); } return decorate(entry); @@ -214,8 +214,8 @@ public class AuthorizedAlbum extends AuthorizedPhotoEntry implements Album { public Photo findPhotoAfter(String aId) { Photo entry = decorated().findPhotoAfter(aId); - while (entry != null - && !_authorizer.isAllowed(entry, new AllOperation())) { + while (entry != null && + !_authorizer.isAllowed(entry, new AllOperation())) { entry = decorated().findPhotoAfter(entry.getId()); } return decorate(entry); diff --git a/src/main/java/org/wamblee/photos/model/plumbing/Producer.java b/src/main/java/org/wamblee/photos/model/plumbing/Producer.java index 9ad3c14..4e5b1da 100644 --- a/src/main/java/org/wamblee/photos/model/plumbing/Producer.java +++ b/src/main/java/org/wamblee/photos/model/plumbing/Producer.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.security.Principal; import java.util.ArrayList; import java.util.List; +import java.util.logging.Logger; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.SessionScoped; @@ -28,8 +29,8 @@ import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; -import org.apache.log4j.Logger; import org.wamblee.cache.Cache; import org.wamblee.cache.EhCache; import org.wamblee.io.ClassPathResource; @@ -37,19 +38,39 @@ import org.wamblee.io.InputResource; import org.wamblee.photos.concurrent.ConcurrentAlbum; import org.wamblee.photos.model.Album; import org.wamblee.photos.model.PhotoEntry; +import org.wamblee.photos.model.authorization.AuthorizedAlbum; import org.wamblee.photos.model.filesystem.FileSystemAlbum; +import org.wamblee.photos.security.PageAuthorizationRule; +import org.wamblee.photos.security.PhotoAuthorizationRule; +import org.wamblee.photos.wicket.HomePage; import org.wamblee.security.authentication.GroupSet; import org.wamblee.security.authentication.Md5HexMessageDigester; import org.wamblee.security.authentication.MessageDigester; import org.wamblee.security.authentication.NameValidator; import org.wamblee.security.authentication.RegexpNameValidator; import org.wamblee.security.authentication.User; +import org.wamblee.security.authentication.UserAccessor; import org.wamblee.security.authentication.UserAdminInitializer; import org.wamblee.security.authentication.UserAdministration; import org.wamblee.security.authentication.UserAdministrationImpl; import org.wamblee.security.authentication.UserSet; import org.wamblee.security.authentication.jpa.JpaGroupSet; import org.wamblee.security.authentication.jpa.JpaUserSet; +import org.wamblee.security.authorization.AbstractAuthorizationRule; +import org.wamblee.security.authorization.AllOperation; +import org.wamblee.security.authorization.AnyUserCondition; +import org.wamblee.security.authorization.AuthorizationInitializer; +import org.wamblee.security.authorization.AuthorizationResult; +import org.wamblee.security.authorization.AuthorizationService; +import org.wamblee.security.authorization.CreateOperation; +import org.wamblee.security.authorization.DefaultOperationRegistry; +import org.wamblee.security.authorization.DeleteOperation; +import org.wamblee.security.authorization.GroupUserCondition; +import org.wamblee.security.authorization.Operation; +import org.wamblee.security.authorization.OperationRegistry; +import org.wamblee.security.authorization.ReadOperation; +import org.wamblee.security.authorization.WriteOperation; +import org.wamblee.security.authorization.jpa.JpaAuthorizationService; /** * @author Erik Brakkee @@ -65,9 +86,24 @@ public class Producer { @Inject private HttpServletRequest request; + @Inject + private HttpSession session; + @PersistenceContext private EntityManager entityManager; + // Created by this producer. + + @Inject + private UserAdministration userAdmin; + + @Inject + private AuthorizationService authorizationService; + + @Inject + @AllPhotos + private Album allPhotos; + private Configuration getCOnfiguration() { LOGGER.info("Initializing configuration"); Configuration config; @@ -115,6 +151,47 @@ public class Producer { } } + @Produces + @ApplicationScoped + public AuthorizationService getAuthorizationService() { + OperationRegistry registry = new DefaultOperationRegistry( + new Operation[] { new AllOperation(), new CreateOperation(), + new DeleteOperation(), new ReadOperation(), + new WriteOperation() }); + UserAccessor userAccessor = new UserAccessor() { + + @Override + public String getCurrentUser() { + Principal principal = request.getUserPrincipal(); + if (principal == null) { + return null; + } + return principal.getName(); + } + }; + AuthorizationService service = new JpaAuthorizationService("DEFAULT", + entityManager, userAccessor, userAdmin, 10000); + + AnyUserCondition anyUserCondition = new AnyUserCondition(); + GroupUserCondition adminUserCondition = new GroupUserCondition( + "administrators"); + + PhotoAuthorizationRule photoEntryRule = new PhotoAuthorizationRule(); + + // Pages that allow access by any authenticated user + PageAuthorizationRule anyUserPageRule = new PageAuthorizationRule( + AuthorizationResult.GRANTED, anyUserCondition, HomePage.class); + + PageAuthorizationRule adminPageRule = new PageAuthorizationRule( + AuthorizationResult.GRANTED, adminUserCondition); + + AuthorizationInitializer initializer = new AuthorizationInitializer( + service, new AbstractAuthorizationRule[] { photoEntryRule, + anyUserPageRule, adminPageRule }); + + return service; + } + @Produces @ApplicationScoped @AllPhotos @@ -139,10 +216,21 @@ public class Producer { @Produces @SessionScoped @AuthorizedPhotos - public Album getAuthorizedPhotos() { + public Album getAuthorizedAlbum() { LOGGER.info("Initializing authorized photos for current session"); + try { + InputResource cacheConfig = new ClassPathResource( + "META-INF/ehcache.xml"); + Cache userCache = new EhCache(cacheConfig, "users"); + Cache authorizedPhotoCache = new EhCache(cacheConfig, "photos"); - return null; + AuthorizedAlbum album = new AuthorizedAlbum(allPhotos, + authorizationService, authorizedPhotoCache, session.getId()); + return album; + } catch (IOException e) { + throw new RuntimeException("Problem initializing authorized album", + e); + } } @Produces diff --git a/src/main/java/org/wamblee/photos/security/PageAuthorizationRule.java b/src/main/java/org/wamblee/photos/security/PageAuthorizationRule.java new file mode 100644 index 0000000..b32f5df --- /dev/null +++ b/src/main/java/org/wamblee/photos/security/PageAuthorizationRule.java @@ -0,0 +1,88 @@ +/* + * Copyright 2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.wamblee.photos.security; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +import org.wamblee.photos.wicket.BasePage; +import org.wamblee.security.authorization.AllOperation; +import org.wamblee.security.authorization.AuthorizationResult; +import org.wamblee.security.authorization.IsaOperationCondition; +import org.wamblee.security.authorization.RegexpPathCondition; +import org.wamblee.security.authorization.UrlAuthorizationRule; +import org.wamblee.security.authorization.UserCondition; + +/** + * AUthorization rule for pages. + */ +@Entity +@DiscriminatorValue("PAGE") +public class PageAuthorizationRule extends UrlAuthorizationRule { + + /** + * Type-safe construction of page authorization rule. + * + * @param aResult + * Result. + * @param aUserCondition + * User condition. + * @param aPageList + * A list of page names. + */ + public PageAuthorizationRule(AuthorizationResult aResult, + UserCondition aUserCondition, Class... aPageList) { + super(aResult, aUserCondition, new RegexpPathCondition( + getPageRegex(aPageList)), BasePage.class, + new IsaOperationCondition(AllOperation.class)); + } + + /** + * Converts a list of page names into a regular expression for the pages. + * + * @param aPageList + * List of pages. + * @return Regexp matching any of the given pagenames. + */ + private static String getPageRegex(Class[] aPageList) { + String result = ""; + for (int i = 0; i < aPageList.length; i++) { + if (result.length() == 0) { + result = "/" + aPageList[i].getSimpleName(); + } else { + result = result + "|/" + aPageList[i].getSimpleName(); + } + } + return result; + } + + /** + * Constructor for OR mapping. + */ + protected PageAuthorizationRule() { + super(); + } + + /* (non-Javadoc) + * @see org.wamblee.security.authorization.UrlAuthorizationRule#getResourcePath(java.lang.Object) + */ + @Override + protected String getResourcePath(Object aResource) { + BasePage page = (BasePage) aResource; + return "/" + page.getClass().getSimpleName(); + } +} diff --git a/src/main/java/org/wamblee/photos/wicket/HomePage.java b/src/main/java/org/wamblee/photos/wicket/HomePage.java index a6126b7..ccb6670 100644 --- a/src/main/java/org/wamblee/photos/wicket/HomePage.java +++ b/src/main/java/org/wamblee/photos/wicket/HomePage.java @@ -44,6 +44,10 @@ public class HomePage extends BasePage { @AllPhotos private Album album; + // @Inject + // @AuthorizedPhotos + // private Album authorized; + /** * Constructor that is invoked when page is invoked without a session. * @@ -68,5 +72,14 @@ public class HomePage extends BasePage { System.out.println("Entry " + i + " " + entry.getId() + " " + entry.getPath()); } + + /* + System.out.println("Authorized Entries: " + authorized.size()); + for (int i = 0; i < authorized.size(); i++) { + PhotoEntry entry = authorized.getEntry(i); + System.out.println("Entry " + i + " " + entry.getId() + " " + + entry.getPath()); + } + */ } } -- 2.31.1