From 42c39b585d59aca9b2d6dca9d08c63a6e2806102 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 6 Nov 2007 18:26:04 +0000 Subject: [PATCH] [MRM-516] Search results return results for all repositories, regardless of security. [MRM-569] Browse shows results for all repositories, regardless of security. Merge of https://svn.apache.org/repos/asf/maven/archiva/branches/archiva-backend-security changes from revision 590763 to HEAD git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@592513 13f79535-47bb-0310-9956-ffa450edef68 --- .../indexer/search/CrossRepositorySearch.java | 8 +- .../search/DefaultCrossRepositorySearch.java | 140 ++++++---- .../search/BytecodeIndexPopulator.java | 19 +- .../DefaultCrossRepositorySearchTest.java | 79 ++++-- .../search/FileContentIndexPopulator.java | 7 +- .../search/HashcodesIndexPopulator.java | 44 ++- .../indexer/search/IndexPopulator.java | 7 +- .../DefaultCrossRepositorySearchTest.xml | 26 +- .../archiva/database/ProjectModelDAO.java | 2 +- .../database/browsing/BrowsingResults.java | 34 ++- .../browsing/DefaultRepositoryBrowsing.java | 80 +++--- .../database/browsing/GroupIdFilter.java | 25 +- .../database/browsing/RepositoryBrowsing.java | 15 +- .../database/constraints/SqlBuilder.java | 80 ++++++ .../UniqueArtifactIdConstraint.java | 47 +++- .../constraints/UniqueGroupIdConstraint.java | 53 +++- .../constraints/UniqueVersionConstraint.java | 60 +++- .../database/jdo/JdoProjectModelDAO.java | 2 +- .../browsing/RepositoryBrowsingTest.java | 18 +- .../UniqueGroupIdConstraintTest.java | 258 +++++++++++++++--- .../UniqueVersionConstraintTest.java | 149 +++++++--- archiva-web/archiva-security/pom.xml | 26 +- .../security/AccessDeniedException.java | 23 +- .../security/ArchivaRoleConstants.java | 15 + .../security/ArchivaSecurityException.java | 42 +++ .../security/ArchivaStandardRolesCheck.java | 103 +++++++ .../maven/archiva/security/ArchivaUser.java | 36 +++ .../security/DefaultUserRepositories.java | 135 +++++++++ .../security/PrincipalNotFoundException.java | 40 +++ .../archiva/security/SecurityStartup.java | 206 ++++++++++++++ .../archiva/security/UserRepositories.java | 52 ++++ .../security/DefaultUserRepositoriesTest.java | 175 ++++++++++++ .../archiva/security/SecurityStartupTest.java | 31 ++- .../META-INF/redback/redback-core.xml | 195 +++++++++++++ .../security/DefaultUserRepositoriesTest.xml | 193 +++++++++++++ .../archiva/security/RoleManagerTest.xml | 43 ++- .../archiva/security/SecurityStartupTest.xml | 210 ++++++++++++++ .../src/test/resources/repository-archiva.xml | 111 ++++++++ .../archiva/web/action/BrowseAction.java | 72 ++++- .../archiva/web/action/GlobalResults.java | 31 +++ .../archiva/web/action/SearchAction.java | 59 +++- .../web/action/ShowArtifactAction.java | 55 +++- .../web/startup/SecuritySynchronization.java | 7 +- .../archiva/web/util/ArchivaXworkUser.java | 77 ++++++ .../src/main/resources/xwork.xml | 2 + .../webapp/WEB-INF/jsp/accessToNoRepos.jsp | 46 ++++ pom.xml | 33 ++- 47 files changed, 2823 insertions(+), 348 deletions(-) create mode 100644 archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/SqlBuilder.java rename archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/AllTests.java => archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java (67%) create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaUser.java create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java create mode 100644 archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java create mode 100644 archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java rename archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/AllTests.java => archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java (56%) create mode 100644 archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml create mode 100644 archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml create mode 100644 archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml create mode 100644 archiva-web/archiva-security/src/test/resources/repository-archiva.xml create mode 100644 archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/GlobalResults.java create mode 100644 archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ArchivaXworkUser.java create mode 100644 archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/accessToNoRepos.jsp diff --git a/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java b/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java index 647e572fb..bf560d1a2 100644 --- a/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java +++ b/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java @@ -1,5 +1,7 @@ package org.apache.maven.archiva.indexer.search; +import java.util.List; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -35,7 +37,7 @@ public interface CrossRepositorySearch * @param limits the limits to apply to the search results. * @return the results. */ - public SearchResults searchForTerm( String term, SearchResultLimits limits ); + public SearchResults searchForTerm( String principal, List selectedRepos, String term, SearchResultLimits limits ); /** * Search for the specific bytecode across all repositories. @@ -44,7 +46,7 @@ public interface CrossRepositorySearch * @param limits the limits to apply to the search results. * @return the results. */ - public SearchResults searchForBytecode( String term, SearchResultLimits limits ); + public SearchResults searchForBytecode( String principal, List selectedRepos, String term, SearchResultLimits limits ); /** * Search for the specific checksum string across all repositories. @@ -53,5 +55,5 @@ public interface CrossRepositorySearch * @param limits the limits to apply to the search results. * @return the results. */ - public SearchResults searchForChecksum( String checksum, SearchResultLimits limits ); + public SearchResults searchForChecksum( String principal, List selectedRepos, String checksum, SearchResultLimits limits ); } diff --git a/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java b/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java index 3021ab2a5..2b67d9caa 100644 --- a/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java +++ b/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java @@ -33,6 +33,9 @@ import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.indexer.RepositoryContentIndex; +import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory; +import org.apache.maven.archiva.indexer.RepositoryIndexException; +import org.apache.maven.archiva.indexer.RepositoryIndexSearchException; import org.apache.maven.archiva.indexer.bytecode.BytecodeHandlers; import org.apache.maven.archiva.indexer.filecontent.FileContentHandlers; import org.apache.maven.archiva.indexer.functors.UserAllowedToSearchRepositoryPredicate; @@ -63,40 +66,20 @@ public class DefaultCrossRepositorySearch implements CrossRepositorySearch, RegistryListener, Initializable { /** - * @plexus.requirement role-hint="bytecode" + * @plexus.requirement role-hint="lucene" */ - private Transformer bytecodeIndexTransformer; - - /** - * @plexus.requirement role-hint="filecontent" - */ - private Transformer filecontentIndexTransformer; - - /** - * @plexus.requirement role-hint="hashcodes" - */ - private Transformer hashcodesIndexTransformer; - - /** - * @plexus.requirement role-hint="searchable" - */ - private Transformer searchableTransformer; - - /** - * @plexus.requirement role-hint="index-exists" - */ - private Predicate indexExistsPredicate; - + private RepositoryContentIndexFactory indexFactory; + /** * @plexus.requirement */ private ArchivaConfiguration configuration; - private List localIndexedRepositories = new ArrayList(); + private List localIndexedRepositories = new ArrayList(); - public SearchResults searchForChecksum( String checksum, SearchResultLimits limits ) + public SearchResults searchForChecksum( String principal, List selectedRepos, String checksum, SearchResultLimits limits ) { - List indexes = getHashcodeIndexes(); + List indexes = getHashcodeIndexes( principal, selectedRepos ); try { @@ -117,9 +100,9 @@ public class DefaultCrossRepositorySearch return new SearchResults(); } - public SearchResults searchForBytecode( String term, SearchResultLimits limits ) + public SearchResults searchForBytecode( String principal, List selectedRepos, String term, SearchResultLimits limits ) { - List indexes = getHashcodeIndexes(); + List indexes = getHashcodeIndexes( principal, selectedRepos ); try { @@ -139,9 +122,9 @@ public class DefaultCrossRepositorySearch return new SearchResults(); } - public SearchResults searchForTerm( String term, SearchResultLimits limits ) + public SearchResults searchForTerm( String principal, List selectedRepos, String term, SearchResultLimits limits ) { - List indexes = getFileContentIndexes(); + List indexes = getFileContentIndexes( principal, selectedRepos ); try { @@ -161,7 +144,7 @@ public class DefaultCrossRepositorySearch return new SearchResults(); } - private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List indexes ) + private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List indexes ) { org.apache.lucene.search.Query specificQuery = luceneQuery.getLuceneQuery(); @@ -175,12 +158,11 @@ public class DefaultCrossRepositorySearch // Setup the converter LuceneEntryConverter converter = null; - RepositoryContentIndex index = (RepositoryContentIndex) indexes.get( 0 ); + RepositoryContentIndex index = indexes.get( 0 ); converter = index.getEntryConverter(); // Process indexes into an array of Searchables. - List searchableList = new ArrayList( indexes ); - CollectionUtils.transform( searchableList, searchableTransformer ); + List searchableList = toSearchables( indexes ); Searchable searchables[] = new Searchable[searchableList.size()]; searchableList.toArray( searchables ); @@ -258,52 +240,102 @@ public class DefaultCrossRepositorySearch return results; } - private Predicate getAllowedToSearchReposPredicate() + private List toSearchables( List indexes ) { - return new UserAllowedToSearchRepositoryPredicate(); + List searchableList = new ArrayList(); + for ( RepositoryContentIndex contentIndex : indexes ) + { + try + { + searchableList.add( contentIndex.getSearchable() ); + } + catch ( RepositoryIndexSearchException e ) + { + getLogger().warn( "Unable to get searchable for index [" + contentIndex.getId() + "] :" + + e.getMessage(), e ); + } + } + return searchableList; } - public List getBytecodeIndexes() + public List getBytecodeIndexes( String principal, List selectedRepos ) { - List ret = new ArrayList(); + List ret = new ArrayList(); - synchronized ( this.localIndexedRepositories ) + for ( ManagedRepositoryConfiguration repoConfig : localIndexedRepositories ) { - ret.addAll( CollectionUtils.select( this.localIndexedRepositories, getAllowedToSearchReposPredicate() ) ); - CollectionUtils.transform( ret, bytecodeIndexTransformer ); - CollectionUtils.filter( ret, indexExistsPredicate ); + // Only used selected repo + if ( selectedRepos.contains( repoConfig.getId() ) ) + { + RepositoryContentIndex index = indexFactory.createBytecodeIndex( repoConfig ); + // If they exist. + if ( indexExists( index ) ) + { + ret.add( index ); + } + } } return ret; } - public List getFileContentIndexes() + public List getFileContentIndexes( String principal, List selectedRepos ) { - List ret = new ArrayList(); + List ret = new ArrayList(); - synchronized ( this.localIndexedRepositories ) + for ( ManagedRepositoryConfiguration repoConfig : localIndexedRepositories ) { - ret.addAll( CollectionUtils.select( this.localIndexedRepositories, getAllowedToSearchReposPredicate() ) ); - CollectionUtils.transform( ret, filecontentIndexTransformer ); - CollectionUtils.filter( ret, indexExistsPredicate ); + // Only used selected repo + if ( selectedRepos.contains( repoConfig.getId() ) ) + { + RepositoryContentIndex index = indexFactory.createFileContentIndex( repoConfig ); + // If they exist. + if ( indexExists( index ) ) + { + ret.add( index ); + } + } } return ret; } - public List getHashcodeIndexes() + public List getHashcodeIndexes( String principal, List selectedRepos ) { - List ret = new ArrayList(); + List ret = new ArrayList(); - synchronized ( this.localIndexedRepositories ) + for ( ManagedRepositoryConfiguration repoConfig : localIndexedRepositories ) { - ret.addAll( CollectionUtils.select( this.localIndexedRepositories, getAllowedToSearchReposPredicate() ) ); - CollectionUtils.transform( ret, hashcodesIndexTransformer ); - CollectionUtils.filter( ret, indexExistsPredicate ); + // Only used selected repo + if ( selectedRepos.contains( repoConfig.getId() ) ) + { + RepositoryContentIndex index = indexFactory.createHashcodeIndex( repoConfig ); + // If they exist. + if ( indexExists( index ) ) + { + ret.add( index ); + } + } } return ret; } + + private boolean indexExists( RepositoryContentIndex index ) + { + try + { + return index.exists(); + } + catch ( RepositoryIndexException e ) + { + getLogger().info( + "Repository Content Index [" + index.getId() + "] for repository [" + + index.getRepository().getId() + "] does not exist yet in [" + + index.getIndexDirectory().getAbsolutePath() + "]." ); + return false; + } + } public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) { diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/BytecodeIndexPopulator.java b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/BytecodeIndexPopulator.java index eec1a08d5..4587ef7a7 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/BytecodeIndexPopulator.java +++ b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/BytecodeIndexPopulator.java @@ -19,15 +19,16 @@ package org.apache.maven.archiva.indexer.search; * under the License. */ -import junit.framework.AssertionFailedError; import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord; import org.apache.maven.archiva.indexer.bytecode.BytecodeRecordLoader; import org.apache.maven.archiva.model.ArchivaArtifact; import java.io.File; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; + +import junit.framework.AssertionFailedError; /** * BytecodeIndexPopulator @@ -39,10 +40,10 @@ public class BytecodeIndexPopulator implements IndexPopulator { - public Map getObjectMap() + public Map getObjectMap() { - Map dumps = new HashMap(); + Map dumps = new HashMap(); // archiva-common-1.0.jar.txt dumps.put( "archiva-common", @@ -86,15 +87,13 @@ public class BytecodeIndexPopulator return artifact; } - public Map populate( File basedir ) + public Map populate( File basedir ) { - Map records = new HashMap(); + Map records = new HashMap(); - Map artifactDumps = getObjectMap(); - for ( Iterator iter = artifactDumps.entrySet().iterator(); iter.hasNext(); ) + for ( Entry entry : getObjectMap().entrySet() ) { - Map.Entry entry = (Map.Entry) iter.next(); - ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue(); + ArchivaArtifact artifact = entry.getValue(); File dumpFile = getDumpFile( basedir, artifact ); BytecodeRecord record = BytecodeRecordLoader.loadRecord( dumpFile, artifact ); record.setRepositoryId( "test-repo" ); diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java index fef16cba7..cee75ec0a 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java +++ b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java @@ -28,10 +28,16 @@ import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.indexer.MockConfiguration; import org.apache.maven.archiva.indexer.RepositoryContentIndex; import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory; +import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord; +import org.apache.maven.archiva.indexer.filecontent.FileContentRecord; +import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecord; import org.codehaus.plexus.PlexusTestCase; import org.codehaus.plexus.util.FileUtils; import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; /** @@ -47,6 +53,7 @@ public class DefaultCrossRepositorySearchTest private static final String TEST_DEFAULT_REPO_ID = "testDefaultRepo"; + @Override protected void setUp() throws Exception { @@ -86,17 +93,17 @@ public class DefaultCrossRepositorySearchTest RepositoryContentIndex indexContents = indexFactory.createFileContentIndex( repository ); // Now populate them. - Map hashcodesMap = ( new HashcodesIndexPopulator() ).populate( new File( getBasedir() ) ); + Map hashcodesMap = new HashcodesIndexPopulator().populate( new File( getBasedir() ) ); indexHashcode.indexRecords( hashcodesMap.values() ); assertEquals( "Hashcode Key Count", hashcodesMap.size(), indexHashcode.getAllRecordKeys().size() ); assertRecordCount( indexHashcode, hashcodesMap.size() ); - Map bytecodeMap = ( new BytecodeIndexPopulator() ).populate( new File( getBasedir() ) ); + Map bytecodeMap = new BytecodeIndexPopulator().populate( new File( getBasedir() ) ); indexBytecode.indexRecords( bytecodeMap.values() ); assertEquals( "Bytecode Key Count", bytecodeMap.size(), indexBytecode.getAllRecordKeys().size() ); assertRecordCount( indexBytecode, bytecodeMap.size() ); - Map contentMap = ( new FileContentIndexPopulator() ).populate( new File( getBasedir() ) ); + Map contentMap = new FileContentIndexPopulator().populate( new File( getBasedir() ) ); indexContents.indexRecords( contentMap.values() ); assertEquals( "File Content Key Count", contentMap.size(), indexContents.getAllRecordKeys().size() ); assertRecordCount( indexContents, contentMap.size() ); @@ -125,23 +132,31 @@ public class DefaultCrossRepositorySearchTest { CrossRepositorySearch search = lookupCrossRepositorySearch(); - SearchResultLimits limits = new SearchResultLimits( 0 ); - limits.setPageSize( 20 ); - - SearchResults results = search.searchForTerm( "org", limits ); - assertResults( 1, 7, results ); + String expectedRepos[] = new String[] { + TEST_DEFAULT_REPO_ID + }; + + String expectedResults[] = new String[] { + "org","org2","org3","org4","org5","org6","org7" + }; + + assertSearchResults( expectedRepos, expectedResults, search, "org" ); } public void testSearchTerm_Junit() throws Exception { CrossRepositorySearch search = lookupCrossRepositorySearch(); - - SearchResultLimits limits = new SearchResultLimits( 0 ); - limits.setPageSize( 20 ); - - SearchResults results = search.searchForTerm( "junit", limits ); - assertResults( 1, 3, results ); + + String expectedRepos[] = new String[] { + TEST_DEFAULT_REPO_ID + }; + + String expectedResults[] = new String[] { + "junit","junit2","junit3" + }; + + assertSearchResults( expectedRepos, expectedResults, search, "junit" ); } public void testSearchInvalidTerm() @@ -149,21 +164,37 @@ public class DefaultCrossRepositorySearchTest { CrossRepositorySearch search = lookupCrossRepositorySearch(); - SearchResultLimits limits = new SearchResultLimits( 0 ); - limits.setPageSize( 20 ); - - SearchResults results = search.searchForTerm( "monosodium", limits ); - assertResults( 1, 0, results ); + String expectedRepos[] = new String[] { + TEST_DEFAULT_REPO_ID + }; + + String expectedResults[] = new String[] { + // Nothing. + }; + + assertSearchResults( expectedRepos, expectedResults, search, "monosodium" ); } - - private void assertResults( int repoCount, int hitCount, SearchResults results ) + + private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search, String term ) + throws Exception { + SearchResultLimits limits = new SearchResultLimits( 0 ); + limits.setPageSize( 20 ); + + List selectedRepos = new ArrayList(); + selectedRepos.addAll( Arrays.asList( expectedRepos ) ); + + SearchResults results = search.searchForTerm( "guest", selectedRepos, term, limits ); + assertNotNull( "Search Results should not be null.", results ); - assertEquals( "Repository Hits", repoCount, results.getRepositories().size() ); + assertEquals( "Repository Hits", expectedRepos.length, results.getRepositories().size() ); + // TODO: test the repository ids returned. - assertEquals( "Search Result Hits", hitCount, results.getHits().size() ); + assertEquals( "Search Result Hits", expectedResults.length, results.getHits().size() ); + // TODO: test the order of hits. + // TODO: test the value of the hits. } - + protected ManagedRepositoryConfiguration createRepository( String id, String name, File location ) { ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration(); diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java index d9b1c3846..326061d56 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java +++ b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/FileContentIndexPopulator.java @@ -21,6 +21,7 @@ package org.apache.maven.archiva.indexer.search; import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.indexer.filecontent.FileContentRecord; +import org.apache.maven.archiva.model.ArchivaArtifact; import java.io.File; import java.io.IOException; @@ -38,14 +39,14 @@ import junit.framework.AssertionFailedError; public class FileContentIndexPopulator implements IndexPopulator { - public Map getObjectMap() + public Map getObjectMap() { return null; } - public Map populate( File basedir ) + public Map populate( File basedir ) { - Map map = new HashMap(); + Map map = new HashMap(); File repoDir = new File( basedir, "src/test/managed-repository" ); diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/HashcodesIndexPopulator.java b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/HashcodesIndexPopulator.java index 4fa9f6034..6dcb146a6 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/HashcodesIndexPopulator.java +++ b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/HashcodesIndexPopulator.java @@ -1,22 +1,48 @@ package org.apache.maven.archiva.indexer.search; -import junit.framework.AssertionFailedError; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecord; import org.apache.maven.archiva.indexer.hashcodes.HashcodesRecordLoader; import org.apache.maven.archiva.model.ArchivaArtifact; import java.io.File; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; + +import junit.framework.AssertionFailedError; +/** + * HashcodesIndexPopulator + * + * @author Joakim Erdfelt + * @version $Id$ + */ public class HashcodesIndexPopulator implements IndexPopulator { - public Map getObjectMap() + public Map getObjectMap() { - Map dumps = new HashMap(); + Map dumps = new HashMap(); // archiva-common-1.0.jar.txt dumps.put( "archiva-common", @@ -52,15 +78,13 @@ public class HashcodesIndexPopulator return dumps; } - public Map populate( File basedir ) + public Map populate( File basedir ) { - Map records = new HashMap(); + Map records = new HashMap(); - Map artifactDumps = getObjectMap(); - for ( Iterator iter = artifactDumps.entrySet().iterator(); iter.hasNext(); ) + for ( Entry entry : getObjectMap().entrySet() ) { - Map.Entry entry = (Map.Entry) iter.next(); - ArchivaArtifact artifact = (ArchivaArtifact) entry.getValue(); + ArchivaArtifact artifact = entry.getValue(); File dumpFile = getDumpFile( basedir, artifact ); HashcodesRecord record = HashcodesRecordLoader.loadRecord( dumpFile, artifact ); record.setRepositoryId( "test-repo" ); diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/IndexPopulator.java b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/IndexPopulator.java index a483f717c..6f4892dac 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/IndexPopulator.java +++ b/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/IndexPopulator.java @@ -19,6 +19,9 @@ package org.apache.maven.archiva.indexer.search; * under the License. */ +import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord; +import org.apache.maven.archiva.model.ArchivaArtifact; + import java.io.File; import java.util.Map; @@ -30,7 +33,7 @@ import java.util.Map; */ public interface IndexPopulator { - public Map getObjectMap(); + public Map getObjectMap(); - public Map populate( File basedir ); + public Map populate( File basedir ); } diff --git a/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.xml b/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.xml index 4b078f6a8..61a859c7a 100644 --- a/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.xml +++ b/archiva-base/archiva-indexer/src/test/resources/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.xml @@ -25,29 +25,9 @@ DefaultCrossRepositorySearch - org.apache.commons.collections.Transformer - bytecode - bytecodeIndexTransformer - - - org.apache.commons.collections.Transformer - filecontent - filecontentIndexTransformer - - - org.apache.commons.collections.Transformer - hashcodes - hashcodesIndexTransformer - - - org.apache.commons.collections.Transformer - searchable - searchableTransformer - - - org.apache.commons.collections.Predicate - index-exists - indexExistsPredicate + org.apache.maven.archiva.indexer.RepositoryContentIndexFactory + lucene + indexFactory org.apache.maven.archiva.configuration.ArchivaConfiguration diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/ProjectModelDAO.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/ProjectModelDAO.java index 318e4a4ad..492d6d7bf 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/ProjectModelDAO.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/ProjectModelDAO.java @@ -57,7 +57,7 @@ public interface ProjectModelDAO public ArchivaProjectModel getProjectModel( String groupId, String artifactId, String version ) throws ObjectNotFoundException, ArchivaDatabaseException; - public List /**/queryProjectModels( Constraint constraint ) + public List queryProjectModels( Constraint constraint ) throws ObjectNotFoundException, ArchivaDatabaseException; public ArchivaProjectModel saveProjectModel( ArchivaProjectModel model ) diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/BrowsingResults.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/BrowsingResults.java index 6cc7f8a7e..ccf526662 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/BrowsingResults.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/BrowsingResults.java @@ -32,14 +32,16 @@ import java.util.List; public class BrowsingResults { private String selectedGroupId; - + private String selectedArtifactId; - private List groupIds = null; + private List selectedRepositoryIds = null; + + private List groupIds = null; - private List artifacts = null; + private List artifacts = null; - private List versions = null; + private List versions = null; public BrowsingResults() { @@ -50,19 +52,19 @@ public class BrowsingResults { this.selectedGroupId = groupId; } - + public BrowsingResults( String groupId, String artifactId ) { this.selectedGroupId = groupId; this.selectedArtifactId = artifactId; } - public List getArtifacts() + public List getArtifacts() { return artifacts; } - public List getGroupIds() + public List getGroupIds() { return groupIds; } @@ -77,7 +79,7 @@ public class BrowsingResults return selectedGroupId; } - public List getVersions() + public List getVersions() { return versions; } @@ -97,18 +99,28 @@ public class BrowsingResults return CollectionUtils.isNotEmpty( versions ); } - public void setArtifacts( List artifacts ) + public void setArtifacts( List artifacts ) { this.artifacts = artifacts; } - public void setGroupIds( List groupIds ) + public void setGroupIds( List groupIds ) { this.groupIds = groupIds; } - public void setVersions( List versions ) + public void setVersions( List versions ) { this.versions = versions; } + + public List getSelectedRepositoryIds() + { + return selectedRepositoryIds; + } + + public void setSelectedRepositoryIds( List selectedRepositoryIds ) + { + this.selectedRepositoryIds = selectedRepositoryIds; + } } diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java index c3b1058ca..6249352a0 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/DefaultRepositoryBrowsing.java @@ -22,6 +22,8 @@ package org.apache.maven.archiva.database.browsing; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.PredicateUtils; import org.apache.commons.collections.functors.NotPredicate; +import org.apache.commons.lang.StringUtils; +import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.database.ArchivaDAO; import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.database.ObjectNotFoundException; @@ -32,14 +34,14 @@ import org.apache.maven.archiva.database.constraints.UniqueVersionConstraint; import org.apache.maven.archiva.database.updater.DatabaseUpdater; import org.apache.maven.archiva.model.ArchivaArtifact; import org.apache.maven.archiva.model.ArchivaProjectModel; -import org.apache.maven.archiva.common.utils.VersionUtil; +import org.apache.maven.archiva.model.Keys; import org.codehaus.plexus.logging.AbstractLogEnabled; import java.util.Collections; +import java.util.HashMap; import java.util.List; -import java.util.Iterator; import java.util.Map; -import java.util.HashMap; +import java.util.Map.Entry; /** * DefaultRepositoryBrowsing @@ -62,23 +64,26 @@ public class DefaultRepositoryBrowsing */ private DatabaseUpdater dbUpdater; - public BrowsingResults getRoot() + public BrowsingResults getRoot( String principle, List observableRepositoryIds ) { - List groups = dao.query( new UniqueGroupIdConstraint() ); + List groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds ) ); BrowsingResults results = new BrowsingResults(); + results.setSelectedRepositoryIds( observableRepositoryIds ); results.setGroupIds( GroupIdFilter.filterGroups( groups ) ); return results; } - public BrowsingResults selectArtifactId( String groupId, String artifactId ) + public BrowsingResults selectArtifactId( String principle, List observableRepositoryIds, String groupId, + String artifactId ) { // NOTE: No group Id or artifact Id's should be returned here. - List versions = dao.query( new UniqueVersionConstraint( groupId, artifactId ) ); + List versions = dao.query( new UniqueVersionConstraint( observableRepositoryIds, groupId, artifactId ) ); BrowsingResults results = new BrowsingResults( groupId, artifactId ); + results.setSelectedRepositoryIds( observableRepositoryIds ); processSnapshots( versions ); @@ -87,10 +92,10 @@ public class DefaultRepositoryBrowsing return results; } - public BrowsingResults selectGroupId( String groupId ) + public BrowsingResults selectGroupId( String principle, List observableRepositoryIds, String groupId ) { - List groups = dao.query( new UniqueGroupIdConstraint( groupId ) ); - List artifacts = dao.query( new UniqueArtifactIdConstraint( groupId ) ); + List groups = dao.query( new UniqueGroupIdConstraint( observableRepositoryIds, groupId ) ); + List artifacts = dao.query( new UniqueArtifactIdConstraint( observableRepositoryIds, groupId ) ); BrowsingResults results = new BrowsingResults( groupId ); @@ -104,10 +109,11 @@ public class DefaultRepositoryBrowsing return results; } - public ArchivaProjectModel selectVersion( String groupId, String artifactId, String version ) + public ArchivaProjectModel selectVersion( String principle, List observableRepositoryIds, String groupId, + String artifactId, String version ) throws ObjectNotFoundException, ArchivaDatabaseException { - ArchivaArtifact pomArtifact = getArtifact( groupId, artifactId, version ); + ArchivaArtifact pomArtifact = getArtifact( principle, observableRepositoryIds, groupId, artifactId, version ); ArchivaProjectModel model; version = pomArtifact.getVersion(); @@ -123,7 +129,8 @@ public class DefaultRepositoryBrowsing return model; } - private ArchivaArtifact getArtifact( String groupId, String artifactId, String version ) + private ArchivaArtifact getArtifact( String principle, List observableRepositoryIds, String groupId, + String artifactId, String version ) throws ObjectNotFoundException, ArchivaDatabaseException { ArchivaArtifact pomArtifact = null; @@ -139,18 +146,30 @@ public class DefaultRepositoryBrowsing if ( pomArtifact == null ) { - throw new ObjectNotFoundException( - "Unable to find artifact [" + groupId + ":" + artifactId + ":" + version + "]" ); + throw new ObjectNotFoundException( "Unable to find artifact [" + Keys.toKey( groupId, artifactId, version ) + + "]" ); + } + + // Allowed to see this? + if ( observableRepositoryIds.contains( pomArtifact.getModel().getRepositoryId() ) ) + { + return pomArtifact; + } + else + { + throw new ObjectNotFoundException( "Unable to find artifact " + Keys.toKey( groupId, artifactId, version ) + + " in observable repository [" + StringUtils.join( observableRepositoryIds.iterator(), ", " ) + + "] for user " + principle ); } - return pomArtifact; } - public List getUsedBy( String groupId, String artifactId, String version ) + public List getUsedBy( String principle, List observableRepositoryIds, String groupId, + String artifactId, String version ) throws ArchivaDatabaseException { - ProjectsByArtifactUsageConstraint constraint = - new ProjectsByArtifactUsageConstraint( groupId, artifactId, version ); - List results = dao.getProjectModelDAO().queryProjectModels( constraint ); + ProjectsByArtifactUsageConstraint constraint = new ProjectsByArtifactUsageConstraint( groupId, artifactId, + version ); + List results = dao.getProjectModelDAO().queryProjectModels( constraint ); if ( results == null ) { // defensive. to honor contract as specified. never null. @@ -178,15 +197,14 @@ public class DefaultRepositoryBrowsing * * @param versions */ - private void processSnapshots( List versions ) + private void processSnapshots( List versions ) { - Map snapshots = new HashMap(); + Map snapshots = new HashMap(); getLogger().info( "Processing snapshots." ); - for ( Iterator iter = versions.iterator(); iter.hasNext(); ) + for ( String version : versions ) { - String version = (String) iter.next(); if ( VersionUtil.isSnapshot( version ) ) { String baseVersion = VersionUtil.getBaseVersion( version ); @@ -197,9 +215,9 @@ public class DefaultRepositoryBrowsing } } - for ( Iterator it = ( snapshots.entrySet() ).iterator(); it.hasNext(); ) + for ( Entry entry : snapshots.entrySet() ) { - String baseVersion = (String) ( (Map.Entry) it.next() ).getValue(); + String baseVersion = entry.getValue(); if ( !versions.contains( baseVersion ) ) { versions.add( baseVersion ); @@ -227,14 +245,12 @@ public class DefaultRepositoryBrowsing { if ( VersionUtil.isGenericSnapshot( version ) ) { - List versions = dao.query( new UniqueVersionConstraint( groupId, artifactId ) ); + List versions = dao.query( new UniqueVersionConstraint( groupId, artifactId ) ); Collections.sort( versions ); Collections.reverse( versions ); - for ( Iterator iter = versions.iterator(); iter.hasNext(); ) + for ( String uniqueVersion : versions ) { - String uniqueVersion = (String) iter.next(); - if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) ) { getLogger().info( "Retrieving artifact with version " + uniqueVersion ); @@ -266,8 +282,8 @@ public class DefaultRepositoryBrowsing if ( model == null ) { - throw new ObjectNotFoundException( - "Unable to find project model for [" + groupId + ":" + artifactId + ":" + version + "]" ); + throw new ObjectNotFoundException( "Unable to find project model for [" + + Keys.toKey( groupId, artifactId, version ) + "]" ); } return model; diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/GroupIdFilter.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/GroupIdFilter.java index 27f14e0da..18b7bdba5 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/GroupIdFilter.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/GroupIdFilter.java @@ -20,7 +20,6 @@ package org.apache.maven.archiva.database.browsing; */ import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -77,21 +76,19 @@ public class GroupIdFilter * @param groups the list of groupIds. * @return */ - public static List filterGroups( List groups ) + public static List filterGroups( List groups ) { GroupTreeNode tree = buildGroupTree( groups ); return collateGroups( tree ); } - public static GroupTreeNode buildGroupTree( List groups ) + public static GroupTreeNode buildGroupTree( List groups ) { GroupTreeNode rootNode = new GroupTreeNode(); // build a tree structure - for ( Iterator i = groups.iterator(); i.hasNext(); ) + for ( String groupId : groups ) { - String groupId = (String) i.next(); - StringTokenizer tok = new StringTokenizer( groupId, GROUP_SEPARATOR ); GroupTreeNode node = rootNode; @@ -108,7 +105,7 @@ public class GroupIdFilter } else { - node = (GroupTreeNode) node.getChildren().get( part ); + node = node.getChildren().get( part ); } } } @@ -116,16 +113,14 @@ public class GroupIdFilter return rootNode; } - private static List collateGroups( GroupTreeNode rootNode ) + private static List collateGroups( GroupTreeNode rootNode ) { - List groups = new ArrayList(); - for ( Iterator i = rootNode.getChildren().values().iterator(); i.hasNext(); ) + List groups = new ArrayList(); + for ( GroupTreeNode node : rootNode.getChildren().values() ) { - GroupTreeNode node = (GroupTreeNode) i.next(); - while ( node.getChildren().size() == 1 ) { - node = (GroupTreeNode) node.getChildren().values().iterator().next(); + node = node.getChildren().values().iterator().next(); } groups.add( node.getFullName() ); @@ -139,7 +134,7 @@ public class GroupIdFilter private final String fullName; - private final Map children = new TreeMap(); + private final Map children = new TreeMap(); GroupTreeNode() { @@ -163,7 +158,7 @@ public class GroupIdFilter return fullName; } - public Map getChildren() + public Map getChildren() { return children; } diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java index d8efa48b1..4cea46941 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsing.java @@ -38,7 +38,7 @@ public interface RepositoryBrowsing * * @return the root browsing results. */ - public BrowsingResults getRoot(); + public BrowsingResults getRoot( String principle, List observableRepositoryIds ); /** * Get the {@link BrowsingResults} for the selected groupId. @@ -46,7 +46,7 @@ public interface RepositoryBrowsing * @param groupId the groupId to select. * @return the {@link BrowsingResults} for the specified groupId. */ - public BrowsingResults selectGroupId( String groupId ); + public BrowsingResults selectGroupId( String principle, List observableRepositoryIds, String groupId ); /** * Get the {@link BrowsingResults} for the selected groupId & artifactId. @@ -55,7 +55,8 @@ public interface RepositoryBrowsing * @param artifactId the artifactId selected * @return the {@link BrowsingResults} for the specified groupId / artifactId combo. */ - public BrowsingResults selectArtifactId( String groupId, String artifactId ); + public BrowsingResults selectArtifactId( String principle, List observableRepositoryIds, String groupId, + String artifactId ); /** * Get the {@link ArchivaProjectModel} for the selected groupId / artifactId / version combo. @@ -67,9 +68,10 @@ public interface RepositoryBrowsing * @throws ObjectNotFoundException if the artifact object or project object isn't found in the database. * @throws ArchivaDatabaseException if there is a fundamental database error. */ - public ArchivaProjectModel selectVersion( String groupId, String artifactId, String version ) + public ArchivaProjectModel selectVersion( String principle, List observableRepositoryIds, String groupId, + String artifactId, String version ) throws ObjectNotFoundException, ArchivaDatabaseException; - + /** * Get the {@link List} of {@link ArchivaProjectModel} that are used by the provided * groupId, artifactId, and version specified. @@ -80,6 +82,7 @@ public interface RepositoryBrowsing * @return the {@link List} of {@link ArchivaProjectModel} objects. (never null, but can be empty) * @throws ArchivaDatabaseException if there is a fundamental database error. */ - public List getUsedBy( String groupId, String artifactId, String version ) + public List getUsedBy( String principle, List observableRepositoryIds, String groupId, + String artifactId, String version ) throws ArchivaDatabaseException; } diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/SqlBuilder.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/SqlBuilder.java new file mode 100644 index 000000000..208475dab --- /dev/null +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/SqlBuilder.java @@ -0,0 +1,80 @@ +package org.apache.maven.archiva.database.constraints; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.apache.commons.lang.StringUtils; + +import java.util.List; + +/** + * SqlBuilder - common sql building mechanisms. + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class SqlBuilder +{ + /** + * Append a sql specific where clause within "()" braces that selects the specific + * repository ids provided. + * + * NOTE: This does not append the "WHERE" statement itself. + * + * @param sql the sql buffer to append to. + * @param fieldId the field id for the repository Id. + * @param selectedRepositoryIds the list of repository ids to provide. + */ + public static void appendWhereSelectedRepositories( StringBuffer sql, String fieldId, + List selectedRepositoryIds ) + { + if ( fieldId == null ) + { + throw new NullPointerException( "Null field id is not allowed." ); + } + + if ( StringUtils.isBlank( fieldId ) ) + { + throw new IllegalArgumentException( "Blank field id is not allowed." ); + } + + if ( selectedRepositoryIds == null ) + { + throw new NullPointerException( "Selected repositories cannot be null." ); + } + + if ( selectedRepositoryIds.isEmpty() ) + { + throw new IllegalArgumentException( "Selected repositories cannot be null." ); + } + + sql.append( " (" ); + boolean multiple = false; + for ( String repo : selectedRepositoryIds ) + { + if ( multiple ) + { + sql.append( " || " ); + } + sql.append( " " ).append( fieldId ).append( " == \"" ).append( repo ).append( "\"" ); + multiple = true; + } + sql.append( " )" ); + } +} diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java index f5aa43826..47766b94e 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueArtifactIdConstraint.java @@ -22,6 +22,8 @@ package org.apache.maven.archiva.database.constraints; import org.apache.maven.archiva.database.Constraint; import org.apache.maven.archiva.model.ArchivaArtifactModel; +import java.util.List; + /** * Obtain a set of unique ArtifactIds for the specified groupId. * @@ -32,7 +34,24 @@ public class UniqueArtifactIdConstraint extends AbstractSimpleConstraint implements Constraint { - private String sql; + private StringBuffer sql = new StringBuffer(); + + /** + * Obtain a set of unique ArtifactIds for the specified groupId. + * + * @param groupId the groupId to search for artifactIds within. + */ + public UniqueArtifactIdConstraint( List selectedRepositoryIds, String groupId ) + { + appendSelect( sql ); + sql.append( " WHERE " ); + SqlBuilder.appendWhereSelectedRepositories( sql, "repositoryId", selectedRepositoryIds ); + sql.append( " && " ); + appendWhereSelectedGroupId( sql ); + appendGroupBy( sql ); + + super.params = new Object[] { groupId }; + } /** * Obtain a set of unique ArtifactIds for the specified groupId. @@ -41,13 +60,15 @@ public class UniqueArtifactIdConstraint */ public UniqueArtifactIdConstraint( String groupId ) { - sql = "SELECT artifactId FROM " + ArchivaArtifactModel.class.getName() - + " WHERE groupId == selectedGroupId PARAMETERS String selectedGroupId" - + " GROUP BY artifactId ORDER BY artifactId ASCENDING"; + appendSelect( sql ); + sql.append( " WHERE " ); + appendWhereSelectedGroupId( sql ); + appendGroupBy( sql ); super.params = new Object[] { groupId }; } + @SuppressWarnings("unchecked") public Class getResultClass() { return String.class; @@ -55,6 +76,22 @@ public class UniqueArtifactIdConstraint public String getSelectSql() { - return sql; + return sql.toString(); } + + private void appendGroupBy( StringBuffer buf ) + { + buf.append( " GROUP BY artifactId ORDER BY artifactId ASCENDING" ); + } + + private void appendSelect( StringBuffer buf ) + { + buf.append( "SELECT artifactId FROM " ).append( ArchivaArtifactModel.class.getName() ); + } + + private void appendWhereSelectedGroupId( StringBuffer buf ) + { + buf.append( " groupId == selectedGroupId PARAMETERS String selectedGroupId" ); + } + } diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraint.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraint.java index f8a77a487..06490c211 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraint.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraint.java @@ -22,6 +22,8 @@ package org.apache.maven.archiva.database.constraints; import org.apache.maven.archiva.database.Constraint; import org.apache.maven.archiva.model.ArchivaArtifactModel; +import java.util.List; + /** * UniqueGroupIdConstraint * @@ -32,24 +34,46 @@ public class UniqueGroupIdConstraint extends AbstractSimpleConstraint implements Constraint { - private String sql; + private StringBuffer sql = new StringBuffer(); public UniqueGroupIdConstraint() { /* this assumes search for no groupId prefix */ - sql = "SELECT groupId FROM " + ArchivaArtifactModel.class.getName() - + " GROUP BY groupId ORDER BY groupId ASCENDING"; + appendSelect( sql ); + appendGroupBy( sql ); + } + + public UniqueGroupIdConstraint( List selectedRepositories ) + { + appendSelect( sql ); + sql.append( " WHERE " ); + SqlBuilder.appendWhereSelectedRepositories( sql, "repositoryId", selectedRepositories ); + appendGroupBy( sql ); + } + + public UniqueGroupIdConstraint( List selectedRepositories, String groupIdPrefix ) + { + appendSelect( sql ); + sql.append( " WHERE " ); + SqlBuilder.appendWhereSelectedRepositories( sql, "repositoryId", selectedRepositories ); + sql.append( " && " ); + appendWhereGroupIdStartsWith( sql ); + appendGroupBy( sql ); + + super.params = new Object[] { groupIdPrefix }; } public UniqueGroupIdConstraint( String groupIdPrefix ) { - sql = "SELECT groupId FROM " + ArchivaArtifactModel.class.getName() - + " WHERE groupId.startsWith(groupIdPrefix) PARAMETERS String groupIdPrefix" - + " GROUP BY groupId ORDER BY groupId ASCENDING"; + appendSelect( sql ); + sql.append( " WHERE " ); + appendWhereGroupIdStartsWith( sql ); + appendGroupBy( sql ); super.params = new Object[] { groupIdPrefix }; } + @SuppressWarnings("unchecked") public Class getResultClass() { return String.class; @@ -57,6 +81,21 @@ public class UniqueGroupIdConstraint public String getSelectSql() { - return sql; + return sql.toString(); + } + + private void appendGroupBy( StringBuffer buf ) + { + buf.append( " GROUP BY groupId ORDER BY groupId ASCENDING" ); + } + + private void appendSelect( StringBuffer buf ) + { + buf.append( "SELECT groupId FROM " ).append( ArchivaArtifactModel.class.getName() ); + } + + private void appendWhereGroupIdStartsWith( StringBuffer buf ) + { + buf.append( " groupId.startsWith(groupIdPrefix) PARAMETERS String groupIdPrefix" ); } } diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraint.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraint.java index 6c7a4d73e..c36e34f82 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraint.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraint.java @@ -23,6 +23,8 @@ import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.database.Constraint; import org.apache.maven.archiva.model.ArchivaArtifactModel; +import java.util.List; + /** * Obtain the list of version's for specific GroupId and ArtifactId. * @@ -33,7 +35,36 @@ public class UniqueVersionConstraint extends AbstractSimpleConstraint implements Constraint { - private String sql; + private StringBuffer sql = new StringBuffer(); + + /** + * Obtain the list of version's for specific GroupId and ArtifactId. + * + * @param selectedRepositoryIds the selected repository ids. + * @param groupId the selected groupId. + * @param artifactId the selected artifactId. + */ + public UniqueVersionConstraint( List selectedRepositoryIds, String groupId, String artifactId ) + { + if ( StringUtils.isBlank( groupId ) ) + { + throw new IllegalArgumentException( "A blank groupId is not allowed." ); + } + + if ( StringUtils.isBlank( artifactId ) ) + { + throw new IllegalArgumentException( "A blank artifactId is not allowed." ); + } + + appendSelect( sql ); + sql.append( " WHERE " ); + SqlBuilder.appendWhereSelectedRepositories( sql, "repositoryId", selectedRepositoryIds ); + sql.append( " && " ); + appendWhereSelectedGroupIdArtifactId( sql ); + appendGroupBy( sql ); + + super.params = new Object[] { groupId, artifactId }; + } /** * Obtain the list of version's for specific GroupId and ArtifactId. @@ -53,14 +84,15 @@ public class UniqueVersionConstraint throw new IllegalArgumentException( "A blank artifactId is not allowed." ); } - sql = "SELECT version FROM " + ArchivaArtifactModel.class.getName() - + " WHERE groupId == selectedGroupId && artifactId == selectedArtifactId" - + " PARAMETERS String selectedGroupId, String selectedArtifactId" - + " GROUP BY version ORDER BY version ASCENDING"; + appendSelect( sql ); + sql.append( " WHERE " ); + appendWhereSelectedGroupIdArtifactId( sql ); + appendGroupBy( sql ); super.params = new Object[] { groupId, artifactId }; } + @SuppressWarnings("unchecked") public Class getResultClass() { return String.class; @@ -68,6 +100,22 @@ public class UniqueVersionConstraint public String getSelectSql() { - return sql; + return sql.toString(); + } + + private void appendGroupBy( StringBuffer buf ) + { + buf.append( " GROUP BY version ORDER BY version ASCENDING" ); + } + + private void appendSelect( StringBuffer buf ) + { + buf.append( "SELECT version FROM " ).append( ArchivaArtifactModel.class.getName() ); + } + + private void appendWhereSelectedGroupIdArtifactId( StringBuffer buf ) + { + buf.append( " groupId == selectedGroupId && artifactId == selectedArtifactId" ); + buf.append( " PARAMETERS String selectedGroupId, String selectedArtifactId" ); } } diff --git a/archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoProjectModelDAO.java b/archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoProjectModelDAO.java index 6da3a4120..f643bdfd2 100644 --- a/archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoProjectModelDAO.java +++ b/archiva-database/src/main/java/org/apache/maven/archiva/database/jdo/JdoProjectModelDAO.java @@ -74,7 +74,7 @@ public class JdoProjectModelDAO return (ArchivaProjectModel) jdo.getObjectById( ArchivaProjectModel.class, key, null ); } - public List queryProjectModels( Constraint constraint ) + public List queryProjectModels( Constraint constraint ) throws ObjectNotFoundException, ArchivaDatabaseException { return jdo.queryObjects( ArchivaProjectModel.class, constraint ); diff --git a/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java b/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java index c1c7ac280..8f2e6bf27 100644 --- a/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java +++ b/archiva-database/src/test/java/org/apache/maven/archiva/database/browsing/RepositoryBrowsingTest.java @@ -24,6 +24,7 @@ import org.apache.maven.archiva.database.ArchivaDAO; import org.apache.maven.archiva.database.ArtifactDAO; import org.apache.maven.archiva.model.ArchivaArtifact; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -36,13 +37,24 @@ import java.util.List; public class RepositoryBrowsingTest extends AbstractArchivaDatabaseTestCase { + private static final List GUEST_REPO_IDS; + + private static final String USER_GUEST = "guest"; + + static + { + GUEST_REPO_IDS = new ArrayList(); + GUEST_REPO_IDS.add( "central" ); + GUEST_REPO_IDS.add( "snapshots" ); + } + private ArtifactDAO artifactDao; public ArchivaArtifact createArtifact( String groupId, String artifactId, String version ) { ArchivaArtifact artifact = artifactDao.createArtifact( groupId, artifactId, version, "", "jar" ); artifact.getModel().setLastModified( new Date() ); // mandatory field. - artifact.getModel().setRepositoryId( "testable_repo" ); + artifact.getModel().setRepositoryId( "central" ); return artifact; } @@ -97,7 +109,7 @@ public class RepositoryBrowsingTest saveTestData(); RepositoryBrowsing browser = lookupBrowser(); - BrowsingResults results = browser.selectGroupId( "org.apache.maven.test" ); + BrowsingResults results = browser.selectGroupId( USER_GUEST, GUEST_REPO_IDS, "org.apache.maven.test" ); assertNotNull( "Browsing Results should not be null.", results ); String expectedSubGroupIds[] = new String[] { "org.apache.maven.test.foo" }; @@ -110,7 +122,7 @@ public class RepositoryBrowsingTest saveTestData(); RepositoryBrowsing browser = lookupBrowser(); - BrowsingResults results = browser.getRoot(); + BrowsingResults results = browser.getRoot( USER_GUEST, GUEST_REPO_IDS ); assertNotNull( "Browsing Results should not be null.", results ); String expectedRootGroupIds[] = new String[] { "commons-lang", "org" }; diff --git a/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java b/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java index 4de63506f..b32ea06cf 100644 --- a/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java +++ b/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueGroupIdConstraintTest.java @@ -26,6 +26,7 @@ import org.apache.maven.archiva.database.ArtifactDAO; import org.apache.maven.archiva.database.SimpleConstraint; import org.apache.maven.archiva.model.ArchivaArtifact; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; @@ -42,91 +43,268 @@ public class UniqueGroupIdConstraintTest { private ArtifactDAO artifactDao; - protected void setUp() + public void testConstraintGroupIdParamCommonsLang() throws Exception { - super.setUp(); + setupArtifacts(); - ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" ); - artifactDao = dao.getArtifactDAO(); + assertConstraint( new String[] { "commons-lang" }, new UniqueGroupIdConstraint( "commons-lang" ) ); } - public ArchivaArtifact createArtifact( String groupId, String artifactId, String version ) + public void testConstraintGroupIdParamNoRepos() + throws Exception { - ArchivaArtifact artifact = artifactDao.createArtifact( groupId, artifactId, version, "", "jar" ); - artifact.getModel().setLastModified( new Date() ); // mandatory field. - artifact.getModel().setRepositoryId( "testable_repo" ); - return artifact; + try + { + List selectedRepos = new ArrayList(); + new UniqueGroupIdConstraint( selectedRepos, "org" ); + fail( "Should have thrown an IllegalArgumentException due to lack of specified repos." ); + } + catch ( IllegalArgumentException e ) + { + // expected path. + } } - public void testConstraint() + public void testConstraintGroupIdParamNullRepos() throws Exception { - ArchivaArtifact artifact; + try + { + new UniqueGroupIdConstraint( (List) null, "org" ); + fail( "Should have thrown an NullPointerException due to lack of specified repos." ); + } + catch ( NullPointerException e ) + { + // expected path. + } + } - // Setup artifacts in fresh DB. - artifact = createArtifact( "commons-lang", "commons-lang", "2.0" ); - artifactDao.saveArtifact( artifact ); + public void testConstraintGroupIdParamOrg() + throws Exception + { + setupArtifacts(); - artifact = createArtifact( "commons-lang", "commons-lang", "2.1" ); - artifactDao.saveArtifact( artifact ); + assertConstraint( new String[] { + "org.apache.maven.test", + "org.apache.maven.test.foo", + "org.apache.maven.shared", + "org.apache.archiva", + "org.codehaus.modello", + "org.codehaus.mojo" }, new UniqueGroupIdConstraint( "org" ) ); + } - artifact = createArtifact( "org.apache.maven.test", "test-one", "1.2" ); - artifactDao.saveArtifact( artifact ); + public void testConstraintGroupIdParamOrgApache() + throws Exception + { + setupArtifacts(); - artifact = createArtifact( "org.apache.maven.test.foo", "test-two", "1.0" ); - artifactDao.saveArtifact( artifact ); + assertConstraint( new String[] { + "org.apache.maven.test", + "org.apache.maven.test.foo", + "org.apache.maven.shared", + "org.apache.archiva" }, new UniqueGroupIdConstraint( "org.apache" ) ); + } - artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.0" ); - artifactDao.saveArtifact( artifact ); + public void testConstraintGroupIdParamOrgApacheMaven() + throws Exception + { + setupArtifacts(); - artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1" ); - artifactDao.saveArtifact( artifact ); + assertConstraint( new String[] { + "org.apache.maven.test", + "org.apache.maven.test.foo", + "org.apache.maven.shared" }, new UniqueGroupIdConstraint( "org.apache.maven" ) ); + } - artifact = createArtifact( "org.codehaus.modello", "test-two", "3.0" ); - artifactDao.saveArtifact( artifact ); + public void testConstraintGroupIdParamOrgApacheSnapshotsOnly() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "snapshots" ); + + assertConstraint( new String[] { "org.apache.archiva" }, new UniqueGroupIdConstraint( observableRepositories, + "org.apache" ) ); + } + + public void testConstraintGroupIdParamOrgSnapshotsOnly() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "snapshots" ); + + assertConstraint( new String[] { "org.apache.archiva", "org.codehaus.modello", "org.codehaus.mojo" }, + new UniqueGroupIdConstraint( observableRepositories, "org" ) ); + } + + public void testConstraintNoGroupIdParam() + throws Exception + { + setupArtifacts(); assertConstraint( new String[] { "commons-lang", "org.apache.maven.test", "org.apache.maven.test.foo", "org.apache.maven.shared", - "org.codehaus.modello" }, new UniqueGroupIdConstraint() ); - assertConstraint( new String[] { "commons-lang" }, new UniqueGroupIdConstraint( "commons-lang" ) ); - assertConstraint( new String[] { - "org.apache.maven.test", - "org.apache.maven.test.foo", - "org.apache.maven.shared" }, new UniqueGroupIdConstraint( "org.apache.maven" ) ); + "org.codehaus.modello", + "org.codehaus.mojo", + "org.apache.archiva" }, new UniqueGroupIdConstraint() ); + } + + public void testConstraintNoGroupIdParamCentralAndSnapshots() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "central" ); + observableRepositories.add( "snapshots" ); + assertConstraint( new String[] { + "commons-lang", "org.apache.maven.test", "org.apache.maven.test.foo", - "org.apache.maven.shared" }, new UniqueGroupIdConstraint( "org.apache" ) ); + "org.apache.maven.shared", + "org.codehaus.modello", + "org.codehaus.mojo", + "org.apache.archiva" }, new UniqueGroupIdConstraint( observableRepositories ) ); + } + + public void testConstraintNoGroupIdParamCentralOnly() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "central" ); + assertConstraint( new String[] { + "commons-lang", "org.apache.maven.test", "org.apache.maven.test.foo", "org.apache.maven.shared", - "org.codehaus.modello" }, new UniqueGroupIdConstraint( "org" ) ); + "org.codehaus.modello" }, new UniqueGroupIdConstraint( observableRepositories ) ); + } + + public void testConstraintNoGroupIdParamNoRepos() + throws Exception + { + try + { + List selectedRepos = new ArrayList(); + new UniqueGroupIdConstraint( selectedRepos ); + fail( "Should have thrown an IllegalArgumentException due to lack of specified repos." ); + } + catch ( IllegalArgumentException e ) + { + // expected path. + } + } + + public void testConstraintNoGroupIdParamNullRepos() + throws Exception + { + try + { + new UniqueGroupIdConstraint( (List) null ); + fail( "Should have thrown an NullPointerException due to lack of specified repos." ); + } + catch ( NullPointerException e ) + { + // expected path. + } + } + + public void testConstraintNoGroupIdParamSnapshotsOnly() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "snapshots" ); + + assertConstraint( new String[] { "org.codehaus.modello", "org.codehaus.mojo", "org.apache.archiva" }, + new UniqueGroupIdConstraint( observableRepositories ) ); } private void assertConstraint( String[] expectedGroupIds, SimpleConstraint constraint ) throws Exception { String prefix = "Unique Group IDs: "; - - List results = dao.query( constraint ); + + List results = dao.query( constraint ); assertNotNull( prefix + "Not Null", results ); assertEquals( prefix + "Results.size", expectedGroupIds.length, results.size() ); - List groupIdList = Arrays.asList( expectedGroupIds ); + List groupIdList = Arrays.asList( expectedGroupIds ); - Iterator it = results.iterator(); + Iterator it = results.iterator(); while ( it.hasNext() ) { String actualGroupId = (String) it.next(); assertTrue( prefix + "groupId result should not be blank.", StringUtils.isNotBlank( actualGroupId ) ); - assertTrue( prefix + " groupId result <" + actualGroupId + "> exists in expected GroupIds.", - groupIdList.contains( actualGroupId ) ); + assertTrue( prefix + " groupId result <" + actualGroupId + "> exists in expected GroupIds.", groupIdList + .contains( actualGroupId ) ); } } + private ArchivaArtifact createArtifact( String repoId, String groupId, String artifactId, String version ) + { + ArchivaArtifact artifact = artifactDao.createArtifact( groupId, artifactId, version, "", "jar" ); + artifact.getModel().setLastModified( new Date() ); // mandatory field. + artifact.getModel().setRepositoryId( repoId ); + return artifact; + } + + private void setupArtifacts() + throws Exception + { + ArchivaArtifact artifact; + + // Setup artifacts in fresh DB. + artifact = createArtifact( "central", "commons-lang", "commons-lang", "2.0" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "central", "commons-lang", "commons-lang", "2.1" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "central", "org.apache.maven.test", "test-one", "1.2" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "central", "org.apache.maven.test.foo", "test-two", "1.0" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "central", "org.apache.maven.shared", "test-two", "2.0" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "central", "org.apache.maven.shared", "test-two", "2.1" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "central", "org.codehaus.modello", "test-two", "3.0" ); + artifactDao.saveArtifact( artifact ); + + // Snapshots repository artifacts + artifact = createArtifact( "snapshots", "org.codehaus.modello", "test-three", "1.0-SNAPSHOT" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "snapshots", "org.codehaus.mojo", "testable-maven-plugin", "2.1-SNAPSHOT" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "snapshots", "org.apache.archiva", "testable", "1.1-alpha-1-20070822.033400-43" ); + artifactDao.saveArtifact( artifact ); + } + + protected void setUp() + throws Exception + { + super.setUp(); + + ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" ); + artifactDao = dao.getArtifactDAO(); + } } diff --git a/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraintTest.java b/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraintTest.java index 176b7192b..c30a624f1 100644 --- a/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraintTest.java +++ b/archiva-database/src/test/java/org/apache/maven/archiva/database/constraints/UniqueVersionConstraintTest.java @@ -26,9 +26,9 @@ import org.apache.maven.archiva.database.ArtifactDAO; import org.apache.maven.archiva.database.SimpleConstraint; import org.apache.maven.archiva.model.ArchivaArtifact; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.Iterator; import java.util.List; /** @@ -42,87 +42,152 @@ public class UniqueVersionConstraintTest { private ArtifactDAO artifactDao; - protected void setUp() + public void testConstraintGroupIdArtifactIdCommonsLang() throws Exception { - super.setUp(); + setupArtifacts(); - ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" ); - artifactDao = dao.getArtifactDAO(); + assertConstraint( new String[] { "2.0", "2.1" }, new UniqueVersionConstraint( "commons-lang", "commons-lang" ) ); + } + + public void testConstraintGroupIdArtifactIdInvalid() + throws Exception + { + setupArtifacts(); + + assertConstraint( new String[] {}, new UniqueVersionConstraint( "org.apache", "invalid" ) ); + assertConstraint( new String[] {}, new UniqueVersionConstraint( "org.apache.test", "invalid" ) ); + assertConstraint( new String[] {}, new UniqueVersionConstraint( "invalid", "test-two" ) ); + } + + public void testConstraintGroupIdArtifactIdMavenSharedTestTwo() + throws Exception + { + setupArtifacts(); + + assertConstraint( new String[] { "2.0", "2.1-SNAPSHOT", "2.1.1", "2.1-alpha-1" }, + new UniqueVersionConstraint( "org.apache.maven.shared", "test-two" ) ); + } + + public void testConstraintGroupIdArtifactIdMavenSharedTestTwoCentralOnly() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "central" ); + + assertConstraint( new String[] { "2.0", "2.1.1", "2.1-alpha-1" }, + new UniqueVersionConstraint( observableRepositories, "org.apache.maven.shared", "test-two" ) ); + } + + public void testConstraintGroupIdArtifactIdMavenSharedTestTwoSnapshotsOnly() + throws Exception + { + setupArtifacts(); + + List observableRepositories = new ArrayList(); + observableRepositories.add( "snapshots" ); + + assertConstraint( new String[] { "2.1-SNAPSHOT" }, + new UniqueVersionConstraint( observableRepositories, "org.apache.maven.shared", "test-two" ) ); + } + + public void testConstraintGroupIdArtifactIdMavenTestOne() + throws Exception + { + setupArtifacts(); + + assertConstraint( new String[] { "1.2" }, new UniqueVersionConstraint( "org.apache.maven.test", "test-one" ) ); } - public ArchivaArtifact createArtifact( String groupId, String artifactId, String version ) + public void testConstraintGroupIdArtifactIdModelloLong() + throws Exception + { + setupArtifacts(); + + assertConstraint( new String[] { "3.0" }, new UniqueVersionConstraint( "org.codehaus.modello", "modellong" ) ); + } + + private void assertConstraint( String[] versions, SimpleConstraint constraint ) + { + String prefix = "Unique Versions: "; + + List results = dao.query( constraint ); + assertNotNull( prefix + "Not Null", results ); + assertEquals( prefix + "Results.size", versions.length, results.size() ); + + List expectedVersions = Arrays.asList( versions ); + + for ( String actualVersion : results ) + { + assertTrue( prefix + "version result should not be blank.", StringUtils.isNotBlank( actualVersion ) ); + assertTrue( prefix + "version result <" + actualVersion + "> exists in expected versions.", + expectedVersions.contains( actualVersion ) ); + } + } + + private ArchivaArtifact createArtifact( String repoId, String groupId, String artifactId, String version ) { ArchivaArtifact artifact = artifactDao.createArtifact( groupId, artifactId, version, "", "jar" ); artifact.getModel().setLastModified( new Date() ); // mandatory field. - artifact.getModel().setRepositoryId( "testable_repo" ); + artifact.getModel().setRepositoryId( repoId ); return artifact; } - public void testConstraint() + private void setupArtifacts() throws Exception { ArchivaArtifact artifact; // Setup artifacts in fresh DB. - artifact = createArtifact( "commons-lang", "commons-lang", "2.0" ); + artifact = createArtifact( "central", "commons-lang", "commons-lang", "2.0" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "commons-lang", "commons-lang", "2.1" ); + artifact = createArtifact( "central", "commons-lang", "commons-lang", "2.1" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.test", "test-one", "1.2" ); + artifact = createArtifact( "central", "org.apache.maven.test", "test-one", "1.2" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.test.foo", "test-two", "1.0" ); + artifact = createArtifact( "central", "org.apache.maven.test.foo", "test-two", "1.0" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.0" ); + artifact = createArtifact( "central", "org.apache.maven.shared", "test-two", "2.0" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1-SNAPSHOT" ); + artifact = createArtifact( "central", "org.apache.maven.shared", "test-two", "2.1.1" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1.1" ); + artifact = createArtifact( "central", "org.apache.maven.shared", "test-two", "2.1-alpha-1" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.shared", "test-two", "2.1-alpha-1" ); + artifact = createArtifact( "central", "org.apache.maven.shared", "test-bar", "2.1" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.apache.maven.shared", "test-bar", "2.1" ); + artifact = createArtifact( "central", "org.codehaus.modello", "modellong", "3.0" ); artifactDao.saveArtifact( artifact ); - artifact = createArtifact( "org.codehaus.modello", "modellong", "3.0" ); + // Snapshots repository artifacts + artifact = createArtifact( "snapshots", "org.apache.maven.shared", "test-two", "2.1-SNAPSHOT" ); artifactDao.saveArtifact( artifact ); - assertConstraint( new String[] {}, new UniqueVersionConstraint( "org.apache", "invalid" ) ); - assertConstraint( new String[] {}, new UniqueVersionConstraint( "org.apache.test", "invalid" ) ); - assertConstraint( new String[] {}, new UniqueVersionConstraint( "invalid", "test-two" ) ); + artifact = createArtifact( "snapshots", "org.codehaus.modello", "test-three", "1.0-SNAPSHOT" ); + artifactDao.saveArtifact( artifact ); - assertConstraint( new String[] { "2.0", "2.1" }, new UniqueVersionConstraint( "commons-lang", "commons-lang" ) ); - assertConstraint( new String[] { "1.2" }, new UniqueVersionConstraint( "org.apache.maven.test", "test-one" ) ); - assertConstraint( new String[] { "2.0", "2.1-SNAPSHOT", "2.1.1", "2.1-alpha-1" }, - new UniqueVersionConstraint( "org.apache.maven.shared", "test-two" ) ); - assertConstraint( new String[] { "3.0" }, new UniqueVersionConstraint( "org.codehaus.modello", "modellong" ) ); + artifact = createArtifact( "snapshots", "org.codehaus.mojo", "testable-maven-plugin", "2.1-SNAPSHOT" ); + artifactDao.saveArtifact( artifact ); + + artifact = createArtifact( "snapshots", "org.apache.archiva", "testable", "1.1-alpha-1-20070822.033400-43" ); + artifactDao.saveArtifact( artifact ); } - private void assertConstraint( String[] versions, SimpleConstraint constraint ) + protected void setUp() + throws Exception { - String prefix = "Unique Versions: "; - - List results = dao.query( constraint ); - assertNotNull( prefix + "Not Null", results ); - assertEquals( prefix + "Results.size", versions.length, results.size() ); - - List expectedVersions = Arrays.asList( versions ); + super.setUp(); - Iterator it = results.iterator(); - while ( it.hasNext() ) - { - String actualVersion = (String) it.next(); - assertTrue( prefix + "version result should not be blank.", StringUtils.isNotBlank( actualVersion ) ); - assertTrue( prefix + "version result <" + actualVersion + "> exists in expected versions.", - expectedVersions.contains( actualVersion ) ); - } + ArchivaDAO dao = (ArchivaDAO) lookup( ArchivaDAO.ROLE, "jdo" ); + artifactDao = dao.getArtifactDAO(); } } diff --git a/archiva-web/archiva-security/pom.xml b/archiva-web/archiva-security/pom.xml index 5837eee9f..5ba0428be 100644 --- a/archiva-web/archiva-security/pom.xml +++ b/archiva-web/archiva-security/pom.xml @@ -28,23 +28,41 @@ archiva-security Archiva Web :: Security Configuration + + org.apache.maven.archiva + archiva-configuration + + + org.codehaus.plexus.redback + redback-system + + + org.codehaus.plexus.redback + redback-rbac-model + org.codehaus.plexus.redback redback-rbac-role-manager + org.codehaus.plexus.redback - redback-rbac-memory + redback-authorization-rbac test org.codehaus.plexus.redback - redback-xwork-integration + redback-keys-memory test - org.apache.derby - derby + org.codehaus.plexus.redback + redback-users-memory + test + + + org.codehaus.plexus.redback + redback-rbac-memory test diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/AllTests.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java similarity index 67% rename from archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/AllTests.java rename to archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java index 9c2a8f21f..2c3ea5e40 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/AllTests.java +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java @@ -1,4 +1,4 @@ -package org.apache.maven.archiva.indexer.search; +package org.apache.maven.archiva.security; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,23 +19,22 @@ package org.apache.maven.archiva.indexer.search; * under the License. */ -import junit.framework.Test; -import junit.framework.TestSuite; - /** - * AllTests - conveinence test suite for IDE users. + * AccessDeniedException * * @author Joakim Erdfelt * @version $Id$ */ -public class AllTests +public class AccessDeniedException + extends ArchivaSecurityException { - public static Test suite() + public AccessDeniedException( String message, Throwable cause ) + { + super( message, cause ); + } + + public AccessDeniedException( String message ) { - TestSuite suite = new TestSuite( "Test for org.apache.maven.archiva.indexer.search" ); - //$JUnit-BEGIN$ - suite.addTestSuite( DefaultCrossRepositorySearchTest.class ); - //$JUnit-END$ - return suite; + super( message ); } } diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java index 0be90a7b0..78745ec35 100644 --- a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java @@ -35,6 +35,10 @@ public class ArchivaRoleConstants public static final String REGISTERED_USER_ROLE = "Registered User"; public static final String GUEST_ROLE = "Guest"; + + // principals + + public static final String PRINCIPAL_GUEST = "guest"; // dynamic role prefixes public static final String REPOSITORY_MANAGER_ROLE_PREFIX = "Repository Manager"; @@ -68,4 +72,15 @@ public class ArchivaRoleConstants public static final String TEMPLATE_REPOSITORY_MANAGER = "archiva-repository-manager"; public static final String TEMPLATE_REPOSITORY_OBSERVER = "archiva-repository-observer"; + + public static final String TEMPLATE_GLOBAL_REPOSITORY_OBSERVER = "archiva-global-repository-observer"; + + public static final String TEMPLATE_SYSTEM_ADMIN = "archiva-system-administrator"; + + public static final String TEMPLATE_GUEST = "archiva-guest"; + + public static String toRepositoryObserverRoleName( String repoId ) + { + return REPOSITORY_OBSERVER_ROLE_PREFIX + " - " + repoId; + } } diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java new file mode 100644 index 000000000..47973fc25 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java @@ -0,0 +1,42 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.apache.maven.archiva.common.ArchivaException; + +/** + * ArchivaSecurityException + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class ArchivaSecurityException + extends ArchivaException +{ + public ArchivaSecurityException( String message, Throwable cause ) + { + super( message, cause ); + } + + public ArchivaSecurityException( String message ) + { + super( message ); + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java new file mode 100644 index 000000000..434c2f612 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java @@ -0,0 +1,103 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.system.check.EnvironmentCheck; + +import java.util.List; + +/** + * ArchivaStandardRolesCheck tests for the existance of expected / standard roles and permissions. + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.codehaus.plexus.redback.system.check.EnvironmentCheck" + * role-hint="required-roles" + */ +public class ArchivaStandardRolesCheck + extends AbstractLogEnabled + implements EnvironmentCheck +{ + /** + * @plexus.requirement role-hint="cached" + */ + private RBACManager rbacManager; + + /** + * boolean detailing if this environment check has been executed + */ + private boolean checked = false; + + @SuppressWarnings("unchecked") + public void validateEnvironment( List violations ) + { + if ( !checked ) + { + String expectedRoles[] = new String[] { + ArchivaRoleConstants.SYSTEM_ADMINISTRATOR_ROLE, + ArchivaRoleConstants.GLOBAL_REPOSITORY_MANAGER_ROLE, + ArchivaRoleConstants.GLOBAL_REPOSITORY_OBSERVER_ROLE, + ArchivaRoleConstants.GUEST_ROLE, + ArchivaRoleConstants.REGISTERED_USER_ROLE, + ArchivaRoleConstants.USER_ADMINISTRATOR_ROLE }; + + getLogger().info( "Checking the existance of required roles." ); + + for ( String roleName : expectedRoles ) + { + if ( !rbacManager.roleExists( roleName ) ) + { + violations.add( "Unable to validate the existances of the '" + roleName + "' role." ); + } + } + + String expectedOperations[] = new String[] { + ArchivaRoleConstants.OPERATION_MANAGE_USERS, + ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION, + ArchivaRoleConstants.OPERATION_REGENERATE_INDEX, + ArchivaRoleConstants.OPERATION_RUN_INDEXER, + ArchivaRoleConstants.OPERATION_ACCESS_REPORT, + ArchivaRoleConstants.OPERATION_ADD_REPOSITORY, + ArchivaRoleConstants.OPERATION_DELETE_REPOSITORY, + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, + ArchivaRoleConstants.OPERATION_EDIT_REPOSITORY, + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD, + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, + "archiva-guest" }; + + getLogger().info( "Checking the existance of required operations." ); + + for ( String operation : expectedOperations ) + { + if ( !rbacManager.operationExists( operation ) ) + { + violations.add( "Unable to validate the existances of the '" + operation + "' operation." ); + } + } + + checked = true; + } + + } + +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaUser.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaUser.java new file mode 100644 index 000000000..bdf70da8d --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaUser.java @@ -0,0 +1,36 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * ArchivaUser- interface to access the active principal. + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public interface ArchivaUser +{ + /** + * Get the active principal from the security system. + * + * @return the active principal. (if not authenticated, the guest principal is returned) + */ + public String getActivePrincipal(); +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java new file mode 100644 index 000000000..88b740b19 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java @@ -0,0 +1,135 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.codehaus.plexus.redback.authentication.AuthenticationResult; +import org.codehaus.plexus.redback.authorization.AuthorizationException; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.role.RoleManager; +import org.codehaus.plexus.redback.role.RoleManagerException; +import org.codehaus.plexus.redback.system.DefaultSecuritySession; +import org.codehaus.plexus.redback.system.SecuritySession; +import org.codehaus.plexus.redback.system.SecuritySystem; +import org.codehaus.plexus.redback.users.User; +import org.codehaus.plexus.redback.users.UserNotFoundException; + +/** + * DefaultUserRepositories + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.apache.maven.archiva.security.UserRepositories" + * role-hint="default" + */ +public class DefaultUserRepositories + implements UserRepositories +{ + /** + * @plexus.requirement + */ + private SecuritySystem securitySystem; + + /** + * @plexus.requirement role-hint="cached" + */ + private RBACManager rbacManager; + + /** + * @plexus.requirement role-hint="default" + */ + private RoleManager roleManager; + + /** + * @plexus.requirement + */ + private ArchivaConfiguration archivaConfiguration; + + public List getObservableRepositoryIds( String principal ) + throws PrincipalNotFoundException, AccessDeniedException, ArchivaSecurityException + { + + try + { + User user = securitySystem.getUserManager().findUser( principal ); + + if ( user.isLocked() ) + { + throw new AccessDeniedException( "User " + principal + "(" + user.getFullName() + ") is locked." ); + } + + AuthenticationResult authn = new AuthenticationResult( true, principal, null ); + SecuritySession securitySession = new DefaultSecuritySession( authn, user ); + + List repoIds = new ArrayList(); + + List repos = archivaConfiguration.getConfiguration().getManagedRepositories(); + + for ( ManagedRepositoryConfiguration repo : repos ) + { + try + { + String repoId = repo.getId(); + if ( securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, repoId ) ) + { + repoIds.add( repoId ); + } + } + catch ( AuthorizationException e ) + { + // swallow. + } + } + + return repoIds; + } + catch ( UserNotFoundException e ) + { + throw new PrincipalNotFoundException( "Unable to find principal " + principal + "" ); + } + } + + public void createMissingRepositoryRoles( String repoId ) + throws ArchivaSecurityException + { + try + { + if ( !roleManager.templatedRoleExists( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId ) ) + { + roleManager.createTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId ); + } + + if ( !roleManager.templatedRoleExists( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, repoId ) ) + { + roleManager.createTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, repoId ); + } + } + catch ( RoleManagerException e ) + { + throw new ArchivaSecurityException( "Unable to create roles for configured repositories: " + e.getMessage(), + e ); + } + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java new file mode 100644 index 000000000..196204436 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java @@ -0,0 +1,40 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * PrincipalNotFoundException + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class PrincipalNotFoundException + extends ArchivaSecurityException +{ + public PrincipalNotFoundException( String message, Throwable cause ) + { + super( message, cause ); + } + + public PrincipalNotFoundException( String message ) + { + super( message ); + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java new file mode 100644 index 000000000..8a6c51c96 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java @@ -0,0 +1,206 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.apache.commons.collections.CollectionUtils; +import org.apache.maven.archiva.common.ArchivaException; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.rbac.RbacManagerException; +import org.codehaus.plexus.redback.rbac.UserAssignment; +import org.codehaus.plexus.redback.system.check.EnvironmentCheck; +import org.codehaus.plexus.registry.Registry; +import org.codehaus.plexus.registry.RegistryListener; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * SecurityStartup + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.apache.maven.archiva.security.SecurityStartup" + */ +public class SecurityStartup + extends AbstractLogEnabled + implements RegistryListener +{ + /** + * @plexus.requirement + */ + private UserRepositories userRepos; + + /** + * @plexus.requirement role-hint="cached" + */ + private RBACManager rbacManager; + + /** + * @plexus.requirement role="org.codehaus.plexus.redback.system.check.EnvironmentCheck" + */ + private Map checkers; + + /** + * @plexus.requirement + */ + private ArchivaConfiguration archivaConfiguration; + + public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + if ( ConfigurationNames.isManagedRepositories( propertyName ) ) + { + createMissingManagedRepositoryRoles( archivaConfiguration.getConfiguration().getManagedRepositories() ); + } + } + + public void assignRepositoryObserverToGuestUser( List repos ) + { + for ( ManagedRepositoryConfiguration repoConfig : repos ) + { + String repoId = repoConfig.getId(); + + // TODO: Use the Redback / UserConfiguration..getString( "redback.default.guest" ) to get the right name. + String principal = "guest"; + + try + { + UserAssignment ua; + + if ( rbacManager.userAssignmentExists( principal ) ) + { + ua = rbacManager.getUserAssignment( principal ); + } + else + { + ua = rbacManager.createUserAssignment( principal ); + } + + ua.addRoleName( ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) ); + rbacManager.saveUserAssignment( ua ); + } + catch ( RbacManagerException e ) + { + getLogger().warn( + "Unable to add role [" + ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) + + "] to " + principal + " user.", e ); + } + } + } + + public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + /* do nothing */ + } + + public void createMissingManagedRepositoryRoles( List repos ) + { + // NOTE: Remote Repositories do not have roles or security placed around them. + + for ( ManagedRepositoryConfiguration repoConfig : repos ) + { + // manage roles for repositories + try + { + userRepos.createMissingRepositoryRoles( repoConfig.getId() ); + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + } + } + + public void createMissingRepositoryRoles( List repoIds ) + { + for ( String repoId : repoIds ) + { + // manage roles for repositories + try + { + userRepos.createMissingRepositoryRoles( repoId ); + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + } + } + + public void executeEnvironmentChecks() + throws ArchivaException + { + if ( ( checkers == null ) || CollectionUtils.isEmpty( checkers.values() ) ) + { + throw new ArchivaException( "Unable to initialize the Redback Security Environment, " + + "no Environment Check components found." ); + } + + List violations = new ArrayList(); + + for ( Entry entry : checkers.entrySet() ) + { + EnvironmentCheck check = entry.getValue(); + getLogger().info( "Running Environment Check: " + entry.getKey() ); + check.validateEnvironment( violations ); + } + + if ( CollectionUtils.isNotEmpty( violations ) ) + { + StringBuffer msg = new StringBuffer(); + msg.append( "EnvironmentCheck Failure.\n" ); + msg.append( "======================================================================\n" ); + msg.append( " ENVIRONMENT FAILURE !! \n" ); + msg.append( "\n" ); + + for ( String violation : violations ) + { + msg.append( violation ).append( "\n" ); + } + + msg.append( "\n" ); + msg.append( "======================================================================" ); + getLogger().fatalError( msg.toString() ); + + throw new ArchivaException( "Unable to initialize Redback Security Environment, [" + violations.size() + + "] violation(s) encountered, See log for details." ); + } + } + + public void startup() + throws ArchivaException + { + executeEnvironmentChecks(); + + createMissingManagedRepositoryRoles( archivaConfiguration.getConfiguration().getManagedRepositories() ); + archivaConfiguration.addChangeListener( this ); + + if ( archivaConfiguration.isDefaulted() ) + { + assignRepositoryObserverToGuestUser( archivaConfiguration.getConfiguration().getManagedRepositories() ); + } + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java new file mode 100644 index 000000000..c448a26b3 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java @@ -0,0 +1,52 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.util.List; + +/** + * UserRepositories + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public interface UserRepositories +{ + /** + * Get the list of observable repository ids for the user specified. + * + * @param principal the principle to obtain the observable repository ids from. + * @return the list of observable repository ids. + * @throws PrincipalNotFoundException + * @throws AccessDeniedException + * @throws ArchivaSecurityException + */ + public List getObservableRepositoryIds( String principal ) + throws PrincipalNotFoundException, AccessDeniedException, ArchivaSecurityException; + + /** + * Create any missing repository roles for the provided repository id. + * + * @param repoId the repository id to work off of. + * @throws ArchivaSecurityException if there was a problem creating the repository roles. + */ + public void createMissingRepositoryRoles( String repoId ) + throws ArchivaSecurityException; +} diff --git a/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java new file mode 100644 index 000000000..d99aea220 --- /dev/null +++ b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java @@ -0,0 +1,175 @@ +package org.apache.maven.archiva.security; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.io.File; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.codehaus.plexus.PlexusTestCase; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.role.RoleManager; +import org.codehaus.plexus.redback.system.SecuritySystem; +import org.codehaus.plexus.redback.users.User; +import org.codehaus.plexus.redback.users.UserManager; + +/** + * DefaultUserRepositoriesTest + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class DefaultUserRepositoriesTest + extends PlexusTestCase +{ + private static final String USER_GUEST = "guest"; + + private static final String USER_ADMIN = "admin"; + + private static final String USER_ALPACA = "alpaca"; + + private SecuritySystem securitySystem; + + private RBACManager rbacManager; + + private RoleManager roleManager; + + private ArchivaConfiguration archivaConfiguration; + + private UserRepositories userRepos; + + public void testGetObservableRepositoryIds() + throws Exception + { + // create some users. + createUser( USER_ALPACA, "Al 'Archiva' Paca" ); + + assertEquals( "Expected users", 3, securitySystem.getUserManager().getUsers().size() ); + + // some unassigned repo observer roles. + setupRepository( "central" ); + setupRepository( "corporate" ); + setupRepository( "internal" ); + setupRepository( "snapshots" ); + setupRepository( "secret" ); + + // some assigned repo observer roles. + assignRepositoryObserverRole( USER_ALPACA, "corporate" ); + assignRepositoryObserverRole( USER_ALPACA, "central" ); + assignRepositoryObserverRole( USER_GUEST, "corporate" ); + // the global repo observer role. + assignGlobalRepositoryObserverRole( USER_ADMIN ); + + assertRepoIds( new String[] { "central", "corporate" }, userRepos.getObservableRepositoryIds( USER_ALPACA ) ); + assertRepoIds( new String[] { "coporate" }, userRepos.getObservableRepositoryIds( USER_GUEST ) ); + assertRepoIds( new String[] { "central", "internal", "corporate", "snapshots", "secret" }, userRepos + .getObservableRepositoryIds( USER_ADMIN ) ); + } + + private void assertRepoIds( String[] expectedRepoIds, List observableRepositoryIds ) + { + assertNotNull( "Observable Repository Ids cannot be null.", observableRepositoryIds ); + + if ( expectedRepoIds.length != observableRepositoryIds.size() ) + { + fail( "Size of Observable Repository Ids wrong, expected <" + expectedRepoIds.length + "> but got <" + + observableRepositoryIds.size() + "> instead. \nExpected: [" + StringUtils.join( expectedRepoIds, "," ) + + "]\nActual: [" + StringUtils.join( observableRepositoryIds.iterator(), "," ) + "]" ); + } + } + + private void setupRepository( String repoId ) + throws Exception + { + // Add repo to configuration. + ManagedRepositoryConfiguration repoConfig = new ManagedRepositoryConfiguration(); + repoConfig.setId( repoId ); + repoConfig.setName( "Testable repo <" + repoId + ">" ); + repoConfig.setLocation( getTestPath( "target/test-repo/" + repoId ) ); + archivaConfiguration.getConfiguration().addManagedRepository( repoConfig ); + + // Add repo roles to security. + userRepos.createMissingRepositoryRoles( repoId ); + } + + private void assignGlobalRepositoryObserverRole( String principal ) + throws Exception + { + roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_GLOBAL_REPOSITORY_OBSERVER, principal ); + } + + private void assignRepositoryObserverRole( String principal, String repoId ) + throws Exception + { + roleManager.assignTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId, principal ); + } + + private User createUser( String principal, String fullname ) + { + UserManager userManager = securitySystem.getUserManager(); + + User user = userManager.createUser( principal, fullname, principal + "@testable.archiva.apache.org" ); + securitySystem.getPolicy().setEnabled( false ); + userManager.addUser( user ); + securitySystem.getPolicy().setEnabled( true ); + + return user; + } + + @Override + protected void setUp() + throws Exception + { + super.setUp(); + + File srcConfig = getTestFile( "src/test/resources/repository-archiva.xml" ); + File destConfig = getTestFile( "target/test-conf/archiva.xml" ); + + destConfig.getParentFile().mkdirs(); + destConfig.delete(); + + FileUtils.copyFile( srcConfig, destConfig ); + + securitySystem = (SecuritySystem) lookup( SecuritySystem.class, "testable" ); + rbacManager = (RBACManager) lookup( RBACManager.class, "memory" ); + roleManager = (RoleManager) lookup( RoleManager.class, "default" ); + userRepos = (UserRepositories) lookup( UserRepositories.class, "default" ); + archivaConfiguration = (ArchivaConfiguration) lookup( ArchivaConfiguration.class ); + + // Some basic asserts. + assertNotNull( securitySystem ); + assertNotNull( rbacManager ); + assertNotNull( roleManager ); + assertNotNull( userRepos ); + assertNotNull( archivaConfiguration ); + + // Setup Admin User. + User adminUser = createUser( USER_ADMIN, "Admin User" ); + roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_SYSTEM_ADMIN, adminUser.getPrincipal().toString() ); + + // Setup Guest User. + User guestUser = createUser( USER_GUEST, "Guest User" ); + roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_GUEST, guestUser.getPrincipal().toString() ); + + } +} diff --git a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/AllTests.java b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java similarity index 56% rename from archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/AllTests.java rename to archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java index 2160e8e4c..f3924f934 100644 --- a/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/AllTests.java +++ b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java @@ -1,4 +1,4 @@ -package org.apache.maven.archiva.indexer; +package org.apache.maven.archiva.security; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,28 +19,31 @@ package org.apache.maven.archiva.indexer; * under the License. */ -import junit.framework.Test; -import junit.framework.TestSuite; +import org.codehaus.plexus.PlexusTestCase; /** - * AllTests - conveinence test suite for IDE users. + * SecurityStartupTest * * @author Joakim Erdfelt * @version $Id$ */ -public class AllTests +public class SecurityStartupTest + extends PlexusTestCase { + private SecurityStartup secStart; - public static Test suite() + @Override + protected void setUp() + throws Exception { - TestSuite suite = new TestSuite( "Test for org.apache.maven.archiva.indexer" ); - //$JUnit-BEGIN$ - suite.addTest( org.apache.maven.archiva.indexer.bytecode.AllTests.suite() ); - suite.addTest( org.apache.maven.archiva.indexer.hashcodes.AllTests.suite() ); - suite.addTest( org.apache.maven.archiva.indexer.query.AllTests.suite() ); - suite.addTest( org.apache.maven.archiva.indexer.search.AllTests.suite() ); - //$JUnit-END$ - return suite; + super.setUp(); + + secStart = (SecurityStartup) lookup( SecurityStartup.class ); } + public void testEnvironmentChecks() + throws Exception + { + secStart.executeEnvironmentChecks(); + } } diff --git a/archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml b/archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml new file mode 100644 index 000000000..794d52762 --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml @@ -0,0 +1,195 @@ + + + 1.0.0 + Redback XWork Integration Security Core + + + global + * + true + global resource implies full access for authorization + + + username + ${username} + true + replaced with the username of the principal at authorization check time + + + + + configuration-edit + configuration-edit + edit configuration + true + + + user-management-user-create + user-management-user-create + create user + true + + + user-management-user-edit + user-management-user-edit + edit user + true + + + user-management-user-role + user-management-user-role + user roles + true + + + user-management-user-delete + user-management-user-delete + delete user + true + + + user-management-user-list + user-management-user-list + list users + true + + + user-management-role-grant + user-management-role-grant + grant role + true + + + user-management-role-drop + user-management-role-drop + drop role + true + + + user-management-rbac-admin + user-management-rbac-admin + administer rbac + true + + + guest-access + guest-access + access guest + true + + + + + system-administrator + System Administrator + true + true + + + edit-redback-configuration + Edit Redback Configuration + configuration-edit + global + true + + + manage-rbac-setup + User RBAC Management + user-management-rbac-admin + global + true + + + + user-administrator + + + + user-administrator + User Administrator + true + true + + + drop-roles-for-anyone + Drop Roles for Anyone + user-management-role-drop + global + true + + + grant-roles-for-anyone + Grant Roles for Anyone + user-management-role-grant + global + true + + + user-create + Create Users + user-management-user-create + global + true + + + user-delete + Delete Users + user-management-user-delete + global + true + + + user-edit + Edit Users + user-management-user-edit + global + true + + + access-users-roles + Access Users Roles + user-management-user-role + global + true + + + access-user-list + Access User List + user-management-user-list + global + true + + + + + registered-user + Registered User + true + true + + + edit-user-by-username + Edit User Data by Username + user-management-user-edit + username + true + + + + + guest + Guest + true + true + + + guest-permission + Guest Permission + guest-access + global + true + + + + + \ No newline at end of file diff --git a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml new file mode 100644 index 000000000..5de5fb286 --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml @@ -0,0 +1,193 @@ + + + + + + org.apache.maven.archiva.security.UserRepositories + default + org.apache.maven.archiva.security.DefaultUserRepositories + DefaultUserRepositories + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + securitySystem + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration + + + + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + org.codehaus.plexus.redback.system.DefaultSecuritySystem + DefaultSecuritySystem: + + + org.codehaus.plexus.redback.authentication.AuthenticationManager + authnManager + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + authorizer + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.keys.KeyManager + memory + keyManager + + + org.codehaus.plexus.redback.policy.UserSecurityPolicy + policy + + + + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer + RbacAuthorizer: + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + manager + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + evaluator + + + org.codehaus.plexus.redback.configuration.UserConfiguration + default + config + + + + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + + + + org.codehaus.plexus.redback.role.RoleManager + default + org.codehaus.plexus.redback.role.DefaultRoleManager + RoleProfileManager: + + + org.codehaus.plexus.redback.role.merger.RoleModelMerger + default + modelMerger + + + org.codehaus.plexus.redback.role.validator.RoleModelValidator + default + modelValidator + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + modelProcessor + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + templateProcessor + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor + DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor + DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + org.apache.maven.archiva.configuration.DefaultArchivaConfiguration + + + org.codehaus.plexus.registry.Registry + configured + + + + + org.codehaus.plexus.registry.Registry + configured + org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry + + + + + + + + + + diff --git a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml index 65ede8171..d45485407 100644 --- a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml +++ b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml @@ -34,7 +34,7 @@ - + org.codehaus.plexus.redback.role.processor.RoleModelProcessor default org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor @@ -47,6 +47,7 @@ + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor default @@ -60,5 +61,45 @@ + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + required-roles + org.apache.maven.archiva.security.ArchivaStandardRolesCheck + ArchivaStandardRolesCheck tests for the existance of expected / standard roles and permissions. + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.apache.maven.archiva.security.SecurityStartup + org.apache.maven.archiva.security.SecurityStartup + SecurityStartup + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + checkers + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration + + + + diff --git a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml new file mode 100644 index 000000000..a29933aef --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml @@ -0,0 +1,210 @@ + + + + + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + required-roles + org.apache.maven.archiva.security.ArchivaStandardRolesCheck + ArchivaStandardRolesCheck tests for the existance of expected / standard roles and permissions. + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.apache.maven.archiva.security.SecurityStartup + org.apache.maven.archiva.security.SecurityStartup + SecurityStartup + + + org.apache.maven.archiva.security.UserRepositories + userRepos + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + checkers + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration + + + + + + org.apache.maven.archiva.security.UserRepositories + default + org.apache.maven.archiva.security.DefaultUserRepositories + DefaultUserRepositories + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + securitySystem + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor + DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor + DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.RoleManager + default + org.codehaus.plexus.redback.role.DefaultRoleManager + singleton + RoleProfileManager: + + + org.codehaus.plexus.redback.role.merger.RoleModelMerger + default + modelMerger + + + org.codehaus.plexus.redback.role.validator.RoleModelValidator + default + modelValidator + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + modelProcessor + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + templateProcessor + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.PlexusContainer + container + + + + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + org.codehaus.plexus.redback.system.DefaultSecuritySystem + DefaultSecuritySystem: + + + org.codehaus.plexus.redback.authentication.AuthenticationManager + authnManager + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + authorizer + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.keys.KeyManager + memory + keyManager + + + org.codehaus.plexus.redback.policy.UserSecurityPolicy + policy + + + + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer + RbacAuthorizer: + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + manager + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + evaluator + + + org.codehaus.plexus.redback.configuration.UserConfiguration + default + config + + + + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + + + + diff --git a/archiva-web/archiva-security/src/test/resources/repository-archiva.xml b/archiva-web/archiva-security/src/test/resources/repository-archiva.xml new file mode 100644 index 000000000..f642851be --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/repository-archiva.xml @@ -0,0 +1,111 @@ + + + + + + 2 + + + + + artifacts + + **/*.pom + **/*.jar + **/*.ear + **/*.war + **/*.car + **/*.sar + **/*.mar + **/*.rar + **/*.dtd + **/*.tld + **/*.tar.gz + **/*.tar.bz2 + **/*.zip + + + + indexable-content + + **/*.txt + **/*.TXT + **/*.block + **/*.config + **/*.pom + **/*.xml + **/*.xsd + **/*.dtd + **/*.tld + + + + auto-remove + + **/*.bak + **/*~ + **/*- + + + + ignored + + **/.htaccess + **/KEYS + **/*.rb + **/*.sh + **/.svn/** + **/.DAV/** + + + + + update-db-artifact + create-missing-checksums + update-db-repository-metadata + validate-checksum + validate-signature + index-content + auto-remove + auto-rename + + + update-db-bad-content + + + + + 0 0 * * ? + + index-artifact + update-db-project + validate-repository-metadata + index-archive-toc + update-db-bytecode-stats + index-public-methods + + + not-present-remove-db-artifact + not-present-remove-db-project + not-present-remove-indexed + + + + diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java index e76b40cad..2bc042231 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/BrowseAction.java @@ -19,11 +19,20 @@ package org.apache.maven.archiva.web.action; * under the License. */ +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.database.browsing.BrowsingResults; import org.apache.maven.archiva.database.browsing.RepositoryBrowsing; +import org.apache.maven.archiva.security.AccessDeniedException; +import org.apache.maven.archiva.security.ArchivaSecurityException; +import org.apache.maven.archiva.security.ArchivaUser; +import org.apache.maven.archiva.security.PrincipalNotFoundException; +import org.apache.maven.archiva.security.UserRepositories; import org.codehaus.plexus.xwork.action.PlexusActionSupport; +import java.util.Collections; +import java.util.List; + /** * Browse the repository. * @@ -39,6 +48,16 @@ public class BrowseAction * @plexus.requirement role-hint="default" */ private RepositoryBrowsing repoBrowsing; + + /** + * @plexus.requirement + */ + private UserRepositories userRepositories; + + /** + * @plexus.requirement role-hint="xwork" + */ + private ArchivaUser archivaUser; private BrowsingResults results; @@ -48,7 +67,13 @@ public class BrowseAction public String browse() { - this.results = repoBrowsing.getRoot(); + List selectedRepos = getObservableRepos(); + if ( CollectionUtils.isEmpty( selectedRepos ) ) + { + return GlobalResults.ACCESS_TO_NO_REPOS; + } + + this.results = repoBrowsing.getRoot( getPrincipal(), selectedRepos ); return SUCCESS; } @@ -61,7 +86,14 @@ public class BrowseAction return ERROR; } - this.results = repoBrowsing.selectGroupId( groupId ); + List selectedRepos = getObservableRepos(); + if ( CollectionUtils.isEmpty( selectedRepos ) ) + { + return GlobalResults.ACCESS_TO_NO_REPOS; + } + + + this.results = repoBrowsing.selectGroupId( getPrincipal(), selectedRepos, groupId ); return SUCCESS; } @@ -81,9 +113,43 @@ public class BrowseAction return ERROR; } - this.results = repoBrowsing.selectArtifactId( groupId, artifactId ); + List selectedRepos = getObservableRepos(); + if ( CollectionUtils.isEmpty( selectedRepos ) ) + { + return GlobalResults.ACCESS_TO_NO_REPOS; + } + + + this.results = repoBrowsing.selectArtifactId( getPrincipal(), selectedRepos, groupId, artifactId ); return SUCCESS; } + + private String getPrincipal() + { + return archivaUser.getActivePrincipal(); + } + + private List getObservableRepos() + { + try + { + return userRepositories.getObservableRepositoryIds( getPrincipal() ); + } + catch ( PrincipalNotFoundException e ) + { + getLogger().warn( e.getMessage(), e ); + } + catch ( AccessDeniedException e ) + { + getLogger().warn( e.getMessage(), e ); + // TODO: pass this onto the screen. + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + return Collections.emptyList(); + } public String getGroupId() { diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/GlobalResults.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/GlobalResults.java new file mode 100644 index 000000000..15b7ae5d8 --- /dev/null +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/GlobalResults.java @@ -0,0 +1,31 @@ +package org.apache.maven.archiva.web.action; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * GlobalResults - constants for global result definitions. + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class GlobalResults +{ + public static final String ACCESS_TO_NO_REPOS = "access_to_no_repos"; +} diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java index 37ca5146f..2785f7414 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java @@ -19,6 +19,7 @@ package org.apache.maven.archiva.web.action; * under the License. */ +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.database.ArchivaDAO; import org.apache.maven.archiva.database.Constraint; @@ -28,9 +29,15 @@ import org.apache.maven.archiva.indexer.RepositoryIndexSearchException; import org.apache.maven.archiva.indexer.search.CrossRepositorySearch; import org.apache.maven.archiva.indexer.search.SearchResultLimits; import org.apache.maven.archiva.indexer.search.SearchResults; +import org.apache.maven.archiva.security.AccessDeniedException; +import org.apache.maven.archiva.security.ArchivaSecurityException; +import org.apache.maven.archiva.security.ArchivaUser; +import org.apache.maven.archiva.security.PrincipalNotFoundException; +import org.apache.maven.archiva.security.UserRepositories; import org.codehaus.plexus.xwork.action.PlexusActionSupport; import java.net.MalformedURLException; +import java.util.Collections; import java.util.List; /** @@ -60,6 +67,16 @@ public class SearchAction * @plexus.requirement role-hint="default" */ private CrossRepositorySearch crossRepoSearch; + + /** + * @plexus.requirement + */ + private UserRepositories userRepositories; + + /** + * @plexus.requirement role-hint="xwork" + */ + private ArchivaUser archivaUser; private static final String RESULTS = "results"; @@ -79,8 +96,14 @@ public class SearchAction assert q != null && q.length() != 0; SearchResultLimits limits = new SearchResultLimits( 0 ); + + List selectedRepos = getObservableRepos(); + if ( CollectionUtils.isEmpty( selectedRepos ) ) + { + return GlobalResults.ACCESS_TO_NO_REPOS; + } - results = crossRepoSearch.searchForTerm( q, limits ); + results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits ); if ( results.isEmpty() ) { @@ -125,16 +148,42 @@ public class SearchAction // 1 hit? return it's information directly! return ARTIFACT; } - else - { - return RESULTS; - } + + return RESULTS; } + @Override public String doInput() { return INPUT; } + + private String getPrincipal() + { + return archivaUser.getActivePrincipal(); + } + + private List getObservableRepos() + { + try + { + return userRepositories.getObservableRepositoryIds( getPrincipal() ); + } + catch ( PrincipalNotFoundException e ) + { + getLogger().warn( e.getMessage(), e ); + } + catch ( AccessDeniedException e ) + { + getLogger().warn( e.getMessage(), e ); + // TODO: pass this onto the screen. + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + return Collections.emptyList(); + } public String getQ() { diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java index 2c750c72d..faaa8261d 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ShowArtifactAction.java @@ -26,8 +26,14 @@ import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.database.ObjectNotFoundException; import org.apache.maven.archiva.database.browsing.RepositoryBrowsing; import org.apache.maven.archiva.model.ArchivaProjectModel; +import org.apache.maven.archiva.security.AccessDeniedException; +import org.apache.maven.archiva.security.ArchivaSecurityException; +import org.apache.maven.archiva.security.ArchivaUser; +import org.apache.maven.archiva.security.PrincipalNotFoundException; +import org.apache.maven.archiva.security.UserRepositories; import org.codehaus.plexus.xwork.action.PlexusActionSupport; +import java.util.Collections; import java.util.List; /** @@ -46,6 +52,16 @@ public class ShowArtifactAction * @plexus.requirement role-hint="default" */ private RepositoryBrowsing repoBrowsing; + + /** + * @plexus.requirement + */ + private UserRepositories userRepositories; + + /** + * @plexus.requirement role-hint="xwork" + */ + private ArchivaUser archivaUser; /* .\ Input Parameters \.________________________________________ */ @@ -86,7 +102,7 @@ public class ShowArtifactAction { try { - this.model = repoBrowsing.selectVersion( groupId, artifactId, version ); + this.model = repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); } catch ( ObjectNotFoundException oe ) { @@ -104,7 +120,7 @@ public class ShowArtifactAction public String dependencies() throws ObjectNotFoundException, ArchivaDatabaseException { - this.model = repoBrowsing.selectVersion( groupId, artifactId, version ); + this.model = repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); this.dependencies = model.getDependencies(); @@ -117,7 +133,7 @@ public class ShowArtifactAction public String mailingLists() throws ObjectNotFoundException, ArchivaDatabaseException { - this.model = repoBrowsing.selectVersion( groupId, artifactId, version ); + this.model = repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); this.mailingLists = model.getMailingLists(); return SUCCESS; @@ -142,9 +158,9 @@ public class ShowArtifactAction public String dependees() throws ObjectNotFoundException, ArchivaDatabaseException { - this.model = repoBrowsing.selectVersion( groupId, artifactId, version ); + this.model = repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); - this.dependees = repoBrowsing.getUsedBy( groupId, artifactId, version ); + this.dependees = repoBrowsing.getUsedBy( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); return SUCCESS; } @@ -155,10 +171,37 @@ public class ShowArtifactAction public String dependencyTree() throws ObjectNotFoundException, ArchivaDatabaseException { - this.model = repoBrowsing.selectVersion( groupId, artifactId, version ); + this.model = repoBrowsing.selectVersion( getPrincipal(), getObservableRepos(), groupId, artifactId, version ); return SUCCESS; } + + private String getPrincipal() + { + return archivaUser.getActivePrincipal(); + } + + private List getObservableRepos() + { + try + { + return userRepositories.getObservableRepositoryIds( getPrincipal() ); + } + catch ( PrincipalNotFoundException e ) + { + getLogger().warn( e.getMessage(), e ); + } + catch ( AccessDeniedException e ) + { + getLogger().warn( e.getMessage(), e ); + // TODO: pass this onto the screen. + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + return Collections.emptyList(); + } public void validate() { diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/SecuritySynchronization.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/SecuritySynchronization.java index 0153a7b23..10283a90f 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/SecuritySynchronization.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/SecuritySynchronization.java @@ -193,14 +193,13 @@ public class SecuritySynchronization ua = rbacManager.createUserAssignment( principal ); } - ua.addRoleName( ArchivaRoleConstants.REPOSITORY_OBSERVER_ROLE_PREFIX + " - " + repoId ); + ua.addRoleName( ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) ); rbacManager.saveUserAssignment( ua ); } catch ( RbacManagerException e ) { - getLogger().warn( - "Unable to add role [" + ArchivaRoleConstants.REPOSITORY_OBSERVER_ROLE_PREFIX + " - " - + repoId + "] to " + principal + " user.", e ); + getLogger().warn( "Unable to add role [" + ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) + + "] to " + principal + " user.", e ); } } } diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ArchivaXworkUser.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ArchivaXworkUser.java new file mode 100644 index 000000000..44223b82c --- /dev/null +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/util/ArchivaXworkUser.java @@ -0,0 +1,77 @@ +package org.apache.maven.archiva.web.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import com.opensymphony.xwork.ActionContext; + +import org.apache.maven.archiva.security.ArchivaRoleConstants; +import org.apache.maven.archiva.security.ArchivaUser; +import org.codehaus.plexus.redback.system.SecuritySession; +import org.codehaus.plexus.redback.users.User; + +import java.util.HashMap; +import java.util.Map; + +/** + * ArchivaXworkUser + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.apache.maven.archiva.security.ArchivaUser" + * role-hint="xwork" + */ +public class ArchivaXworkUser + implements ArchivaUser +{ + private Map getContextSession() + { + ActionContext context = ActionContext.getContext(); + Map sessionMap = context.getSession(); + if ( sessionMap == null ) + { + sessionMap = new HashMap(); + } + + return sessionMap; + } + + private SecuritySession getSecuritySession() + { + return (SecuritySession) getContextSession().get( SecuritySession.ROLE ); + } + + public String getActivePrincipal() + { + SecuritySession securitySession = getSecuritySession(); + if ( securitySession == null ) + { + return ArchivaRoleConstants.PRINCIPAL_GUEST; + } + + User user = securitySession.getUser(); + if ( user == null ) + { + return ArchivaRoleConstants.PRINCIPAL_GUEST; + } + + return (String) user.getPrincipal(); + } +} diff --git a/archiva-web/archiva-webapp/src/main/resources/xwork.xml b/archiva-web/archiva-webapp/src/main/resources/xwork.xml index d75ae3172..53c8596cd 100644 --- a/archiva-web/archiva-webapp/src/main/resources/xwork.xml +++ b/archiva-web/archiva-webapp/src/main/resources/xwork.xml @@ -82,6 +82,7 @@ + index index @@ -126,6 +127,7 @@ /WEB-INF/jsp/generalError.jsp + /WEB-INF/jsp/accessToNoRepos.jsp diff --git a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/accessToNoRepos.jsp b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/accessToNoRepos.jsp new file mode 100644 index 000000000..5ed04736f --- /dev/null +++ b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/accessToNoRepos.jsp @@ -0,0 +1,46 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + +<%@ taglib prefix="ww" uri="/webwork" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + You have access to no repositories + + + + + +
+ +
+ You have access to no repositories. + Ask your system administrator for access. +
+ +
+ +
+
+
+ + + + diff --git a/pom.xml b/pom.xml index 2fb881c95..39c90e752 100644 --- a/pom.xml +++ b/pom.xml @@ -579,12 +579,40 @@ org.codehaus.plexus.redback redback-rbac-memory ${redback.version} + test + + + org.codehaus.plexus.redback + redback-users-memory + ${redback.version} + test + + + org.codehaus.plexus.redback + redback-keys-memory + ${redback.version} + test + + + org.codehaus.plexus.redback + redback-rbac-model + ${redback.version} + + + org.codehaus.plexus.redback + redback-authorization-rbac + ${redback.version} org.codehaus.plexus.redback redback-rbac-role-manager ${redback.version} + + org.codehaus.plexus.redback + redback-system + ${redback.version} + org.codehaus.plexus.redback redback-taglib @@ -862,13 +890,16 @@ 2.0.5 1.0-beta-2 - 1.0-alpha-3 + 1.0-alpha-4 codehaus.snapshots http://snapshots.repository.codehaus.org/ + + true + -- 2.39.5