From: Martin Stockhammer Date: Sun, 19 Dec 2021 17:41:02 +0000 (+0100) Subject: Refactoring - consolidating package names X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5e8ae2434d547387b85d4822d49d37a78ad2bd20;p=archiva.git Refactoring - consolidating package names --- diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Artifact.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Artifact.java deleted file mode 100644 index c8fae1e41..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Artifact.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import java.io.Serializable; - -/** - * @author Martin Stockhammer - */ -@Schema(name="Artifact", description = "Information about artifacts") -public class Artifact implements Serializable -{ - private static final long serialVersionUID = 7581578317346876555L; - private String name; - - @Schema(name="name",description = "The name of the artifact") - public String getName( ) - { - return name; - } - - public void setName( String name ) - { - this.name = name; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ArtifactTransferRequest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ArtifactTransferRequest.java deleted file mode 100644 index ce22bc4ae..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ArtifactTransferRequest.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import java.io.Serializable; - -/** - * @author Martin Stockhammer - */ -public class ArtifactTransferRequest implements Serializable -{ - private static final long serialVersionUID = -7377281345536573342L; - - private String path; - - @Schema(description = "The path to the artifact") - public String getPath( ) - { - return path; - } - - public void setPath( String path ) - { - this.path = path; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/BeanInformation.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/BeanInformation.java deleted file mode 100644 index b795acddc..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/BeanInformation.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.Objects; - -/** - * @author Martin Stockhammer - */ -@XmlRootElement(name="beanInformation") -@Schema(name="BeanInformation",description = "Information about a bean instance.") -public class BeanInformation implements Serializable -{ - private static final long serialVersionUID = -432385743277355987L; - private String id; - private String displayName; - private String descriptionKey; - private String defaultDescription; - private boolean readonly; - - public BeanInformation( ) - { - } - - public BeanInformation( String id, String displayName, String descriptionKey, String defaultDescription, boolean readonly ) - { - this.id = id; - this.displayName = displayName; - this.descriptionKey = descriptionKey; - this.defaultDescription = defaultDescription; - this.readonly = readonly; - } - - @Schema(description = "The identifier") - public String getId( ) - { - return id; - } - - public void setId( String id ) - { - this.id = id; - } - - @Schema(name="display_name", description = "The display name") - public String getDisplayName( ) - { - return displayName; - } - - public void setDisplayName( String displayName ) - { - this.displayName = displayName; - } - - @Schema(name="description_key", description = "The translation key for the description") - public String getDescriptionKey( ) - { - return descriptionKey; - } - - public void setDescriptionKey( String descriptionKey ) - { - this.descriptionKey = descriptionKey; - } - - @Schema(name="default_description", description = "The description translated in the default language") - public String getDefaultDescription( ) - { - return defaultDescription; - } - - public void setDefaultDescription( String defaultDescription ) - { - this.defaultDescription = defaultDescription; - } - - @Schema(description = "True, if this bean cannot be removed") - public boolean isReadonly( ) - { - return readonly; - } - - public void setReadonly( boolean readonly ) - { - this.readonly = readonly; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - BeanInformation that = (BeanInformation) o; - return readonly == that.readonly && id.equals( that.id ) && Objects.equals( displayName, that.displayName ) && Objects.equals( descriptionKey, that.descriptionKey ) && Objects.equals( defaultDescription, that.defaultDescription ); - } - - @Override - public int hashCode( ) - { - return Objects.hash( id, displayName, descriptionKey, defaultDescription, readonly ); - } - - @Override - public String toString( ) - { - return "BeanInformation{" + - "id='" + id + '\'' + - ", display_name='" + displayName + '\'' + - ", description_key='" + descriptionKey + '\'' + - ", default_description='" + defaultDescription + '\'' + - ", readonly=" + readonly + - '}'; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/CacheConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/CacheConfiguration.java deleted file mode 100644 index 353890013..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/CacheConfiguration.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; - -/** - * @author Olivier Lamy - * @author Martin Stockhammer - * @since 3.0 - */ -@XmlRootElement( name = "cacheConfiguration" ) -@Schema(name="CacheConfiguration",description = "Cache configuration attributes") -public class CacheConfiguration - implements Serializable -{ - private static final long serialVersionUID = 5479989049980673894L; - /** - * TimeToIdleSeconds. - */ - private int timeToIdleSeconds = -1; - - /** - * TimeToLiveSeconds. - */ - private int timeToLiveSeconds = -1; - - /** - * max elements in memory. - */ - private int maxEntriesInMemory = -1; - - /** - * max elements on disk. - */ - private int maxEntriesOnDisk = -1; - - public CacheConfiguration() - { - // no op - } - - public static CacheConfiguration of( org.apache.archiva.admin.model.beans.CacheConfiguration beanConfiguration ) { - CacheConfiguration newConfig = new CacheConfiguration( ); - newConfig.setMaxEntriesInMemory( beanConfiguration.getMaxElementsInMemory() ); - newConfig.setMaxEntriesOnDisk( beanConfiguration.getMaxElementsOnDisk() ); - newConfig.setTimeToIdleSeconds( beanConfiguration.getTimeToIdleSeconds( ) ); - newConfig.setTimeToLiveSeconds( beanConfiguration.getTimeToLiveSeconds( ) ); - return newConfig; - } - - @Schema(name="time_to_idle_seconds", description = "The maximum number of seconds an element can exist in the cache without being accessed. "+ - "The element expires at this limit and will no longer be returned from the cache.") - public int getTimeToIdleSeconds() - { - return timeToIdleSeconds; - } - - public void setTimeToIdleSeconds( int timeToIdleSeconds ) - { - this.timeToIdleSeconds = timeToIdleSeconds; - } - - @Schema(name="time_to_live_seconds", description = "The maximum number of seconds an element can exist in the cache regardless of use. "+ - "The element expires at this limit and will no longer be returned from the cache.") - public int getTimeToLiveSeconds() - { - return timeToLiveSeconds; - } - - public void setTimeToLiveSeconds( int timeToLiveSeconds ) - { - this.timeToLiveSeconds = timeToLiveSeconds; - } - - @Schema(name="max_entries_in_memory", description = "The maximum cache entries to keep in memory. If the limit is reached, older entries will be evicted, or persisted on disk.") - public int getMaxEntriesInMemory() - { - return maxEntriesInMemory; - } - - public void setMaxEntriesInMemory( int maxEntriesInMemory ) - { - this.maxEntriesInMemory = maxEntriesInMemory; - } - - @Schema(name="max_entries_on_disk", description = "The maximum cache entries to keep on disk. If the limit is reached, older entries will be evicted.") - public int getMaxEntriesOnDisk() - { - return maxEntriesOnDisk; - } - - public void setMaxEntriesOnDisk( int maxEntriesOnDisk ) - { - this.maxEntriesOnDisk = maxEntriesOnDisk; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - CacheConfiguration that = (CacheConfiguration) o; - - if ( timeToIdleSeconds != that.timeToIdleSeconds ) return false; - if ( timeToLiveSeconds != that.timeToLiveSeconds ) return false; - if ( maxEntriesInMemory != that.maxEntriesInMemory ) return false; - return maxEntriesOnDisk == that.maxEntriesOnDisk; - } - - @Override - public int hashCode( ) - { - int result = timeToIdleSeconds; - result = 31 * result + timeToLiveSeconds; - result = 31 * result + maxEntriesInMemory; - result = 31 * result + maxEntriesOnDisk; - return result; - } - - @Override - public String toString() - { - final StringBuilder sb = new StringBuilder(); - sb.append( "CacheConfiguration" ); - sb.append( "{time_to_idle_seconds=" ).append( timeToIdleSeconds ); - sb.append( ", time_to_live_seconds=" ).append( timeToLiveSeconds ); - sb.append( ", max_elements_in_memory=" ).append( maxEntriesInMemory ); - sb.append( ", max_elements_on_disk=" ).append( maxEntriesOnDisk ); - sb.append( '}' ); - return sb.toString(); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java deleted file mode 100644 index d5612c6f3..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.storage.StorageAsset; - -import java.io.Serializable; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; - -/** - * @author Martin Stockhammer - */ -@Schema(name="FileInfo",description = "Information about a file stored in the repository") -public class FileInfo implements Serializable -{ - private static final long serialVersionUID = 900497784542880195L; - private OffsetDateTime modified; - private String fileName; - private String path; - - public FileInfo( ) - { - } - - public static FileInfo of( StorageAsset asset ) { - FileInfo fileInfo = new FileInfo( ); - fileInfo.setFileName( asset.getName() ); - fileInfo.setPath( asset.getPath() ); - fileInfo.setModified( asset.getModificationTime( ).atOffset( ZoneOffset.UTC ) ); - return fileInfo; - } - - @Schema(description = "Time when the file was last modified") - public OffsetDateTime getModified( ) - { - return modified; - } - - public void setModified( OffsetDateTime modified ) - { - this.modified = modified; - } - - @Schema(name="file_name", description = "Name of the file") - public String getFileName( ) - { - return fileName; - } - - public void setFileName( String fileName ) - { - this.fileName = fileName; - } - - @Schema(name="path", description = "Path to the file relative to the repository directory") - public String getPath( ) - { - return path; - } - - public void setPath( String path ) - { - this.path = path; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - FileInfo fileInfo = (FileInfo) o; - - if ( modified != null ? !modified.equals( fileInfo.modified ) : fileInfo.modified != null ) return false; - if ( fileName != null ? !fileName.equals( fileInfo.fileName ) : fileInfo.fileName != null ) return false; - return path != null ? path.equals( fileInfo.path ) : fileInfo.path == null; - } - - @Override - public int hashCode( ) - { - int result = modified != null ? modified.hashCode( ) : 0; - result = 31 * result + ( fileName != null ? fileName.hashCode( ) : 0 ); - result = 31 * result + ( path != null ? path.hashCode( ) : 0 ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "FileInfo{" ); - sb.append( "modified=" ).append( modified ); - sb.append( ", fileName='" ).append( fileName ).append( '\'' ); - sb.append( ", path='" ).append( path ).append( '\'' ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java deleted file mode 100644 index b3bc50930..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/IndexingTask.java +++ /dev/null @@ -1,158 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask; -import org.apache.archiva.scheduler.repository.model.RepositoryTask; - -import java.io.Serializable; - -/** - * @author Martin Stockhammer - */ -@Schema(name="IndexingTask",description = "Information about indexing tasks") -public class IndexingTask implements Serializable -{ - private static final long serialVersionUID = -1947200162602613310L; - private String repositoryId = ""; - private boolean fullRepository; - private boolean updateOnly; - private String resource = ""; - private boolean running = false; - private long maxExecutionTimeMs = 0; - - public static IndexingTask of( org.apache.archiva.admin.model.beans.IndexingTask repositoryTask ) { - IndexingTask indexingTask = new IndexingTask( ); - indexingTask.setFullRepository( repositoryTask.isFullScan()); - indexingTask.setUpdateOnly( repositoryTask.isUpdateOnly() ); - indexingTask.setResource( repositoryTask.getResource() ); - indexingTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() ); - indexingTask.setRepositoryId( repositoryTask.getRepositoryId() ); - return indexingTask; - } - - @Schema(name="repository_id",description = "Identifier of the repository this task is running on") - public String getRepositoryId( ) - { - return repositoryId; - } - - public void setRepositoryId( String repositoryId ) - { - this.repositoryId = repositoryId==null?"":repositoryId; - } - - @Schema( name = "full_repository", description = "True, if this is a full repository index scan" ) - public boolean isFullRepository( ) - { - return fullRepository; - } - - public void setFullRepository( boolean fullRepository ) - { - this.fullRepository = fullRepository; - } - - @Schema(name="update_only", description = "True, if this is only updating the index with new files") - public boolean isUpdateOnly( ) - { - return updateOnly; - } - - public void setUpdateOnly( boolean updateOnly ) - { - this.updateOnly = updateOnly; - } - - @Schema(name="resource",description = "The resource that should be updated, if this is not a full repo update") - public String getResource( ) - { - return resource; - } - - public void setResource( String resource ) - { - this.resource = resource == null ? "" : resource; - } - - @Schema(name="running", description = "True, if this task is currently running") - public boolean isRunning( ) - { - return running; - } - - public void setRunning( boolean running ) - { - this.running = running; - } - - @Schema(name="max_execution_time_ms",description = "Maximum task execution time in ms") - public long getMaxExecutionTimeMs( ) - { - return maxExecutionTimeMs; - } - - public void setMaxExecutionTimeMs( long maxExecutionTimeMs ) - { - this.maxExecutionTimeMs = maxExecutionTimeMs; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - IndexingTask that = (IndexingTask) o; - - if ( fullRepository != that.fullRepository ) return false; - if ( updateOnly != that.updateOnly ) return false; - if ( running != that.running ) return false; - if ( maxExecutionTimeMs != that.maxExecutionTimeMs ) return false; - if ( !repositoryId.equals( that.repositoryId ) ) return false; - return resource.equals( that.resource ); - } - - @Override - public int hashCode( ) - { - int result = repositoryId.hashCode( ); - result = 31 * result + ( fullRepository ? 1 : 0 ); - result = 31 * result + ( updateOnly ? 1 : 0 ); - result = 31 * result + resource.hashCode( ); - result = 31 * result + ( running ? 1 : 0 ); - result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "IndexingTask{" ); - sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' ); - sb.append( ", fullRepository=" ).append( fullRepository ); - sb.append( ", updateOnly=" ).append( updateOnly ); - sb.append( ", resource='" ).append( resource ).append( '\'' ); - sb.append( ", running=" ).append( running ); - sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs ); - sb.append( '}' ); - return sb.toString( ); - } - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/LdapConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/LdapConfiguration.java deleted file mode 100644 index d6d481a15..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/LdapConfiguration.java +++ /dev/null @@ -1,327 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.TreeMap; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@XmlRootElement(name="ldapConfiguration") -@Schema(name="LdapConfiguration", description = "LDAP configuration attributes") -public class LdapConfiguration implements Serializable -{ - private static final long serialVersionUID = -4736767846016398583L; - - private String hostName = ""; - private int port = 389; - private String baseDn = ""; - private String groupsBaseDn = ""; - private String bindDn = ""; - private String bindPassword = ""; - private String authenticationMethod = "none"; - private String contextFactory; - private boolean sslEnabled = false; - private boolean bindAuthenticatorEnabled = true; - private boolean useRoleNameAsGroup = false; - private Map properties = new TreeMap<>(); - private boolean writable = false; - private List availableContextFactories; - - public LdapConfiguration( ) - { - } - - public static LdapConfiguration of( org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfiguration ) { - LdapConfiguration newCfg = new LdapConfiguration( ); - newCfg.setAuthenticationMethod( ldapConfiguration.getAuthenticationMethod( ) ); - newCfg.setBaseDn( ldapConfiguration.getBaseDn( ) ); - newCfg.setGroupsBaseDn( ldapConfiguration.getBaseGroupsDn() ); - newCfg.setBindDn( ldapConfiguration.getBindDn() ); - newCfg.setBindPassword( ldapConfiguration.getPassword() ); - newCfg.setBindAuthenticatorEnabled( ldapConfiguration.isBindAuthenticatorEnabled() ); - newCfg.setHostName( ldapConfiguration.getHostName( ) ); - newCfg.setSslEnabled( ldapConfiguration.isSsl() ); - newCfg.setContextFactory( ldapConfiguration.getContextFactory() ); - if (ldapConfiguration.getPort()<=0) { - newCfg.setPort( newCfg.isSslEnabled() ? 636 : 389 ); - } else - { - newCfg.setPort( ldapConfiguration.getPort( ) ); - } - newCfg.setProperties( ldapConfiguration.getExtraProperties( ) ); - newCfg.setWritable( ldapConfiguration.isWritable() ); - return newCfg; - } - - @Schema(name="host_name", description = "The hostname to use to connect to the LDAP server") - public String getHostName( ) - { - return hostName; - } - - public void setHostName( String hostName ) - { - this.hostName = hostName==null?"":hostName; - } - - @Schema(description = "The port to use to connect to the LDAP server") - public int getPort( ) - { - return port; - } - - public void setPort( int port ) - { - this.port = port; - } - - @Schema(name="context_factory",description = "The class name of the LDAP context factory") - public String getContextFactory( ) - { - return contextFactory; - } - - public void setContextFactory( String contextFactory ) - { - this.contextFactory = contextFactory; - } - - - @Schema(name="ssl_enabled", description = "True, if SSL/TLS should be used for connecting the LDAP server") - public boolean isSslEnabled( ) - { - return sslEnabled; - } - - public void setSslEnabled( boolean sslEnabled ) - { - this.sslEnabled = sslEnabled; - } - - @Schema(name="base_dn", description = "The BASE DN used for the LDAP server") - public String getBaseDn( ) - { - return baseDn; - } - - public void setBaseDn( String baseDn ) - { - this.baseDn = baseDn == null ? "" : baseDn; - } - - @Schema(name="bind_dn", description = "The distinguished name of the bind user which is used to bind to the LDAP server") - public String getBindDn( ) - { - return bindDn; - } - - public void setBindDn( String bindDn ) - { - this.bindDn = bindDn == null ? "" : bindDn; - } - - @Schema(name="bind_password", description = "The password used to bind to the ldap server") - public String getBindPassword( ) - { - return bindPassword; - } - - public void setBindPassword( String bindPassword ) - { - this.bindPassword = bindPassword==null?"":bindPassword; - } - - @Schema(name="groups_base_dn", description = "The distinguished name of the base to use for searching group.") - public String getGroupsBaseDn( ) - { - return groupsBaseDn; - } - - public void setGroupsBaseDn( String groupsBaseDn ) - { - this.groupsBaseDn = groupsBaseDn==null?"":groupsBaseDn; - } - - @Schema(name="authentication_method", description = "The authentication method used to bind to the LDAP server (PLAINTEXT, SASL, ...)") - public String getAuthenticationMethod( ) - { - return authenticationMethod; - } - - public void setAuthenticationMethod( String authenticationMethod ) - { - this.authenticationMethod = authenticationMethod==null?"":authenticationMethod; - } - - @Schema(name="bind_authenticator_enabled", description = "True, if the LDAP bind authentication is used for logging in to Archiva") - public boolean isBindAuthenticatorEnabled( ) - { - return bindAuthenticatorEnabled; - } - - public void setBindAuthenticatorEnabled( boolean bindAuthenticatorEnabled ) - { - this.bindAuthenticatorEnabled = bindAuthenticatorEnabled; - } - - @Schema(name="user_role_name_as_group", description = "True, if the archiva role name is also the LDAP group name") - public boolean isUseRoleNameAsGroup( ) - { - return useRoleNameAsGroup; - } - - public void setUseRoleNameAsGroup( boolean useRoleNameAsGroup ) - { - this.useRoleNameAsGroup = useRoleNameAsGroup; - } - - @Schema(description = "LDAP ConnectionFactory environment properties") - public Map getProperties( ) - { - return properties; - } - - public void setProperties( Map properties ) - { - this.properties = new TreeMap<>( properties ); - } - - public void addProperty(String key, String value) { - this.properties.put( key, value ); - } - - @Schema(description = "True, if attributes in the the LDAP server can be edited by Archiva") - public boolean isWritable( ) - { - return writable; - } - - public void setWritable( boolean writable ) - { - this.writable = writable; - } - - @Schema(name="available_context_factories", description = "The LDAP context factories that are known and available") - public List getAvailableContextFactories( ) - { - return availableContextFactories; - } - - public void setAvailableContextFactories( List availableContextFactories ) - { - this.availableContextFactories = new ArrayList<>( availableContextFactories ); - } - - public void addAvailableContextFactory(String contextFactory) { - if (!this.availableContextFactories.contains( contextFactory ) ) { - this.availableContextFactories.add( contextFactory ); - } - } - - - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - LdapConfiguration that = (LdapConfiguration) o; - - if ( port != that.port ) return false; - if ( sslEnabled != that.sslEnabled ) return false; - if ( bindAuthenticatorEnabled != that.bindAuthenticatorEnabled ) return false; - if ( useRoleNameAsGroup != that.useRoleNameAsGroup ) return false; - if ( writable != that.writable ) return false; - if ( !Objects.equals( hostName, that.hostName ) ) return false; - if ( !Objects.equals( baseDn, that.baseDn ) ) return false; - if ( !Objects.equals( bindDn, that.bindDn ) ) return false; - if ( !Objects.equals( groupsBaseDn, that.groupsBaseDn ) ) - return false; - if ( !Objects.equals( bindPassword, that.bindPassword ) ) return false; - if ( !Objects.equals( authenticationMethod, that.authenticationMethod ) ) - return false; - return properties.equals( that.properties ); - } - - @Override - public int hashCode( ) - { - int result = hostName != null ? hostName.hashCode( ) : 0; - result = 31 * result + port; - result = 31 * result + ( sslEnabled ? 1 : 0 ); - result = 31 * result + ( baseDn != null ? baseDn.hashCode( ) : 0 ); - result = 31 * result + ( bindDn != null ? bindDn.hashCode( ) : 0 ); - result = 31 * result + ( groupsBaseDn != null ? groupsBaseDn.hashCode( ) : 0 ); - result = 31 * result + ( bindPassword != null ? bindPassword.hashCode( ) : 0 ); - result = 31 * result + ( authenticationMethod != null ? authenticationMethod.hashCode( ) : 0 ); - result = 31 * result + ( bindAuthenticatorEnabled ? 1 : 0 ); - result = 31 * result + ( useRoleNameAsGroup ? 1 : 0 ); - result = 31 * result + properties.hashCode( ); - result = 31 * result + ( writable ? 1 : 0 ); - return result; - } - - @SuppressWarnings( "StringBufferReplaceableByString" ) - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "LdapConfiguration{" ); - sb.append( "host_name='" ).append( hostName ).append( '\'' ); - sb.append( ", port=" ).append( port ); - sb.append( ", ssl_enabled=" ).append( sslEnabled ); - sb.append( ", base_dn='" ).append( baseDn ).append( '\'' ); - sb.append( ", groups_base_dn='" ).append( groupsBaseDn ).append( '\'' ); - sb.append( ", bind_dn='" ).append( bindDn ).append( '\'' ); - sb.append( ", bind_password='" ).append( bindPassword ).append( '\'' ); - sb.append( ", authentication_method='" ).append( authenticationMethod ).append( '\'' ); - sb.append( ", bind_authenticator_enabled=" ).append( bindAuthenticatorEnabled ); - sb.append( ", use_role_name_as_group=" ).append( useRoleNameAsGroup ); - sb.append( ", properties=" ).append( properties ); - sb.append( ", writable=" ).append( writable ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java deleted file mode 100644 index 99455f148..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java +++ /dev/null @@ -1,264 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.ManagedRepository; -import org.apache.archiva.repository.RepositoryType; -import org.apache.archiva.repository.features.ArtifactCleanupFeature; -import org.apache.archiva.repository.features.IndexCreationFeature; -import org.apache.archiva.repository.features.StagingRepositoryFeature; - -import java.time.Period; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * @author Martin Stockhammer - */ -@Schema(name="MavenManagedRepository",description = "A managed repository stores artifacts locally") -public class MavenManagedRepository extends Repository -{ - private static final long serialVersionUID = -6853748886201905029L; - - boolean blocksRedeployments; - List releaseSchemes = new ArrayList<>( ); - boolean deleteSnapshotsOfRelease = false; - private Period retentionPeriod; - private int retentionCount; - private String indexPath; - private String packedIndexPath; - private boolean skipPackedIndexCreation; - private boolean hasStagingRepository; - private String stagingRepository; - - - public MavenManagedRepository( ) - { - super.setCharacteristic( Repository.CHARACTERISTIC_MANAGED ); - super.setType( RepositoryType.MAVEN.name( ) ); - } - - protected static void update(MavenManagedRepository repo, ManagedRepository beanRepo) { - repo.setDescription( beanRepo.getDescription() ); - repo.setId( beanRepo.getId() ); - repo.setIndex( true ); - repo.setLayout( beanRepo.getLayout() ); - repo.setBlocksRedeployments( beanRepo.blocksRedeployments() ); - repo.setReleaseSchemes( beanRepo.getActiveReleaseSchemes().stream().map( Objects::toString).collect( Collectors.toList()) ); - repo.setLocation( beanRepo.getLocation().toString() ); - repo.setName( beanRepo.getName()); - repo.setScanned( beanRepo.isScanned() ); - repo.setSchedulingDefinition( beanRepo.getSchedulingDefinition() ); - ArtifactCleanupFeature artifactCleanupFeature = beanRepo.getFeature( ArtifactCleanupFeature.class ).get( ); - repo.setDeleteSnapshotsOfRelease( artifactCleanupFeature.isDeleteReleasedSnapshots()); - repo.setRetentionCount( artifactCleanupFeature.getRetentionCount()); - repo.setRetentionPeriod( artifactCleanupFeature.getRetentionPeriod() ); - IndexCreationFeature icf = beanRepo.getFeature( IndexCreationFeature.class ).get( ); - repo.setIndex( icf.hasIndex( ) ); - repo.setIndexPath( icf.getIndexPath( ).getPath( ) ); - repo.setPackedIndexPath( icf.getPackedIndexPath( ).getPath( ) ); - repo.setSkipPackedIndexCreation( icf.isSkipPackedIndexCreation() ); - StagingRepositoryFeature srf = beanRepo.getFeature( StagingRepositoryFeature.class ).get( ); - repo.setHasStagingRepository( srf.isStageRepoNeeded( ) ); - repo.setStagingRepository( srf.getStagingRepository()!=null?srf.getStagingRepository().getId():"" ); - } - - public static MavenManagedRepository of( ManagedRepository beanRepo ) { - MavenManagedRepository repo = new MavenManagedRepository( ); - update( repo, beanRepo ); - return repo; - } - - @Schema(name="blocks_redeployments",description = "True, if redeployments to this repository are not allowed") - public boolean isBlocksRedeployments( ) - { - return blocksRedeployments; - } - - public void setBlocksRedeployments( boolean blocksRedeployments ) - { - this.blocksRedeployments = blocksRedeployments; - } - - @Schema(name="release_schemes", description = "The release schemes this repository is used for (e.g. RELEASE, SNAPSHOT)") - public List getReleaseSchemes( ) - { - return releaseSchemes; - } - - public void setReleaseSchemes( List releaseSchemes ) - { - this.releaseSchemes = new ArrayList<>( releaseSchemes ); - } - - public void addReleaseScheme(String scheme) { - if (!this.releaseSchemes.contains( scheme )) - { - this.releaseSchemes.add( scheme ); - } - } - - @Schema(name="delete_snaphots_of_release", description = "True, if snapshots are deleted, after a version is released") - public boolean isDeleteSnapshotsOfRelease( ) - { - return deleteSnapshotsOfRelease; - } - - public void setDeleteSnapshotsOfRelease( boolean deleteSnapshotsOfRelease ) - { - this.deleteSnapshotsOfRelease = deleteSnapshotsOfRelease; - } - - @Schema(name="retention_period", description = "The period after which snapshots are deleted.") - public Period getRetentionPeriod( ) - { - return retentionPeriod; - } - - public void setRetentionPeriod( Period retentionPeriod ) - { - this.retentionPeriod = retentionPeriod; - } - - @Schema(name="retention_count", description = "Number of snapshot artifacts to keep.") - public int getRetentionCount( ) - { - return retentionCount; - } - - public void setRetentionCount( int retentionCount ) - { - this.retentionCount = retentionCount; - } - - @Schema( name = "index_path", description = "Path to the directory that contains the index, relative to the repository base directory" ) - public String getIndexPath( ) - { - return indexPath; - } - - public void setIndexPath( String indexPath ) - { - this.indexPath = indexPath; - } - - @Schema( name = "packed_index_path", description = "Path to the directory that contains the packed index, relative to the repository base directory" ) - public String getPackedIndexPath( ) - { - return packedIndexPath; - } - - public void setPackedIndexPath( String packedIndexPath ) - { - this.packedIndexPath = packedIndexPath; - } - - @Schema(name="skip_packed_index_creation", description = "True, if packed index is not created during index update") - public boolean isSkipPackedIndexCreation( ) - { - return skipPackedIndexCreation; - } - - public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation ) - { - this.skipPackedIndexCreation = skipPackedIndexCreation; - } - - @Schema(name="has_staging_repository", description = "True, if this repository has a staging repository assigned") - public boolean isHasStagingRepository( ) - { - return hasStagingRepository; - } - - public void setHasStagingRepository( boolean hasStagingRepository ) - { - this.hasStagingRepository = hasStagingRepository; - } - - @Schema(name="staging_repository", description = "The id of the assigned staging repository") - public String getStagingRepository( ) - { - return stagingRepository; - } - - public void setStagingRepository( String stagingRepository ) - { - this.stagingRepository = stagingRepository; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - if ( !super.equals( o ) ) return false; - - MavenManagedRepository that = (MavenManagedRepository) o; - - if ( blocksRedeployments != that.blocksRedeployments ) return false; - return releaseSchemes != null ? releaseSchemes.equals( that.releaseSchemes ) : that.releaseSchemes == null; - } - - @Override - public int hashCode( ) - { - int result = super.hashCode( ); - result = 31 * result + ( blocksRedeployments ? 1 : 0 ); - result = 31 * result + ( releaseSchemes != null ? releaseSchemes.hashCode( ) : 0 ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "ManagedRepository{" ); - sb.append( "blocksRedeployments=" ).append( blocksRedeployments ); - sb.append( ", releaseSchemes=" ).append( releaseSchemes ); - sb.append( ", id='" ).append( id ).append( '\'' ); - sb.append( ", name='" ).append( name ).append( '\'' ); - sb.append( ", description='" ).append( description ).append( '\'' ); - sb.append( ", type='" ).append( type ).append( '\'' ); - sb.append( ", location='" ).append( location ).append( '\'' ); - sb.append( ", scanned=" ).append( scanned ); - sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' ); - sb.append( ", index=" ).append( index ); - sb.append( ", layout='" ).append( layout ).append( '\'' ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java deleted file mode 100644 index 32809f63c..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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.archiva.repository.ManagedRepository; - -import java.io.Serializable; - -/** - * @author Martin Stockhammer - */ -public class MavenManagedRepositoryUpdate extends MavenManagedRepository implements Serializable -{ - private static final long serialVersionUID = -9181643343284109862L; - private boolean resetStats = false; - - public static MavenManagedRepositoryUpdate of( ManagedRepository repository ) { - MavenManagedRepositoryUpdate repo = new MavenManagedRepositoryUpdate( ); - update( repo, repository ); - return repo; - } - - public boolean isResetStats( ) - { - return resetStats; - } - - public void setResetStats( boolean resetStats ) - { - this.resetStats = resetStats; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenRemoteRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenRemoteRepository.java deleted file mode 100644 index 3f05fb4ee..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenRemoteRepository.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Map; -import java.util.TreeMap; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@Schema(name="MavenRemoteRepository",description = "A remote repository definition is used to pull artifacts from other repositories") -public class MavenRemoteRepository extends Repository -{ - private static final long serialVersionUID = 5625043398766480265L; - String loginUser; - String loginPassword; - String checkPath; - Map extraParameters = new TreeMap<>( ); - Map requestHeader = new TreeMap<>( ); - long timeoutMs; - - @Schema(name="login_user",description = "Username for login to the remote repository") - public String getLoginUser( ) - { - return loginUser; - } - - public void setLoginUser( String loginUser ) - { - this.loginUser = loginUser; - } - - @Schema(name="login_password",description = "Password for connecting to the remote repository") - public String getLoginPassword( ) - { - return loginPassword; - } - - public void setLoginPassword( String loginPassword ) - { - this.loginPassword = loginPassword; - } - - @Schema(name="check_path",description = "Path relative to the repository URL that is used to check of availability of the remote repository.") - public String getCheckPath( ) - { - return checkPath; - } - - public void setCheckPath( String checkPath ) - { - this.checkPath = checkPath; - } - - @Schema(name="extra_parameters", description = "Key-Value map with extra parameters sent to the remote repository") - public Map getExtraParameters( ) - { - return extraParameters; - } - - public void setExtraParameters( Map extraParameters ) - { - this.extraParameters = new TreeMap<>( extraParameters ); - } - - public void addExtraParameter(String key, String value) { - this.extraParameters.put( key, value ); - } - - @Schema(name="request_header",description = "Key-Value map with request headers that are sent to the remote repository") - public Map getRequestHeader( ) - { - return requestHeader; - } - - public void setRequestHeader( Map requestHeader ) - { - this.requestHeader = new TreeMap<>( requestHeader ); - } - - public void addRequestHeader(String headerName, String headerValue) { - this.requestHeader.put( headerName, headerValue ); - } - - @Schema(name="timeout_ms", description = "The time in milliseconds after that a request to the remote repository is aborted") - public long getTimeoutMs( ) - { - return timeoutMs; - } - - public void setTimeoutMs( long timeoutMs ) - { - this.timeoutMs = timeoutMs; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - if ( !super.equals( o ) ) return false; - - MavenRemoteRepository that = (MavenRemoteRepository) o; - - if ( timeoutMs != that.timeoutMs ) return false; - if ( loginUser != null ? !loginUser.equals( that.loginUser ) : that.loginUser != null ) return false; - if ( loginPassword != null ? !loginPassword.equals( that.loginPassword ) : that.loginPassword != null ) - return false; - if ( checkPath != null ? !checkPath.equals( that.checkPath ) : that.checkPath != null ) return false; - if ( extraParameters != null ? !extraParameters.equals( that.extraParameters ) : that.extraParameters != null ) - return false; - return requestHeader != null ? requestHeader.equals( that.requestHeader ) : that.requestHeader == null; - } - - @Override - public int hashCode( ) - { - int result = super.hashCode( ); - result = 31 * result + ( loginUser != null ? loginUser.hashCode( ) : 0 ); - result = 31 * result + ( loginPassword != null ? loginPassword.hashCode( ) : 0 ); - result = 31 * result + ( checkPath != null ? checkPath.hashCode( ) : 0 ); - result = 31 * result + ( extraParameters != null ? extraParameters.hashCode( ) : 0 ); - result = 31 * result + ( requestHeader != null ? requestHeader.hashCode( ) : 0 ); - result = 31 * result + (int) ( timeoutMs ^ ( timeoutMs >>> 32 ) ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "RemoteRepository{" ); - sb.append( "loginUser='" ).append( loginUser ).append( '\'' ); - sb.append( ", loginPassword='" ).append( loginPassword ).append( '\'' ); - sb.append( ", checkPath='" ).append( checkPath ).append( '\'' ); - sb.append( ", extraParameters=" ).append( extraParameters ); - sb.append( ", requestHeader=" ).append( requestHeader ); - sb.append( ", timeOut=" ).append( timeoutMs ); - sb.append( ", id='" ).append( id ).append( '\'' ); - sb.append( ", name='" ).append( name ).append( '\'' ); - sb.append( ", description='" ).append( description ).append( '\'' ); - sb.append( ", type='" ).append( type ).append( '\'' ); - sb.append( ", location='" ).append( location ).append( '\'' ); - sb.append( ", scanned=" ).append( scanned ); - sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' ); - sb.append( ", index=" ).append( index ); - sb.append( ", layout='" ).append( layout ).append( '\'' ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MergeConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MergeConfiguration.java deleted file mode 100644 index 95a286b31..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MergeConfiguration.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.Objects; - -import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; - -/** - * Index merge configuration. - * - * @author Martin Stockhammer - * @since 3.0 - */ -@XmlRootElement(name="mergeConfiguration") -@Schema(name="MergeConfiguration", description = "Configuration settings for index merge of remote repositories.") -public class MergeConfiguration implements Serializable -{ - private static final long serialVersionUID = -3629274059574459133L; - - private String mergedIndexPath = DEFAULT_INDEX_PATH; - private int mergedIndexTtlMinutes = 30; - private String indexMergeSchedule = ""; - - @Schema(name="merged_index_path", description = "The path where the merged index is stored. The path is relative to the repository directory of the group.") - public String getMergedIndexPath( ) - { - return mergedIndexPath; - } - - public void setMergedIndexPath( String mergedIndexPath ) - { - this.mergedIndexPath = mergedIndexPath; - } - - @Schema(name="merged_index_ttl_minutes", description = "The Time to Life of the merged index in minutes.") - public int getMergedIndexTtlMinutes( ) - { - return mergedIndexTtlMinutes; - } - - public void setMergedIndexTtlMinutes( int mergedIndexTtlMinutes ) - { - this.mergedIndexTtlMinutes = mergedIndexTtlMinutes; - } - - @Schema(name="index_merge_schedule", description = "Cron expression that defines the times/intervals for index merging.") - public String getIndexMergeSchedule( ) - { - return indexMergeSchedule; - } - - public void setIndexMergeSchedule( String indexMergeSchedule ) - { - this.indexMergeSchedule = indexMergeSchedule; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - MergeConfiguration that = (MergeConfiguration) o; - - if ( mergedIndexTtlMinutes != that.mergedIndexTtlMinutes ) return false; - if ( !Objects.equals( mergedIndexPath, that.mergedIndexPath ) ) - return false; - return Objects.equals( indexMergeSchedule, that.indexMergeSchedule ); - } - - @Override - public int hashCode( ) - { - int result = mergedIndexPath != null ? mergedIndexPath.hashCode( ) : 0; - result = 31 * result + mergedIndexTtlMinutes; - result = 31 * result + ( indexMergeSchedule != null ? indexMergeSchedule.hashCode( ) : 0 ); - return result; - } - - @SuppressWarnings( "StringBufferReplaceableByString" ) - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "MergeConfiguration{" ); - sb.append( "mergedIndexPath='" ).append( mergedIndexPath ).append( '\'' ); - sb.append( ", mergedIndexTtlMinutes=" ).append( mergedIndexTtlMinutes ); - sb.append( ", indexMergeSchedule='" ).append( indexMergeSchedule ).append( '\'' ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java deleted file mode 100644 index 04f77b9db..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/Repository.java +++ /dev/null @@ -1,289 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.ManagedRepository; -import org.apache.archiva.repository.RemoteRepository; - -import java.io.Serializable; -import java.util.Locale; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@Schema(description = "Repository data") -public class Repository implements Serializable -{ - private static final long serialVersionUID = -4741025877287175182L; - - public static final String CHARACTERISTIC_MANAGED = "managed"; - public static final String CHARACTERISTIC_REMOTE = "remote"; - public static final String CHARACTERISTIC_UNKNOWN = "unknown"; - - protected String id; - protected String name; - protected String description; - protected String type; - protected String characteristic; - protected String location; - protected boolean scanned; - protected String schedulingDefinition; - protected boolean index; - protected String layout; - - public Repository( ) - { - } - - public static Repository of( org.apache.archiva.repository.Repository repository ) { - Repository newRepo = new Repository( ); - newRepo.setId( repository.getId() ); - newRepo.setName( repository.getName( ) ); - newRepo.setDescription( repository.getDescription( ) ); - newRepo.setLocation( repository.getLocation().toASCIIString() ); - newRepo.setIndex( repository.hasIndex() ); - newRepo.setLayout( repository.getLayout() ); - newRepo.setType( repository.getType().name() ); - newRepo.setScanned( repository.isScanned() ); - newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() ); - if (repository instanceof RemoteRepository ) { - newRepo.setCharacteristic( CHARACTERISTIC_REMOTE ); - } else if (repository instanceof ManagedRepository ) { - newRepo.setCharacteristic( CHARACTERISTIC_MANAGED ); - } else { - newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN ); - } - return newRepo; - } - - public static Repository of( org.apache.archiva.repository.Repository repository, Locale locale ) { - Locale myLocale; - if (locale==null) { - myLocale = Locale.getDefault( ); - } else { - myLocale = locale; - } - String repoName = repository.getName( myLocale ); - if (repoName==null) { - repoName = repository.getName( ); - } - String description = repository.getDescription( myLocale ); - if (description==null) { - description = repository.getDescription( ); - } - Repository newRepo = new Repository( ); - newRepo.setId( repository.getId() ); - newRepo.setName( repoName ); - newRepo.setDescription( description ); - newRepo.setLocation( repository.getLocation().toASCIIString() ); - newRepo.setIndex( repository.hasIndex() ); - newRepo.setLayout( repository.getLayout() ); - newRepo.setType( repository.getType().name() ); - newRepo.setScanned( repository.isScanned() ); - newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() ); - if (repository instanceof RemoteRepository ) { - newRepo.setCharacteristic( CHARACTERISTIC_REMOTE ); - } else if (repository instanceof ManagedRepository ) { - newRepo.setCharacteristic( CHARACTERISTIC_MANAGED ); - } else { - newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN ); - } - return newRepo; - } - - @Schema(description = "Category of the repository. Either 'managed' or 'remote'.") - public String getCharacteristic( ) - { - return characteristic; - } - - public void setCharacteristic( String characteristic ) - { - this.characteristic = characteristic; - } - - @Schema(description = "Unique identifier of the repository") - public String getId( ) - { - return id; - } - - public void setId( String id ) - { - this.id = id; - } - - @Schema(description = "Display name of the repository") - public String getName( ) - { - return name; - } - - public void setName( String name ) - { - this.name = name; - } - - @Schema(description = "Description of the repository") - public String getDescription( ) - { - return description; - } - - public void setDescription( String description ) - { - this.description = description; - } - - @Schema(description = "Repository type") - public String getType( ) - { - return type; - } - - public void setType( String type ) - { - this.type = type; - } - - @Schema(description = "The location, where the repository data can be found") - public String getLocation( ) - { - return location; - } - - public void setLocation( String location ) - { - this.location = location; - } - - @Schema(description = "True, if this repository is scanned regularly") - public boolean isScanned( ) - { - return scanned; - } - - public void setScanned( boolean scanned ) - { - this.scanned = scanned; - } - - @Schema(name="scheduling_definition",description = "Definition of regular scheduled scan") - public String getSchedulingDefinition( ) - { - return schedulingDefinition; - } - - public void setSchedulingDefinition( String schedulingDefinition ) - { - this.schedulingDefinition = schedulingDefinition; - } - - @Schema(description = "True, if this is a indexed repository") - public boolean isIndex( ) - { - return index; - } - - public void setIndex( boolean index ) - { - this.index = index; - } - - @Schema(description = "Layout type is implementation specific") - public String getLayout( ) - { - return layout; - } - - public void setLayout( String layout ) - { - this.layout = layout; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - Repository that = (Repository) o; - - if ( scanned != that.scanned ) return false; - if ( index != that.index ) return false; - if ( id != null ? !id.equals( that.id ) : that.id != null ) return false; - if ( name != null ? !name.equals( that.name ) : that.name != null ) return false; - if ( description != null ? !description.equals( that.description ) : that.description != null ) return false; - if ( type != null ? !type.equals( that.type ) : that.type != null ) return false; - if ( location != null ? !location.equals( that.location ) : that.location != null ) return false; - if ( schedulingDefinition != null ? !schedulingDefinition.equals( that.schedulingDefinition ) : that.schedulingDefinition != null ) - return false; - return layout != null ? layout.equals( that.layout ) : that.layout == null; - } - - @Override - public int hashCode( ) - { - int result = id != null ? id.hashCode( ) : 0; - result = 31 * result + ( name != null ? name.hashCode( ) : 0 ); - result = 31 * result + ( description != null ? description.hashCode( ) : 0 ); - result = 31 * result + ( type != null ? type.hashCode( ) : 0 ); - result = 31 * result + ( location != null ? location.hashCode( ) : 0 ); - result = 31 * result + ( scanned ? 1 : 0 ); - result = 31 * result + ( schedulingDefinition != null ? schedulingDefinition.hashCode( ) : 0 ); - result = 31 * result + ( index ? 1 : 0 ); - result = 31 * result + ( layout != null ? layout.hashCode( ) : 0 ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "Repository{" ); - sb.append( "id='" ).append( id ).append( '\'' ); - sb.append( ", name='" ).append( name ).append( '\'' ); - sb.append( ", description='" ).append( description ).append( '\'' ); - sb.append( ", type='" ).append( type ).append( '\'' ); - sb.append( ", location='" ).append( location ).append( '\'' ); - sb.append( ", scanned=" ).append( scanned ); - sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' ); - sb.append( ", index=" ).append( index ); - sb.append( ", layout='" ).append( layout ).append( '\'' ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryGroup.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryGroup.java deleted file mode 100644 index 1ca68a0fb..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryGroup.java +++ /dev/null @@ -1,178 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.Repository; -import org.apache.archiva.repository.features.IndexCreationFeature; -import org.apache.archiva.repository.features.RepositoryFeature; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * @author Martin Stockhammer - */ -@XmlRootElement(name="repositoryGroup") -@Schema(name="RepositoryGroup", description = "Information about a repository group, which combines multiple repositories as one virtual repository.") -public class RepositoryGroup implements Serializable -{ - private static final long serialVersionUID = -7319687481737616081L; - private String id; - private String name; - private List repositories = new ArrayList<>( ); - private String location; - MergeConfiguration mergeConfiguration; - - public RepositoryGroup( ) - { - } - - public RepositoryGroup(String id) { - this.id = id; - } - - public static RepositoryGroup of( org.apache.archiva.repository.RepositoryGroup modelObj ) { - RepositoryGroup result = new RepositoryGroup( ); - MergeConfiguration mergeConfig = new MergeConfiguration( ); - result.setMergeConfiguration( mergeConfig ); - result.setId( modelObj.getId() ); - result.setName( modelObj.getName() ); - result.setLocation( modelObj.getLocation().toString() ); - result.setRepositories( modelObj.getRepositories().stream().map( Repository::getId ).collect( Collectors.toList()) ); - if (modelObj.supportsFeature( IndexCreationFeature.class )) { - IndexCreationFeature icf = modelObj.getFeature( IndexCreationFeature.class ).get(); - mergeConfig.setMergedIndexPath( icf.getIndexPath( ).toString() ); - mergeConfig.setMergedIndexTtlMinutes( modelObj.getMergedIndexTTL( ) ); - mergeConfig.setIndexMergeSchedule( modelObj.getSchedulingDefinition() ); - } - return result; - } - - @Schema(description = "The unique id of the repository group.") - public String getId( ) - { - return id; - } - - public void setId( String id ) - { - this.id = id; - } - - @Schema(description = "The list of ids of repositories which are member of the repository group.") - public List getRepositories( ) - { - return repositories; - } - - public void setRepositories( List repositories ) - { - this.repositories = new ArrayList<>( repositories ); - } - - public void addRepository(String repositoryId) { - if (!this.repositories.contains( repositoryId )) { - this.repositories.add( repositoryId ); - } - } - - @Schema(name="merge_configuration",description = "The configuration for index merge.") - public MergeConfiguration getMergeConfiguration( ) - { - return mergeConfiguration; - } - - public void setMergeConfiguration( MergeConfiguration mergeConfiguration ) - { - this.mergeConfiguration = mergeConfiguration; - } - - @Schema(description = "The storage location of the repository. The merged index is stored relative to this location.") - public String getLocation( ) - { - return location; - } - - public void setLocation( String location ) - { - this.location = location; - } - - @Schema(description = "The name of the repository group") - public String getName( ) - { - return name; - } - - public void setName( String name ) - { - this.name = name; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - RepositoryGroup that = (RepositoryGroup) o; - - return id.equals( that.id ); - } - - @Override - public int hashCode( ) - { - return id.hashCode( ); - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "RepositoryGroup{" ); - sb.append( "id='" ).append( id ).append( '\'' ); - sb.append( ", name='" ).append( name ).append( '\'' ); - sb.append( ", repositories=" ).append( repositories ); - sb.append( ", location='" ).append( location ).append( '\'' ); - sb.append( ", mergeConfiguration=" ).append( mergeConfiguration ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryStatistics.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryStatistics.java deleted file mode 100644 index 1417a1986..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/RepositoryStatistics.java +++ /dev/null @@ -1,291 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.scanner.RepositoryScanStatistics; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.time.Duration; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Map; -import java.util.TreeMap; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@XmlRootElement(name="repositoryStatistics") -@Schema(name="RepositoryStatistics", description = "Statistics data") -public class RepositoryStatistics implements Serializable -{ - private static final long serialVersionUID = 7943367882738452531L; - - private OffsetDateTime scanEndTime; - private OffsetDateTime scanStartTime; - private long scanDurationMs; - private long totalArtifactCount; - private long totalArtifactFileSize; - private long totalFileCount; - private long totalGroupCount; - private long totalProjectCount; - private long newFileCount; - private Map totalCountForType = new TreeMap<>( ); - private Map customValues = new TreeMap<>( ); - - public RepositoryStatistics( ) - { - } - - public static RepositoryStatistics of( org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics modelStats ) { - RepositoryStatistics newStats = new RepositoryStatistics( ); - newStats.setScanStartTime( modelStats.getScanStartTime().toInstant().atOffset( ZoneOffset.UTC ) ); - newStats.setScanEndTime( modelStats.getScanEndTime( ).toInstant( ).atOffset( ZoneOffset.UTC ) ); - newStats.setNewFileCount( modelStats.getNewFileCount() ); - newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() ); - newStats.setTotalArtifactCount( modelStats.getTotalArtifactCount() ); - newStats.setTotalArtifactFileSize( modelStats.getTotalArtifactFileSize() ); - newStats.setTotalCountForType( modelStats.getTotalCountForType() ); - newStats.setTotalFileCount( modelStats.getTotalFileCount() ); - newStats.setTotalGroupCount( modelStats.getTotalGroupCount() ); - newStats.setTotalProjectCount( modelStats.getTotalProjectCount() ); - for (String key : modelStats.getAvailableCustomValues()) { - newStats.addCustomValue( key, modelStats.getCustomValue( key ) ); - } - return newStats; - } - - public static RepositoryStatistics of( RepositoryScanStatistics scanStatistics ) { - RepositoryStatistics newStats = new RepositoryStatistics( ); - newStats.setScanStartTime( scanStatistics.getWhenGathered().toInstant().atOffset( ZoneOffset.UTC ) ); - newStats.setScanEndTime( OffsetDateTime.now(ZoneOffset.UTC) ); - newStats.setNewFileCount( scanStatistics.getNewFileCount() ); - newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() ); - newStats.setTotalArtifactCount( scanStatistics.getTotalFileCount() ); - newStats.setTotalArtifactFileSize( scanStatistics.getTotalSize() ); - newStats.setTotalFileCount( scanStatistics.getTotalFileCount() ); - newStats.setTotalGroupCount( 0 ); - newStats.setTotalProjectCount( 0 ); - return newStats; - } - - @Schema(name="scan_end_time", description = "Date and time when the last scan finished") - public OffsetDateTime getScanEndTime( ) - { - return scanEndTime; - } - - public void setScanEndTime( OffsetDateTime scanEndTime ) - { - this.scanEndTime = scanEndTime; - } - - @Schema( name = "scan_start_time", description = "Date and time when the last scan started" ) - public OffsetDateTime getScanStartTime( ) - { - return scanStartTime; - } - - public void setScanStartTime( OffsetDateTime scanStartTime ) - { - this.scanStartTime = scanStartTime; - } - - @Schema(name="total_artifact_count", description = "The number of artifacts scanned") - public long getTotalArtifactCount( ) - { - return totalArtifactCount; - } - - public void setTotalArtifactCount( long totalArtifactCount ) - { - this.totalArtifactCount = totalArtifactCount; - } - - @Schema(name="total_artifact_file_size", description = "The cumulative size of all files scanned") - public long getTotalArtifactFileSize( ) - { - return totalArtifactFileSize; - } - - public void setTotalArtifactFileSize( long totalArtifactFileSize ) - { - this.totalArtifactFileSize = totalArtifactFileSize; - } - - @Schema(name="total_file_count", description = "The total number of files scanned") - public long getTotalFileCount( ) - { - return totalFileCount; - } - - public void setTotalFileCount( long totalFileCount ) - { - this.totalFileCount = totalFileCount; - } - - @Schema(name="total_group_count", description = "The number of groups scanned") - public long getTotalGroupCount( ) - { - return totalGroupCount; - } - - public void setTotalGroupCount( long totalGroupCount ) - { - this.totalGroupCount = totalGroupCount; - } - - @Schema(name="total_project_count", description = "The number of projects scanned") - public long getTotalProjectCount( ) - { - return totalProjectCount; - } - - public void setTotalProjectCount( long totalProjectCount ) - { - this.totalProjectCount = totalProjectCount; - } - - @Schema(name="new_file_count", description = "Number of files registered as new") - public long getNewFileCount( ) - { - return newFileCount; - } - - public void setNewFileCount( long newFileCount ) - { - this.newFileCount = newFileCount; - } - - @Schema(name="scan_duration_ms", description = "The duration of the last scan in ms") - public long getScanDurationMs( ) - { - return scanDurationMs; - } - - public void setScanDurationMs( long scanDurationMs ) - { - this.scanDurationMs = scanDurationMs; - } - - @Schema(name="total_count_for_type", description = "File counts partitioned by file types") - public Map getTotalCountForType( ) - { - return totalCountForType; - } - - public void setTotalCountForType( Map totalCountForType ) - { - this.totalCountForType = new TreeMap<>( totalCountForType ); - } - - public void addTotalCountForType( String type, Long value ) - { - this.totalCountForType.put( type, value ); - } - - @Schema(name="custom_values", description = "Custom statistic values") - public Map getCustomValues( ) - { - return customValues; - } - - public void setCustomValues( Map customValues ) - { - this.customValues = new TreeMap<>( customValues ); - } - - public void addCustomValue(String type, Long value) { - this.customValues.put( type, value ); - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - RepositoryStatistics that = (RepositoryStatistics) o; - - if ( scanDurationMs != that.scanDurationMs ) return false; - if ( totalArtifactCount != that.totalArtifactCount ) return false; - if ( totalArtifactFileSize != that.totalArtifactFileSize ) return false; - if ( totalFileCount != that.totalFileCount ) return false; - if ( totalGroupCount != that.totalGroupCount ) return false; - if ( totalProjectCount != that.totalProjectCount ) return false; - if ( newFileCount != that.newFileCount ) return false; - if ( scanEndTime != null ? !scanEndTime.equals( that.scanEndTime ) : that.scanEndTime != null ) return false; - if ( scanStartTime != null ? !scanStartTime.equals( that.scanStartTime ) : that.scanStartTime != null ) - return false; - if ( !totalCountForType.equals( that.totalCountForType ) ) return false; - return customValues.equals( that.customValues ); - } - - @Override - public int hashCode( ) - { - int result = scanEndTime != null ? scanEndTime.hashCode( ) : 0; - result = 31 * result + ( scanStartTime != null ? scanStartTime.hashCode( ) : 0 ); - result = 31 * result + (int) ( scanDurationMs ^ ( scanDurationMs >>> 32 ) ); - result = 31 * result + (int) ( totalArtifactCount ^ ( totalArtifactCount >>> 32 ) ); - result = 31 * result + (int) ( totalArtifactFileSize ^ ( totalArtifactFileSize >>> 32 ) ); - result = 31 * result + (int) ( totalFileCount ^ ( totalFileCount >>> 32 ) ); - result = 31 * result + (int) ( totalGroupCount ^ ( totalGroupCount >>> 32 ) ); - result = 31 * result + (int) ( totalProjectCount ^ ( totalProjectCount >>> 32 ) ); - result = 31 * result + (int) ( newFileCount ^ ( newFileCount >>> 32 ) ); - result = 31 * result + totalCountForType.hashCode( ); - result = 31 * result + customValues.hashCode( ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "RepositoryStatistics{" ); - sb.append( "scanEndTime=" ).append( scanEndTime ); - sb.append( ", scanStartTime=" ).append( scanStartTime ); - sb.append( ", scanDurationMs=" ).append( scanDurationMs ); - sb.append( ", totalArtifactCount=" ).append( totalArtifactCount ); - sb.append( ", totalArtifactFileSize=" ).append( totalArtifactFileSize ); - sb.append( ", totalFileCount=" ).append( totalFileCount ); - sb.append( ", totalGroupCount=" ).append( totalGroupCount ); - sb.append( ", totalProjectCount=" ).append( totalProjectCount ); - sb.append( ", newFileCount=" ).append( newFileCount ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java deleted file mode 100644 index 27c6b02b5..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanStatus.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.admin.model.beans.MetadataScanTask; -import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask; -import org.apache.archiva.scheduler.repository.model.RepositoryTask; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author Martin Stockhammer - */ -@Schema(name="ScanStatus", description = "Status of repository scan tasks") -public class ScanStatus implements Serializable -{ - private boolean scanRunning = false; - private int scanQueued = 0; - private boolean indexRunning = false; - private int indexQueued = 0; - private List indexingQueue = new ArrayList<>( ); - private List scanQueue = new ArrayList<>( ); - - public ScanStatus( ) - { - } - - public static ScanStatus of( org.apache.archiva.admin.model.beans.ScanStatus modelStatus ) { - ScanStatus status = new ScanStatus( ); - status.setIndexRunning( modelStatus.isIndexScanRunning() ); - status.setScanRunning( modelStatus.isMetadataScanRunning() ); - List indexQueue = modelStatus.getIndexingQueue( ); - status.setIndexingQueue( indexQueue.stream().map(IndexingTask::of).collect( Collectors.toList()) ); - status.setIndexQueued( indexQueue.size( ) > 0 ? indexQueue.size( ) - 1 : 0 ); - List scanQueue = modelStatus.getScanQueue( ); - status.setScanQueue( scanQueue.stream().map( ScanTask::of ).collect( Collectors.toList()) ); - status.setScanQueued( scanQueue.size( ) > 0 ? scanQueue.size( ) - 1 : 0 ); - return status; - - } - - @Schema( name = "scan_running", description = "True, if a scan is currently running" ) - public boolean isScanRunning( ) - { - return scanRunning; - } - - public void setScanRunning( boolean scanRunning ) - { - this.scanRunning = scanRunning; - } - - @Schema(name ="scan_queued", description = "Number of scans in the task queue") - public int getScanQueued( ) - { - return scanQueued; - } - - public void setScanQueued( int scanQueued ) - { - this.scanQueued = scanQueued; - } - - @Schema(name="index_running", description = "True, if there is a index task currently running") - public boolean isIndexRunning( ) - { - return indexRunning; - } - - public void setIndexRunning( boolean indexRunning ) - { - this.indexRunning = indexRunning; - } - - @Schema(name="index_queued", description = "Number of queued index tasks") - public int getIndexQueued( ) - { - return indexQueued; - } - - public void setIndexQueued( int indexQueued ) - { - this.indexQueued = indexQueued; - } - - @Schema( name = "indexing_queue", description = "List of indexing tasks waiting for execution" ) - public List getIndexingQueue( ) - { - return indexingQueue; - } - - public void setIndexingQueue( List indexingQueue ) - { - this.indexingQueue = new ArrayList<>( indexingQueue ); - } - - @Schema(name="scan_queue", description = "List of scan tasks waiting for execution") - public List getScanQueue( ) - { - return scanQueue; - } - - public void setScanQueue( List scanQueue ) - { - this.scanQueue = new ArrayList<>( scanQueue ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java deleted file mode 100644 index 1dc1530e6..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ScanTask.java +++ /dev/null @@ -1,157 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.admin.model.beans.MetadataScanTask; -import org.apache.archiva.scheduler.repository.model.RepositoryTask; - -import java.io.Serializable; - -/** - * @author Martin Stockhammer - */ -@Schema(name="ScanTask", description = "Repository scan task information") -public class ScanTask implements Serializable -{ - private static final long serialVersionUID = -681163357370848098L; - private String repositoryId=""; - private boolean updateRelatedArtifacts; - private boolean fullRepository; - private boolean running = false; - private String resource = ""; - private long maxExecutionTimeMs = 0; - - public static ScanTask of( MetadataScanTask repositoryTask ) { - ScanTask scanTask = new ScanTask( ); - scanTask.setFullRepository( repositoryTask.isFullScan()); - scanTask.setUpdateRelatedArtifacts( repositoryTask.isUpdateRelatedArtifacts() ); - scanTask.setResource( repositoryTask.getResource() ); - scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() ); - scanTask.setRepositoryId( repositoryTask.getRepositoryId( ) ); - return scanTask; - } - - @Schema(name="repository_id", description = "Identifier of the repository, this task is running on") - public String getRepositoryId( ) - { - return repositoryId; - } - - public void setRepositoryId( String repositoryId ) - { - this.repositoryId = repositoryId==null?"":repositoryId; - } - - @Schema(name="update_related_artifacts", description = "True, if related artifacts are updated too.") - public boolean isUpdateRelatedArtifacts( ) - { - return updateRelatedArtifacts; - } - - public void setUpdateRelatedArtifacts( boolean updateRelatedArtifacts ) - { - this.updateRelatedArtifacts = updateRelatedArtifacts; - } - - @Schema(name="full_repository",description = "True, if this is a full repository scan") - public boolean isFullRepository( ) - { - return fullRepository; - } - - public void setFullRepository( boolean fullRepository ) - { - this.fullRepository = fullRepository; - } - - @Schema(name="running", description = "True, if this task is currently running") - public boolean isRunning( ) - { - return running; - } - - public void setRunning( boolean running ) - { - this.running = running; - } - - @Schema(name="resource",description = "Name of the resource to update") - public String getResource( ) - { - return resource; - } - - public void setResource( String resource ) - { - this.resource = resource==null?"":resource; - } - - @Schema(name="max_excecution_time_ms",description = "Maximum execution time in ms") - public long getMaxExecutionTimeMs( ) - { - return maxExecutionTimeMs; - } - - public void setMaxExecutionTimeMs( long maxExecutionTimeMs ) - { - this.maxExecutionTimeMs = maxExecutionTimeMs; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - ScanTask scanTask = (ScanTask) o; - - if ( updateRelatedArtifacts != scanTask.updateRelatedArtifacts ) return false; - if ( fullRepository != scanTask.fullRepository ) return false; - if ( running != scanTask.running ) return false; - if ( maxExecutionTimeMs != scanTask.maxExecutionTimeMs ) return false; - if ( !repositoryId.equals( scanTask.repositoryId ) ) return false; - return resource.equals( scanTask.resource ); - } - - @Override - public int hashCode( ) - { - int result = repositoryId.hashCode( ); - result = 31 * result + ( updateRelatedArtifacts ? 1 : 0 ); - result = 31 * result + ( fullRepository ? 1 : 0 ); - result = 31 * result + ( running ? 1 : 0 ); - result = 31 * result + resource.hashCode( ); - result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) ); - return result; - } - - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "ScanTask{" ); - sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' ); - sb.append( ", updateRelatedArtifacts=" ).append( updateRelatedArtifacts ); - sb.append( ", fullRepository=" ).append( fullRepository ); - sb.append( ", running=" ).append( running ); - sb.append( ", resource='" ).append( resource ).append( '\'' ); - sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/SecurityConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/SecurityConfiguration.java deleted file mode 100644 index efe02a4f3..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/SecurityConfiguration.java +++ /dev/null @@ -1,179 +0,0 @@ -package org.apache.archiva.rest.api.model.v2;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** - * @author Martin Stockhammer - */ -@XmlRootElement(name = "securityConfiguration") -@Schema(name = "SecurityConfiguration", description = "Security configuration attributes.") -public class SecurityConfiguration implements Serializable -{ - private static final long serialVersionUID = -4186866365979053029L; - - private List activeUserManagers = new ArrayList<>( ); - private List activeRbacManagers = new ArrayList<>( ); - private Map properties = new TreeMap<>( ); - private boolean userCacheEnabled=false; - private boolean ldapActive=false; - - public SecurityConfiguration() { - - } - - public static SecurityConfiguration ofRedbackConfiguration( RedbackRuntimeConfiguration configuration ) { - SecurityConfiguration secConfig = new SecurityConfiguration( ); - secConfig.setActiveRbacManagers( configuration.getRbacManagerImpls() ); - secConfig.setActiveUserManagers( configuration.getUserManagerImpls() ); - secConfig.setProperties( configuration.getConfigurationProperties() ); - boolean rbLdapActive = configuration.getUserManagerImpls( ).stream( ).anyMatch( um -> um.contains( "ldap" ) ); - secConfig.setLdapActive( rbLdapActive ); - secConfig.setUserCacheEnabled( configuration.isUseUsersCache() ); - return secConfig; - } - - @Schema(name="active_user_managers", description = "List of ids of the active user managers") - public List getActiveUserManagers( ) - { - return activeUserManagers; - } - - public void setActiveUserManagers( List activeUserManagers ) - { - this.activeUserManagers = new ArrayList<>( activeUserManagers ); - } - - public void addSelectedUserManager(String userManager) { - this.activeUserManagers.add( userManager ); - } - - @Schema(name="active_rbac_managers", description = "List of ids of the active rbac managers") - public List getActiveRbacManagers( ) - { - return activeRbacManagers; - } - - public void setActiveRbacManagers( List activeRbacManagers ) - { - this.activeRbacManagers = new ArrayList<>( activeRbacManagers ); - } - - public void addSelectedRbacManager(String rbacManager) { - this.activeRbacManagers.add( rbacManager ); - } - - @Schema(description = "Map of all security properties") - public Map getProperties( ) - { - return properties; - } - - public void setProperties( Map properties ) - { - this.properties = new TreeMap<>( properties ); - } - - @Schema(name="user_cache_enabled", description = "True, if the user cache is active. It caches data from user backend.") - public boolean isUserCacheEnabled( ) - { - return userCacheEnabled; - } - - public void setUserCacheEnabled( boolean userCacheEnabled ) - { - this.userCacheEnabled = userCacheEnabled; - } - - @Schema(name="ldap_active", description = "True, if LDAP is used as user manager") - public boolean isLdapActive( ) - { - return ldapActive; - } - - public void setLdapActive( boolean ldapActive ) - { - this.ldapActive = ldapActive; - } - - @Override - public boolean equals( Object o ) - { - if ( this == o ) return true; - if ( o == null || getClass( ) != o.getClass( ) ) return false; - - SecurityConfiguration that = (SecurityConfiguration) o; - - if ( userCacheEnabled != that.userCacheEnabled ) return false; - if ( ldapActive != that.ldapActive ) return false; - if ( !activeUserManagers.equals( that.activeUserManagers ) ) return false; - if ( !activeRbacManagers.equals( that.activeRbacManagers ) ) return false; - return properties.equals( that.properties ); - } - - @Override - public int hashCode( ) - { - int result = activeUserManagers.hashCode( ); - result = 31 * result + activeRbacManagers.hashCode( ); - result = 31 * result + properties.hashCode( ); - result = 31 * result + ( userCacheEnabled ? 1 : 0 ); - result = 31 * result + ( ldapActive ? 1 : 0 ); - return result; - } - - @SuppressWarnings( "StringBufferReplaceableByString" ) - @Override - public String toString( ) - { - final StringBuilder sb = new StringBuilder( "SecurityConfiguration{" ); - sb.append( "active_user_managers=" ).append( activeUserManagers ); - sb.append( ", active_rbac_managers=" ).append( activeRbacManagers ); - sb.append( ", properties=" ).append( properties ); - sb.append( ", user_cache_enabled=" ).append( userCacheEnabled ); - sb.append( ", ldap_active=" ).append( ldapActive ); - sb.append( '}' ); - return sb.toString( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ValidationError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ValidationError.java deleted file mode 100644 index efa1ec987..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/ValidationError.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.apache.archiva.rest.api.model.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author Martin Stockhammer - */ -@XmlRootElement(name = "validationError") -@Schema(name = "ValidationError", description = "A validation error.") -public class ValidationError implements Serializable -{ - private static final long serialVersionUID = 2079020598090660171L; - - String key; - String field; - String category; - String type; - List parameter; - - - public ValidationError( ) - { - } - - public ValidationError( String key, String field, String category, String type, List parameter) { - this.key = key; - this.field = field; - this.category = category; - this.type = type; - if (parameter==null) { - this.parameter = new ArrayList<>( ); - } else - { - this.parameter = parameter; - } - } - - /** - * Creates a new instance based on the given error - * @param error the error instance - * @return - */ - public static ValidationError of( org.apache.archiva.repository.validation.ValidationError error ) { - return error != null ? new ValidationError( error.getErrorKey( ), error.getAttribute( ), error.getCategory( ), - error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) ) - : new ValidationError( ); - } - - /** - * Creates a new instance based on the field name and the error instance - * @param fieldName the name of the field to which the error applies - * @param error the error definition - * @return a new validation error instance - */ - public static ValidationError of( String fieldName, org.apache.archiva.repository.validation.ValidationError error ) { - return error != null ? new ValidationError( error.getErrorKey( ), fieldName, error.getCategory( ), - error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) ) - : new ValidationError( ); - } - - @Schema(name="key", description = "The full key of the validation error") - public String getKey( ) - { - return key; - } - - public void setKey( String key ) - { - this.key = key; - } - - @Schema(name="field", description = "The name of the field where the error was detected") - public String getField( ) - { - return field; - } - - public void setField( String field ) - { - this.field = field; - } - - @Schema(name="category", description = "The name of the category this error is assigned to") - public String getCategory( ) - { - return category; - } - - public void setCategory( String category ) - { - this.category = category; - } - - @Schema(name="type", description = "The type of the error. This is a unique string that defines the type of error, e.g. empty, bad_number_range, ... .") - public String getType( ) - { - return type; - } - - public void setType( String type ) - { - this.type = type; - } - - @Schema(name="parameter", description = "The list of parameters, that can be used to create a translated error message") - public List getParameter( ) - { - return parameter; - } - - public void setParameter( List parameter ) - { - this.parameter = parameter; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/ArtifactCleanupInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/ArtifactCleanupInfo.java deleted file mode 100644 index 879bb8b50..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/ArtifactCleanupInfo.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.apache.archiva.rest.api.model.v2.repository;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import java.time.Period; - -/** - * @author Martin Stockhammer - */ -@Schema(name="ArtifactCleanupInfo",description = "Information for artifact cleanup feature of repository") -public class ArtifactCleanupInfo -{ - boolean deleteReleasedSnapshots; - Period retentionPeriod; - int retentionCount; - - @Schema(name="delete_released_snapshots",description = "True, if snapshots are deleted after a release was published") - public boolean isDeleteReleasedSnapshots( ) - { - return deleteReleasedSnapshots; - } - - public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots ) - { - this.deleteReleasedSnapshots = deleteReleasedSnapshots; - } - - @Schema(name="retention_period",description = "Time, after that snapshot artifacts are marked for deletion") - public Period getRetentionPeriod( ) - { - return retentionPeriod; - } - - public void setRetentionPeriod( Period retentionPeriod ) - { - this.retentionPeriod = retentionPeriod; - } - - @Schema(name="retention_count",description = "Maximum number of snapshot artifacts to keep") - public int getRetentionCount( ) - { - return retentionCount; - } - - public void setRetentionCount( int retentionCount ) - { - this.retentionCount = retentionCount; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/IndexCreationInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/IndexCreationInfo.java deleted file mode 100644 index ebc506bd2..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/IndexCreationInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.apache.archiva.rest.api.model.v2.repository;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.Repository; -import org.apache.archiva.repository.storage.StorageAsset; - -import java.net.URI; - -/** - * @author Martin Stockhammer - */ -@Schema(name="IndexCreationInfo",description = "Information about index creation feature of repositories") -public class IndexCreationInfo -{ - private boolean skipPackedIndexCreation = false; - private String indexPath; - private String packedIndexPath; - - @Schema(name="skip_packed_index_creation",description = "True, if the packed index will not be created") - public boolean isSkipPackedIndexCreation( ) - { - return skipPackedIndexCreation; - } - - public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation ) - { - this.skipPackedIndexCreation = skipPackedIndexCreation; - } - - @Schema(name="index_path",description = "Path to the index directory relative to the repository base directory") - public String getIndexPath( ) - { - return indexPath; - } - - public void setIndexPath( String indexPath ) - { - this.indexPath = indexPath; - } - - @Schema(name="packed_index_path",description = "Path to the packed index directory relative to the repository base directory") - public String getPackedIndexPath( ) - { - return packedIndexPath; - } - - public void setPackedIndexPath( String packedIndexPath ) - { - this.packedIndexPath = packedIndexPath; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/RemoteIndexInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/RemoteIndexInfo.java deleted file mode 100644 index c7dedc500..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/RemoteIndexInfo.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apache.archiva.rest.api.model.v2.repository;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import java.net.URI; - -/** - * @author Martin Stockhammer - */ -@Schema(name="RemoteIndexInfo",description = "Information about remote indexes") -public class RemoteIndexInfo -{ - private boolean downloadRemoteIndex = false; - private String indexUri; - - @Schema(name="download_remote_index",description = "True, if the index will be downloaded from the remote repository") - public boolean isDownloadRemoteIndex( ) - { - return downloadRemoteIndex; - } - - public void setDownloadRemoteIndex( boolean downloadRemoteIndex ) - { - this.downloadRemoteIndex = downloadRemoteIndex; - } - - @Schema(name="index_uri", description = "The URI that specifies the path to the remote index") - public String getIndexUri( ) - { - return indexUri; - } - - public void setIndexUri( String indexUri ) - { - this.indexUri = indexUri; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/StagingInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/StagingInfo.java deleted file mode 100644 index 1014d9faa..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/repository/StagingInfo.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.apache.archiva.rest.api.model.v2.repository;/* - * 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. - */ - -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.repository.ManagedRepository; - -/** - * @author Martin Stockhammer - */ -@Schema(name="StagingInfo",description = "Information about staging feature of a repository") -public class StagingInfo -{ - private String stagingRepository; - private boolean stageRepoNeeded; - - @Schema(name="staging_repo",description = "The repository id of the staging repository") - public String getStagingRepository( ) - { - return stagingRepository; - } - - public void setStagingRepository( String stagingRepository ) - { - this.stagingRepository = stagingRepository; - } - - @Schema(name="stage_repo_needed",description = "True, if this repository needs a staging repository") - public boolean isStageRepoNeeded( ) - { - return stageRepoNeeded; - } - - public void setStageRepoNeeded( boolean stageRepoNeeded ) - { - this.stageRepoNeeded = stageRepoNeeded; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestError.java deleted file mode 100644 index 17c5b89d2..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestError.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; -import org.apache.archiva.rest.api.model.v2.ValidationError; -import org.apache.commons.lang3.StringUtils; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@XmlRootElement( name = "archivaRestError" ) -@Schema(name="ArchivaRestError", description = "Contains a list of error messages that resulted from the current REST call") -public class ArchivaRestError - implements Serializable -{ - - private static final long serialVersionUID = -8892617571273167067L; - private List errorMessages = new ArrayList<>( 1 ); - private List validationErrors; - - public ArchivaRestError() - { - // no op - } - - public ArchivaRestError( ArchivaRestServiceException e ) - { - errorMessages.addAll( e.getErrorMessages() ); - if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) ) - { - errorMessages.add( new ErrorMessage( e.getMessage(), null ) ); - } - if (e instanceof ValidationException) { - this.validationErrors = ( (ValidationException) e ).getValidationErrors( ); - } - } - - public ArchivaRestError( ValidationException e ) - { - errorMessages.addAll( e.getErrorMessages() ); - if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) ) - { - errorMessages.add( new ErrorMessage( e.getMessage(), null ) ); - } - this.validationErrors = e.getValidationErrors( ); - } - - @Schema(name="error_messages", description = "The list of errors that occurred while processing the REST request") - public List getErrorMessages() - { - return errorMessages; - } - - public void setErrorMessages( List errorMessages ) - { - this.errorMessages = errorMessages; - } - - public void addErrorMessage( ErrorMessage errorMessage ) - { - this.errorMessages.add( errorMessage ); - } - - @Schema( name = "has_validation_errors", description = "True, if the error contains validation errors" ) - public boolean hasValidationErrors( ) - { - return this.validationErrors != null && this.validationErrors.size( ) > 0; - } - - @Schema( name = "validation_errors", description = "The list of validation errors") - public List getValidationErrors() { - return hasValidationErrors() ? this.validationErrors : Collections.emptyList( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestServiceException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestServiceException.java deleted file mode 100644 index 3aabbe91f..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ArchivaRestServiceException.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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; - -/** - * Generic REST Service Exception that contains error information. - * - * @author Martin Stockhammer - * @since 3.0 - */ -public class ArchivaRestServiceException extends Exception -{ - private int httpErrorCode = 500; - - private List errorMessages = new ArrayList(0); - - public ArchivaRestServiceException( String s ) - { - super( s ); - } - - public ArchivaRestServiceException( String s, int httpErrorCode ) - { - super( s ); - this.httpErrorCode = httpErrorCode; - } - - public ArchivaRestServiceException( ErrorMessage errorMessage ) - { - errorMessages.add( errorMessage ); - } - - public ArchivaRestServiceException( ErrorMessage errorMessage, int httpResponseCode ) - { - this.httpErrorCode = httpResponseCode; - errorMessages.add( errorMessage ); - } - - public ArchivaRestServiceException( List errorMessage ) - { - errorMessages.addAll( errorMessage ); - } - - public ArchivaRestServiceException( List errorMessage, int httpResponseCode ) - { - this.httpErrorCode = httpResponseCode; - errorMessages.addAll( errorMessage ); - } - - public int getHttpErrorCode() - { - return httpErrorCode; - } - - public void setHttpErrorCode( int httpErrorCode ) - { - this.httpErrorCode = httpErrorCode; - } - - public List getErrorMessages() - { - if ( errorMessages == null ) - { - this.errorMessages = new ArrayList(); - } - return errorMessages; - } - - public void setErrorMessages( List errorMessages ) - { - this.errorMessages = errorMessages; - } - - public void addErrorMessage( ErrorMessage errorMessage ) - { - this.errorMessages.add( errorMessage ); - } - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java deleted file mode 100644 index fee06c9e7..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.apache.archiva.rest.api.services.v2;/* - * 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. - */ - -/* - * 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.archiva.rest.api.services.v2.ErrorMessage; - -import java.util.List; - -/** - * @author Martin Stockhammer - */ -public interface ErrorKeys -{ - - String PREFIX = "archiva."; - - String VALIDATION_ERROR = PREFIX + "validation_error"; - - String REPOSITORY_GROUP_PREFIX = PREFIX + "repository_group."; - String REPOSITORY_PREFIX = PREFIX + "repository."; - - String INVALID_RESULT_SET_ERROR = "archiva.result_set.invalid"; - String REPOSITORY_ADMIN_ERROR = "archiva.repositoryadmin.error"; - String LDAP_CF_INIT_FAILED = "archiva.ldap.cf.init.failed"; - String LDAP_USER_MAPPER_INIT_FAILED = "archiva.ldap.usermapper.init.failed"; - String LDAP_COMMUNICATION_ERROR = "archiva.ldap.communication_error"; - String LDAP_INVALID_NAME = "archiva.ldap.invalid_name"; - String LDAP_GENERIC_ERROR = "archiva.ldap.generic_error"; - String LDAP_SERVICE_UNAVAILABLE = "archiva.ldap.service_unavailable"; - String LDAP_SERVICE_AUTHENTICATION_FAILED = "archiva.ldap.authentication.failed"; - String LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED = "archiva.ldap.authentication.not_supported"; - String LDAP_SERVICE_NO_PERMISSION = "archiva.ldap.no_permissions"; - - String PROPERTY_NOT_FOUND = "archiva.property.not.found"; - - String MISSING_DATA = "archiva.missing.data"; - - String REPOSITORY_GROUP_NOT_FOUND = REPOSITORY_GROUP_PREFIX+"notfound"; - String REPOSITORY_GROUP_ADD_FAILED = REPOSITORY_GROUP_PREFIX+"add.failed" ; - String REPOSITORY_GROUP_EXIST = REPOSITORY_GROUP_PREFIX+"exists"; - String REPOSITORY_GROUP_UPDATE_FAILED = REPOSITORY_GROUP_PREFIX + "update.failed"; - - String REPOSITORY_GROUP_DELETE_FAILED = REPOSITORY_GROUP_PREFIX + "delete.failed"; - String REPOSITORY_NOT_FOUND = REPOSITORY_PREFIX + "notfound"; - String REPOSITORY_MANAGED_NOT_FOUND = REPOSITORY_PREFIX + "managed.notfound"; - String REPOSITORY_REMOTE_NOT_FOUND = REPOSITORY_PREFIX + "remote.notfound"; - - String REPOSITORY_METADATA_ERROR = REPOSITORY_PREFIX + "metadata_error"; - - String TASK_QUEUE_FAILED = PREFIX + "task.queue_failed"; - String REPOSITORY_SCAN_FAILED = REPOSITORY_PREFIX + "scan.failed"; - String ARTIFACT_EXISTS_AT_DEST = REPOSITORY_PREFIX + "artifact.dest.exists"; - String REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED = REPOSITORY_PREFIX + "remote.index.download_failed"; - String REPOSITORY_WRONG_TYPE = REPOSITORY_PREFIX + "wrong_type"; - String REPOSITORY_DELETE_FAILED = REPOSITORY_PREFIX + "delete.failed"; - String REPOSITORY_INVALID_ID = REPOSITORY_PREFIX + "invalid.id"; - String REPOSITORY_ID_EXISTS = REPOSITORY_PREFIX + "id.exists"; - String REPOSITORY_UPDATE_FAILED = REPOSITORY_PREFIX + "update.failed"; - String ARTIFACT_NOT_FOUND = REPOSITORY_PREFIX + "artifact.notfound"; - String REPOSITORY_LAYOUT_ERROR = REPOSITORY_PREFIX + "layout.error"; - - String ARTIFACT_COPY_ERROR = REPOSITORY_PREFIX + "artifact.copy.error"; - - /** - * The given user was not found - * Parameters: - * - User Id - */ - String USER_NOT_FOUND = PREFIX+"user.not_found"; - - /** - * Error from UserManager - * Parameters: - * - Error Message - */ - String USER_MANAGER_ERROR = PREFIX+"user_manager.error"; - - /** - * Permission to the repository denied. - * Parameters: - * - Repository Id - * - Permission ID - */ - String PERMISSION_REPOSITORY_DENIED = PREFIX + "permission.repository.denied"; - - /** - * A generic authorization error thrown during the authorization check. - * Parameters: - * - Error message - */ - String AUTHORIZATION_ERROR = PREFIX + "authorization.error"; - - /** - * When the operation needs authentication, but not authenticated user was found in the request context. - */ - String NOT_AUTHENTICATED = PREFIX + "user.not_authenticated"; -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorMessage.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorMessage.java deleted file mode 100644 index c8f767cea..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorMessage.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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 io.swagger.v3.oas.annotations.media.Schema; - -import javax.xml.bind.annotation.XmlRootElement; -import java.io.Serializable; - -/** - * @author Olivier Lamy - * @author Martin Stockhammer - * @since 3.0 - */ -@XmlRootElement( name = "errorMessage" ) -@Schema(name="ErrorMessage",description = "Information about the error, that occurred while processing the REST request.") -public class ErrorMessage - implements Serializable -{ - private String errorKey = ""; - - private String[] args = EMPTY; - - private String message = ""; - - private static final String[] EMPTY = new String[0]; - - public ErrorMessage() - { - // no op - } - - public ErrorMessage( String errorKey ) - { - this.errorKey = errorKey; - this.args = EMPTY; - } - - public ErrorMessage( String errorKey, String[] args ) - { - this.errorKey = errorKey; - this.args = args; - } - - public static ErrorMessage of(String errorKey, String... args) { - return new ErrorMessage( errorKey, args ); - } - - @Schema(name="error_key", description = "The key of the error message. If this is empty, the message message must be set.") - public String getErrorKey() - { - return errorKey; - } - - public void setErrorKey( String errorKey ) - { - this.errorKey = errorKey; - } - - @Schema(description = "Parameters that can be filled to the translated error message") - public String[] getArgs() - { - return args; - } - - public void setArgs( String[] args ) - { - this.args = args; - } - - @Schema(description = "Full error message. Either additional to the key in the default language, or if the message is without key.") - public String getMessage() - { - return message; - } - - public void setMessage( String message ) - { - this.message = message; - } - - public ErrorMessage message( String message ) - { - this.message = message; - return this; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java deleted file mode 100644 index 3da674307..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryGroupService.java +++ /dev/null @@ -1,257 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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 io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.headers.Header; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.parameters.RequestBody; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.redback.authorization.RedbackAuthorization; -import org.apache.archiva.rest.api.model.v2.RepositoryGroup; -import org.apache.archiva.security.common.ArchivaRoleConstants; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import java.util.List; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT; - -/** - * Endpoint for repository groups that combine multiple repositories into a single virtual repository. - * - * @author Olivier Lamy - * @author Martin Stockhammer - * @since 3.0 - */ -@Path( "/repository_groups" ) -@Schema( name = "RepositoryGroups", description = "Managing of repository groups or virtual repositories" ) -public interface RepositoryGroupService -{ - @Path( "" ) - @GET - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns all repository group entries.", - parameters = { - @Parameter( name = "q", description = "Search term" ), - @Parameter( name = "offset", description = "The offset of the first element returned" ), - @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), - @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), - @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ) - }, - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the list could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - PagedResult getRepositoriesGroups( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, - @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, - @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, - @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, - @QueryParam( "order" ) @DefaultValue( "asc" ) String order ) - throws ArchivaRestServiceException; - - @Path( "{id}" ) - @GET - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns a single repository group configuration.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration is returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository group with the given id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - RepositoryGroup getRepositoryGroup( @PathParam( "id" ) String repositoryGroupId ) - throws ArchivaRestServiceException; - - @Path( "" ) - @POST - @Consumes( {APPLICATION_JSON} ) - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Creates a new group entry.", - requestBody = - @RequestBody( required = true, description = "The configuration of the repository group.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) - ) - , - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "201", - description = "If the repository group was created", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) - ), - @ApiResponse( responseCode = "303", description = "The repository group exists already", - headers = { - @Header( name = "Location", description = "The URL of existing group", schema = @Schema( type = "string" ) ) - } - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "422", description = "The body data is not valid", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) - throws ArchivaRestServiceException; - - @Path( "{id}" ) - @PUT - @Consumes( {APPLICATION_JSON} ) - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns all repository group entries.", - requestBody = - @RequestBody( required = true, description = "The configuration of the repository group.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) - ) - , - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the group is returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "422", description = "The body data is not valid", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - RepositoryGroup updateRepositoryGroup( @PathParam( "id" ) String groupId, RepositoryGroup repositoryGroup ) - throws ArchivaRestServiceException; - - @Path( "{id}" ) - @DELETE - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Deletes the repository group entry with the given id.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the group was deleted" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - } - ) - Response deleteRepositoryGroup( @PathParam( "id" ) String repositoryGroupId ) - throws ArchivaRestServiceException; - - @Path( "{id}/repositories/{repositoryId}" ) - @PUT - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Adds the repository with the given id to the repository group.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the repository was added or if it was already part of the group" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - } - ) - RepositoryGroup addRepositoryToGroup( @PathParam( "id" ) String repositoryGroupId, - @PathParam( "repositoryId" ) String repositoryId ) - throws ArchivaRestServiceException; - - @Path( "{id}/repositories/{repositoryId}" ) - @DELETE - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Removes the repository with the given id from the repository group.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the repository was removed." - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "Either the group with the given id does not exist, or the repository was not part of the group.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - } - ) - RepositoryGroup deleteRepositoryFromGroup( @PathParam( "id" ) String repositoryGroupId, - @PathParam( "repositoryId" ) String repositoryId ) - throws ArchivaRestServiceException; - - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java deleted file mode 100644 index c9c6f4103..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java +++ /dev/null @@ -1,272 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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 io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.redback.authorization.RedbackAuthorization; -import org.apache.archiva.rest.api.model.v2.Repository; -import org.apache.archiva.rest.api.model.v2.RepositoryStatistics; -import org.apache.archiva.rest.api.model.v2.ScanStatus; -import org.apache.archiva.security.common.ArchivaRoleConstants; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.List; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@Path( "repositories" ) -@Tag(name = "v2") -@Tag(name = "v2/Repositories") -@Schema(name="RepositoryService",description = "Manage repositories of all types") -public interface RepositoryService -{ - - @Path( "" ) - @GET - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns all managed repositories.", - parameters = { - @Parameter( name = "q", description = "Search term" ), - @Parameter( name = "offset", description = "The offset of the first element returned" ), - @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), - @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), - @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ), - @Parameter( name = "locale", description = "The locale for name and description" ) - }, - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the list could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - PagedResult getRepositories( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, - @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, - @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, - @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, - @QueryParam( "order" ) @DefaultValue( "asc" ) String order, - @QueryParam( "locale" ) String localeString) throws ArchivaRestServiceException; - - @Path( "managed/{id}/statistics" ) - @GET - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns repository statistic data.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the statistics could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - RepositoryStatistics getManagedRepositoryStatistics( @PathParam( "id" ) String repositoryId ) - throws ArchivaRestServiceException; - - @Path ("managed/{id}/scan/schedule") - @POST - @Produces ({ APPLICATION_JSON }) - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) - @Operation( summary = "Returns repository statistic data.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the statistics could be returned" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response scheduleRepositoryScan( @PathParam ("id") String repositoryId, - @QueryParam ("fullScan") boolean fullScan ) - throws ArchivaRestServiceException; - - - @Path ("managed/{id}/scan/now") - @POST - @Produces ({ APPLICATION_JSON }) - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) - @Operation( summary = "Runs a repository scan instantly and waits for the response.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the statistics could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - RepositoryStatistics scanRepositoryImmediately( @PathParam ("id") String repositoryId ) - throws ArchivaRestServiceException; - - - @Path ("managed/{id}/scan/status") - @GET - @Produces ({ APPLICATION_JSON }) - @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) - @Operation( summary = "Returns status of running and scheduled scans.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the status could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ScanStatus.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - ScanStatus getScanStatus( @PathParam ("id") String repositoryId ) - throws ArchivaRestServiceException; - - @Path ("managed/{id}/scan") - @DELETE - @Produces ({ APPLICATION_JSON }) - @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) - @Operation( summary = "Cancels and removes all tasks for the given repository.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the task was removed successfully" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response removeScanningTaskFromQueue( @PathParam ("id") String repositoryId ) - throws ArchivaRestServiceException; - - - - @Path ("remote/{id}/index/download/start") - @POST - @Produces ({ APPLICATION_JSON }) - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) - @Operation( summary = "Schedules a task for remote index download.", - parameters = { - @Parameter( name = "full", description = "If true, download the full index, otherwise try a update download." ) - }, - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the task was scheduled" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response scheduleDownloadRemoteIndex( @PathParam ("id") String repositoryId, - @QueryParam( "immediate" ) boolean immediately, - @QueryParam ("full") boolean full, @Context UriInfo uriInfo ) - throws ArchivaRestServiceException; - - - @Path ("remote/index/downloads") - @GET - @Produces ({ APPLICATION_JSON }) - @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) - @Operation( summary = "Returns a list of running downloads from the remote repository.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the artifact was deleted" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - List getRunningRemoteDownloads(); - - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RestConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RestConfiguration.java deleted file mode 100644 index 10118d048..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RestConfiguration.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.apache.archiva.rest.api.services.v2;/* - * 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. - */ - -/* - * 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. - */ - -/** - * @author Martin Stockhammer - */ -public interface RestConfiguration -{ - String DEFAULT_PAGE_LIMIT = "10"; -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/SecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/SecurityConfigurationService.java deleted file mode 100644 index e8cc0d9cb..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/SecurityConfigurationService.java +++ /dev/null @@ -1,353 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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 io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.model.PropertyEntry; -import org.apache.archiva.redback.authorization.RedbackAuthorization; -import org.apache.archiva.rest.api.model.v2.BeanInformation; -import org.apache.archiva.rest.api.model.v2.CacheConfiguration; -import org.apache.archiva.rest.api.model.v2.LdapConfiguration; -import org.apache.archiva.rest.api.model.v2.SecurityConfiguration; -import org.apache.archiva.security.common.ArchivaRoleConstants; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import java.util.List; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT; - -/** - * - * Service for configuration of redback and security related settings. - * - * @author Martin Stockhammer - * @since 3.0 - */ -@Path( "/security" ) -@Tag(name = "v2") -@Tag(name = "v2/Security") -@SecurityRequirement(name = "BearerAuth") -public interface SecurityConfigurationService -{ - @Path("config") - @GET - @Produces({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Returns the security configuration that is currently active.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration could be retrieved", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SecurityConfiguration.class)) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - SecurityConfiguration getConfiguration() - throws ArchivaRestServiceException; - - @Path("config") - @PUT - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Updates the security configuration.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration was updated" - ), - @ApiResponse( responseCode = "422", description = "Invalid content data", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the configuration", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration) - throws ArchivaRestServiceException; - - - @Path( "config/properties" ) - @GET - @Produces( { APPLICATION_JSON } ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns all configuration properties. The result is paged.", - parameters = { - @Parameter(name = "q", description = "Search term"), - @Parameter(name = "offset", description = "The offset of the first element returned"), - @Parameter(name = "limit", description = "Maximum number of items to return in the response"), - @Parameter(name = "orderBy", description = "List of attribute used for sorting (key, value)"), - @Parameter(name = "order", description = "The sort order. Either ascending (asc) or descending (desc)") - }, - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the list could be returned", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class)) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - PagedResult getConfigurationProperties( @QueryParam("q") @DefaultValue( "" ) String searchTerm, - @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, - @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, - @QueryParam( "orderBy") @DefaultValue( "key" ) List orderBy, - @QueryParam("order") @DefaultValue( "asc" ) String order ) throws ArchivaRestServiceException; - - @Path("config/properties/{propertyName}") - @GET - @Produces({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Returns a single configuration property value.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - parameters = { - @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to get the value for") - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration could be retrieved", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PropertyEntry.class)) - ), - @ApiResponse( responseCode = "404", description = "The given property name does not exist", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - PropertyEntry getConfigurationProperty( @PathParam ( "propertyName" ) String propertyName) - throws ArchivaRestServiceException; - - - @Path("config/properties/{propertyName}") - @PUT - @Consumes({ APPLICATION_JSON}) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Updates a single property value of the security configuration.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - parameters = { - @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to update") - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the property value was updated." - ), - @ApiResponse( responseCode = "400", description = "The body data is not valid", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), - @ApiResponse( responseCode = "404", description = "The given property name does not exist", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - Response updateConfigurationProperty( @PathParam ( "propertyName" ) String propertyName, PropertyEntry propertyValue) - throws ArchivaRestServiceException; - - @Path("config/ldap") - @GET - @Produces({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Returns the LDAP configuration that is currently active.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration could be retrieved", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = LdapConfiguration.class)) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException; - - @Path("config/ldap") - @PUT - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Updates the LDAP configuration that is currently active.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration was updated" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException; - - @Path("config/ldap/verify") - @POST - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Checks the given LDAP configuration.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the check was successful" - ), - @ApiResponse( responseCode = "400", - description = "If the check was not successful", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - Response verifyLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException; - - @Path("config/cache") - @GET - @Produces({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Returns the cache configuration that is currently active.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration could be retrieved", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = CacheConfiguration.class)) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException; - - @Path("config/cache") - @PUT - @Consumes({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Updates the LDAP configuration that is currently active.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the configuration was updated" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException; - - - @Path("user_managers") - @GET - @Produces({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Returns the available user manager implementations.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the list could be retrieved", - content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema( - schema = @Schema(implementation = BeanInformation.class))) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - List getAvailableUserManagers() - throws ArchivaRestServiceException; - - @Path("rbac_managers") - @GET - @Produces({ APPLICATION_JSON }) - @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) - @Operation( summary = "Returns the available RBAC manager implementations.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the list could be retrieved", - content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema( - schema = @Schema(implementation = BeanInformation.class))) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) - } - ) - List getAvailableRbacManagers() - throws ArchivaRestServiceException; - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ValidationException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ValidationException.java deleted file mode 100644 index 7c44f298e..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ValidationException.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.apache.archiva.rest.api.services.v2; -/* - * 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.archiva.repository.Repository; -import org.apache.archiva.repository.validation.ValidationResponse; -import org.apache.archiva.rest.api.model.v2.ValidationError; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Exception is thrown - * - * @author Martin Stockhammer - */ -public class ValidationException extends ArchivaRestServiceException -{ - public static final int DEFAULT_CODE = 422; - - public static final ErrorMessage DEFAULT_MESSAGE = new ErrorMessage( ErrorKeys.VALIDATION_ERROR ); - - private List validationErrors; - - public ValidationException( ) - { - super( DEFAULT_MESSAGE, DEFAULT_CODE ); - } - - public ValidationException( int errorCode ) - { - super( DEFAULT_MESSAGE, errorCode ); - } - - public ValidationException( List errors ) - { - super( DEFAULT_MESSAGE, DEFAULT_CODE ); - this.validationErrors = errors; - } - - public static ValidationException of( List errorList ) - { - return new ValidationException( errorList.stream( ).map( ValidationError::of ).collect( Collectors.toList( ) ) ); - } - - public static ValidationException of( Map> errorMap ) - { - return new ValidationException( errorMap.entrySet( ).stream( ) - .flatMap( v -> v.getValue( ).stream( ).map( k -> ValidationError.of(v.getKey(), k))) - .collect( Collectors.toList( ) ) ); - } - - public static ValidationException of( ValidationResponse result ) - { - if ( result.isValid( ) ) - { - return new ValidationException( ); - } - else - { - return new ValidationException( result.getResult( ).entrySet( ).stream( ).flatMap( - v -> v.getValue( ).stream( ).map( e -> ValidationError.of( v.getKey( ), e ) ) ).collect( Collectors.toList( ) ) ); - } - } - - public List getValidationErrors( ) - { - return validationErrors == null ? Collections.emptyList( ) : validationErrors; - } - - public void setValidationErrors( List validationErrors ) - { - this.validationErrors = validationErrors; - } - - public void addValidationError( ValidationError error ) - { - if ( this.validationErrors == null ) - { - this.validationErrors = new ArrayList<>( ); - } - this.validationErrors.add( error ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java deleted file mode 100644 index 5e63682ee..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/maven/MavenManagedRepositoryService.java +++ /dev/null @@ -1,370 +0,0 @@ -package org.apache.archiva.rest.api.services.v2.maven; -/* - * 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 io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.headers.Header; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.OAuthScope; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.redback.authorization.RedbackAuthorization; -import org.apache.archiva.rest.api.model.v2.FileInfo; -import org.apache.archiva.rest.api.model.v2.MavenManagedRepository; -import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate; -import org.apache.archiva.rest.api.services.v2.ArchivaRestError; -import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; -import org.apache.archiva.security.common.ArchivaRoleConstants; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.List; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.apache.archiva.rest.api.services.v2.RestConfiguration.DEFAULT_PAGE_LIMIT; - -/** - * Service interface for managing managed maven repositories - * - * @author Martin Stockhammer - * @since 3.0 - */ -@Schema( name = "ManagedRepositoryService", description = "Managing and configuration of managed repositories" ) -@Path( "repositories/maven/managed" ) -@Tag(name = "v2") -@Tag(name = "v2/Repositories") -public interface MavenManagedRepositoryService -{ - @Path( "" ) - @GET - @Produces( {APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns all managed repositories.", - parameters = { - @Parameter( name = "q", description = "Search term" ), - @Parameter( name = "offset", description = "The offset of the first element returned" ), - @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), - @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), - @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ) - }, - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the list could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - PagedResult getManagedRepositories( - @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, - @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, - @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, - @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, - @QueryParam( "order" ) @DefaultValue( "asc" ) String order ) - throws ArchivaRestServiceException; - - - @Path( "{id}" ) - @GET - @Produces( {MediaType.APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Returns the managed repository with the given id.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the managed repository could be returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - MavenManagedRepository getManagedRepository( @PathParam( "id" ) String repositoryId ) - throws ArchivaRestServiceException; - - - @Path( "{id}" ) - @DELETE - @Produces( {MediaType.APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Deletes the managed repository with the given id.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the managed repository could be returned" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response deleteManagedRepository( @PathParam( "id" ) String repositoryId, - @QueryParam( "deleteContent" ) boolean deleteContent ) - throws ArchivaRestServiceException; - - - @Path( "" ) - @POST - @Consumes( {MediaType.APPLICATION_JSON} ) - @Produces( {MediaType.APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Creates the managed repository", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "201", - description = "If the managed repository could be created", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) ) - ), - @ApiResponse( responseCode = "303", description = "The repository exists already", - headers = { - @Header( name = "Location", description = "The URL of existing repository ", schema = @Schema( type = "string" ) ) - } - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "422", description = "The body data is not valid", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) - throws ArchivaRestServiceException; - - - @Path( "{id}" ) - @PUT - @Consumes( {MediaType.APPLICATION_JSON} ) - @Produces( {MediaType.APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) - @Operation( summary = "Updates the managed repository with the given id", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the managed repository could be updated", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "422", description = "The body data is not valid", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - MavenManagedRepository updateManagedRepository( @PathParam( "id" ) String repositoryId, MavenManagedRepositoryUpdate managedRepository ) - throws ArchivaRestServiceException; - - - @Path( "{id}/path/{filePath: .+}" ) - @GET - @Produces( {MediaType.APPLICATION_JSON} ) - @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, resource = "{id}") - @Operation( summary = "Returns the status of a given file in the repository", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the file status is returned", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = FileInfo.class ) ) - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the file does not exist.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - FileInfo getFileStatus( @PathParam( "id" ) String repositoryId, @PathParam( "filePath" ) String fileLocation ) - throws ArchivaRestServiceException; - - - /** - * Permissions are checked in impl - * will copy an artifact from the source repository to the target repository - */ - @Path ("{srcId}/path/{path: .+}/copyto/{dstId}") - @POST - @Produces({APPLICATION_JSON}) - @RedbackAuthorization (noPermission = true) - @Operation( summary = "Copies a artifact from the source repository to the destination repository", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, - scopes = { - "{srcId}" - } - ), - @SecurityRequirement( - name= ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD, - scopes = { - "{dstId}" - } - ) - - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the artifact was copied" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository does not exist, or if the artifact was not found", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response copyArtifact( @PathParam( "srcId" ) String srcRepositoryId, @PathParam( "dstId" ) String dstRepositoryId, - @PathParam( "path" ) String path ) - throws ArchivaRestServiceException; - - - @Path ("{id}/path/{path: .+}") - @DELETE - @Consumes ({ APPLICATION_JSON }) - @RedbackAuthorization (noPermission = true) - @Operation( summary = "Deletes a artifact in the repository.", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_RUN_INDEXER - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the artifact was deleted" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The repository or the artifact does not exist", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response deleteArtifact( @PathParam( "id" ) String repositoryId, @PathParam( "path" ) String path ) - throws ArchivaRestServiceException; - - @Path ( "{id}/co/{group}/{project}/{version}" ) - @DELETE - @Produces ({ MediaType.APPLICATION_JSON }) - @RedbackAuthorization (noPermission = true) - @Operation( summary = "Removes a version tree in the repository", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the deletion was successful" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the version does not exist.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response removeProjectVersion( @PathParam ( "id" ) String repositoryId, - @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId, - @PathParam ( "version" ) String version ) - throws org.apache.archiva.rest.api.services.ArchivaRestServiceException; - - - @Path ( "{id}/co/{group}/{project}" ) - @DELETE - @Produces ({ MediaType.APPLICATION_JSON }) - @RedbackAuthorization (noPermission = true) - @Operation( summary = "Removes a project tree in the repository", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the deletion was successful" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the project does not exist.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId ) - throws org.apache.archiva.rest.api.services.ArchivaRestServiceException; - - @Path ( "{id}/co/{namespace}" ) - @DELETE - @Produces ({ MediaType.APPLICATION_JSON }) - @RedbackAuthorization (noPermission = true) - @Operation( summary = "Removes a namespace tree in the repository", - security = { - @SecurityRequirement( - name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION - ) - }, - responses = { - @ApiResponse( responseCode = "200", - description = "If the deletion was successful" - ), - @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete namespaces in repositories", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), - @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the namespace does not exist.", - content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) - } - ) - Response deleteNamespace( @PathParam ("id") String repositoryId, @PathParam ( "namespace" ) String namespace ) - throws org.apache.archiva.rest.api.services.ArchivaRestServiceException; - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/package-info.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/package-info.java deleted file mode 100644 index 0cd02b0ef..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/package-info.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ - -/** - *

This is the V2 REST API of Archiva. It uses JAX-RS annotations for defining the endpoints. - * The API is documented with OpenApi annotations.

- * - *

Some design principles of the API and classes:

- *
    - *
  • All services use V2 model classes. Internal models are always converted to V2 classes.
  • - *
  • Schema attributes use the snake case syntax (lower case with '_' as divider)
  • - *
  • Return code 200 and 201 (POST) is used for successful execution.
  • - *
  • Return code 403 is used, if the user has not the permission for the action.
  • - *
  • Return code 422 is used for input that has invalid data.
  • - *
- * - *

Querying entity lists

- *

The main entities of a given path are retrieved on the base path. - * Further sub entities or entries may be retrieved via subpaths. - * A single entity is returned by the "{id}" path. Be careful with technical paths that are parallel to the - * id path. Avoid naming conflicts with the id and technical paths. - * Entity attributes may be retrieved by "{id}/{attribute}" path or if there are lists or collections by - * "{id}/mycollection/{subentryid}"

- * - *
    - *
  • GET method is used for retrieving entities on the base path ""
  • - *
  • The query for base entities should always return a paged result and be filterable and sortable
  • - *
  • Query parameters for filtering, ordering and limits should be optional and proper defaults must be set
  • - *
  • Return code 200 is used for successful retrieval
  • - *
  • This action is idempotent
  • - *
- * - *

Querying single entities

- *

Single entities are retrieved on the path "{id}"

- *
    - *
  • GET method is used for retrieving a single entity. The id is always a path parameter.
  • - *
  • Return code 200 is used for successful retrieval
  • - *
  • Return code 404 is used if the entity with the given id does not exist
  • - *
  • This action is idempotent
  • - *
- * - *

Creating entities

- *

The main entities are created on the base path "".

- *
    - *
  • POST is used for creating new entities
  • - *
  • The POST body must always have a complete definition of the entity.
  • - *
  • A unique id or name attribute is required for entities. If the id is generated during POST, - * it must be returned by response body.
  • - *
  • A successful POST request should always return the entity definition as it would be returned by the GET request.
  • - *
  • Return code 201 is used for successful creation of the new entity.
  • - *
  • A successful response has a Location header with the URL for retrieving the single created entity.
  • - *
  • Return code 303 is used, if the entity exists already
  • - *
  • This action is not idempotent
  • - *
- * - *

Updating entities

- *

The path for entity update must contain the '{id}' of the entity. The path should be the same as for the GET operation.

- *
    - *
  • PUT is used for updating existing entities
  • - *
  • The body contains a JSON object. Only existing attributes are updated.
  • - *
  • A successful PUT request should return the complete entity definition as it would be returned by the GET request.
  • - *
  • Return code 200 is used for successful update of the new entity. Even if nothing changed.
  • - *
  • This action is idempotent
  • - *
- * - *

Deleting entities

- *

The path for entity deletion must contain the '{id}' of the entity. The path should be the same as - * for the GET operation.

- *
    - *
  • DELETE is used for deleting existing entities
  • - *
  • The successful operation has no request and no response body
  • - *
  • Return code 200 is used for successful deletion of the new entity.
  • - *
  • This action is not idempotent
  • - *
- * - *

Errors

- *
    - *
  • A error uses a return code >=400
  • - *
  • All errors use the same result object ({@link org.apache.archiva.rest.api.services.v2.ArchivaRestError}
  • - *
  • Error messages are returned as keys. Translation is part of the client application.
  • - *
- * - * @author Martin Stockhammer - * @since 3.0 - */ -package org.apache.archiva.rest.api.services.v2; \ No newline at end of file diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Artifact.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Artifact.java new file mode 100644 index 000000000..980bab270 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Artifact.java @@ -0,0 +1,43 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; + +/** + * @author Martin Stockhammer + */ +@Schema(name="Artifact", description = "Information about artifacts") +public class Artifact implements Serializable +{ + private static final long serialVersionUID = 7581578317346876555L; + private String name; + + @Schema(name="name",description = "The name of the artifact") + public String getName( ) + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ArtifactTransferRequest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ArtifactTransferRequest.java new file mode 100644 index 000000000..5a517786f --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ArtifactTransferRequest.java @@ -0,0 +1,43 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; + +/** + * @author Martin Stockhammer + */ +public class ArtifactTransferRequest implements Serializable +{ + private static final long serialVersionUID = -7377281345536573342L; + + private String path; + + @Schema(description = "The path to the artifact") + public String getPath( ) + { + return path; + } + + public void setPath( String path ) + { + this.path = path; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/BeanInformation.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/BeanInformation.java new file mode 100644 index 000000000..0d28a539d --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/BeanInformation.java @@ -0,0 +1,151 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +/** + * @author Martin Stockhammer + */ +@XmlRootElement(name="beanInformation") +@Schema(name="BeanInformation",description = "Information about a bean instance.") +public class BeanInformation implements Serializable +{ + private static final long serialVersionUID = -432385743277355987L; + private String id; + private String displayName; + private String descriptionKey; + private String defaultDescription; + private boolean readonly; + + public BeanInformation( ) + { + } + + public BeanInformation( String id, String displayName, String descriptionKey, String defaultDescription, boolean readonly ) + { + this.id = id; + this.displayName = displayName; + this.descriptionKey = descriptionKey; + this.defaultDescription = defaultDescription; + this.readonly = readonly; + } + + @Schema(description = "The identifier") + public String getId( ) + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + @Schema(name="display_name", description = "The display name") + public String getDisplayName( ) + { + return displayName; + } + + public void setDisplayName( String displayName ) + { + this.displayName = displayName; + } + + @Schema(name="description_key", description = "The translation key for the description") + public String getDescriptionKey( ) + { + return descriptionKey; + } + + public void setDescriptionKey( String descriptionKey ) + { + this.descriptionKey = descriptionKey; + } + + @Schema(name="default_description", description = "The description translated in the default language") + public String getDefaultDescription( ) + { + return defaultDescription; + } + + public void setDefaultDescription( String defaultDescription ) + { + this.defaultDescription = defaultDescription; + } + + @Schema(description = "True, if this bean cannot be removed") + public boolean isReadonly( ) + { + return readonly; + } + + public void setReadonly( boolean readonly ) + { + this.readonly = readonly; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + BeanInformation that = (BeanInformation) o; + return readonly == that.readonly && id.equals( that.id ) && Objects.equals( displayName, that.displayName ) && Objects.equals( descriptionKey, that.descriptionKey ) && Objects.equals( defaultDescription, that.defaultDescription ); + } + + @Override + public int hashCode( ) + { + return Objects.hash( id, displayName, descriptionKey, defaultDescription, readonly ); + } + + @Override + public String toString( ) + { + return "BeanInformation{" + + "id='" + id + '\'' + + ", display_name='" + displayName + '\'' + + ", description_key='" + descriptionKey + '\'' + + ", default_description='" + defaultDescription + '\'' + + ", readonly=" + readonly + + '}'; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/CacheConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/CacheConfiguration.java new file mode 100644 index 000000000..1e58a6780 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/CacheConfiguration.java @@ -0,0 +1,152 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * @author Olivier Lamy + * @author Martin Stockhammer + * @since 3.0 + */ +@XmlRootElement( name = "cacheConfiguration" ) +@Schema(name="CacheConfiguration",description = "Cache configuration attributes") +public class CacheConfiguration + implements Serializable +{ + private static final long serialVersionUID = 5479989049980673894L; + /** + * TimeToIdleSeconds. + */ + private int timeToIdleSeconds = -1; + + /** + * TimeToLiveSeconds. + */ + private int timeToLiveSeconds = -1; + + /** + * max elements in memory. + */ + private int maxEntriesInMemory = -1; + + /** + * max elements on disk. + */ + private int maxEntriesOnDisk = -1; + + public CacheConfiguration() + { + // no op + } + + public static CacheConfiguration of( org.apache.archiva.admin.model.beans.CacheConfiguration beanConfiguration ) { + CacheConfiguration newConfig = new CacheConfiguration( ); + newConfig.setMaxEntriesInMemory( beanConfiguration.getMaxElementsInMemory() ); + newConfig.setMaxEntriesOnDisk( beanConfiguration.getMaxElementsOnDisk() ); + newConfig.setTimeToIdleSeconds( beanConfiguration.getTimeToIdleSeconds( ) ); + newConfig.setTimeToLiveSeconds( beanConfiguration.getTimeToLiveSeconds( ) ); + return newConfig; + } + + @Schema(name="time_to_idle_seconds", description = "The maximum number of seconds an element can exist in the cache without being accessed. "+ + "The element expires at this limit and will no longer be returned from the cache.") + public int getTimeToIdleSeconds() + { + return timeToIdleSeconds; + } + + public void setTimeToIdleSeconds( int timeToIdleSeconds ) + { + this.timeToIdleSeconds = timeToIdleSeconds; + } + + @Schema(name="time_to_live_seconds", description = "The maximum number of seconds an element can exist in the cache regardless of use. "+ + "The element expires at this limit and will no longer be returned from the cache.") + public int getTimeToLiveSeconds() + { + return timeToLiveSeconds; + } + + public void setTimeToLiveSeconds( int timeToLiveSeconds ) + { + this.timeToLiveSeconds = timeToLiveSeconds; + } + + @Schema(name="max_entries_in_memory", description = "The maximum cache entries to keep in memory. If the limit is reached, older entries will be evicted, or persisted on disk.") + public int getMaxEntriesInMemory() + { + return maxEntriesInMemory; + } + + public void setMaxEntriesInMemory( int maxEntriesInMemory ) + { + this.maxEntriesInMemory = maxEntriesInMemory; + } + + @Schema(name="max_entries_on_disk", description = "The maximum cache entries to keep on disk. If the limit is reached, older entries will be evicted.") + public int getMaxEntriesOnDisk() + { + return maxEntriesOnDisk; + } + + public void setMaxEntriesOnDisk( int maxEntriesOnDisk ) + { + this.maxEntriesOnDisk = maxEntriesOnDisk; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + CacheConfiguration that = (CacheConfiguration) o; + + if ( timeToIdleSeconds != that.timeToIdleSeconds ) return false; + if ( timeToLiveSeconds != that.timeToLiveSeconds ) return false; + if ( maxEntriesInMemory != that.maxEntriesInMemory ) return false; + return maxEntriesOnDisk == that.maxEntriesOnDisk; + } + + @Override + public int hashCode( ) + { + int result = timeToIdleSeconds; + result = 31 * result + timeToLiveSeconds; + result = 31 * result + maxEntriesInMemory; + result = 31 * result + maxEntriesOnDisk; + return result; + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(); + sb.append( "CacheConfiguration" ); + sb.append( "{time_to_idle_seconds=" ).append( timeToIdleSeconds ); + sb.append( ", time_to_live_seconds=" ).append( timeToLiveSeconds ); + sb.append( ", max_elements_in_memory=" ).append( maxEntriesInMemory ); + sb.append( ", max_elements_on_disk=" ).append( maxEntriesOnDisk ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/FileInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/FileInfo.java new file mode 100644 index 000000000..359d1cbe8 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/FileInfo.java @@ -0,0 +1,132 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.repository.storage.StorageAsset; + +import java.io.Serializable; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +/** + * @author Martin Stockhammer + */ +@Schema(name="FileInfo",description = "Information about a file stored in the repository") +public class FileInfo implements Serializable +{ + private static final long serialVersionUID = 900497784542880195L; + private OffsetDateTime modified; + private String fileName; + private String path; + + public FileInfo( ) + { + } + + public static FileInfo of( StorageAsset asset ) { + FileInfo fileInfo = new FileInfo( ); + fileInfo.setFileName( asset.getName() ); + fileInfo.setPath( asset.getPath() ); + fileInfo.setModified( asset.getModificationTime( ).atOffset( ZoneOffset.UTC ) ); + return fileInfo; + } + + @Schema(description = "Time when the file was last modified") + public OffsetDateTime getModified( ) + { + return modified; + } + + public void setModified( OffsetDateTime modified ) + { + this.modified = modified; + } + + @Schema(name="file_name", description = "Name of the file") + public String getFileName( ) + { + return fileName; + } + + public void setFileName( String fileName ) + { + this.fileName = fileName; + } + + @Schema(name="path", description = "Path to the file relative to the repository directory") + public String getPath( ) + { + return path; + } + + public void setPath( String path ) + { + this.path = path; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + FileInfo fileInfo = (FileInfo) o; + + if ( modified != null ? !modified.equals( fileInfo.modified ) : fileInfo.modified != null ) return false; + if ( fileName != null ? !fileName.equals( fileInfo.fileName ) : fileInfo.fileName != null ) return false; + return path != null ? path.equals( fileInfo.path ) : fileInfo.path == null; + } + + @Override + public int hashCode( ) + { + int result = modified != null ? modified.hashCode( ) : 0; + result = 31 * result + ( fileName != null ? fileName.hashCode( ) : 0 ); + result = 31 * result + ( path != null ? path.hashCode( ) : 0 ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "FileInfo{" ); + sb.append( "modified=" ).append( modified ); + sb.append( ", fileName='" ).append( fileName ).append( '\'' ); + sb.append( ", path='" ).append( path ).append( '\'' ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/IndexingTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/IndexingTask.java new file mode 100644 index 000000000..42f25cb24 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/IndexingTask.java @@ -0,0 +1,156 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; + +/** + * @author Martin Stockhammer + */ +@Schema(name="IndexingTask",description = "Information about indexing tasks") +public class IndexingTask implements Serializable +{ + private static final long serialVersionUID = -1947200162602613310L; + private String repositoryId = ""; + private boolean fullRepository; + private boolean updateOnly; + private String resource = ""; + private boolean running = false; + private long maxExecutionTimeMs = 0; + + public static IndexingTask of( org.apache.archiva.admin.model.beans.IndexingTask repositoryTask ) { + IndexingTask indexingTask = new IndexingTask( ); + indexingTask.setFullRepository( repositoryTask.isFullScan()); + indexingTask.setUpdateOnly( repositoryTask.isUpdateOnly() ); + indexingTask.setResource( repositoryTask.getResource() ); + indexingTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() ); + indexingTask.setRepositoryId( repositoryTask.getRepositoryId() ); + return indexingTask; + } + + @Schema(name="repository_id",description = "Identifier of the repository this task is running on") + public String getRepositoryId( ) + { + return repositoryId; + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId==null?"":repositoryId; + } + + @Schema( name = "full_repository", description = "True, if this is a full repository index scan" ) + public boolean isFullRepository( ) + { + return fullRepository; + } + + public void setFullRepository( boolean fullRepository ) + { + this.fullRepository = fullRepository; + } + + @Schema(name="update_only", description = "True, if this is only updating the index with new files") + public boolean isUpdateOnly( ) + { + return updateOnly; + } + + public void setUpdateOnly( boolean updateOnly ) + { + this.updateOnly = updateOnly; + } + + @Schema(name="resource",description = "The resource that should be updated, if this is not a full repo update") + public String getResource( ) + { + return resource; + } + + public void setResource( String resource ) + { + this.resource = resource == null ? "" : resource; + } + + @Schema(name="running", description = "True, if this task is currently running") + public boolean isRunning( ) + { + return running; + } + + public void setRunning( boolean running ) + { + this.running = running; + } + + @Schema(name="max_execution_time_ms",description = "Maximum task execution time in ms") + public long getMaxExecutionTimeMs( ) + { + return maxExecutionTimeMs; + } + + public void setMaxExecutionTimeMs( long maxExecutionTimeMs ) + { + this.maxExecutionTimeMs = maxExecutionTimeMs; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + IndexingTask that = (IndexingTask) o; + + if ( fullRepository != that.fullRepository ) return false; + if ( updateOnly != that.updateOnly ) return false; + if ( running != that.running ) return false; + if ( maxExecutionTimeMs != that.maxExecutionTimeMs ) return false; + if ( !repositoryId.equals( that.repositoryId ) ) return false; + return resource.equals( that.resource ); + } + + @Override + public int hashCode( ) + { + int result = repositoryId.hashCode( ); + result = 31 * result + ( fullRepository ? 1 : 0 ); + result = 31 * result + ( updateOnly ? 1 : 0 ); + result = 31 * result + resource.hashCode( ); + result = 31 * result + ( running ? 1 : 0 ); + result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "IndexingTask{" ); + sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' ); + sb.append( ", fullRepository=" ).append( fullRepository ); + sb.append( ", updateOnly=" ).append( updateOnly ); + sb.append( ", resource='" ).append( resource ).append( '\'' ); + sb.append( ", running=" ).append( running ); + sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs ); + sb.append( '}' ); + return sb.toString( ); + } + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/LdapConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/LdapConfiguration.java new file mode 100644 index 000000000..15372cd5a --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/LdapConfiguration.java @@ -0,0 +1,327 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@XmlRootElement(name="ldapConfiguration") +@Schema(name="LdapConfiguration", description = "LDAP configuration attributes") +public class LdapConfiguration implements Serializable +{ + private static final long serialVersionUID = -4736767846016398583L; + + private String hostName = ""; + private int port = 389; + private String baseDn = ""; + private String groupsBaseDn = ""; + private String bindDn = ""; + private String bindPassword = ""; + private String authenticationMethod = "none"; + private String contextFactory; + private boolean sslEnabled = false; + private boolean bindAuthenticatorEnabled = true; + private boolean useRoleNameAsGroup = false; + private Map properties = new TreeMap<>(); + private boolean writable = false; + private List availableContextFactories; + + public LdapConfiguration( ) + { + } + + public static LdapConfiguration of( org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfiguration ) { + LdapConfiguration newCfg = new LdapConfiguration( ); + newCfg.setAuthenticationMethod( ldapConfiguration.getAuthenticationMethod( ) ); + newCfg.setBaseDn( ldapConfiguration.getBaseDn( ) ); + newCfg.setGroupsBaseDn( ldapConfiguration.getBaseGroupsDn() ); + newCfg.setBindDn( ldapConfiguration.getBindDn() ); + newCfg.setBindPassword( ldapConfiguration.getPassword() ); + newCfg.setBindAuthenticatorEnabled( ldapConfiguration.isBindAuthenticatorEnabled() ); + newCfg.setHostName( ldapConfiguration.getHostName( ) ); + newCfg.setSslEnabled( ldapConfiguration.isSsl() ); + newCfg.setContextFactory( ldapConfiguration.getContextFactory() ); + if (ldapConfiguration.getPort()<=0) { + newCfg.setPort( newCfg.isSslEnabled() ? 636 : 389 ); + } else + { + newCfg.setPort( ldapConfiguration.getPort( ) ); + } + newCfg.setProperties( ldapConfiguration.getExtraProperties( ) ); + newCfg.setWritable( ldapConfiguration.isWritable() ); + return newCfg; + } + + @Schema(name="host_name", description = "The hostname to use to connect to the LDAP server") + public String getHostName( ) + { + return hostName; + } + + public void setHostName( String hostName ) + { + this.hostName = hostName==null?"":hostName; + } + + @Schema(description = "The port to use to connect to the LDAP server") + public int getPort( ) + { + return port; + } + + public void setPort( int port ) + { + this.port = port; + } + + @Schema(name="context_factory",description = "The class name of the LDAP context factory") + public String getContextFactory( ) + { + return contextFactory; + } + + public void setContextFactory( String contextFactory ) + { + this.contextFactory = contextFactory; + } + + + @Schema(name="ssl_enabled", description = "True, if SSL/TLS should be used for connecting the LDAP server") + public boolean isSslEnabled( ) + { + return sslEnabled; + } + + public void setSslEnabled( boolean sslEnabled ) + { + this.sslEnabled = sslEnabled; + } + + @Schema(name="base_dn", description = "The BASE DN used for the LDAP server") + public String getBaseDn( ) + { + return baseDn; + } + + public void setBaseDn( String baseDn ) + { + this.baseDn = baseDn == null ? "" : baseDn; + } + + @Schema(name="bind_dn", description = "The distinguished name of the bind user which is used to bind to the LDAP server") + public String getBindDn( ) + { + return bindDn; + } + + public void setBindDn( String bindDn ) + { + this.bindDn = bindDn == null ? "" : bindDn; + } + + @Schema(name="bind_password", description = "The password used to bind to the ldap server") + public String getBindPassword( ) + { + return bindPassword; + } + + public void setBindPassword( String bindPassword ) + { + this.bindPassword = bindPassword==null?"":bindPassword; + } + + @Schema(name="groups_base_dn", description = "The distinguished name of the base to use for searching group.") + public String getGroupsBaseDn( ) + { + return groupsBaseDn; + } + + public void setGroupsBaseDn( String groupsBaseDn ) + { + this.groupsBaseDn = groupsBaseDn==null?"":groupsBaseDn; + } + + @Schema(name="authentication_method", description = "The authentication method used to bind to the LDAP server (PLAINTEXT, SASL, ...)") + public String getAuthenticationMethod( ) + { + return authenticationMethod; + } + + public void setAuthenticationMethod( String authenticationMethod ) + { + this.authenticationMethod = authenticationMethod==null?"":authenticationMethod; + } + + @Schema(name="bind_authenticator_enabled", description = "True, if the LDAP bind authentication is used for logging in to Archiva") + public boolean isBindAuthenticatorEnabled( ) + { + return bindAuthenticatorEnabled; + } + + public void setBindAuthenticatorEnabled( boolean bindAuthenticatorEnabled ) + { + this.bindAuthenticatorEnabled = bindAuthenticatorEnabled; + } + + @Schema(name="user_role_name_as_group", description = "True, if the archiva role name is also the LDAP group name") + public boolean isUseRoleNameAsGroup( ) + { + return useRoleNameAsGroup; + } + + public void setUseRoleNameAsGroup( boolean useRoleNameAsGroup ) + { + this.useRoleNameAsGroup = useRoleNameAsGroup; + } + + @Schema(description = "LDAP ConnectionFactory environment properties") + public Map getProperties( ) + { + return properties; + } + + public void setProperties( Map properties ) + { + this.properties = new TreeMap<>( properties ); + } + + public void addProperty(String key, String value) { + this.properties.put( key, value ); + } + + @Schema(description = "True, if attributes in the the LDAP server can be edited by Archiva") + public boolean isWritable( ) + { + return writable; + } + + public void setWritable( boolean writable ) + { + this.writable = writable; + } + + @Schema(name="available_context_factories", description = "The LDAP context factories that are known and available") + public List getAvailableContextFactories( ) + { + return availableContextFactories; + } + + public void setAvailableContextFactories( List availableContextFactories ) + { + this.availableContextFactories = new ArrayList<>( availableContextFactories ); + } + + public void addAvailableContextFactory(String contextFactory) { + if (!this.availableContextFactories.contains( contextFactory ) ) { + this.availableContextFactories.add( contextFactory ); + } + } + + + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + LdapConfiguration that = (LdapConfiguration) o; + + if ( port != that.port ) return false; + if ( sslEnabled != that.sslEnabled ) return false; + if ( bindAuthenticatorEnabled != that.bindAuthenticatorEnabled ) return false; + if ( useRoleNameAsGroup != that.useRoleNameAsGroup ) return false; + if ( writable != that.writable ) return false; + if ( !Objects.equals( hostName, that.hostName ) ) return false; + if ( !Objects.equals( baseDn, that.baseDn ) ) return false; + if ( !Objects.equals( bindDn, that.bindDn ) ) return false; + if ( !Objects.equals( groupsBaseDn, that.groupsBaseDn ) ) + return false; + if ( !Objects.equals( bindPassword, that.bindPassword ) ) return false; + if ( !Objects.equals( authenticationMethod, that.authenticationMethod ) ) + return false; + return properties.equals( that.properties ); + } + + @Override + public int hashCode( ) + { + int result = hostName != null ? hostName.hashCode( ) : 0; + result = 31 * result + port; + result = 31 * result + ( sslEnabled ? 1 : 0 ); + result = 31 * result + ( baseDn != null ? baseDn.hashCode( ) : 0 ); + result = 31 * result + ( bindDn != null ? bindDn.hashCode( ) : 0 ); + result = 31 * result + ( groupsBaseDn != null ? groupsBaseDn.hashCode( ) : 0 ); + result = 31 * result + ( bindPassword != null ? bindPassword.hashCode( ) : 0 ); + result = 31 * result + ( authenticationMethod != null ? authenticationMethod.hashCode( ) : 0 ); + result = 31 * result + ( bindAuthenticatorEnabled ? 1 : 0 ); + result = 31 * result + ( useRoleNameAsGroup ? 1 : 0 ); + result = 31 * result + properties.hashCode( ); + result = 31 * result + ( writable ? 1 : 0 ); + return result; + } + + @SuppressWarnings( "StringBufferReplaceableByString" ) + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "LdapConfiguration{" ); + sb.append( "host_name='" ).append( hostName ).append( '\'' ); + sb.append( ", port=" ).append( port ); + sb.append( ", ssl_enabled=" ).append( sslEnabled ); + sb.append( ", base_dn='" ).append( baseDn ).append( '\'' ); + sb.append( ", groups_base_dn='" ).append( groupsBaseDn ).append( '\'' ); + sb.append( ", bind_dn='" ).append( bindDn ).append( '\'' ); + sb.append( ", bind_password='" ).append( bindPassword ).append( '\'' ); + sb.append( ", authentication_method='" ).append( authenticationMethod ).append( '\'' ); + sb.append( ", bind_authenticator_enabled=" ).append( bindAuthenticatorEnabled ); + sb.append( ", use_role_name_as_group=" ).append( useRoleNameAsGroup ); + sb.append( ", properties=" ).append( properties ); + sb.append( ", writable=" ).append( writable ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java new file mode 100644 index 000000000..e82db108d --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java @@ -0,0 +1,264 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.repository.ManagedRepository; +import org.apache.archiva.repository.RepositoryType; +import org.apache.archiva.repository.features.ArtifactCleanupFeature; +import org.apache.archiva.repository.features.IndexCreationFeature; +import org.apache.archiva.repository.features.StagingRepositoryFeature; + +import java.time.Period; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author Martin Stockhammer + */ +@Schema(name="MavenManagedRepository",description = "A managed repository stores artifacts locally") +public class MavenManagedRepository extends Repository +{ + private static final long serialVersionUID = -6853748886201905029L; + + boolean blocksRedeployments; + List releaseSchemes = new ArrayList<>( ); + boolean deleteSnapshotsOfRelease = false; + private Period retentionPeriod; + private int retentionCount; + private String indexPath; + private String packedIndexPath; + private boolean skipPackedIndexCreation; + private boolean hasStagingRepository; + private String stagingRepository; + + + public MavenManagedRepository( ) + { + super.setCharacteristic( Repository.CHARACTERISTIC_MANAGED ); + super.setType( RepositoryType.MAVEN.name( ) ); + } + + protected static void update(MavenManagedRepository repo, ManagedRepository beanRepo) { + repo.setDescription( beanRepo.getDescription() ); + repo.setId( beanRepo.getId() ); + repo.setIndex( true ); + repo.setLayout( beanRepo.getLayout() ); + repo.setBlocksRedeployments( beanRepo.blocksRedeployments() ); + repo.setReleaseSchemes( beanRepo.getActiveReleaseSchemes().stream().map( Objects::toString).collect( Collectors.toList()) ); + repo.setLocation( beanRepo.getLocation().toString() ); + repo.setName( beanRepo.getName()); + repo.setScanned( beanRepo.isScanned() ); + repo.setSchedulingDefinition( beanRepo.getSchedulingDefinition() ); + ArtifactCleanupFeature artifactCleanupFeature = beanRepo.getFeature( ArtifactCleanupFeature.class ).get( ); + repo.setDeleteSnapshotsOfRelease( artifactCleanupFeature.isDeleteReleasedSnapshots()); + repo.setRetentionCount( artifactCleanupFeature.getRetentionCount()); + repo.setRetentionPeriod( artifactCleanupFeature.getRetentionPeriod() ); + IndexCreationFeature icf = beanRepo.getFeature( IndexCreationFeature.class ).get( ); + repo.setIndex( icf.hasIndex( ) ); + repo.setIndexPath( icf.getIndexPath( ).getPath( ) ); + repo.setPackedIndexPath( icf.getPackedIndexPath( ).getPath( ) ); + repo.setSkipPackedIndexCreation( icf.isSkipPackedIndexCreation() ); + StagingRepositoryFeature srf = beanRepo.getFeature( StagingRepositoryFeature.class ).get( ); + repo.setHasStagingRepository( srf.isStageRepoNeeded( ) ); + repo.setStagingRepository( srf.getStagingRepository()!=null?srf.getStagingRepository().getId():"" ); + } + + public static MavenManagedRepository of( ManagedRepository beanRepo ) { + MavenManagedRepository repo = new MavenManagedRepository( ); + update( repo, beanRepo ); + return repo; + } + + @Schema(name="blocks_redeployments",description = "True, if redeployments to this repository are not allowed") + public boolean isBlocksRedeployments( ) + { + return blocksRedeployments; + } + + public void setBlocksRedeployments( boolean blocksRedeployments ) + { + this.blocksRedeployments = blocksRedeployments; + } + + @Schema(name="release_schemes", description = "The release schemes this repository is used for (e.g. RELEASE, SNAPSHOT)") + public List getReleaseSchemes( ) + { + return releaseSchemes; + } + + public void setReleaseSchemes( List releaseSchemes ) + { + this.releaseSchemes = new ArrayList<>( releaseSchemes ); + } + + public void addReleaseScheme(String scheme) { + if (!this.releaseSchemes.contains( scheme )) + { + this.releaseSchemes.add( scheme ); + } + } + + @Schema(name="delete_snaphots_of_release", description = "True, if snapshots are deleted, after a version is released") + public boolean isDeleteSnapshotsOfRelease( ) + { + return deleteSnapshotsOfRelease; + } + + public void setDeleteSnapshotsOfRelease( boolean deleteSnapshotsOfRelease ) + { + this.deleteSnapshotsOfRelease = deleteSnapshotsOfRelease; + } + + @Schema(name="retention_period", description = "The period after which snapshots are deleted.") + public Period getRetentionPeriod( ) + { + return retentionPeriod; + } + + public void setRetentionPeriod( Period retentionPeriod ) + { + this.retentionPeriod = retentionPeriod; + } + + @Schema(name="retention_count", description = "Number of snapshot artifacts to keep.") + public int getRetentionCount( ) + { + return retentionCount; + } + + public void setRetentionCount( int retentionCount ) + { + this.retentionCount = retentionCount; + } + + @Schema( name = "index_path", description = "Path to the directory that contains the index, relative to the repository base directory" ) + public String getIndexPath( ) + { + return indexPath; + } + + public void setIndexPath( String indexPath ) + { + this.indexPath = indexPath; + } + + @Schema( name = "packed_index_path", description = "Path to the directory that contains the packed index, relative to the repository base directory" ) + public String getPackedIndexPath( ) + { + return packedIndexPath; + } + + public void setPackedIndexPath( String packedIndexPath ) + { + this.packedIndexPath = packedIndexPath; + } + + @Schema(name="skip_packed_index_creation", description = "True, if packed index is not created during index update") + public boolean isSkipPackedIndexCreation( ) + { + return skipPackedIndexCreation; + } + + public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation ) + { + this.skipPackedIndexCreation = skipPackedIndexCreation; + } + + @Schema(name="has_staging_repository", description = "True, if this repository has a staging repository assigned") + public boolean isHasStagingRepository( ) + { + return hasStagingRepository; + } + + public void setHasStagingRepository( boolean hasStagingRepository ) + { + this.hasStagingRepository = hasStagingRepository; + } + + @Schema(name="staging_repository", description = "The id of the assigned staging repository") + public String getStagingRepository( ) + { + return stagingRepository; + } + + public void setStagingRepository( String stagingRepository ) + { + this.stagingRepository = stagingRepository; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + if ( !super.equals( o ) ) return false; + + MavenManagedRepository that = (MavenManagedRepository) o; + + if ( blocksRedeployments != that.blocksRedeployments ) return false; + return releaseSchemes != null ? releaseSchemes.equals( that.releaseSchemes ) : that.releaseSchemes == null; + } + + @Override + public int hashCode( ) + { + int result = super.hashCode( ); + result = 31 * result + ( blocksRedeployments ? 1 : 0 ); + result = 31 * result + ( releaseSchemes != null ? releaseSchemes.hashCode( ) : 0 ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "ManagedRepository{" ); + sb.append( "blocksRedeployments=" ).append( blocksRedeployments ); + sb.append( ", releaseSchemes=" ).append( releaseSchemes ); + sb.append( ", id='" ).append( id ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", description='" ).append( description ).append( '\'' ); + sb.append( ", type='" ).append( type ).append( '\'' ); + sb.append( ", location='" ).append( location ).append( '\'' ); + sb.append( ", scanned=" ).append( scanned ); + sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' ); + sb.append( ", index=" ).append( index ); + sb.append( ", layout='" ).append( layout ).append( '\'' ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java new file mode 100644 index 000000000..5536ae9b0 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java @@ -0,0 +1,47 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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.archiva.repository.ManagedRepository; + +import java.io.Serializable; + +/** + * @author Martin Stockhammer + */ +public class MavenManagedRepositoryUpdate extends MavenManagedRepository implements Serializable +{ + private static final long serialVersionUID = -9181643343284109862L; + private boolean resetStats = false; + + public static MavenManagedRepositoryUpdate of( ManagedRepository repository ) { + MavenManagedRepositoryUpdate repo = new MavenManagedRepositoryUpdate( ); + update( repo, repository ); + return repo; + } + + public boolean isResetStats( ) + { + return resetStats; + } + + public void setResetStats( boolean resetStats ) + { + this.resetStats = resetStats; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenRemoteRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenRemoteRepository.java new file mode 100644 index 000000000..8375ede5c --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenRemoteRepository.java @@ -0,0 +1,168 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import java.util.Map; +import java.util.TreeMap; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@Schema(name="MavenRemoteRepository",description = "A remote repository definition is used to pull artifacts from other repositories") +public class MavenRemoteRepository extends Repository +{ + private static final long serialVersionUID = 5625043398766480265L; + String loginUser; + String loginPassword; + String checkPath; + Map extraParameters = new TreeMap<>( ); + Map requestHeader = new TreeMap<>( ); + long timeoutMs; + + @Schema(name="login_user",description = "Username for login to the remote repository") + public String getLoginUser( ) + { + return loginUser; + } + + public void setLoginUser( String loginUser ) + { + this.loginUser = loginUser; + } + + @Schema(name="login_password",description = "Password for connecting to the remote repository") + public String getLoginPassword( ) + { + return loginPassword; + } + + public void setLoginPassword( String loginPassword ) + { + this.loginPassword = loginPassword; + } + + @Schema(name="check_path",description = "Path relative to the repository URL that is used to check of availability of the remote repository.") + public String getCheckPath( ) + { + return checkPath; + } + + public void setCheckPath( String checkPath ) + { + this.checkPath = checkPath; + } + + @Schema(name="extra_parameters", description = "Key-Value map with extra parameters sent to the remote repository") + public Map getExtraParameters( ) + { + return extraParameters; + } + + public void setExtraParameters( Map extraParameters ) + { + this.extraParameters = new TreeMap<>( extraParameters ); + } + + public void addExtraParameter(String key, String value) { + this.extraParameters.put( key, value ); + } + + @Schema(name="request_header",description = "Key-Value map with request headers that are sent to the remote repository") + public Map getRequestHeader( ) + { + return requestHeader; + } + + public void setRequestHeader( Map requestHeader ) + { + this.requestHeader = new TreeMap<>( requestHeader ); + } + + public void addRequestHeader(String headerName, String headerValue) { + this.requestHeader.put( headerName, headerValue ); + } + + @Schema(name="timeout_ms", description = "The time in milliseconds after that a request to the remote repository is aborted") + public long getTimeoutMs( ) + { + return timeoutMs; + } + + public void setTimeoutMs( long timeoutMs ) + { + this.timeoutMs = timeoutMs; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + if ( !super.equals( o ) ) return false; + + MavenRemoteRepository that = (MavenRemoteRepository) o; + + if ( timeoutMs != that.timeoutMs ) return false; + if ( loginUser != null ? !loginUser.equals( that.loginUser ) : that.loginUser != null ) return false; + if ( loginPassword != null ? !loginPassword.equals( that.loginPassword ) : that.loginPassword != null ) + return false; + if ( checkPath != null ? !checkPath.equals( that.checkPath ) : that.checkPath != null ) return false; + if ( extraParameters != null ? !extraParameters.equals( that.extraParameters ) : that.extraParameters != null ) + return false; + return requestHeader != null ? requestHeader.equals( that.requestHeader ) : that.requestHeader == null; + } + + @Override + public int hashCode( ) + { + int result = super.hashCode( ); + result = 31 * result + ( loginUser != null ? loginUser.hashCode( ) : 0 ); + result = 31 * result + ( loginPassword != null ? loginPassword.hashCode( ) : 0 ); + result = 31 * result + ( checkPath != null ? checkPath.hashCode( ) : 0 ); + result = 31 * result + ( extraParameters != null ? extraParameters.hashCode( ) : 0 ); + result = 31 * result + ( requestHeader != null ? requestHeader.hashCode( ) : 0 ); + result = 31 * result + (int) ( timeoutMs ^ ( timeoutMs >>> 32 ) ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "RemoteRepository{" ); + sb.append( "loginUser='" ).append( loginUser ).append( '\'' ); + sb.append( ", loginPassword='" ).append( loginPassword ).append( '\'' ); + sb.append( ", checkPath='" ).append( checkPath ).append( '\'' ); + sb.append( ", extraParameters=" ).append( extraParameters ); + sb.append( ", requestHeader=" ).append( requestHeader ); + sb.append( ", timeOut=" ).append( timeoutMs ); + sb.append( ", id='" ).append( id ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", description='" ).append( description ).append( '\'' ); + sb.append( ", type='" ).append( type ).append( '\'' ); + sb.append( ", location='" ).append( location ).append( '\'' ); + sb.append( ", scanned=" ).append( scanned ); + sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' ); + sb.append( ", index=" ).append( index ); + sb.append( ", layout='" ).append( layout ).append( '\'' ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MergeConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MergeConfiguration.java new file mode 100644 index 000000000..053e12993 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MergeConfiguration.java @@ -0,0 +1,128 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; + +/** + * Index merge configuration. + * + * @author Martin Stockhammer + * @since 3.0 + */ +@XmlRootElement(name="mergeConfiguration") +@Schema(name="MergeConfiguration", description = "Configuration settings for index merge of remote repositories.") +public class MergeConfiguration implements Serializable +{ + private static final long serialVersionUID = -3629274059574459133L; + + private String mergedIndexPath = DEFAULT_INDEX_PATH; + private int mergedIndexTtlMinutes = 30; + private String indexMergeSchedule = ""; + + @Schema(name="merged_index_path", description = "The path where the merged index is stored. The path is relative to the repository directory of the group.") + public String getMergedIndexPath( ) + { + return mergedIndexPath; + } + + public void setMergedIndexPath( String mergedIndexPath ) + { + this.mergedIndexPath = mergedIndexPath; + } + + @Schema(name="merged_index_ttl_minutes", description = "The Time to Life of the merged index in minutes.") + public int getMergedIndexTtlMinutes( ) + { + return mergedIndexTtlMinutes; + } + + public void setMergedIndexTtlMinutes( int mergedIndexTtlMinutes ) + { + this.mergedIndexTtlMinutes = mergedIndexTtlMinutes; + } + + @Schema(name="index_merge_schedule", description = "Cron expression that defines the times/intervals for index merging.") + public String getIndexMergeSchedule( ) + { + return indexMergeSchedule; + } + + public void setIndexMergeSchedule( String indexMergeSchedule ) + { + this.indexMergeSchedule = indexMergeSchedule; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + MergeConfiguration that = (MergeConfiguration) o; + + if ( mergedIndexTtlMinutes != that.mergedIndexTtlMinutes ) return false; + if ( !Objects.equals( mergedIndexPath, that.mergedIndexPath ) ) + return false; + return Objects.equals( indexMergeSchedule, that.indexMergeSchedule ); + } + + @Override + public int hashCode( ) + { + int result = mergedIndexPath != null ? mergedIndexPath.hashCode( ) : 0; + result = 31 * result + mergedIndexTtlMinutes; + result = 31 * result + ( indexMergeSchedule != null ? indexMergeSchedule.hashCode( ) : 0 ); + return result; + } + + @SuppressWarnings( "StringBufferReplaceableByString" ) + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "MergeConfiguration{" ); + sb.append( "mergedIndexPath='" ).append( mergedIndexPath ).append( '\'' ); + sb.append( ", mergedIndexTtlMinutes=" ).append( mergedIndexTtlMinutes ); + sb.append( ", indexMergeSchedule='" ).append( indexMergeSchedule ).append( '\'' ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Repository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Repository.java new file mode 100644 index 000000000..d0979649f --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/Repository.java @@ -0,0 +1,289 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.repository.ManagedRepository; +import org.apache.archiva.repository.RemoteRepository; + +import java.io.Serializable; +import java.util.Locale; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@Schema(description = "Repository data") +public class Repository implements Serializable +{ + private static final long serialVersionUID = -4741025877287175182L; + + public static final String CHARACTERISTIC_MANAGED = "managed"; + public static final String CHARACTERISTIC_REMOTE = "remote"; + public static final String CHARACTERISTIC_UNKNOWN = "unknown"; + + protected String id; + protected String name; + protected String description; + protected String type; + protected String characteristic; + protected String location; + protected boolean scanned; + protected String schedulingDefinition; + protected boolean index; + protected String layout; + + public Repository( ) + { + } + + public static Repository of( org.apache.archiva.repository.Repository repository ) { + Repository newRepo = new Repository( ); + newRepo.setId( repository.getId() ); + newRepo.setName( repository.getName( ) ); + newRepo.setDescription( repository.getDescription( ) ); + newRepo.setLocation( repository.getLocation().toASCIIString() ); + newRepo.setIndex( repository.hasIndex() ); + newRepo.setLayout( repository.getLayout() ); + newRepo.setType( repository.getType().name() ); + newRepo.setScanned( repository.isScanned() ); + newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() ); + if (repository instanceof RemoteRepository ) { + newRepo.setCharacteristic( CHARACTERISTIC_REMOTE ); + } else if (repository instanceof ManagedRepository ) { + newRepo.setCharacteristic( CHARACTERISTIC_MANAGED ); + } else { + newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN ); + } + return newRepo; + } + + public static Repository of( org.apache.archiva.repository.Repository repository, Locale locale ) { + Locale myLocale; + if (locale==null) { + myLocale = Locale.getDefault( ); + } else { + myLocale = locale; + } + String repoName = repository.getName( myLocale ); + if (repoName==null) { + repoName = repository.getName( ); + } + String description = repository.getDescription( myLocale ); + if (description==null) { + description = repository.getDescription( ); + } + Repository newRepo = new Repository( ); + newRepo.setId( repository.getId() ); + newRepo.setName( repoName ); + newRepo.setDescription( description ); + newRepo.setLocation( repository.getLocation().toASCIIString() ); + newRepo.setIndex( repository.hasIndex() ); + newRepo.setLayout( repository.getLayout() ); + newRepo.setType( repository.getType().name() ); + newRepo.setScanned( repository.isScanned() ); + newRepo.setSchedulingDefinition( repository.getSchedulingDefinition() ); + if (repository instanceof RemoteRepository ) { + newRepo.setCharacteristic( CHARACTERISTIC_REMOTE ); + } else if (repository instanceof ManagedRepository ) { + newRepo.setCharacteristic( CHARACTERISTIC_MANAGED ); + } else { + newRepo.setCharacteristic( CHARACTERISTIC_UNKNOWN ); + } + return newRepo; + } + + @Schema(description = "Category of the repository. Either 'managed' or 'remote'.") + public String getCharacteristic( ) + { + return characteristic; + } + + public void setCharacteristic( String characteristic ) + { + this.characteristic = characteristic; + } + + @Schema(description = "Unique identifier of the repository") + public String getId( ) + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + @Schema(description = "Display name of the repository") + public String getName( ) + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + @Schema(description = "Description of the repository") + public String getDescription( ) + { + return description; + } + + public void setDescription( String description ) + { + this.description = description; + } + + @Schema(description = "Repository type") + public String getType( ) + { + return type; + } + + public void setType( String type ) + { + this.type = type; + } + + @Schema(description = "The location, where the repository data can be found") + public String getLocation( ) + { + return location; + } + + public void setLocation( String location ) + { + this.location = location; + } + + @Schema(description = "True, if this repository is scanned regularly") + public boolean isScanned( ) + { + return scanned; + } + + public void setScanned( boolean scanned ) + { + this.scanned = scanned; + } + + @Schema(name="scheduling_definition",description = "Definition of regular scheduled scan") + public String getSchedulingDefinition( ) + { + return schedulingDefinition; + } + + public void setSchedulingDefinition( String schedulingDefinition ) + { + this.schedulingDefinition = schedulingDefinition; + } + + @Schema(description = "True, if this is a indexed repository") + public boolean isIndex( ) + { + return index; + } + + public void setIndex( boolean index ) + { + this.index = index; + } + + @Schema(description = "Layout type is implementation specific") + public String getLayout( ) + { + return layout; + } + + public void setLayout( String layout ) + { + this.layout = layout; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + Repository that = (Repository) o; + + if ( scanned != that.scanned ) return false; + if ( index != that.index ) return false; + if ( id != null ? !id.equals( that.id ) : that.id != null ) return false; + if ( name != null ? !name.equals( that.name ) : that.name != null ) return false; + if ( description != null ? !description.equals( that.description ) : that.description != null ) return false; + if ( type != null ? !type.equals( that.type ) : that.type != null ) return false; + if ( location != null ? !location.equals( that.location ) : that.location != null ) return false; + if ( schedulingDefinition != null ? !schedulingDefinition.equals( that.schedulingDefinition ) : that.schedulingDefinition != null ) + return false; + return layout != null ? layout.equals( that.layout ) : that.layout == null; + } + + @Override + public int hashCode( ) + { + int result = id != null ? id.hashCode( ) : 0; + result = 31 * result + ( name != null ? name.hashCode( ) : 0 ); + result = 31 * result + ( description != null ? description.hashCode( ) : 0 ); + result = 31 * result + ( type != null ? type.hashCode( ) : 0 ); + result = 31 * result + ( location != null ? location.hashCode( ) : 0 ); + result = 31 * result + ( scanned ? 1 : 0 ); + result = 31 * result + ( schedulingDefinition != null ? schedulingDefinition.hashCode( ) : 0 ); + result = 31 * result + ( index ? 1 : 0 ); + result = 31 * result + ( layout != null ? layout.hashCode( ) : 0 ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "Repository{" ); + sb.append( "id='" ).append( id ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", description='" ).append( description ).append( '\'' ); + sb.append( ", type='" ).append( type ).append( '\'' ); + sb.append( ", location='" ).append( location ).append( '\'' ); + sb.append( ", scanned=" ).append( scanned ); + sb.append( ", schedulingDefinition='" ).append( schedulingDefinition ).append( '\'' ); + sb.append( ", index=" ).append( index ); + sb.append( ", layout='" ).append( layout ).append( '\'' ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryGroup.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryGroup.java new file mode 100644 index 000000000..6f64a5191 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryGroup.java @@ -0,0 +1,176 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.features.IndexCreationFeature; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Martin Stockhammer + */ +@XmlRootElement(name="repositoryGroup") +@Schema(name="RepositoryGroup", description = "Information about a repository group, which combines multiple repositories as one virtual repository.") +public class RepositoryGroup implements Serializable +{ + private static final long serialVersionUID = -7319687481737616081L; + private String id; + private String name; + private List repositories = new ArrayList<>( ); + private String location; + MergeConfiguration mergeConfiguration; + + public RepositoryGroup( ) + { + } + + public RepositoryGroup(String id) { + this.id = id; + } + + public static RepositoryGroup of( org.apache.archiva.repository.RepositoryGroup modelObj ) { + RepositoryGroup result = new RepositoryGroup( ); + MergeConfiguration mergeConfig = new MergeConfiguration( ); + result.setMergeConfiguration( mergeConfig ); + result.setId( modelObj.getId() ); + result.setName( modelObj.getName() ); + result.setLocation( modelObj.getLocation().toString() ); + result.setRepositories( modelObj.getRepositories().stream().map( Repository::getId ).collect( Collectors.toList()) ); + if (modelObj.supportsFeature( IndexCreationFeature.class )) { + IndexCreationFeature icf = modelObj.getFeature( IndexCreationFeature.class ).get(); + mergeConfig.setMergedIndexPath( icf.getIndexPath( ).toString() ); + mergeConfig.setMergedIndexTtlMinutes( modelObj.getMergedIndexTTL( ) ); + mergeConfig.setIndexMergeSchedule( modelObj.getSchedulingDefinition() ); + } + return result; + } + + @Schema(description = "The unique id of the repository group.") + public String getId( ) + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + + @Schema(description = "The list of ids of repositories which are member of the repository group.") + public List getRepositories( ) + { + return repositories; + } + + public void setRepositories( List repositories ) + { + this.repositories = new ArrayList<>( repositories ); + } + + public void addRepository(String repositoryId) { + if (!this.repositories.contains( repositoryId )) { + this.repositories.add( repositoryId ); + } + } + + @Schema(name="merge_configuration",description = "The configuration for index merge.") + public MergeConfiguration getMergeConfiguration( ) + { + return mergeConfiguration; + } + + public void setMergeConfiguration( MergeConfiguration mergeConfiguration ) + { + this.mergeConfiguration = mergeConfiguration; + } + + @Schema(description = "The storage location of the repository. The merged index is stored relative to this location.") + public String getLocation( ) + { + return location; + } + + public void setLocation( String location ) + { + this.location = location; + } + + @Schema(description = "The name of the repository group") + public String getName( ) + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + RepositoryGroup that = (RepositoryGroup) o; + + return id.equals( that.id ); + } + + @Override + public int hashCode( ) + { + return id.hashCode( ); + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "RepositoryGroup{" ); + sb.append( "id='" ).append( id ).append( '\'' ); + sb.append( ", name='" ).append( name ).append( '\'' ); + sb.append( ", repositories=" ).append( repositories ); + sb.append( ", location='" ).append( location ).append( '\'' ); + sb.append( ", mergeConfiguration=" ).append( mergeConfiguration ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryStatistics.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryStatistics.java new file mode 100644 index 000000000..ab2c916f7 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/RepositoryStatistics.java @@ -0,0 +1,291 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.repository.scanner.RepositoryScanStatistics; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Map; +import java.util.TreeMap; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@XmlRootElement(name="repositoryStatistics") +@Schema(name="RepositoryStatistics", description = "Statistics data") +public class RepositoryStatistics implements Serializable +{ + private static final long serialVersionUID = 7943367882738452531L; + + private OffsetDateTime scanEndTime; + private OffsetDateTime scanStartTime; + private long scanDurationMs; + private long totalArtifactCount; + private long totalArtifactFileSize; + private long totalFileCount; + private long totalGroupCount; + private long totalProjectCount; + private long newFileCount; + private Map totalCountForType = new TreeMap<>( ); + private Map customValues = new TreeMap<>( ); + + public RepositoryStatistics( ) + { + } + + public static RepositoryStatistics of( org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics modelStats ) { + RepositoryStatistics newStats = new RepositoryStatistics( ); + newStats.setScanStartTime( modelStats.getScanStartTime().toInstant().atOffset( ZoneOffset.UTC ) ); + newStats.setScanEndTime( modelStats.getScanEndTime( ).toInstant( ).atOffset( ZoneOffset.UTC ) ); + newStats.setNewFileCount( modelStats.getNewFileCount() ); + newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() ); + newStats.setTotalArtifactCount( modelStats.getTotalArtifactCount() ); + newStats.setTotalArtifactFileSize( modelStats.getTotalArtifactFileSize() ); + newStats.setTotalCountForType( modelStats.getTotalCountForType() ); + newStats.setTotalFileCount( modelStats.getTotalFileCount() ); + newStats.setTotalGroupCount( modelStats.getTotalGroupCount() ); + newStats.setTotalProjectCount( modelStats.getTotalProjectCount() ); + for (String key : modelStats.getAvailableCustomValues()) { + newStats.addCustomValue( key, modelStats.getCustomValue( key ) ); + } + return newStats; + } + + public static RepositoryStatistics of( RepositoryScanStatistics scanStatistics ) { + RepositoryStatistics newStats = new RepositoryStatistics( ); + newStats.setScanStartTime( scanStatistics.getWhenGathered().toInstant().atOffset( ZoneOffset.UTC ) ); + newStats.setScanEndTime( OffsetDateTime.now(ZoneOffset.UTC) ); + newStats.setNewFileCount( scanStatistics.getNewFileCount() ); + newStats.setScanDurationMs( Duration.between( newStats.scanStartTime, newStats.scanEndTime ).toMillis() ); + newStats.setTotalArtifactCount( scanStatistics.getTotalFileCount() ); + newStats.setTotalArtifactFileSize( scanStatistics.getTotalSize() ); + newStats.setTotalFileCount( scanStatistics.getTotalFileCount() ); + newStats.setTotalGroupCount( 0 ); + newStats.setTotalProjectCount( 0 ); + return newStats; + } + + @Schema(name="scan_end_time", description = "Date and time when the last scan finished") + public OffsetDateTime getScanEndTime( ) + { + return scanEndTime; + } + + public void setScanEndTime( OffsetDateTime scanEndTime ) + { + this.scanEndTime = scanEndTime; + } + + @Schema( name = "scan_start_time", description = "Date and time when the last scan started" ) + public OffsetDateTime getScanStartTime( ) + { + return scanStartTime; + } + + public void setScanStartTime( OffsetDateTime scanStartTime ) + { + this.scanStartTime = scanStartTime; + } + + @Schema(name="total_artifact_count", description = "The number of artifacts scanned") + public long getTotalArtifactCount( ) + { + return totalArtifactCount; + } + + public void setTotalArtifactCount( long totalArtifactCount ) + { + this.totalArtifactCount = totalArtifactCount; + } + + @Schema(name="total_artifact_file_size", description = "The cumulative size of all files scanned") + public long getTotalArtifactFileSize( ) + { + return totalArtifactFileSize; + } + + public void setTotalArtifactFileSize( long totalArtifactFileSize ) + { + this.totalArtifactFileSize = totalArtifactFileSize; + } + + @Schema(name="total_file_count", description = "The total number of files scanned") + public long getTotalFileCount( ) + { + return totalFileCount; + } + + public void setTotalFileCount( long totalFileCount ) + { + this.totalFileCount = totalFileCount; + } + + @Schema(name="total_group_count", description = "The number of groups scanned") + public long getTotalGroupCount( ) + { + return totalGroupCount; + } + + public void setTotalGroupCount( long totalGroupCount ) + { + this.totalGroupCount = totalGroupCount; + } + + @Schema(name="total_project_count", description = "The number of projects scanned") + public long getTotalProjectCount( ) + { + return totalProjectCount; + } + + public void setTotalProjectCount( long totalProjectCount ) + { + this.totalProjectCount = totalProjectCount; + } + + @Schema(name="new_file_count", description = "Number of files registered as new") + public long getNewFileCount( ) + { + return newFileCount; + } + + public void setNewFileCount( long newFileCount ) + { + this.newFileCount = newFileCount; + } + + @Schema(name="scan_duration_ms", description = "The duration of the last scan in ms") + public long getScanDurationMs( ) + { + return scanDurationMs; + } + + public void setScanDurationMs( long scanDurationMs ) + { + this.scanDurationMs = scanDurationMs; + } + + @Schema(name="total_count_for_type", description = "File counts partitioned by file types") + public Map getTotalCountForType( ) + { + return totalCountForType; + } + + public void setTotalCountForType( Map totalCountForType ) + { + this.totalCountForType = new TreeMap<>( totalCountForType ); + } + + public void addTotalCountForType( String type, Long value ) + { + this.totalCountForType.put( type, value ); + } + + @Schema(name="custom_values", description = "Custom statistic values") + public Map getCustomValues( ) + { + return customValues; + } + + public void setCustomValues( Map customValues ) + { + this.customValues = new TreeMap<>( customValues ); + } + + public void addCustomValue(String type, Long value) { + this.customValues.put( type, value ); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + RepositoryStatistics that = (RepositoryStatistics) o; + + if ( scanDurationMs != that.scanDurationMs ) return false; + if ( totalArtifactCount != that.totalArtifactCount ) return false; + if ( totalArtifactFileSize != that.totalArtifactFileSize ) return false; + if ( totalFileCount != that.totalFileCount ) return false; + if ( totalGroupCount != that.totalGroupCount ) return false; + if ( totalProjectCount != that.totalProjectCount ) return false; + if ( newFileCount != that.newFileCount ) return false; + if ( scanEndTime != null ? !scanEndTime.equals( that.scanEndTime ) : that.scanEndTime != null ) return false; + if ( scanStartTime != null ? !scanStartTime.equals( that.scanStartTime ) : that.scanStartTime != null ) + return false; + if ( !totalCountForType.equals( that.totalCountForType ) ) return false; + return customValues.equals( that.customValues ); + } + + @Override + public int hashCode( ) + { + int result = scanEndTime != null ? scanEndTime.hashCode( ) : 0; + result = 31 * result + ( scanStartTime != null ? scanStartTime.hashCode( ) : 0 ); + result = 31 * result + (int) ( scanDurationMs ^ ( scanDurationMs >>> 32 ) ); + result = 31 * result + (int) ( totalArtifactCount ^ ( totalArtifactCount >>> 32 ) ); + result = 31 * result + (int) ( totalArtifactFileSize ^ ( totalArtifactFileSize >>> 32 ) ); + result = 31 * result + (int) ( totalFileCount ^ ( totalFileCount >>> 32 ) ); + result = 31 * result + (int) ( totalGroupCount ^ ( totalGroupCount >>> 32 ) ); + result = 31 * result + (int) ( totalProjectCount ^ ( totalProjectCount >>> 32 ) ); + result = 31 * result + (int) ( newFileCount ^ ( newFileCount >>> 32 ) ); + result = 31 * result + totalCountForType.hashCode( ); + result = 31 * result + customValues.hashCode( ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "RepositoryStatistics{" ); + sb.append( "scanEndTime=" ).append( scanEndTime ); + sb.append( ", scanStartTime=" ).append( scanStartTime ); + sb.append( ", scanDurationMs=" ).append( scanDurationMs ); + sb.append( ", totalArtifactCount=" ).append( totalArtifactCount ); + sb.append( ", totalArtifactFileSize=" ).append( totalArtifactFileSize ); + sb.append( ", totalFileCount=" ).append( totalFileCount ); + sb.append( ", totalGroupCount=" ).append( totalGroupCount ); + sb.append( ", totalProjectCount=" ).append( totalProjectCount ); + sb.append( ", newFileCount=" ).append( newFileCount ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanStatus.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanStatus.java new file mode 100644 index 000000000..4e4659487 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanStatus.java @@ -0,0 +1,124 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.admin.model.beans.MetadataScanTask; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Martin Stockhammer + */ +@Schema(name="ScanStatus", description = "Status of repository scan tasks") +public class ScanStatus implements Serializable +{ + private boolean scanRunning = false; + private int scanQueued = 0; + private boolean indexRunning = false; + private int indexQueued = 0; + private List indexingQueue = new ArrayList<>( ); + private List scanQueue = new ArrayList<>( ); + + public ScanStatus( ) + { + } + + public static ScanStatus of( org.apache.archiva.admin.model.beans.ScanStatus modelStatus ) { + ScanStatus status = new ScanStatus( ); + status.setIndexRunning( modelStatus.isIndexScanRunning() ); + status.setScanRunning( modelStatus.isMetadataScanRunning() ); + List indexQueue = modelStatus.getIndexingQueue( ); + status.setIndexingQueue( indexQueue.stream().map(IndexingTask::of).collect( Collectors.toList()) ); + status.setIndexQueued( indexQueue.size( ) > 0 ? indexQueue.size( ) - 1 : 0 ); + List scanQueue = modelStatus.getScanQueue( ); + status.setScanQueue( scanQueue.stream().map( ScanTask::of ).collect( Collectors.toList()) ); + status.setScanQueued( scanQueue.size( ) > 0 ? scanQueue.size( ) - 1 : 0 ); + return status; + + } + + @Schema( name = "scan_running", description = "True, if a scan is currently running" ) + public boolean isScanRunning( ) + { + return scanRunning; + } + + public void setScanRunning( boolean scanRunning ) + { + this.scanRunning = scanRunning; + } + + @Schema(name ="scan_queued", description = "Number of scans in the task queue") + public int getScanQueued( ) + { + return scanQueued; + } + + public void setScanQueued( int scanQueued ) + { + this.scanQueued = scanQueued; + } + + @Schema(name="index_running", description = "True, if there is a index task currently running") + public boolean isIndexRunning( ) + { + return indexRunning; + } + + public void setIndexRunning( boolean indexRunning ) + { + this.indexRunning = indexRunning; + } + + @Schema(name="index_queued", description = "Number of queued index tasks") + public int getIndexQueued( ) + { + return indexQueued; + } + + public void setIndexQueued( int indexQueued ) + { + this.indexQueued = indexQueued; + } + + @Schema( name = "indexing_queue", description = "List of indexing tasks waiting for execution" ) + public List getIndexingQueue( ) + { + return indexingQueue; + } + + public void setIndexingQueue( List indexingQueue ) + { + this.indexingQueue = new ArrayList<>( indexingQueue ); + } + + @Schema(name="scan_queue", description = "List of scan tasks waiting for execution") + public List getScanQueue( ) + { + return scanQueue; + } + + public void setScanQueue( List scanQueue ) + { + this.scanQueue = new ArrayList<>( scanQueue ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanTask.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanTask.java new file mode 100644 index 000000000..15e42d8e5 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ScanTask.java @@ -0,0 +1,156 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.admin.model.beans.MetadataScanTask; + +import java.io.Serializable; + +/** + * @author Martin Stockhammer + */ +@Schema(name="ScanTask", description = "Repository scan task information") +public class ScanTask implements Serializable +{ + private static final long serialVersionUID = -681163357370848098L; + private String repositoryId=""; + private boolean updateRelatedArtifacts; + private boolean fullRepository; + private boolean running = false; + private String resource = ""; + private long maxExecutionTimeMs = 0; + + public static ScanTask of( MetadataScanTask repositoryTask ) { + ScanTask scanTask = new ScanTask( ); + scanTask.setFullRepository( repositoryTask.isFullScan()); + scanTask.setUpdateRelatedArtifacts( repositoryTask.isUpdateRelatedArtifacts() ); + scanTask.setResource( repositoryTask.getResource() ); + scanTask.setMaxExecutionTimeMs( repositoryTask.getMaxExecutionTimeMs() ); + scanTask.setRepositoryId( repositoryTask.getRepositoryId( ) ); + return scanTask; + } + + @Schema(name="repository_id", description = "Identifier of the repository, this task is running on") + public String getRepositoryId( ) + { + return repositoryId; + } + + public void setRepositoryId( String repositoryId ) + { + this.repositoryId = repositoryId==null?"":repositoryId; + } + + @Schema(name="update_related_artifacts", description = "True, if related artifacts are updated too.") + public boolean isUpdateRelatedArtifacts( ) + { + return updateRelatedArtifacts; + } + + public void setUpdateRelatedArtifacts( boolean updateRelatedArtifacts ) + { + this.updateRelatedArtifacts = updateRelatedArtifacts; + } + + @Schema(name="full_repository",description = "True, if this is a full repository scan") + public boolean isFullRepository( ) + { + return fullRepository; + } + + public void setFullRepository( boolean fullRepository ) + { + this.fullRepository = fullRepository; + } + + @Schema(name="running", description = "True, if this task is currently running") + public boolean isRunning( ) + { + return running; + } + + public void setRunning( boolean running ) + { + this.running = running; + } + + @Schema(name="resource",description = "Name of the resource to update") + public String getResource( ) + { + return resource; + } + + public void setResource( String resource ) + { + this.resource = resource==null?"":resource; + } + + @Schema(name="max_excecution_time_ms",description = "Maximum execution time in ms") + public long getMaxExecutionTimeMs( ) + { + return maxExecutionTimeMs; + } + + public void setMaxExecutionTimeMs( long maxExecutionTimeMs ) + { + this.maxExecutionTimeMs = maxExecutionTimeMs; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + ScanTask scanTask = (ScanTask) o; + + if ( updateRelatedArtifacts != scanTask.updateRelatedArtifacts ) return false; + if ( fullRepository != scanTask.fullRepository ) return false; + if ( running != scanTask.running ) return false; + if ( maxExecutionTimeMs != scanTask.maxExecutionTimeMs ) return false; + if ( !repositoryId.equals( scanTask.repositoryId ) ) return false; + return resource.equals( scanTask.resource ); + } + + @Override + public int hashCode( ) + { + int result = repositoryId.hashCode( ); + result = 31 * result + ( updateRelatedArtifacts ? 1 : 0 ); + result = 31 * result + ( fullRepository ? 1 : 0 ); + result = 31 * result + ( running ? 1 : 0 ); + result = 31 * result + resource.hashCode( ); + result = 31 * result + (int) ( maxExecutionTimeMs ^ ( maxExecutionTimeMs >>> 32 ) ); + return result; + } + + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "ScanTask{" ); + sb.append( "repositoryId='" ).append( repositoryId ).append( '\'' ); + sb.append( ", updateRelatedArtifacts=" ).append( updateRelatedArtifacts ); + sb.append( ", fullRepository=" ).append( fullRepository ); + sb.append( ", running=" ).append( running ); + sb.append( ", resource='" ).append( resource ).append( '\'' ); + sb.append( ", maxExecutionTimeMs=" ).append( maxExecutionTimeMs ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/SecurityConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/SecurityConfiguration.java new file mode 100644 index 000000000..a3c062920 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/SecurityConfiguration.java @@ -0,0 +1,179 @@ +package org.apache.archiva.rest.api.v2.model;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * @author Martin Stockhammer + */ +@XmlRootElement(name = "securityConfiguration") +@Schema(name = "SecurityConfiguration", description = "Security configuration attributes.") +public class SecurityConfiguration implements Serializable +{ + private static final long serialVersionUID = -4186866365979053029L; + + private List activeUserManagers = new ArrayList<>( ); + private List activeRbacManagers = new ArrayList<>( ); + private Map properties = new TreeMap<>( ); + private boolean userCacheEnabled=false; + private boolean ldapActive=false; + + public SecurityConfiguration() { + + } + + public static SecurityConfiguration ofRedbackConfiguration( RedbackRuntimeConfiguration configuration ) { + SecurityConfiguration secConfig = new SecurityConfiguration( ); + secConfig.setActiveRbacManagers( configuration.getRbacManagerImpls() ); + secConfig.setActiveUserManagers( configuration.getUserManagerImpls() ); + secConfig.setProperties( configuration.getConfigurationProperties() ); + boolean rbLdapActive = configuration.getUserManagerImpls( ).stream( ).anyMatch( um -> um.contains( "ldap" ) ); + secConfig.setLdapActive( rbLdapActive ); + secConfig.setUserCacheEnabled( configuration.isUseUsersCache() ); + return secConfig; + } + + @Schema(name="active_user_managers", description = "List of ids of the active user managers") + public List getActiveUserManagers( ) + { + return activeUserManagers; + } + + public void setActiveUserManagers( List activeUserManagers ) + { + this.activeUserManagers = new ArrayList<>( activeUserManagers ); + } + + public void addSelectedUserManager(String userManager) { + this.activeUserManagers.add( userManager ); + } + + @Schema(name="active_rbac_managers", description = "List of ids of the active rbac managers") + public List getActiveRbacManagers( ) + { + return activeRbacManagers; + } + + public void setActiveRbacManagers( List activeRbacManagers ) + { + this.activeRbacManagers = new ArrayList<>( activeRbacManagers ); + } + + public void addSelectedRbacManager(String rbacManager) { + this.activeRbacManagers.add( rbacManager ); + } + + @Schema(description = "Map of all security properties") + public Map getProperties( ) + { + return properties; + } + + public void setProperties( Map properties ) + { + this.properties = new TreeMap<>( properties ); + } + + @Schema(name="user_cache_enabled", description = "True, if the user cache is active. It caches data from user backend.") + public boolean isUserCacheEnabled( ) + { + return userCacheEnabled; + } + + public void setUserCacheEnabled( boolean userCacheEnabled ) + { + this.userCacheEnabled = userCacheEnabled; + } + + @Schema(name="ldap_active", description = "True, if LDAP is used as user manager") + public boolean isLdapActive( ) + { + return ldapActive; + } + + public void setLdapActive( boolean ldapActive ) + { + this.ldapActive = ldapActive; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) return true; + if ( o == null || getClass( ) != o.getClass( ) ) return false; + + SecurityConfiguration that = (SecurityConfiguration) o; + + if ( userCacheEnabled != that.userCacheEnabled ) return false; + if ( ldapActive != that.ldapActive ) return false; + if ( !activeUserManagers.equals( that.activeUserManagers ) ) return false; + if ( !activeRbacManagers.equals( that.activeRbacManagers ) ) return false; + return properties.equals( that.properties ); + } + + @Override + public int hashCode( ) + { + int result = activeUserManagers.hashCode( ); + result = 31 * result + activeRbacManagers.hashCode( ); + result = 31 * result + properties.hashCode( ); + result = 31 * result + ( userCacheEnabled ? 1 : 0 ); + result = 31 * result + ( ldapActive ? 1 : 0 ); + return result; + } + + @SuppressWarnings( "StringBufferReplaceableByString" ) + @Override + public String toString( ) + { + final StringBuilder sb = new StringBuilder( "SecurityConfiguration{" ); + sb.append( "active_user_managers=" ).append( activeUserManagers ); + sb.append( ", active_rbac_managers=" ).append( activeRbacManagers ); + sb.append( ", properties=" ).append( properties ); + sb.append( ", user_cache_enabled=" ).append( userCacheEnabled ); + sb.append( ", ldap_active=" ).append( ldapActive ); + sb.append( '}' ); + return sb.toString( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ValidationError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ValidationError.java new file mode 100644 index 000000000..d8e51cb70 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/ValidationError.java @@ -0,0 +1,139 @@ +package org.apache.archiva.rest.api.v2.model; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Martin Stockhammer + */ +@XmlRootElement(name = "validationError") +@Schema(name = "ValidationError", description = "A validation error.") +public class ValidationError implements Serializable +{ + private static final long serialVersionUID = 2079020598090660171L; + + String key; + String field; + String category; + String type; + List parameter; + + + public ValidationError( ) + { + } + + public ValidationError( String key, String field, String category, String type, List parameter) { + this.key = key; + this.field = field; + this.category = category; + this.type = type; + if (parameter==null) { + this.parameter = new ArrayList<>( ); + } else + { + this.parameter = parameter; + } + } + + /** + * Creates a new instance based on the given error + * @param error the error instance + * @return + */ + public static ValidationError of( org.apache.archiva.repository.validation.ValidationError error ) { + return error != null ? new ValidationError( error.getErrorKey( ), error.getAttribute( ), error.getCategory( ), + error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) ) + : new ValidationError( ); + } + + /** + * Creates a new instance based on the field name and the error instance + * @param fieldName the name of the field to which the error applies + * @param error the error definition + * @return a new validation error instance + */ + public static ValidationError of( String fieldName, org.apache.archiva.repository.validation.ValidationError error ) { + return error != null ? new ValidationError( error.getErrorKey( ), fieldName, error.getCategory( ), + error.getType( ), error.getArguments( ).stream( ).map( Object::toString ).collect( Collectors.toList( ) ) ) + : new ValidationError( ); + } + + @Schema(name="key", description = "The full key of the validation error") + public String getKey( ) + { + return key; + } + + public void setKey( String key ) + { + this.key = key; + } + + @Schema(name="field", description = "The name of the field where the error was detected") + public String getField( ) + { + return field; + } + + public void setField( String field ) + { + this.field = field; + } + + @Schema(name="category", description = "The name of the category this error is assigned to") + public String getCategory( ) + { + return category; + } + + public void setCategory( String category ) + { + this.category = category; + } + + @Schema(name="type", description = "The type of the error. This is a unique string that defines the type of error, e.g. empty, bad_number_range, ... .") + public String getType( ) + { + return type; + } + + public void setType( String type ) + { + this.type = type; + } + + @Schema(name="parameter", description = "The list of parameters, that can be used to create a translated error message") + public List getParameter( ) + { + return parameter; + } + + public void setParameter( List parameter ) + { + this.parameter = parameter; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/ArtifactCleanupInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/ArtifactCleanupInfo.java new file mode 100644 index 000000000..145d39041 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/ArtifactCleanupInfo.java @@ -0,0 +1,83 @@ +package org.apache.archiva.rest.api.v2.model.repository;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import java.time.Period; + +/** + * @author Martin Stockhammer + */ +@Schema(name="ArtifactCleanupInfo",description = "Information for artifact cleanup feature of repository") +public class ArtifactCleanupInfo +{ + boolean deleteReleasedSnapshots; + Period retentionPeriod; + int retentionCount; + + @Schema(name="delete_released_snapshots",description = "True, if snapshots are deleted after a release was published") + public boolean isDeleteReleasedSnapshots( ) + { + return deleteReleasedSnapshots; + } + + public void setDeleteReleasedSnapshots( boolean deleteReleasedSnapshots ) + { + this.deleteReleasedSnapshots = deleteReleasedSnapshots; + } + + @Schema(name="retention_period",description = "Time, after that snapshot artifacts are marked for deletion") + public Period getRetentionPeriod( ) + { + return retentionPeriod; + } + + public void setRetentionPeriod( Period retentionPeriod ) + { + this.retentionPeriod = retentionPeriod; + } + + @Schema(name="retention_count",description = "Maximum number of snapshot artifacts to keep") + public int getRetentionCount( ) + { + return retentionCount; + } + + public void setRetentionCount( int retentionCount ) + { + this.retentionCount = retentionCount; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/IndexCreationInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/IndexCreationInfo.java new file mode 100644 index 000000000..276dea820 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/IndexCreationInfo.java @@ -0,0 +1,81 @@ +package org.apache.archiva.rest.api.v2.model.repository;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +/** + * @author Martin Stockhammer + */ +@Schema(name="IndexCreationInfo",description = "Information about index creation feature of repositories") +public class IndexCreationInfo +{ + private boolean skipPackedIndexCreation = false; + private String indexPath; + private String packedIndexPath; + + @Schema(name="skip_packed_index_creation",description = "True, if the packed index will not be created") + public boolean isSkipPackedIndexCreation( ) + { + return skipPackedIndexCreation; + } + + public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation ) + { + this.skipPackedIndexCreation = skipPackedIndexCreation; + } + + @Schema(name="index_path",description = "Path to the index directory relative to the repository base directory") + public String getIndexPath( ) + { + return indexPath; + } + + public void setIndexPath( String indexPath ) + { + this.indexPath = indexPath; + } + + @Schema(name="packed_index_path",description = "Path to the packed index directory relative to the repository base directory") + public String getPackedIndexPath( ) + { + return packedIndexPath; + } + + public void setPackedIndexPath( String packedIndexPath ) + { + this.packedIndexPath = packedIndexPath; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/RemoteIndexInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/RemoteIndexInfo.java new file mode 100644 index 000000000..e2ee855f4 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/RemoteIndexInfo.java @@ -0,0 +1,69 @@ +package org.apache.archiva.rest.api.v2.model.repository;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +/** + * @author Martin Stockhammer + */ +@Schema(name="RemoteIndexInfo",description = "Information about remote indexes") +public class RemoteIndexInfo +{ + private boolean downloadRemoteIndex = false; + private String indexUri; + + @Schema(name="download_remote_index",description = "True, if the index will be downloaded from the remote repository") + public boolean isDownloadRemoteIndex( ) + { + return downloadRemoteIndex; + } + + public void setDownloadRemoteIndex( boolean downloadRemoteIndex ) + { + this.downloadRemoteIndex = downloadRemoteIndex; + } + + @Schema(name="index_uri", description = "The URI that specifies the path to the remote index") + public String getIndexUri( ) + { + return indexUri; + } + + public void setIndexUri( String indexUri ) + { + this.indexUri = indexUri; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/StagingInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/StagingInfo.java new file mode 100644 index 000000000..cd0f0dbd5 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/repository/StagingInfo.java @@ -0,0 +1,69 @@ +package org.apache.archiva.rest.api.v2.model.repository;/* + * 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. + */ + +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +/** + * @author Martin Stockhammer + */ +@Schema(name="StagingInfo",description = "Information about staging feature of a repository") +public class StagingInfo +{ + private String stagingRepository; + private boolean stageRepoNeeded; + + @Schema(name="staging_repo",description = "The repository id of the staging repository") + public String getStagingRepository( ) + { + return stagingRepository; + } + + public void setStagingRepository( String stagingRepository ) + { + this.stagingRepository = stagingRepository; + } + + @Schema(name="stage_repo_needed",description = "True, if this repository needs a staging repository") + public boolean isStageRepoNeeded( ) + { + return stageRepoNeeded; + } + + public void setStageRepoNeeded( boolean stageRepoNeeded ) + { + this.stageRepoNeeded = stageRepoNeeded; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestError.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestError.java new file mode 100644 index 000000000..7444d73b7 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestError.java @@ -0,0 +1,97 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.rest.api.v2.model.ValidationError; +import org.apache.commons.lang3.StringUtils; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@XmlRootElement( name = "archivaRestError" ) +@Schema(name="ArchivaRestError", description = "Contains a list of error messages that resulted from the current REST call") +public class ArchivaRestError + implements Serializable +{ + + private static final long serialVersionUID = -8892617571273167067L; + private List errorMessages = new ArrayList<>( 1 ); + private List validationErrors; + + public ArchivaRestError() + { + // no op + } + + public ArchivaRestError( ArchivaRestServiceException e ) + { + errorMessages.addAll( e.getErrorMessages() ); + if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) ) + { + errorMessages.add( new ErrorMessage( e.getMessage(), null ) ); + } + if (e instanceof ValidationException) { + this.validationErrors = ( (ValidationException) e ).getValidationErrors( ); + } + } + + public ArchivaRestError( ValidationException e ) + { + errorMessages.addAll( e.getErrorMessages() ); + if ( e.getErrorMessages().isEmpty() && StringUtils.isNotEmpty( e.getMessage() ) ) + { + errorMessages.add( new ErrorMessage( e.getMessage(), null ) ); + } + this.validationErrors = e.getValidationErrors( ); + } + + @Schema(name="error_messages", description = "The list of errors that occurred while processing the REST request") + public List getErrorMessages() + { + return errorMessages; + } + + public void setErrorMessages( List errorMessages ) + { + this.errorMessages = errorMessages; + } + + public void addErrorMessage( ErrorMessage errorMessage ) + { + this.errorMessages.add( errorMessage ); + } + + @Schema( name = "has_validation_errors", description = "True, if the error contains validation errors" ) + public boolean hasValidationErrors( ) + { + return this.validationErrors != null && this.validationErrors.size( ) > 0; + } + + @Schema( name = "validation_errors", description = "The list of validation errors") + public List getValidationErrors() { + return hasValidationErrors() ? this.validationErrors : Collections.emptyList( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestServiceException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestServiceException.java new file mode 100644 index 000000000..19f50dffd --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ArchivaRestServiceException.java @@ -0,0 +1,97 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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; + +/** + * Generic REST Service Exception that contains error information. + * + * @author Martin Stockhammer + * @since 3.0 + */ +public class ArchivaRestServiceException extends Exception +{ + private int httpErrorCode = 500; + + private List errorMessages = new ArrayList(0); + + public ArchivaRestServiceException( String s ) + { + super( s ); + } + + public ArchivaRestServiceException( String s, int httpErrorCode ) + { + super( s ); + this.httpErrorCode = httpErrorCode; + } + + public ArchivaRestServiceException( ErrorMessage errorMessage ) + { + errorMessages.add( errorMessage ); + } + + public ArchivaRestServiceException( ErrorMessage errorMessage, int httpResponseCode ) + { + this.httpErrorCode = httpResponseCode; + errorMessages.add( errorMessage ); + } + + public ArchivaRestServiceException( List errorMessage ) + { + errorMessages.addAll( errorMessage ); + } + + public ArchivaRestServiceException( List errorMessage, int httpResponseCode ) + { + this.httpErrorCode = httpResponseCode; + errorMessages.addAll( errorMessage ); + } + + public int getHttpErrorCode() + { + return httpErrorCode; + } + + public void setHttpErrorCode( int httpErrorCode ) + { + this.httpErrorCode = httpErrorCode; + } + + public List getErrorMessages() + { + if ( errorMessages == null ) + { + this.errorMessages = new ArrayList(); + } + return errorMessages; + } + + public void setErrorMessages( List errorMessages ) + { + this.errorMessages = errorMessages; + } + + public void addErrorMessage( ErrorMessage errorMessage ) + { + this.errorMessages.add( errorMessage ); + } + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorKeys.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorKeys.java new file mode 100644 index 000000000..cc0a836a2 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorKeys.java @@ -0,0 +1,125 @@ +package org.apache.archiva.rest.api.v2.svc;/* + * 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. + */ + +/* + * 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. + */ + +/** + * @author Martin Stockhammer + */ +public interface ErrorKeys +{ + + String PREFIX = "archiva."; + + String VALIDATION_ERROR = PREFIX + "validation_error"; + + String REPOSITORY_GROUP_PREFIX = PREFIX + "repository_group."; + String REPOSITORY_PREFIX = PREFIX + "repository."; + + String INVALID_RESULT_SET_ERROR = "archiva.result_set.invalid"; + String REPOSITORY_ADMIN_ERROR = "archiva.repositoryadmin.error"; + String LDAP_CF_INIT_FAILED = "archiva.ldap.cf.init.failed"; + String LDAP_USER_MAPPER_INIT_FAILED = "archiva.ldap.usermapper.init.failed"; + String LDAP_COMMUNICATION_ERROR = "archiva.ldap.communication_error"; + String LDAP_INVALID_NAME = "archiva.ldap.invalid_name"; + String LDAP_GENERIC_ERROR = "archiva.ldap.generic_error"; + String LDAP_SERVICE_UNAVAILABLE = "archiva.ldap.service_unavailable"; + String LDAP_SERVICE_AUTHENTICATION_FAILED = "archiva.ldap.authentication.failed"; + String LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED = "archiva.ldap.authentication.not_supported"; + String LDAP_SERVICE_NO_PERMISSION = "archiva.ldap.no_permissions"; + + String PROPERTY_NOT_FOUND = "archiva.property.not.found"; + + String MISSING_DATA = "archiva.missing.data"; + + String REPOSITORY_GROUP_NOT_FOUND = REPOSITORY_GROUP_PREFIX+"notfound"; + String REPOSITORY_GROUP_ADD_FAILED = REPOSITORY_GROUP_PREFIX+"add.failed" ; + String REPOSITORY_GROUP_EXIST = REPOSITORY_GROUP_PREFIX+"exists"; + String REPOSITORY_GROUP_UPDATE_FAILED = REPOSITORY_GROUP_PREFIX + "update.failed"; + + String REPOSITORY_GROUP_DELETE_FAILED = REPOSITORY_GROUP_PREFIX + "delete.failed"; + String REPOSITORY_NOT_FOUND = REPOSITORY_PREFIX + "notfound"; + String REPOSITORY_MANAGED_NOT_FOUND = REPOSITORY_PREFIX + "managed.notfound"; + String REPOSITORY_REMOTE_NOT_FOUND = REPOSITORY_PREFIX + "remote.notfound"; + + String REPOSITORY_METADATA_ERROR = REPOSITORY_PREFIX + "metadata_error"; + + String TASK_QUEUE_FAILED = PREFIX + "task.queue_failed"; + String REPOSITORY_SCAN_FAILED = REPOSITORY_PREFIX + "scan.failed"; + String ARTIFACT_EXISTS_AT_DEST = REPOSITORY_PREFIX + "artifact.dest.exists"; + String REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED = REPOSITORY_PREFIX + "remote.index.download_failed"; + String REPOSITORY_WRONG_TYPE = REPOSITORY_PREFIX + "wrong_type"; + String REPOSITORY_DELETE_FAILED = REPOSITORY_PREFIX + "delete.failed"; + String REPOSITORY_INVALID_ID = REPOSITORY_PREFIX + "invalid.id"; + String REPOSITORY_ID_EXISTS = REPOSITORY_PREFIX + "id.exists"; + String REPOSITORY_UPDATE_FAILED = REPOSITORY_PREFIX + "update.failed"; + String ARTIFACT_NOT_FOUND = REPOSITORY_PREFIX + "artifact.notfound"; + String REPOSITORY_LAYOUT_ERROR = REPOSITORY_PREFIX + "layout.error"; + + String ARTIFACT_COPY_ERROR = REPOSITORY_PREFIX + "artifact.copy.error"; + + /** + * The given user was not found + * Parameters: + * - User Id + */ + String USER_NOT_FOUND = PREFIX+"user.not_found"; + + /** + * Error from UserManager + * Parameters: + * - Error Message + */ + String USER_MANAGER_ERROR = PREFIX+"user_manager.error"; + + /** + * Permission to the repository denied. + * Parameters: + * - Repository Id + * - Permission ID + */ + String PERMISSION_REPOSITORY_DENIED = PREFIX + "permission.repository.denied"; + + /** + * A generic authorization error thrown during the authorization check. + * Parameters: + * - Error message + */ + String AUTHORIZATION_ERROR = PREFIX + "authorization.error"; + + /** + * When the operation needs authentication, but not authenticated user was found in the request context. + */ + String NOT_AUTHENTICATED = PREFIX + "user.not_authenticated"; +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorMessage.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorMessage.java new file mode 100644 index 000000000..f3deebe68 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ErrorMessage.java @@ -0,0 +1,102 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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 io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * @author Olivier Lamy + * @author Martin Stockhammer + * @since 3.0 + */ +@XmlRootElement( name = "errorMessage" ) +@Schema(name="ErrorMessage",description = "Information about the error, that occurred while processing the REST request.") +public class ErrorMessage + implements Serializable +{ + private String errorKey = ""; + + private String[] args = EMPTY; + + private String message = ""; + + private static final String[] EMPTY = new String[0]; + + public ErrorMessage() + { + // no op + } + + public ErrorMessage( String errorKey ) + { + this.errorKey = errorKey; + this.args = EMPTY; + } + + public ErrorMessage( String errorKey, String[] args ) + { + this.errorKey = errorKey; + this.args = args; + } + + public static ErrorMessage of(String errorKey, String... args) { + return new ErrorMessage( errorKey, args ); + } + + @Schema(name="error_key", description = "The key of the error message. If this is empty, the message message must be set.") + public String getErrorKey() + { + return errorKey; + } + + public void setErrorKey( String errorKey ) + { + this.errorKey = errorKey; + } + + @Schema(description = "Parameters that can be filled to the translated error message") + public String[] getArgs() + { + return args; + } + + public void setArgs( String[] args ) + { + this.args = args; + } + + @Schema(description = "Full error message. Either additional to the key in the default language, or if the message is without key.") + public String getMessage() + { + return message; + } + + public void setMessage( String message ) + { + this.message = message; + } + + public ErrorMessage message( String message ) + { + this.message = message; + return this; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryGroupService.java new file mode 100644 index 000000000..aee7ac331 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryGroupService.java @@ -0,0 +1,256 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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 io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.redback.authorization.RedbackAuthorization; +import org.apache.archiva.rest.api.v2.model.RepositoryGroup; +import org.apache.archiva.security.common.ArchivaRoleConstants; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import java.util.List; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT; + +/** + * Endpoint for repository groups that combine multiple repositories into a single virtual repository. + * + * @author Olivier Lamy + * @author Martin Stockhammer + * @since 3.0 + */ +@Path( "/repository_groups" ) +@Schema( name = "RepositoryGroups", description = "Managing of repository groups or virtual repositories" ) +public interface RepositoryGroupService +{ + @Path( "" ) + @GET + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns all repository group entries.", + parameters = { + @Parameter( name = "q", description = "Search term" ), + @Parameter( name = "offset", description = "The offset of the first element returned" ), + @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), + @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), + @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ) + }, + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the list could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + PagedResult getRepositoriesGroups( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, + @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, + @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, + @QueryParam( "order" ) @DefaultValue( "asc" ) String order ) + throws ArchivaRestServiceException; + + @Path( "{id}" ) + @GET + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns a single repository group configuration.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration is returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository group with the given id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + RepositoryGroup getRepositoryGroup( @PathParam( "id" ) String repositoryGroupId ) + throws ArchivaRestServiceException; + + @Path( "" ) + @POST + @Consumes( {APPLICATION_JSON} ) + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Creates a new group entry.", + requestBody = + @RequestBody( required = true, description = "The configuration of the repository group.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) + ) + , + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "201", + description = "If the repository group was created", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) + ), + @ApiResponse( responseCode = "303", description = "The repository group exists already", + headers = { + @Header( name = "Location", description = "The URL of existing group", schema = @Schema( type = "string" ) ) + } + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "422", description = "The body data is not valid", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) + throws ArchivaRestServiceException; + + @Path( "{id}" ) + @PUT + @Consumes( {APPLICATION_JSON} ) + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns all repository group entries.", + requestBody = + @RequestBody( required = true, description = "The configuration of the repository group.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) + ) + , + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the group is returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryGroup.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "422", description = "The body data is not valid", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + RepositoryGroup updateRepositoryGroup( @PathParam( "id" ) String groupId, RepositoryGroup repositoryGroup ) + throws ArchivaRestServiceException; + + @Path( "{id}" ) + @DELETE + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Deletes the repository group entry with the given id.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the group was deleted" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + } + ) + Response deleteRepositoryGroup( @PathParam( "id" ) String repositoryGroupId ) + throws ArchivaRestServiceException; + + @Path( "{id}/repositories/{repositoryId}" ) + @PUT + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Adds the repository with the given id to the repository group.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the repository was added or if it was already part of the group" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The group with the given id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + } + ) + RepositoryGroup addRepositoryToGroup( @PathParam( "id" ) String repositoryGroupId, + @PathParam( "repositoryId" ) String repositoryId ) + throws ArchivaRestServiceException; + + @Path( "{id}/repositories/{repositoryId}" ) + @DELETE + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Removes the repository with the given id from the repository group.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the repository was removed." + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete the group", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "Either the group with the given id does not exist, or the repository was not part of the group.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + } + ) + RepositoryGroup deleteRepositoryFromGroup( @PathParam( "id" ) String repositoryGroupId, + @PathParam( "repositoryId" ) String repositoryId ) + throws ArchivaRestServiceException; + + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryService.java new file mode 100644 index 000000000..cdecbae31 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RepositoryService.java @@ -0,0 +1,272 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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 io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.redback.authorization.RedbackAuthorization; +import org.apache.archiva.rest.api.v2.model.Repository; +import org.apache.archiva.rest.api.v2.model.RepositoryStatistics; +import org.apache.archiva.rest.api.v2.model.ScanStatus; +import org.apache.archiva.security.common.ArchivaRoleConstants; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.util.List; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@Path( "repositories" ) +@Tag(name = "v2") +@Tag(name = "v2/Repositories") +@Schema(name="RepositoryService",description = "Manage repositories of all types") +public interface RepositoryService +{ + + @Path( "" ) + @GET + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns all managed repositories.", + parameters = { + @Parameter( name = "q", description = "Search term" ), + @Parameter( name = "offset", description = "The offset of the first element returned" ), + @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), + @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), + @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ), + @Parameter( name = "locale", description = "The locale for name and description" ) + }, + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the list could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + PagedResult getRepositories( @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, + @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, + @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, + @QueryParam( "order" ) @DefaultValue( "asc" ) String order, + @QueryParam( "locale" ) String localeString) throws ArchivaRestServiceException; + + @Path( "managed/{id}/statistics" ) + @GET + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns repository statistic data.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the statistics could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + RepositoryStatistics getManagedRepositoryStatistics( @PathParam( "id" ) String repositoryId ) + throws ArchivaRestServiceException; + + @Path ("managed/{id}/scan/schedule") + @POST + @Produces ({ APPLICATION_JSON }) + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) + @Operation( summary = "Returns repository statistic data.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the statistics could be returned" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response scheduleRepositoryScan( @PathParam ("id") String repositoryId, + @QueryParam ("fullScan") boolean fullScan ) + throws ArchivaRestServiceException; + + + @Path ("managed/{id}/scan/now") + @POST + @Produces ({ APPLICATION_JSON }) + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) + @Operation( summary = "Runs a repository scan instantly and waits for the response.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the statistics could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RepositoryStatistics.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + RepositoryStatistics scanRepositoryImmediately( @PathParam ("id") String repositoryId ) + throws ArchivaRestServiceException; + + + @Path ("managed/{id}/scan/status") + @GET + @Produces ({ APPLICATION_JSON }) + @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) + @Operation( summary = "Returns status of running and scheduled scans.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the status could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ScanStatus.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + ScanStatus getScanStatus( @PathParam ("id") String repositoryId ) + throws ArchivaRestServiceException; + + @Path ("managed/{id}/scan") + @DELETE + @Produces ({ APPLICATION_JSON }) + @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) + @Operation( summary = "Cancels and removes all tasks for the given repository.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the task was removed successfully" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response removeScanningTaskFromQueue( @PathParam ("id") String repositoryId ) + throws ArchivaRestServiceException; + + + + @Path ("remote/{id}/index/download/start") + @POST + @Produces ({ APPLICATION_JSON }) + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) + @Operation( summary = "Schedules a task for remote index download.", + parameters = { + @Parameter( name = "full", description = "If true, download the full index, otherwise try a update download." ) + }, + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the task was scheduled" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response scheduleDownloadRemoteIndex( @PathParam ("id") String repositoryId, + @QueryParam( "immediate" ) boolean immediately, + @QueryParam ("full") boolean full, @Context UriInfo uriInfo ) + throws ArchivaRestServiceException; + + + @Path ("remote/index/downloads") + @GET + @Produces ({ APPLICATION_JSON }) + @RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER) + @Operation( summary = "Returns a list of running downloads from the remote repository.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the artifact was deleted" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + List getRunningRemoteDownloads(); + + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RestConfiguration.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RestConfiguration.java new file mode 100644 index 000000000..a363ddb54 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/RestConfiguration.java @@ -0,0 +1,43 @@ +package org.apache.archiva.rest.api.v2.svc;/* + * 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. + */ + +/* + * 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. + */ + +/** + * @author Martin Stockhammer + */ +public interface RestConfiguration +{ + String DEFAULT_PAGE_LIMIT = "10"; +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/SecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/SecurityConfigurationService.java new file mode 100644 index 000000000..2db5243d4 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/SecurityConfigurationService.java @@ -0,0 +1,353 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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 io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.model.PropertyEntry; +import org.apache.archiva.redback.authorization.RedbackAuthorization; +import org.apache.archiva.rest.api.v2.model.BeanInformation; +import org.apache.archiva.rest.api.v2.model.CacheConfiguration; +import org.apache.archiva.rest.api.v2.model.LdapConfiguration; +import org.apache.archiva.rest.api.v2.model.SecurityConfiguration; +import org.apache.archiva.security.common.ArchivaRoleConstants; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import java.util.List; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT; + +/** + * + * Service for configuration of redback and security related settings. + * + * @author Martin Stockhammer + * @since 3.0 + */ +@Path( "/security" ) +@Tag(name = "v2") +@Tag(name = "v2/Security") +@SecurityRequirement(name = "BearerAuth") +public interface SecurityConfigurationService +{ + @Path("config") + @GET + @Produces({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Returns the security configuration that is currently active.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration could be retrieved", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SecurityConfiguration.class)) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + SecurityConfiguration getConfiguration() + throws ArchivaRestServiceException; + + @Path("config") + @PUT + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Updates the security configuration.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration was updated" + ), + @ApiResponse( responseCode = "422", description = "Invalid content data", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the configuration", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration) + throws ArchivaRestServiceException; + + + @Path( "config/properties" ) + @GET + @Produces( { APPLICATION_JSON } ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns all configuration properties. The result is paged.", + parameters = { + @Parameter(name = "q", description = "Search term"), + @Parameter(name = "offset", description = "The offset of the first element returned"), + @Parameter(name = "limit", description = "Maximum number of items to return in the response"), + @Parameter(name = "orderBy", description = "List of attribute used for sorting (key, value)"), + @Parameter(name = "order", description = "The sort order. Either ascending (asc) or descending (desc)") + }, + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the list could be returned", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class)) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + PagedResult getConfigurationProperties( @QueryParam("q") @DefaultValue( "" ) String searchTerm, + @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, + @QueryParam( "orderBy") @DefaultValue( "key" ) List orderBy, + @QueryParam("order") @DefaultValue( "asc" ) String order ) throws ArchivaRestServiceException; + + @Path("config/properties/{propertyName}") + @GET + @Produces({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Returns a single configuration property value.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + parameters = { + @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to get the value for") + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration could be retrieved", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PropertyEntry.class)) + ), + @ApiResponse( responseCode = "404", description = "The given property name does not exist", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + PropertyEntry getConfigurationProperty( @PathParam ( "propertyName" ) String propertyName) + throws ArchivaRestServiceException; + + + @Path("config/properties/{propertyName}") + @PUT + @Consumes({ APPLICATION_JSON}) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Updates a single property value of the security configuration.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + parameters = { + @Parameter(in = ParameterIn.PATH, name="propertyName", description = "The name of the property to update") + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the property value was updated." + ), + @ApiResponse( responseCode = "400", description = "The body data is not valid", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + @ApiResponse( responseCode = "404", description = "The given property name does not exist", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + Response updateConfigurationProperty( @PathParam ( "propertyName" ) String propertyName, PropertyEntry propertyValue) + throws ArchivaRestServiceException; + + @Path("config/ldap") + @GET + @Produces({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Returns the LDAP configuration that is currently active.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration could be retrieved", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = LdapConfiguration.class)) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException; + + @Path("config/ldap") + @PUT + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Updates the LDAP configuration that is currently active.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration was updated" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException; + + @Path("config/ldap/verify") + @POST + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Checks the given LDAP configuration.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the check was successful" + ), + @ApiResponse( responseCode = "400", + description = "If the check was not successful", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + Response verifyLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException; + + @Path("config/cache") + @GET + @Produces({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Returns the cache configuration that is currently active.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration could be retrieved", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = CacheConfiguration.class)) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException; + + @Path("config/cache") + @PUT + @Consumes({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Updates the LDAP configuration that is currently active.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the configuration was updated" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to update the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException; + + + @Path("user_managers") + @GET + @Produces({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Returns the available user manager implementations.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the list could be retrieved", + content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema( + schema = @Schema(implementation = BeanInformation.class))) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + List getAvailableUserManagers() + throws ArchivaRestServiceException; + + @Path("rbac_managers") + @GET + @Produces({ APPLICATION_JSON }) + @RedbackAuthorization(permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION) + @Operation( summary = "Returns the available RBAC manager implementations.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the list could be retrieved", + content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema( + schema = @Schema(implementation = BeanInformation.class))) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ArchivaRestError.class )) ) + } + ) + List getAvailableRbacManagers() + throws ArchivaRestServiceException; + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ValidationException.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ValidationException.java new file mode 100644 index 000000000..c6ca65376 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/ValidationException.java @@ -0,0 +1,102 @@ +package org.apache.archiva.rest.api.v2.svc; +/* + * 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.archiva.repository.Repository; +import org.apache.archiva.repository.validation.ValidationResponse; +import org.apache.archiva.rest.api.v2.model.ValidationError; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Exception is thrown + * + * @author Martin Stockhammer + */ +public class ValidationException extends ArchivaRestServiceException +{ + public static final int DEFAULT_CODE = 422; + + public static final ErrorMessage DEFAULT_MESSAGE = new ErrorMessage( ErrorKeys.VALIDATION_ERROR ); + + private List validationErrors; + + public ValidationException( ) + { + super( DEFAULT_MESSAGE, DEFAULT_CODE ); + } + + public ValidationException( int errorCode ) + { + super( DEFAULT_MESSAGE, errorCode ); + } + + public ValidationException( List errors ) + { + super( DEFAULT_MESSAGE, DEFAULT_CODE ); + this.validationErrors = errors; + } + + public static ValidationException of( List errorList ) + { + return new ValidationException( errorList.stream( ).map( ValidationError::of ).collect( Collectors.toList( ) ) ); + } + + public static ValidationException of( Map> errorMap ) + { + return new ValidationException( errorMap.entrySet( ).stream( ) + .flatMap( v -> v.getValue( ).stream( ).map( k -> ValidationError.of(v.getKey(), k))) + .collect( Collectors.toList( ) ) ); + } + + public static ValidationException of( ValidationResponse result ) + { + if ( result.isValid( ) ) + { + return new ValidationException( ); + } + else + { + return new ValidationException( result.getResult( ).entrySet( ).stream( ).flatMap( + v -> v.getValue( ).stream( ).map( e -> ValidationError.of( v.getKey( ), e ) ) ).collect( Collectors.toList( ) ) ); + } + } + + public List getValidationErrors( ) + { + return validationErrors == null ? Collections.emptyList( ) : validationErrors; + } + + public void setValidationErrors( List validationErrors ) + { + this.validationErrors = validationErrors; + } + + public void addValidationError( ValidationError error ) + { + if ( this.validationErrors == null ) + { + this.validationErrors = new ArrayList<>( ); + } + this.validationErrors.add( error ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/maven/MavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/maven/MavenManagedRepositoryService.java new file mode 100644 index 000000000..404d913d4 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/maven/MavenManagedRepositoryService.java @@ -0,0 +1,369 @@ +package org.apache.archiva.rest.api.v2.svc.maven; +/* + * 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 io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.redback.authorization.RedbackAuthorization; +import org.apache.archiva.rest.api.v2.model.FileInfo; +import org.apache.archiva.rest.api.v2.model.MavenManagedRepository; +import org.apache.archiva.rest.api.v2.model.MavenManagedRepositoryUpdate; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestError; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; +import org.apache.archiva.security.common.ArchivaRoleConstants; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.apache.archiva.rest.api.v2.svc.RestConfiguration.DEFAULT_PAGE_LIMIT; + +/** + * Service interface for managing managed maven repositories + * + * @author Martin Stockhammer + * @since 3.0 + */ +@Schema( name = "ManagedRepositoryService", description = "Managing and configuration of managed repositories" ) +@Path( "repositories/maven/managed" ) +@Tag(name = "v2") +@Tag(name = "v2/Repositories") +public interface MavenManagedRepositoryService +{ + @Path( "" ) + @GET + @Produces( {APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns all managed repositories.", + parameters = { + @Parameter( name = "q", description = "Search term" ), + @Parameter( name = "offset", description = "The offset of the first element returned" ), + @Parameter( name = "limit", description = "Maximum number of items to return in the response" ), + @Parameter( name = "orderBy", description = "List of attribute used for sorting (key, value)" ), + @Parameter( name = "order", description = "The sort order. Either ascending (asc) or descending (desc)" ) + }, + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the list could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = PagedResult.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + PagedResult getManagedRepositories( + @QueryParam( "q" ) @DefaultValue( "" ) String searchTerm, + @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit, + @QueryParam( "orderBy" ) @DefaultValue( "id" ) List orderBy, + @QueryParam( "order" ) @DefaultValue( "asc" ) String order ) + throws ArchivaRestServiceException; + + + @Path( "{id}" ) + @GET + @Produces( {MediaType.APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Returns the managed repository with the given id.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the managed repository could be returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + MavenManagedRepository getManagedRepository( @PathParam( "id" ) String repositoryId ) + throws ArchivaRestServiceException; + + + @Path( "{id}" ) + @DELETE + @Produces( {MediaType.APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Deletes the managed repository with the given id.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the managed repository could be returned" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response deleteManagedRepository( @PathParam( "id" ) String repositoryId, + @QueryParam( "deleteContent" ) boolean deleteContent ) + throws ArchivaRestServiceException; + + + @Path( "" ) + @POST + @Consumes( {MediaType.APPLICATION_JSON} ) + @Produces( {MediaType.APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Creates the managed repository", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "201", + description = "If the managed repository could be created", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) ) + ), + @ApiResponse( responseCode = "303", description = "The repository exists already", + headers = { + @Header( name = "Location", description = "The URL of existing repository ", schema = @Schema( type = "string" ) ) + } + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "422", description = "The body data is not valid", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) + throws ArchivaRestServiceException; + + + @Path( "{id}" ) + @PUT + @Consumes( {MediaType.APPLICATION_JSON} ) + @Produces( {MediaType.APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION ) + @Operation( summary = "Updates the managed repository with the given id", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the managed repository could be updated", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = MavenManagedRepository.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "422", description = "The body data is not valid", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + MavenManagedRepository updateManagedRepository( @PathParam( "id" ) String repositoryId, MavenManagedRepositoryUpdate managedRepository ) + throws ArchivaRestServiceException; + + + @Path( "{id}/path/{filePath: .+}" ) + @GET + @Produces( {MediaType.APPLICATION_JSON} ) + @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, resource = "{id}") + @Operation( summary = "Returns the status of a given file in the repository", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the file status is returned", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = FileInfo.class ) ) + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to add repositories", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the file does not exist.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + FileInfo getFileStatus( @PathParam( "id" ) String repositoryId, @PathParam( "filePath" ) String fileLocation ) + throws ArchivaRestServiceException; + + + /** + * Permissions are checked in impl + * will copy an artifact from the source repository to the target repository + */ + @Path ("{srcId}/path/{path: .+}/copyto/{dstId}") + @POST + @Produces({APPLICATION_JSON}) + @RedbackAuthorization (noPermission = true) + @Operation( summary = "Copies a artifact from the source repository to the destination repository", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, + scopes = { + "{srcId}" + } + ), + @SecurityRequirement( + name= ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD, + scopes = { + "{dstId}" + } + ) + + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the artifact was copied" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository does not exist, or if the artifact was not found", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response copyArtifact( @PathParam( "srcId" ) String srcRepositoryId, @PathParam( "dstId" ) String dstRepositoryId, + @PathParam( "path" ) String path ) + throws ArchivaRestServiceException; + + + @Path ("{id}/path/{path: .+}") + @DELETE + @Consumes ({ APPLICATION_JSON }) + @RedbackAuthorization (noPermission = true) + @Operation( summary = "Deletes a artifact in the repository.", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_RUN_INDEXER + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the artifact was deleted" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The repository or the artifact does not exist", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response deleteArtifact( @PathParam( "id" ) String repositoryId, @PathParam( "path" ) String path ) + throws ArchivaRestServiceException; + + @Path ( "{id}/co/{group}/{project}/{version}" ) + @DELETE + @Produces ({ MediaType.APPLICATION_JSON }) + @RedbackAuthorization (noPermission = true) + @Operation( summary = "Removes a version tree in the repository", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the deletion was successful" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the version does not exist.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response removeProjectVersion( @PathParam ( "id" ) String repositoryId, + @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId, + @PathParam ( "version" ) String version ) + throws org.apache.archiva.rest.api.services.ArchivaRestServiceException; + + + @Path ( "{id}/co/{group}/{project}" ) + @DELETE + @Produces ({ MediaType.APPLICATION_JSON }) + @RedbackAuthorization (noPermission = true) + @Operation( summary = "Removes a project tree in the repository", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the deletion was successful" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete in repositories", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the project does not exist.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId ) + throws org.apache.archiva.rest.api.services.ArchivaRestServiceException; + + @Path ( "{id}/co/{namespace}" ) + @DELETE + @Produces ({ MediaType.APPLICATION_JSON }) + @RedbackAuthorization (noPermission = true) + @Operation( summary = "Removes a namespace tree in the repository", + security = { + @SecurityRequirement( + name = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION + ) + }, + responses = { + @ApiResponse( responseCode = "200", + description = "If the deletion was successful" + ), + @ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to delete namespaces in repositories", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ), + @ApiResponse( responseCode = "404", description = "The managed repository with this id does not exist. Or the namespace does not exist.", + content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ) + } + ) + Response deleteNamespace( @PathParam ("id") String repositoryId, @PathParam ( "namespace" ) String namespace ) + throws org.apache.archiva.rest.api.services.ArchivaRestServiceException; + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/package-info.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/package-info.java new file mode 100644 index 000000000..f4d076383 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/svc/package-info.java @@ -0,0 +1,100 @@ +/* + * 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. + */ +/** + *

This is the V2 REST API of Archiva. It uses JAX-RS annotations for defining the endpoints. + * The API is documented with OpenApi annotations.

+ * + *

Some design principles of the API and classes:

+ *
    + *
  • All services use V2 model classes. Internal models are always converted to V2 classes.
  • + *
  • Schema attributes use the snake case syntax (lower case with '_' as divider)
  • + *
  • Return code 200 and 201 (POST) is used for successful execution.
  • + *
  • Return code 403 is used, if the user has not the permission for the action.
  • + *
  • Return code 422 is used for input that has invalid data.
  • + *
+ * + *

Querying entity lists

+ *

The main entities of a given path are retrieved on the base path. + * Further sub entities or entries may be retrieved via subpaths. + * A single entity is returned by the "{id}" path. Be careful with technical paths that are parallel to the + * id path. Avoid naming conflicts with the id and technical paths. + * Entity attributes may be retrieved by "{id}/{attribute}" path or if there are lists or collections by + * "{id}/mycollection/{subentryid}"

+ * + *
    + *
  • GET method is used for retrieving entities on the base path ""
  • + *
  • The query for base entities should always return a paged result and be filterable and sortable
  • + *
  • Query parameters for filtering, ordering and limits should be optional and proper defaults must be set
  • + *
  • Return code 200 is used for successful retrieval
  • + *
  • This action is idempotent
  • + *
+ * + *

Querying single entities

+ *

Single entities are retrieved on the path "{id}"

+ *
    + *
  • GET method is used for retrieving a single entity. The id is always a path parameter.
  • + *
  • Return code 200 is used for successful retrieval
  • + *
  • Return code 404 is used if the entity with the given id does not exist
  • + *
  • This action is idempotent
  • + *
+ * + *

Creating entities

+ *

The main entities are created on the base path "".

+ *
    + *
  • POST is used for creating new entities
  • + *
  • The POST body must always have a complete definition of the entity.
  • + *
  • A unique id or name attribute is required for entities. If the id is generated during POST, + * it must be returned by response body.
  • + *
  • A successful POST request should always return the entity definition as it would be returned by the GET request.
  • + *
  • Return code 201 is used for successful creation of the new entity.
  • + *
  • A successful response has a Location header with the URL for retrieving the single created entity.
  • + *
  • Return code 303 is used, if the entity exists already
  • + *
  • This action is not idempotent
  • + *
+ * + *

Updating entities

+ *

The path for entity update must contain the '{id}' of the entity. The path should be the same as for the GET operation.

+ *
    + *
  • PUT is used for updating existing entities
  • + *
  • The body contains a JSON object. Only existing attributes are updated.
  • + *
  • A successful PUT request should return the complete entity definition as it would be returned by the GET request.
  • + *
  • Return code 200 is used for successful update of the new entity. Even if nothing changed.
  • + *
  • This action is idempotent
  • + *
+ * + *

Deleting entities

+ *

The path for entity deletion must contain the '{id}' of the entity. The path should be the same as + * for the GET operation.

+ *
    + *
  • DELETE is used for deleting existing entities
  • + *
  • The successful operation has no request and no response body
  • + *
  • Return code 200 is used for successful deletion of the new entity.
  • + *
  • This action is not idempotent
  • + *
+ * + *

Errors

+ *
    + *
  • A error uses a return code >=400
  • + *
  • All errors use the same result object ({@link org.apache.archiva.rest.api.v2.svc.ArchivaRestError}
  • + *
  • Error messages are returned as keys. Translation is part of the client application.
  • + *
+ * + * @author Martin Stockhammer + * @since 3.0 + */ +package org.apache.archiva.rest.api.v2.svc; \ No newline at end of file diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/resources/archiva/openapi-configuration.yaml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/resources/archiva/openapi-configuration.yaml index 7ddbdb92e..379f9dbd5 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/resources/archiva/openapi-configuration.yaml +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/resources/archiva/openapi-configuration.yaml @@ -1,6 +1,6 @@ resourcePackages: - - org.apache.archiva.rest.api.services.v2 - - org.apache.archiva.rest.api.model.v2 + - org.apache.archiva.rest.api.v2.svc + - org.apache.archiva.rest.api.v2.model prettyPrint: true cacheTTL: 0 diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/interceptors/v2/ArchivaRestServiceExceptionMapper.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/interceptors/v2/ArchivaRestServiceExceptionMapper.java deleted file mode 100644 index 129637490..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/interceptors/v2/ArchivaRestServiceExceptionMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.apache.archiva.rest.services.interceptors.v2; -/* - * 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.archiva.rest.api.services.v2.ArchivaRestError; -import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; -import org.springframework.stereotype.Service; - -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -/** - * Maps exceptions to REST responses. - * - * @author Martin Stockhammer - * @since 3.0 - */ -@Provider -@Service( "v2.archivaRestServiceExceptionMapper" ) -public class ArchivaRestServiceExceptionMapper - implements ExceptionMapper -{ - @Override - public Response toResponse( final ArchivaRestServiceException e ) - { - ArchivaRestError restError = new ArchivaRestError( e ); - - Response.ResponseBuilder responseBuilder = Response.status( e.getHttpErrorCode() ).entity( restError ); - if ( e.getMessage() != null ) - { - responseBuilder = responseBuilder.status( new Response.StatusType() - { - public int getStatusCode() - { - return e.getHttpErrorCode(); - } - - public Response.Status.Family getFamily() - { - return Response.Status.Family.familyOf( e.getHttpErrorCode( ) ); - } - - public String getReasonPhrase() - { - return e.getMessage(); - } - } ); - } - return responseBuilder.build(); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java deleted file mode 100644 index 7b776a7f7..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java +++ /dev/null @@ -1,389 +0,0 @@ -package org.apache.archiva.rest.services.v2; -/* - * 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.archiva.admin.model.AuditInformation; -import org.apache.archiva.admin.model.RepositoryAdminException; -import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.util.QueryHelper; -import org.apache.archiva.redback.authentication.AuthenticationResult; -import org.apache.archiva.redback.authorization.AuthorizationException; -import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; -import org.apache.archiva.redback.rest.services.RedbackRequestInformation; -import org.apache.archiva.redback.system.DefaultSecuritySession; -import org.apache.archiva.redback.system.SecuritySession; -import org.apache.archiva.redback.system.SecuritySystem; -import org.apache.archiva.redback.users.User; -import org.apache.archiva.redback.users.UserManagerException; -import org.apache.archiva.redback.users.UserNotFoundException; -import org.apache.archiva.repository.ManagedRepository; -import org.apache.archiva.repository.ReleaseScheme; -import org.apache.archiva.repository.Repository; -import org.apache.archiva.repository.RepositoryRegistry; -import org.apache.archiva.repository.RepositoryType; -import org.apache.archiva.repository.content.ContentItem; -import org.apache.archiva.repository.content.LayoutException; -import org.apache.archiva.repository.storage.fs.FsStorageUtil; -import org.apache.archiva.rest.api.model.v2.FileInfo; -import org.apache.archiva.rest.api.model.v2.MavenManagedRepository; -import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate; -import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; -import org.apache.archiva.rest.api.services.v2.ErrorKeys; -import org.apache.archiva.rest.api.services.v2.ErrorMessage; -import org.apache.archiva.rest.api.services.v2.maven.MavenManagedRepositoryService; -import org.apache.archiva.security.common.ArchivaRoleConstants; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.io.IOException; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS; -import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD; - -/** - * @author Martin Stockhammer - */ -@Service("v2.managedMavenRepositoryService#rest") -public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService -{ - @Context - HttpServletResponse httpServletResponse; - - @Context - UriInfo uriInfo; - - private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class ); - private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} ); - static - { - QUERY_HELPER.addStringFilter( "id", ManagedRepository::getId ); - QUERY_HELPER.addStringFilter( "name", ManagedRepository::getName ); - QUERY_HELPER.addStringFilter( "location", (r) -> r.getLocation().toString() ); - QUERY_HELPER.addBooleanFilter( "snapshot", (r) -> r.getActiveReleaseSchemes( ).contains( ReleaseScheme.SNAPSHOT ) ); - QUERY_HELPER.addBooleanFilter( "release", (r) -> r.getActiveReleaseSchemes().contains( ReleaseScheme.RELEASE )); - QUERY_HELPER.addNullsafeFieldComparator( "id", ManagedRepository::getId ); - QUERY_HELPER.addNullsafeFieldComparator( "name", ManagedRepository::getName ); - } - - private ManagedRepositoryAdmin managedRepositoryAdmin; - private RepositoryRegistry repositoryRegistry; - private SecuritySystem securitySystem; - - public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem, - RepositoryRegistry repositoryRegistry, - ManagedRepositoryAdmin managedRepositoryAdmin ) - { - this.securitySystem = securitySystem; - this.repositoryRegistry = repositoryRegistry; - this.managedRepositoryAdmin = managedRepositoryAdmin; - } - - protected AuditInformation getAuditInformation( ) - { - RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); - User user; - String remoteAddr; - if (redbackRequestInformation==null) { - user = null; - remoteAddr = null; - } else - { - user = redbackRequestInformation.getUser( ); - remoteAddr = redbackRequestInformation.getRemoteAddr( ); - } - return new AuditInformation( user, remoteAddr ); - } - - @Override - public PagedResult getManagedRepositories( final String searchTerm, final Integer offset, - final Integer limit, final List orderBy, - final String order ) throws ArchivaRestServiceException - { - try - { - Collection repos = repositoryRegistry.getManagedRepositories( ); - final Predicate queryFilter = QUERY_HELPER.getQueryFilter( searchTerm ).and( r -> r.getType() == RepositoryType.MAVEN ); - final Comparator comparator = QUERY_HELPER.getComparator( orderBy, order ); - int totalCount = Math.toIntExact( repos.stream( ).filter( queryFilter ).count( ) ); - return PagedResult.of( totalCount, offset, limit, repos.stream( ).filter( queryFilter ).sorted( comparator ) - .map(mr -> MavenManagedRepository.of(mr)).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) ); - } - catch (ArithmeticException e) { - log.error( "Invalid number of repositories detected." ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) ); - } - } - - @Override - public MavenManagedRepository getManagedRepository( String repositoryId ) throws ArchivaRestServiceException - { - ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId ); - if (repo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); - } - if (repo.getType()!=RepositoryType.MAVEN) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 ); - } - return MavenManagedRepository.of( repo ); - } - - @Override - public Response deleteManagedRepository( String repositoryId, boolean deleteContent ) throws ArchivaRestServiceException - { - ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId ); - if (repo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); - } - if (repo.getType()!=RepositoryType.MAVEN) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 ); - } - try - { - managedRepositoryAdmin.deleteManagedRepository( repositoryId, getAuditInformation( ), deleteContent ); - return Response.ok( ).build( ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_DELETE_FAILED, e.getMessage( ) ) ); - } - } - - private org.apache.archiva.admin.model.beans.ManagedRepository convert(MavenManagedRepository repository) { - org.apache.archiva.admin.model.beans.ManagedRepository repoBean = new org.apache.archiva.admin.model.beans.ManagedRepository( ); - repoBean.setId( repository.getId( ) ); - repoBean.setName( repository.getName() ); - repoBean.setDescription( repository.getDescription() ); - repoBean.setBlockRedeployments( repository.isBlocksRedeployments() ); - repoBean.setCronExpression( repository.getSchedulingDefinition() ); - repoBean.setLocation( repository.getLocation() ); - repoBean.setReleases( repository.getReleaseSchemes().contains( ReleaseScheme.RELEASE.name() ) ); - repoBean.setSnapshots( repository.getReleaseSchemes().contains( ReleaseScheme.SNAPSHOT.name() ) ); - repoBean.setScanned( repository.isScanned() ); - repoBean.setDeleteReleasedSnapshots( repository.isDeleteSnapshotsOfRelease() ); - repoBean.setSkipPackedIndexCreation( repository.isSkipPackedIndexCreation() ); - repoBean.setRetentionCount( repository.getRetentionCount() ); - repoBean.setRetentionPeriod( repository.getRetentionPeriod().getDays() ); - repoBean.setIndexDirectory( repository.getIndexPath() ); - repoBean.setPackedIndexDirectory( repository.getPackedIndexPath() ); - repoBean.setLayout( repository.getLayout() ); - repoBean.setType( RepositoryType.MAVEN.name( ) ); - return repoBean; - } - - @Override - public MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) throws ArchivaRestServiceException - { - final String repoId = managedRepository.getId( ); - if ( StringUtils.isEmpty( repoId ) ) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, repoId ), 422 ); - } - Repository repo = repositoryRegistry.getRepository( repoId ); - if (repo!=null) { - httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( repoId ).build( ).toString( ) ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, repoId ), 303 ); - } - try - { - managedRepositoryAdmin.addManagedRepository( convert( managedRepository ), managedRepository.isHasStagingRepository(), getAuditInformation() ); - httpServletResponse.setStatus( 201 ); - return MavenManagedRepository.of( repositoryRegistry.getManagedRepository( repoId ) ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - } - - @Override - public MavenManagedRepository updateManagedRepository( final String repositoryId, final MavenManagedRepositoryUpdate managedRepository ) throws ArchivaRestServiceException - { - org.apache.archiva.admin.model.beans.ManagedRepository repo = convert( managedRepository ); - try - { - managedRepositoryAdmin.updateManagedRepository( repo, managedRepository.isHasStagingRepository( ), getAuditInformation( ), managedRepository.isResetStats( ) ); - ManagedRepository newRepo = repositoryRegistry.getManagedRepository( managedRepository.getId( ) ); - if (newRepo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_UPDATE_FAILED, repositoryId ) ); - } - return MavenManagedRepository.of( newRepo ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - } - - @Override - public FileInfo getFileStatus( String repositoryId, String fileLocation ) throws ArchivaRestServiceException - { - ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId ); - if (repo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); - } - try - { - ContentItem contentItem = repo.getContent( ).toItem( fileLocation ); - if (contentItem.getAsset( ).exists( )) { - return FileInfo.of( contentItem.getAsset( ) ); - } else { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, repositoryId, fileLocation ), 404 ); - } - } - catch ( LayoutException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage( ) ) ); - } - } - - @Override - public Response copyArtifact( String srcRepositoryId, String dstRepositoryId, - String path ) throws ArchivaRestServiceException - { - final AuditInformation auditInformation = getAuditInformation( ); - final String userName = auditInformation.getUser( ).getUsername( ); - if ( StringUtils.isEmpty( userName ) ) - { - httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.NOT_AUTHENTICATED ), 401 ); - } - ManagedRepository srcRepo = repositoryRegistry.getManagedRepository( srcRepositoryId ); - if (srcRepo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, srcRepositoryId ), 404 ); - } - ManagedRepository dstRepo = repositoryRegistry.getManagedRepository( dstRepositoryId ); - if (dstRepo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, dstRepositoryId ), 404 ); - } - checkAuthority( auditInformation.getUser().getUsername(), srcRepositoryId, dstRepositoryId ); - try - { - ContentItem srcItem = srcRepo.getContent( ).toItem( path ); - ContentItem dstItem = dstRepo.getContent( ).toItem( path ); - if (!srcItem.getAsset().exists()){ - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, srcRepositoryId, path ), 404 ); - } - if (dstItem.getAsset().exists()) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_EXISTS_AT_DEST, srcRepositoryId, path ), 400 ); - } - FsStorageUtil.copyAsset( srcItem.getAsset( ), dstItem.getAsset( ), true ); - } - catch ( LayoutException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage() ) ); - } - catch ( IOException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_COPY_ERROR, e.getMessage() ) ); - } - return Response.ok( ).build(); - } - - private void checkAuthority(final String userName, final String srcRepositoryId, final String dstRepositoryId ) throws ArchivaRestServiceException { - User user = null; - try - { - user = securitySystem.getUserManager().findUser( userName ); - } - catch ( UserNotFoundException e ) - { - httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_NOT_FOUND, userName ), 401 ); - } - catch ( UserManagerException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_MANAGER_ERROR, e.getMessage( ) ) ); - } - - // check karma on source : read - AuthenticationResult authn = new AuthenticationResult( true, userName, null ); - SecuritySession securitySession = new DefaultSecuritySession( authn, user ); - try - { - boolean authz = - securitySystem.isAuthorized( securitySession, OPERATION_REPOSITORY_ACCESS, - srcRepositoryId ); - if ( !authz ) - { - throw new ArchivaRestServiceException(ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, srcRepositoryId, OPERATION_REPOSITORY_ACCESS ), 403); - } - } - catch ( AuthorizationException e ) - { - log.error( "Error reading permission: {}", e.getMessage(), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403); - } - - // check karma on target: write - try - { - boolean authz = - securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD, - dstRepositoryId ); - if ( !authz ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, dstRepositoryId, OPERATION_REPOSITORY_UPLOAD ) ); - } - } - catch ( AuthorizationException e ) - { - log.error( "Error reading permission: {}", e.getMessage(), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403); - } - - - } - - @Override - public Response deleteArtifact( String repositoryId, String path ) throws ArchivaRestServiceException - { - - return null; - } - - - @Override - public Response removeProjectVersion( String repositoryId, String namespace, String projectId, String version ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException - { - return null; - } - - @Override - public Response deleteProject( String repositoryId, String namespace, String projectId ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException - { - return null; - } - - @Override - public Response deleteNamespace( String repositoryId, String namespace ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException - { - return null; - } - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java deleted file mode 100644 index 9ecd914ae..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryGroupService.java +++ /dev/null @@ -1,328 +0,0 @@ -package org.apache.archiva.rest.services.v2;/* - * 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. - */ - -/* - * 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.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.util.QueryHelper; -import org.apache.archiva.configuration.RepositoryGroupConfiguration; -import org.apache.archiva.repository.EditableRepositoryGroup; -import org.apache.archiva.repository.RepositoryException; -import org.apache.archiva.repository.RepositoryRegistry; -import org.apache.archiva.repository.base.ConfigurationHandler; -import org.apache.archiva.repository.validation.CheckedResult; -import org.apache.archiva.repository.validation.ValidationError; -import org.apache.archiva.rest.api.model.v2.MergeConfiguration; -import org.apache.archiva.rest.api.model.v2.RepositoryGroup; -import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; -import org.apache.archiva.rest.api.services.v2.ErrorKeys; -import org.apache.archiva.rest.api.services.v2.ErrorMessage; -import org.apache.archiva.rest.api.services.v2.RepositoryGroupService; -import org.apache.archiva.rest.api.services.v2.ValidationException; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * REST V2 Implementation for repository groups. - * - * @author Martin Stockhammer - * @see RepositoryGroupService - * @since 3.0 - */ -@Service( "v2.repositoryGroupService#rest" ) -public class DefaultRepositoryGroupService implements RepositoryGroupService -{ - private final ConfigurationHandler configurationHandler; - - @Context - HttpServletResponse httpServletResponse; - - @Context - UriInfo uriInfo; - - final private RepositoryRegistry repositoryRegistry; - - - private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryGroupService.class ); - private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id"} ); - - static - { - QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.RepositoryGroup::getId ); - QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.RepositoryGroup::getId ); - } - - - public DefaultRepositoryGroupService( RepositoryRegistry repositoryRegistry, ConfigurationHandler configurationHandler ) - { - this.repositoryRegistry = repositoryRegistry; - this.configurationHandler = configurationHandler; - } - - @Override - public PagedResult getRepositoriesGroups( String searchTerm, Integer offset, Integer limit, List orderBy, String order ) throws ArchivaRestServiceException - { - try - { - Predicate filter = QUERY_HELPER.getQueryFilter( searchTerm ); - Comparator ordering = QUERY_HELPER.getComparator( orderBy, QUERY_HELPER.isAscending( order ) ); - int totalCount = Math.toIntExact( repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).count( ) ); - List result = repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).sorted( ordering ).skip( offset ).limit( limit ).map( - RepositoryGroup::of - ).collect( Collectors.toList( ) ); - return new PagedResult<>( totalCount, offset, limit, result ); - } - catch ( ArithmeticException e ) - { - log.error( "Could not convert total count: {}", e.getMessage( ) ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) ); - } - - } - - @Override - public RepositoryGroup getRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException - { - if ( StringUtils.isEmpty( repositoryGroupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); - return RepositoryGroup.of( group ); - } - - private RepositoryGroupConfiguration toConfig( RepositoryGroup group ) - { - RepositoryGroupConfiguration result = new RepositoryGroupConfiguration( ); - result.setId( group.getId( ) ); - result.setName( group.getName() ); - result.setLocation( group.getLocation( ) ); - result.setRepositories( group.getRepositories( ) ); - MergeConfiguration mergeConfig = group.getMergeConfiguration( ); - if ( mergeConfig != null ) - { - result.setMergedIndexPath( mergeConfig.getMergedIndexPath( ) ); - result.setMergedIndexTtl( mergeConfig.getMergedIndexTtlMinutes( ) ); - result.setCronExpression( mergeConfig.getIndexMergeSchedule( ) ); - } - return result; - } - - @Override - public RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException - { - final String groupId = repositoryGroup.getId( ); - if ( StringUtils.isEmpty( groupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, groupId ), 422 ); - } - if ( repositoryRegistry.hasRepositoryGroup( groupId ) ) - { - httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( groupId ).build( ).toString( ) ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, groupId ), 303 ); - } - try - { - - RepositoryGroupConfiguration configuration = toConfig( repositoryGroup ); - CheckedResult>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration ); - if ( validationResult.isValid( ) ) - { - httpServletResponse.setStatus( 201 ); - return RepositoryGroup.of( validationResult.getRepository( ) ); - } - else - { - throw ValidationException.of( validationResult.getResult( ) ); - } - } - catch ( RepositoryException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) ); - } - } - - @Override - public RepositoryGroup updateRepositoryGroup( final String repositoryGroupId, final RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException - { - if ( StringUtils.isEmpty( repositoryGroupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - if ( !repositoryRegistry.hasRepositoryGroup( repositoryGroupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND ), 404 ); - } - repositoryGroup.setId( repositoryGroupId ); - try - { - RepositoryGroupConfiguration configuration = toConfig( repositoryGroup ); - CheckedResult>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration ); - if ( validationResult.isValid( ) ) - { - httpServletResponse.setStatus( 201 ); - return RepositoryGroup.of( validationResult.getRepository( ) ); - } - else - { - throw ValidationException.of( validationResult.getResult( ) ); - } - } - catch ( RepositoryException e ) - { - log.error( "Exception during repository group update: {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ) ); - - } - } - - @Override - public Response deleteRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException - { - if ( StringUtils.isEmpty( repositoryGroupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - try - { - org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); - if ( group == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - repositoryRegistry.removeRepositoryGroup( group ); - return Response.ok( ).build( ); - } - catch ( RepositoryException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) ); - } - } - - @Override - public RepositoryGroup addRepositoryToGroup( String repositoryGroupId, String repositoryId ) throws ArchivaRestServiceException - { - if ( StringUtils.isEmpty( repositoryGroupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - if ( StringUtils.isEmpty( repositoryId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 ); - } - try - { - org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); - if ( repositoryGroup == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - if ( !( repositoryGroup instanceof EditableRepositoryGroup ) ) - { - log.error( "This group instance is not editable: {}", repositoryGroupId ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 ); - } - EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup; - if ( editableRepositoryGroup.getRepositories( ).stream( ).anyMatch( repo -> repositoryId.equals( repo.getId( ) ) ) ) - { - log.info( "Repository {} is already member of group {}", repositoryId, repositoryGroupId ); - return RepositoryGroup.of( editableRepositoryGroup ); - } - org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository( repositoryId ); - if ( managedRepo == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 ); - } - editableRepositoryGroup.addRepository( managedRepo ); - org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup ); - return RepositoryGroup.of( newGroup ); - } - catch ( RepositoryException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 ); - } - } - - @Override - public RepositoryGroup deleteRepositoryFromGroup( final String repositoryGroupId, final String repositoryId ) throws org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException - { - if ( StringUtils.isEmpty( repositoryGroupId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, repositoryGroupId ), 404 ); - } - if ( StringUtils.isEmpty( repositoryId ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); - } - try - { - org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); - if ( repositoryGroup == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); - } - if ( repositoryGroup.getRepositories( ).stream( ).noneMatch( r -> repositoryId.equals( r.getId( ) ) ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); - } - if ( !( repositoryGroup instanceof EditableRepositoryGroup ) ) - { - log.error( "This group instance is not editable: {}", repositoryGroupId ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 ); - } - EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup; - editableRepositoryGroup.removeRepository( repositoryId ); - org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup ); - return RepositoryGroup.of( newGroup ); - } - catch ( RepositoryException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 ); - } - } - - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java deleted file mode 100644 index da498c20b..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java +++ /dev/null @@ -1,244 +0,0 @@ -package org.apache.archiva.rest.services.v2; -/* - * 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.archiva.admin.model.RepositoryAdminException; -import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.util.QueryHelper; -import org.apache.archiva.components.rest.util.RestUtil; -import org.apache.archiva.metadata.repository.MetadataRepositoryException; -import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager; -import org.apache.archiva.repository.RemoteRepository; -import org.apache.archiva.repository.RepositoryRegistry; -import org.apache.archiva.repository.scanner.RepositoryScanner; -import org.apache.archiva.repository.scanner.RepositoryScannerException; -import org.apache.archiva.rest.api.model.v2.Repository; -import org.apache.archiva.rest.api.model.v2.RepositoryStatistics; -import org.apache.archiva.rest.api.model.v2.ScanStatus; -import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; -import org.apache.archiva.rest.api.services.v2.ErrorKeys; -import org.apache.archiva.rest.api.services.v2.ErrorMessage; -import org.apache.archiva.rest.api.services.v2.RepositoryService; -import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException; -import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.inject.Named; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * @author Martin Stockhammer - * @since 3.0 - */ -@Service( "v2.repositoryService#rest" ) -public class DefaultRepositoryService implements RepositoryService -{ - - final - RepositoryRegistry repositoryRegistry; - - final - RepositoryStatisticsManager repositoryStatisticsManager; - - private final RepositoryTaskAdministration repositoryTaskAdministration; - - private final RepositoryScanner repoScanner; - - private final DownloadRemoteIndexScheduler downloadRemoteIndexScheduler; - - private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryService.class ); - private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} ); - - static - { - QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.Repository::getId ); - QUERY_HELPER.addStringFilter( "name", org.apache.archiva.repository.Repository::getName ); - QUERY_HELPER.addStringFilter( "description", org.apache.archiva.repository.Repository::getDescription ); - QUERY_HELPER.addStringFilter( "type", repo -> repo.getType( ).name( ) ); - QUERY_HELPER.addBooleanFilter( "scanned", org.apache.archiva.repository.Repository::isScanned ); - QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.Repository::getId ); - QUERY_HELPER.addNullsafeFieldComparator( "name", org.apache.archiva.repository.Repository::getName ); - QUERY_HELPER.addNullsafeFieldComparator( "type", repo -> repo.getType( ).name( ) ); - QUERY_HELPER.addNullsafeFieldComparator( "boolean", org.apache.archiva.repository.Repository::isScanned ); - } - - public DefaultRepositoryService( RepositoryRegistry repositoryRegistry, RepositoryStatisticsManager repositoryStatisticsManager, - @Named( value = "repositoryTaskAdministration#default") RepositoryTaskAdministration repositoryTaskAdministration, - RepositoryScanner repoScanner, DownloadRemoteIndexScheduler downloadRemoteIndexScheduler ) - { - this.repositoryRegistry = repositoryRegistry; - this.repositoryStatisticsManager = repositoryStatisticsManager; - this.repoScanner = repoScanner; - this.repositoryTaskAdministration = repositoryTaskAdministration; - this.downloadRemoteIndexScheduler = downloadRemoteIndexScheduler; - } - - private void handleAdminException( RepositoryAdminException e ) throws ArchivaRestServiceException - { - log.error( "Repository admin error: {}", e.getMessage( ), e ); - if ( e.keyExists( ) ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PREFIX + e.getKey( ), e.getParameters( ) ) ); - } - else - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - } - - - @Override - public PagedResult getRepositories( String searchTerm, Integer offset, Integer limit, List orderBy, String order, - String localeString ) throws ArchivaRestServiceException - { - final Locale locale = StringUtils.isNotEmpty( localeString ) ? Locale.forLanguageTag( localeString ) : Locale.getDefault( ); - boolean isAscending = QUERY_HELPER.isAscending( order ); - Predicate filter = QUERY_HELPER.getQueryFilter( searchTerm ); - Comparator comparator = QUERY_HELPER.getComparator( orderBy, isAscending ); - try - { - int totalCount = Math.toIntExact( repositoryRegistry.getRepositories( ).stream( ).filter( filter ).count( ) ); - return new PagedResult<>( totalCount, offset, limit, repositoryRegistry.getRepositories( ).stream( ) - .filter( filter ).skip( offset ).limit( limit ).sorted( comparator ).map( repo -> Repository.of( repo, locale ) ) - .collect( Collectors.toList( ) ) ); - } - catch ( ArithmeticException e ) - { - log.error( "Invalid integer conversion for totalCount" ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) ); - } - } - - @Override - public RepositoryStatistics getManagedRepositoryStatistics( String repositoryId ) throws ArchivaRestServiceException - { - if ( repositoryRegistry.getManagedRepository( repositoryId ) == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_MANAGED_NOT_FOUND, repositoryId ), 404 ); - } - try - { - return RepositoryStatistics.of( repositoryStatisticsManager.getLastStatistics( repositoryId ) ); - } - catch ( MetadataRepositoryException e ) - { - log.error( "Metadata error: {} ", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_METADATA_ERROR, e.getMessage( ) ) ); - } - } - - @Override - public Response scheduleRepositoryScan( String repositoryId, boolean fullScan ) throws ArchivaRestServiceException - { - try - { - repositoryTaskAdministration.scheduleFullScan( repositoryId ); - return Response.ok( ).build( ); - } - catch ( RepositoryAdminException e ) - { - handleAdminException( e ); - return Response.serverError( ).build( ); - } - } - - @Override - public RepositoryStatistics scanRepositoryImmediately( String repositoryId ) throws ArchivaRestServiceException - { - long sinceWhen = RepositoryScanner.FRESH_SCAN; - try - { - return RepositoryStatistics.of( repoScanner.scan( repositoryRegistry.getManagedRepository( repositoryId ), sinceWhen ) ); - } - catch ( RepositoryScannerException e ) - { - log.error( e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage( ) ) ); - } - } - - @Override - public ScanStatus getScanStatus( String repositoryId ) throws ArchivaRestServiceException - { - try - { - return ScanStatus.of( repositoryTaskAdministration.getCurrentScanStatus( ) ); - } - catch ( RepositoryAdminException e ) - { - handleAdminException( e ); - return new ScanStatus(); - } - } - - @Override - public Response removeScanningTaskFromQueue( String repositoryId ) throws ArchivaRestServiceException - { - try - { - repositoryTaskAdministration.cancelTasks( repositoryId ); - return Response.ok( ).build( ); - } - catch ( RepositoryAdminException e ) - { - handleAdminException( e ); - return Response.serverError( ).build( ); - } - } - - - @Override - public Response scheduleDownloadRemoteIndex( String repositoryId, boolean immediately, boolean full, - UriInfo uriInfo ) throws ArchivaRestServiceException - { - boolean immediateSet = RestUtil.isFlagSet( uriInfo, "immediate" ); - boolean fullSet = RestUtil.isFlagSet( uriInfo, "full" ); - RemoteRepository repo = repositoryRegistry.getRemoteRepository( repositoryId ); - if (repo==null) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_NOT_FOUND, repositoryId ), 404 ); - } - try - { - downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, immediateSet, fullSet ); - return Response.ok( ).build( ); - } - catch ( DownloadRemoteIndexException e ) - { - log.error( "Could not schedule index download for repository {}: {}", repositoryId, e.getMessage(), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED, e.getMessage( ) ) ); - } - } - - - - @Override - public List getRunningRemoteDownloads( ) - { - return downloadRemoteIndexScheduler.getRunningRemoteDownloadIds( ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java deleted file mode 100644 index 360d03ebc..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultSecurityConfigurationService.java +++ /dev/null @@ -1,677 +0,0 @@ -package org.apache.archiva.rest.services.v2;/* - * 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. - */ - -/* - * 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.archiva.admin.model.RepositoryAdminException; -import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration; -import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.model.PropertyEntry; -import org.apache.archiva.components.rest.util.QueryHelper; -import org.apache.archiva.redback.authentication.Authenticator; -import org.apache.archiva.redback.common.ldap.connection.LdapConnection; -import org.apache.archiva.redback.common.ldap.connection.LdapConnectionConfiguration; -import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory; -import org.apache.archiva.redback.common.ldap.connection.LdapException; -import org.apache.archiva.redback.common.ldap.user.LdapUserMapper; -import org.apache.archiva.redback.policy.CookieSettings; -import org.apache.archiva.redback.policy.PasswordRule; -import org.apache.archiva.redback.rbac.RBACManager; -import org.apache.archiva.redback.role.RoleManager; -import org.apache.archiva.redback.users.UserManager; -import org.apache.archiva.rest.api.model.v2.BeanInformation; -import org.apache.archiva.rest.api.model.v2.CacheConfiguration; -import org.apache.archiva.rest.api.model.v2.LdapConfiguration; -import org.apache.archiva.rest.api.model.v2.SecurityConfiguration; -import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException; -import org.apache.archiva.rest.api.services.v2.ErrorKeys; -import org.apache.archiva.rest.api.services.v2.ErrorMessage; -import org.apache.archiva.rest.api.services.v2.SecurityConfigurationService; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import javax.inject.Named; -import javax.naming.AuthenticationException; -import javax.naming.AuthenticationNotSupportedException; -import javax.naming.CommunicationException; -import javax.naming.InvalidNameException; -import javax.naming.NamingException; -import javax.naming.NoPermissionException; -import javax.naming.ServiceUnavailableException; -import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.ResourceBundle; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static org.apache.archiva.rest.api.services.v2.ErrorKeys.INVALID_RESULT_SET_ERROR; -import static org.apache.archiva.rest.api.services.v2.ErrorKeys.REPOSITORY_ADMIN_ERROR; - -/** - * @author Martin Stockhammer - */ -@Service( "v2.defaultSecurityConfigurationService" ) -public class DefaultSecurityConfigurationService implements SecurityConfigurationService -{ - private static final Logger log = LoggerFactory.getLogger( DefaultSecurityConfigurationService.class ); - - private static final String[] KNOWN_LDAP_CONTEXT_PROVIDERS = {"com.sun.jndi.ldap.LdapCtxFactory","com.ibm.jndi.LDAPCtxFactory"}; - private final List availableContextProviders = new ArrayList<>( ); - - private static final QueryHelper PROP_QUERY_HELPER = new QueryHelper<>( new String[]{"key"} ); - - static - { - PROP_QUERY_HELPER.addStringFilter( "key", PropertyEntry::getKey ); - PROP_QUERY_HELPER.addStringFilter( "value", PropertyEntry::getValue ); - PROP_QUERY_HELPER.addNullsafeFieldComparator( "key", PropertyEntry::getKey ); - PROP_QUERY_HELPER.addNullsafeFieldComparator( "value", PropertyEntry::getValue ); - - } - - private ResourceBundle bundle; - - - @Inject - private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin; - - @Inject - private ApplicationContext applicationContext; - - @Inject - @Named( value = "userManager#default" ) - private UserManager userManager; - - @Inject - @Named( value = "rbacManager#default" ) - private RBACManager rbacManager; - - @Inject - private RoleManager roleManager; - - @Inject - @Named( value = "ldapConnectionFactory#configurable" ) - private LdapConnectionFactory ldapConnectionFactory; - - @Inject - private LdapUserMapper ldapUserMapper; - - - @PostConstruct - void init( ) - { - bundle = ResourceBundle.getBundle( "org.apache.archiva.rest.RestBundle" ); - for (String ldapClass : KNOWN_LDAP_CONTEXT_PROVIDERS) { - if (isContextFactoryAvailable( ldapClass )) { - availableContextProviders.add( ldapClass ); - } - } - } - - @Override - public SecurityConfiguration getConfiguration( ) throws ArchivaRestServiceException - { - try - { - RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - - log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); - - return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfiguration ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); - } - } - - private void updateConfig( SecurityConfiguration newConfig, RedbackRuntimeConfiguration rbConfig ) - { - rbConfig.setUserManagerImpls( newConfig.getActiveUserManagers( ) ); - rbConfig.setRbacManagerImpls( newConfig.getActiveRbacManagers( ) ); - rbConfig.setUseUsersCache( newConfig.isUserCacheEnabled( ) ); - Map props = rbConfig.getConfigurationProperties( ); - for ( Map.Entry newProp : newConfig.getProperties( ).entrySet( ) ) - { - props.put( newProp.getKey( ), newProp.getValue( ) ); - } - } - - private void updateConfig( LdapConfiguration newConfig, RedbackRuntimeConfiguration rbConfig ) - { - org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfig = rbConfig.getLdapConfiguration( ); - ldapConfig.setBaseDn( newConfig.getBaseDn( ) ); - ldapConfig.setAuthenticationMethod( newConfig.getAuthenticationMethod( ) ); - ldapConfig.setBindAuthenticatorEnabled( newConfig.isBindAuthenticatorEnabled( ) ); - ldapConfig.setBindDn( newConfig.getBindDn( ) ); - ldapConfig.setSsl( newConfig.isSslEnabled( ) ); - ldapConfig.setBaseGroupsDn( newConfig.getGroupsBaseDn( ) ); - ldapConfig.setHostName( newConfig.getHostName( ) ); - ldapConfig.setPort( newConfig.getPort( ) ); - ldapConfig.setPassword( newConfig.getBindPassword( ) ); - ldapConfig.setUseRoleNameAsGroup( newConfig.isUseRoleNameAsGroup( ) ); - ldapConfig.setWritable( newConfig.isWritable( ) ); - ldapConfig.setContextFactory( newConfig.getContextFactory( ) ); - - Map props = ldapConfig.getExtraProperties( ); - for ( Map.Entry newProp : newConfig.getProperties( ).entrySet( ) ) - { - props.put( newProp.getKey( ), newProp.getValue( ) ); - } - } - - private void updateConfig( CacheConfiguration newConfig, RedbackRuntimeConfiguration rbConfig ) - { - org.apache.archiva.admin.model.beans.CacheConfiguration cacheConfig = rbConfig.getUsersCacheConfiguration( ); - cacheConfig.setMaxElementsInMemory( newConfig.getMaxEntriesInMemory( ) ); - cacheConfig.setMaxElementsOnDisk( newConfig.getMaxEntriesOnDisk( ) ); - cacheConfig.setTimeToLiveSeconds( newConfig.getTimeToLiveSeconds( ) ); - cacheConfig.setTimeToIdleSeconds( newConfig.getTimeToIdleSeconds( ) ); - } - - @Override - public SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration ) throws ArchivaRestServiceException - { - if ( newConfiguration == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 ); - } - try - { - RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - boolean userManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveUserManagers( ), conf.getUserManagerImpls( ) ); - boolean rbacManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveRbacManagers( ), conf.getRbacManagerImpls( ) ); - - boolean ldapConfigured = newConfiguration.getActiveUserManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) ); - if ( !ldapConfigured ) - { - ldapConfigured= newConfiguration.getActiveRbacManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) ); - } - - updateConfig( newConfiguration, conf ); - redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf ); - - if ( userManagerChanged ) - { - log.info( "user managerImpls changed to {} so reload it", - newConfiguration.getActiveUserManagers( ) ); - userManager.initialize( ); - } - - if ( rbacManagerChanged ) - { - log.info( "rbac manager changed to {} so reload it", - newConfiguration.getActiveRbacManagers( ) ); - rbacManager.initialize( ); - roleManager.initialize( ); - } - - if ( ldapConfigured ) - { - try - { - ldapConnectionFactory.initialize( ); - } - catch ( Exception e ) - { - log.error( "Could not initialize LDAP connection factory: {}", e.getMessage( ) ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_CF_INIT_FAILED, e.getMessage( ) ) ); - } - } - Collection passwordRules = applicationContext.getBeansOfType( PasswordRule.class ).values( ); - - for ( PasswordRule passwordRule : passwordRules ) - { - passwordRule.initialize( ); - } - - Collection cookieSettingsList = - applicationContext.getBeansOfType( CookieSettings.class ).values( ); - - for ( CookieSettings cookieSettings : cookieSettingsList ) - { - cookieSettings.initialize( ); - } - - Collection authenticators = - applicationContext.getBeansOfType( Authenticator.class ).values( ); - - for ( Authenticator authenticator : authenticators ) - { - try - { - log.debug( "Initializing authenticatior " + authenticator.getId( ) ); - authenticator.initialize( ); - } - catch ( Exception e ) - { - log.error( "Initialization of authenticator failed " + authenticator.getId( ), e ); - } - } - - if ( ldapConfigured ) - { - try - { - ldapUserMapper.initialize( ); - } - catch ( Exception e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_USER_MAPPER_INIT_FAILED, e.getMessage( ) ) ); - } - } - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - try - { - return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ) ); - } - catch ( RepositoryAdminException e ) - { - log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) ); - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - } - - @Override - public PagedResult getConfigurationProperties( String searchTerm, Integer offset, Integer limit, List orderBy, String order ) throws ArchivaRestServiceException - { - try - { - RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - - log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); - - boolean ascending = PROP_QUERY_HELPER.isAscending( order ); - Predicate filter = PROP_QUERY_HELPER.getQueryFilter( searchTerm ); - Comparator comparator = PROP_QUERY_HELPER.getComparator( orderBy, ascending ); - Map props = redbackRuntimeConfiguration.getConfigurationProperties( ); - int totalCount = Math.toIntExact( props.entrySet( ).stream( ).map( - entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) ) - ).filter( filter ).count( ) ); - List result = props.entrySet( ).stream( ).map( - entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) ) - ).filter( filter ) - .sorted( comparator ) - .skip( offset ).limit( limit ) - .collect( Collectors.toList( ) ); - return new PagedResult<>( totalCount, offset, limit, result ); - } catch (ArithmeticException e) { - log.error( "The total count of the result properties is higher than max integer value!" ); - throw new ArchivaRestServiceException( ErrorMessage.of( INVALID_RESULT_SET_ERROR ) ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); - } - } - - @Override - public PropertyEntry getConfigurationProperty( String propertyName ) throws ArchivaRestServiceException - { - try - { - RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - if ( conf.getConfigurationProperties( ).containsKey( propertyName ) ) - { - String value = conf.getConfigurationProperties( ).get( propertyName ); - return new PropertyEntry( propertyName, value ); - } - else - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 ); - } - - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - - } - - @Override - public Response updateConfigurationProperty( String propertyName, PropertyEntry propertyValue ) throws ArchivaRestServiceException - { - if ( propertyValue == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 ); - } - try - { - RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - if ( conf.getConfigurationProperties( ).containsKey( propertyName ) ) - { - conf.getConfigurationProperties( ).put( propertyName, propertyValue.getValue( ) ); - redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf ); - return Response.ok( ).build( ); - } - else - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 ); - } - - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - } - - @Override - public LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException - { - try - { - RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - - log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); - - LdapConfiguration ldapConfig = LdapConfiguration.of( redbackRuntimeConfiguration.getLdapConfiguration( ) ); - ldapConfig.setAvailableContextFactories( availableContextProviders ); - return ldapConfig; - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); - } - - } - - @Override - public LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException - { - try - { - RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - - log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); - - updateConfig( configuration, redbackRuntimeConfiguration ); - - redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration ); - ldapConnectionFactory.initialize( ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); - } - - try - { - return LdapConfiguration.of( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ).getLdapConfiguration() ); - } - catch ( RepositoryAdminException e ) - { - log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) ); - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); - } - - } - - static Properties toProperties( Map values ) - { - Properties result = new Properties( ); - for ( Map.Entry entry : values.entrySet( ) ) - { - result.setProperty( entry.getKey( ), entry.getValue( ) ); - } - return result; - } - - private static boolean isContextFactoryAvailable( final String factoryClass) - { - try - { - return Thread.currentThread().getContextClassLoader().loadClass( factoryClass ) - != null; - } - catch ( ClassNotFoundException e ) - { - return false; - } - } - - - @Override - public Response verifyLdapConfiguration( LdapConfiguration ldapConfiguration ) throws ArchivaRestServiceException - { - LdapConnection ldapConnection = null; - try - { - LdapConnectionConfiguration ldapConnectionConfiguration = - new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ), - ldapConfiguration.getBaseDn( ), ldapConfiguration.getContextFactory( ), - ldapConfiguration.getBindDn( ), ldapConfiguration.getBindPassword( ), - ldapConfiguration.getAuthenticationMethod( ), - toProperties( ldapConfiguration.getProperties( ) ) ); - ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) ); - - ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration ); - } - catch ( InvalidNameException e ) - { - log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 ); - } - catch ( LdapException e ) - { - handleLdapException( e ); - } - finally - { - if ( ldapConnection != null ) - { - try - { - ldapConnection.close( ); - } - catch ( NamingException e ) - { - log.error( "Could not close connection: {}", e.getMessage( ) ); - } - } - ldapConnection = null; - } - - try - { - // verify groups dn value too - - LdapConnectionConfiguration ldapConnectionConfiguration = new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ), - ldapConfiguration.getGroupsBaseDn( ), - ldapConfiguration.getContextFactory( ), ldapConfiguration.getBindDn( ), - ldapConfiguration.getBindPassword( ), - ldapConfiguration.getAuthenticationMethod( ), - toProperties( ldapConfiguration.getProperties( ) ) ); - - ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) ); - - ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration ); - } - catch ( InvalidNameException e ) - { - log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 ); - } - catch ( LdapException e ) - { - handleLdapException( e ); - } - finally - { - if ( ldapConnection != null ) - { - try - { - ldapConnection.close( ); - } - catch ( NamingException e ) - { - log.error( "Could not close connection: {}", e.getMessage( ), e ); - } - } - } - - return Response.ok( ).build( ); - } - - private void handleLdapException( LdapException e ) throws ArchivaRestServiceException - { - Throwable rootCause = e.getRootCause( ); - if ( rootCause instanceof CommunicationException ) - { - log.warn( "LDAP connection check failed with CommunicationException: {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_COMMUNICATION_ERROR, e.getMessage( ) ), 400 ); - } else if (rootCause instanceof ServiceUnavailableException ) { - log.warn( "LDAP connection check failed with ServiceUnavailableException: {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_UNAVAILABLE, e.getMessage( ) ), 400 ); - } else if (rootCause instanceof AuthenticationException ) { - log.warn( "LDAP connection check failed with AuthenticationException: {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_FAILED, e.getMessage( ) ), 400 ); - } else if (rootCause instanceof AuthenticationNotSupportedException ) { - log.warn( "LDAP connection check failed with AuthenticationNotSupportedException: {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED, e.getMessage( ) ), 400 ); - } else if (rootCause instanceof NoPermissionException ) { - log.warn( "LDAP connection check failed with NoPermissionException: {}", e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_NO_PERMISSION, e.getMessage( ) ), 400 ); - } - log.warn( "LDAP connection check failed: {} - {}", e.getClass().getName(), e.getMessage( ), e ); - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_GENERIC_ERROR, e.getMessage( ) ), 400 ); - } - - @Override - public CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException - { - try - { - RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - - log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); - - return CacheConfiguration.of( redbackRuntimeConfiguration.getUsersCacheConfiguration( ) ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); - } - - } - - @Override - public CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException - { - if ( cacheConfiguration == null ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 ); - } - try - { - RedbackRuntimeConfiguration redbackRuntimeConfiguration = - redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); - - log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); - updateConfig( cacheConfiguration, redbackRuntimeConfiguration ); - redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration ); - return getCacheConfiguration( ); - } - catch ( RepositoryAdminException e ) - { - throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); - } - } - - @Override - public List getAvailableUserManagers( ) - { - Map beans = applicationContext.getBeansOfType( UserManager.class ); - - if ( beans.isEmpty( ) ) - { - return Collections.emptyList( ); - } - - return beans.entrySet( ).stream( ) - .filter( entry -> entry.getValue( ).isFinalImplementation( ) ) - .map( ( Map.Entry entry ) -> { - UserManager um = entry.getValue( ); - String id = StringUtils.substringAfter( entry.getKey( ), "#" ); - String displayName = bundle.getString( "user_manager." + id + ".display_name" ); - String description = bundle.getString( "user_manager." + id + ".description" ); - return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, um.getDescriptionKey( ), description, um.isReadOnly( ) ); - } ).collect( Collectors.toList( ) ); - } - - @Override - public List getAvailableRbacManagers( ) - { - Map beans = applicationContext.getBeansOfType( RBACManager.class ); - - if ( beans.isEmpty( ) ) - { - return Collections.emptyList( ); - } - - return beans.entrySet( ).stream( ) - .filter( entry -> entry.getValue( ).isFinalImplementation( ) ) - .map( ( Map.Entry entry ) -> { - RBACManager rm = entry.getValue( ); - String id = StringUtils.substringAfter( entry.getKey( ), "#" ); - String displayName = bundle.getString( "rbac_manager." + id + ".display_name" ); - String description = bundle.getString( "rbac_manager." + id + ".description" ); - return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, rm.getDescriptionKey( ), description, rm.isReadOnly( ) ); - } ).collect( Collectors.toList( ) ); - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/ArchivaRestServiceExceptionMapper.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/ArchivaRestServiceExceptionMapper.java new file mode 100644 index 000000000..096e8fd3c --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/ArchivaRestServiceExceptionMapper.java @@ -0,0 +1,67 @@ +package org.apache.archiva.rest.v2.interceptor; +/* + * 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.archiva.rest.api.v2.svc.ArchivaRestError; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; +import org.springframework.stereotype.Service; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +/** + * Maps exceptions to REST responses. + * + * @author Martin Stockhammer + * @since 3.0 + */ +@Provider +@Service( "v2.archivaRestServiceExceptionMapper" ) +public class ArchivaRestServiceExceptionMapper + implements ExceptionMapper +{ + @Override + public Response toResponse( final ArchivaRestServiceException e ) + { + ArchivaRestError restError = new ArchivaRestError( e ); + + Response.ResponseBuilder responseBuilder = Response.status( e.getHttpErrorCode() ).entity( restError ); + if ( e.getMessage() != null ) + { + responseBuilder = responseBuilder.status( new Response.StatusType() + { + public int getStatusCode() + { + return e.getHttpErrorCode(); + } + + public Response.Status.Family getFamily() + { + return Response.Status.Family.familyOf( e.getHttpErrorCode( ) ); + } + + public String getReasonPhrase() + { + return e.getMessage(); + } + } ); + } + return responseBuilder.build(); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultMavenManagedRepositoryService.java new file mode 100644 index 000000000..0c67cd4c9 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultMavenManagedRepositoryService.java @@ -0,0 +1,389 @@ +package org.apache.archiva.rest.v2.svc; +/* + * 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.archiva.admin.model.AuditInformation; +import org.apache.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.util.QueryHelper; +import org.apache.archiva.redback.authentication.AuthenticationResult; +import org.apache.archiva.redback.authorization.AuthorizationException; +import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; +import org.apache.archiva.redback.rest.services.RedbackRequestInformation; +import org.apache.archiva.redback.system.DefaultSecuritySession; +import org.apache.archiva.redback.system.SecuritySession; +import org.apache.archiva.redback.system.SecuritySystem; +import org.apache.archiva.redback.users.User; +import org.apache.archiva.redback.users.UserManagerException; +import org.apache.archiva.redback.users.UserNotFoundException; +import org.apache.archiva.repository.ManagedRepository; +import org.apache.archiva.repository.ReleaseScheme; +import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.RepositoryType; +import org.apache.archiva.repository.content.ContentItem; +import org.apache.archiva.repository.content.LayoutException; +import org.apache.archiva.repository.storage.fs.FsStorageUtil; +import org.apache.archiva.rest.api.v2.model.FileInfo; +import org.apache.archiva.rest.api.v2.model.MavenManagedRepository; +import org.apache.archiva.rest.api.v2.model.MavenManagedRepositoryUpdate; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; +import org.apache.archiva.rest.api.v2.svc.ErrorKeys; +import org.apache.archiva.rest.api.v2.svc.ErrorMessage; +import org.apache.archiva.rest.api.v2.svc.maven.MavenManagedRepositoryService; +import org.apache.archiva.security.common.ArchivaRoleConstants; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS; +import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD; + +/** + * @author Martin Stockhammer + */ +@Service("v2.managedMavenRepositoryService#rest") +public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService +{ + @Context + HttpServletResponse httpServletResponse; + + @Context + UriInfo uriInfo; + + private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class ); + private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} ); + static + { + QUERY_HELPER.addStringFilter( "id", ManagedRepository::getId ); + QUERY_HELPER.addStringFilter( "name", ManagedRepository::getName ); + QUERY_HELPER.addStringFilter( "location", (r) -> r.getLocation().toString() ); + QUERY_HELPER.addBooleanFilter( "snapshot", (r) -> r.getActiveReleaseSchemes( ).contains( ReleaseScheme.SNAPSHOT ) ); + QUERY_HELPER.addBooleanFilter( "release", (r) -> r.getActiveReleaseSchemes().contains( ReleaseScheme.RELEASE )); + QUERY_HELPER.addNullsafeFieldComparator( "id", ManagedRepository::getId ); + QUERY_HELPER.addNullsafeFieldComparator( "name", ManagedRepository::getName ); + } + + private ManagedRepositoryAdmin managedRepositoryAdmin; + private RepositoryRegistry repositoryRegistry; + private SecuritySystem securitySystem; + + public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem, + RepositoryRegistry repositoryRegistry, + ManagedRepositoryAdmin managedRepositoryAdmin ) + { + this.securitySystem = securitySystem; + this.repositoryRegistry = repositoryRegistry; + this.managedRepositoryAdmin = managedRepositoryAdmin; + } + + protected AuditInformation getAuditInformation( ) + { + RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); + User user; + String remoteAddr; + if (redbackRequestInformation==null) { + user = null; + remoteAddr = null; + } else + { + user = redbackRequestInformation.getUser( ); + remoteAddr = redbackRequestInformation.getRemoteAddr( ); + } + return new AuditInformation( user, remoteAddr ); + } + + @Override + public PagedResult getManagedRepositories( final String searchTerm, final Integer offset, + final Integer limit, final List orderBy, + final String order ) throws ArchivaRestServiceException + { + try + { + Collection repos = repositoryRegistry.getManagedRepositories( ); + final Predicate queryFilter = QUERY_HELPER.getQueryFilter( searchTerm ).and( r -> r.getType() == RepositoryType.MAVEN ); + final Comparator comparator = QUERY_HELPER.getComparator( orderBy, order ); + int totalCount = Math.toIntExact( repos.stream( ).filter( queryFilter ).count( ) ); + return PagedResult.of( totalCount, offset, limit, repos.stream( ).filter( queryFilter ).sorted( comparator ) + .map(mr -> MavenManagedRepository.of(mr)).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) ); + } + catch (ArithmeticException e) { + log.error( "Invalid number of repositories detected." ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) ); + } + } + + @Override + public MavenManagedRepository getManagedRepository( String repositoryId ) throws ArchivaRestServiceException + { + ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId ); + if (repo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); + } + if (repo.getType()!=RepositoryType.MAVEN) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 ); + } + return MavenManagedRepository.of( repo ); + } + + @Override + public Response deleteManagedRepository( String repositoryId, boolean deleteContent ) throws ArchivaRestServiceException + { + ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId ); + if (repo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); + } + if (repo.getType()!=RepositoryType.MAVEN) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 ); + } + try + { + managedRepositoryAdmin.deleteManagedRepository( repositoryId, getAuditInformation( ), deleteContent ); + return Response.ok( ).build( ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_DELETE_FAILED, e.getMessage( ) ) ); + } + } + + private org.apache.archiva.admin.model.beans.ManagedRepository convert(MavenManagedRepository repository) { + org.apache.archiva.admin.model.beans.ManagedRepository repoBean = new org.apache.archiva.admin.model.beans.ManagedRepository( ); + repoBean.setId( repository.getId( ) ); + repoBean.setName( repository.getName() ); + repoBean.setDescription( repository.getDescription() ); + repoBean.setBlockRedeployments( repository.isBlocksRedeployments() ); + repoBean.setCronExpression( repository.getSchedulingDefinition() ); + repoBean.setLocation( repository.getLocation() ); + repoBean.setReleases( repository.getReleaseSchemes().contains( ReleaseScheme.RELEASE.name() ) ); + repoBean.setSnapshots( repository.getReleaseSchemes().contains( ReleaseScheme.SNAPSHOT.name() ) ); + repoBean.setScanned( repository.isScanned() ); + repoBean.setDeleteReleasedSnapshots( repository.isDeleteSnapshotsOfRelease() ); + repoBean.setSkipPackedIndexCreation( repository.isSkipPackedIndexCreation() ); + repoBean.setRetentionCount( repository.getRetentionCount() ); + repoBean.setRetentionPeriod( repository.getRetentionPeriod().getDays() ); + repoBean.setIndexDirectory( repository.getIndexPath() ); + repoBean.setPackedIndexDirectory( repository.getPackedIndexPath() ); + repoBean.setLayout( repository.getLayout() ); + repoBean.setType( RepositoryType.MAVEN.name( ) ); + return repoBean; + } + + @Override + public MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) throws ArchivaRestServiceException + { + final String repoId = managedRepository.getId( ); + if ( StringUtils.isEmpty( repoId ) ) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, repoId ), 422 ); + } + Repository repo = repositoryRegistry.getRepository( repoId ); + if (repo!=null) { + httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( repoId ).build( ).toString( ) ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, repoId ), 303 ); + } + try + { + managedRepositoryAdmin.addManagedRepository( convert( managedRepository ), managedRepository.isHasStagingRepository(), getAuditInformation() ); + httpServletResponse.setStatus( 201 ); + return MavenManagedRepository.of( repositoryRegistry.getManagedRepository( repoId ) ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + } + + @Override + public MavenManagedRepository updateManagedRepository( final String repositoryId, final MavenManagedRepositoryUpdate managedRepository ) throws ArchivaRestServiceException + { + org.apache.archiva.admin.model.beans.ManagedRepository repo = convert( managedRepository ); + try + { + managedRepositoryAdmin.updateManagedRepository( repo, managedRepository.isHasStagingRepository( ), getAuditInformation( ), managedRepository.isResetStats( ) ); + ManagedRepository newRepo = repositoryRegistry.getManagedRepository( managedRepository.getId( ) ); + if (newRepo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_UPDATE_FAILED, repositoryId ) ); + } + return MavenManagedRepository.of( newRepo ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + } + + @Override + public FileInfo getFileStatus( String repositoryId, String fileLocation ) throws ArchivaRestServiceException + { + ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId ); + if (repo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); + } + try + { + ContentItem contentItem = repo.getContent( ).toItem( fileLocation ); + if (contentItem.getAsset( ).exists( )) { + return FileInfo.of( contentItem.getAsset( ) ); + } else { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, repositoryId, fileLocation ), 404 ); + } + } + catch ( LayoutException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage( ) ) ); + } + } + + @Override + public Response copyArtifact( String srcRepositoryId, String dstRepositoryId, + String path ) throws ArchivaRestServiceException + { + final AuditInformation auditInformation = getAuditInformation( ); + final String userName = auditInformation.getUser( ).getUsername( ); + if ( StringUtils.isEmpty( userName ) ) + { + httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.NOT_AUTHENTICATED ), 401 ); + } + ManagedRepository srcRepo = repositoryRegistry.getManagedRepository( srcRepositoryId ); + if (srcRepo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, srcRepositoryId ), 404 ); + } + ManagedRepository dstRepo = repositoryRegistry.getManagedRepository( dstRepositoryId ); + if (dstRepo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, dstRepositoryId ), 404 ); + } + checkAuthority( auditInformation.getUser().getUsername(), srcRepositoryId, dstRepositoryId ); + try + { + ContentItem srcItem = srcRepo.getContent( ).toItem( path ); + ContentItem dstItem = dstRepo.getContent( ).toItem( path ); + if (!srcItem.getAsset().exists()){ + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, srcRepositoryId, path ), 404 ); + } + if (dstItem.getAsset().exists()) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_EXISTS_AT_DEST, srcRepositoryId, path ), 400 ); + } + FsStorageUtil.copyAsset( srcItem.getAsset( ), dstItem.getAsset( ), true ); + } + catch ( LayoutException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage() ) ); + } + catch ( IOException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_COPY_ERROR, e.getMessage() ) ); + } + return Response.ok( ).build(); + } + + private void checkAuthority(final String userName, final String srcRepositoryId, final String dstRepositoryId ) throws ArchivaRestServiceException { + User user = null; + try + { + user = securitySystem.getUserManager().findUser( userName ); + } + catch ( UserNotFoundException e ) + { + httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_NOT_FOUND, userName ), 401 ); + } + catch ( UserManagerException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_MANAGER_ERROR, e.getMessage( ) ) ); + } + + // check karma on source : read + AuthenticationResult authn = new AuthenticationResult( true, userName, null ); + SecuritySession securitySession = new DefaultSecuritySession( authn, user ); + try + { + boolean authz = + securitySystem.isAuthorized( securitySession, OPERATION_REPOSITORY_ACCESS, + srcRepositoryId ); + if ( !authz ) + { + throw new ArchivaRestServiceException(ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, srcRepositoryId, OPERATION_REPOSITORY_ACCESS ), 403); + } + } + catch ( AuthorizationException e ) + { + log.error( "Error reading permission: {}", e.getMessage(), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403); + } + + // check karma on target: write + try + { + boolean authz = + securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD, + dstRepositoryId ); + if ( !authz ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, dstRepositoryId, OPERATION_REPOSITORY_UPLOAD ) ); + } + } + catch ( AuthorizationException e ) + { + log.error( "Error reading permission: {}", e.getMessage(), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403); + } + + + } + + @Override + public Response deleteArtifact( String repositoryId, String path ) throws ArchivaRestServiceException + { + + return null; + } + + + @Override + public Response removeProjectVersion( String repositoryId, String namespace, String projectId, String version ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException + { + return null; + } + + @Override + public Response deleteProject( String repositoryId, String namespace, String projectId ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException + { + return null; + } + + @Override + public Response deleteNamespace( String repositoryId, String namespace ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException + { + return null; + } + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryGroupService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryGroupService.java new file mode 100644 index 000000000..ede4fbb46 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryGroupService.java @@ -0,0 +1,328 @@ +package org.apache.archiva.rest.v2.svc;/* + * 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. + */ + +/* + * 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.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.util.QueryHelper; +import org.apache.archiva.configuration.RepositoryGroupConfiguration; +import org.apache.archiva.repository.EditableRepositoryGroup; +import org.apache.archiva.repository.RepositoryException; +import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.base.ConfigurationHandler; +import org.apache.archiva.repository.validation.CheckedResult; +import org.apache.archiva.repository.validation.ValidationError; +import org.apache.archiva.rest.api.v2.model.MergeConfiguration; +import org.apache.archiva.rest.api.v2.model.RepositoryGroup; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; +import org.apache.archiva.rest.api.v2.svc.ErrorKeys; +import org.apache.archiva.rest.api.v2.svc.ErrorMessage; +import org.apache.archiva.rest.api.v2.svc.RepositoryGroupService; +import org.apache.archiva.rest.api.v2.svc.ValidationException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * REST V2 Implementation for repository groups. + * + * @author Martin Stockhammer + * @see RepositoryGroupService + * @since 3.0 + */ +@Service( "v2.repositoryGroupService#rest" ) +public class DefaultRepositoryGroupService implements RepositoryGroupService +{ + private final ConfigurationHandler configurationHandler; + + @Context + HttpServletResponse httpServletResponse; + + @Context + UriInfo uriInfo; + + final private RepositoryRegistry repositoryRegistry; + + + private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryGroupService.class ); + private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id"} ); + + static + { + QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.RepositoryGroup::getId ); + QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.RepositoryGroup::getId ); + } + + + public DefaultRepositoryGroupService( RepositoryRegistry repositoryRegistry, ConfigurationHandler configurationHandler ) + { + this.repositoryRegistry = repositoryRegistry; + this.configurationHandler = configurationHandler; + } + + @Override + public PagedResult getRepositoriesGroups( String searchTerm, Integer offset, Integer limit, List orderBy, String order ) throws ArchivaRestServiceException + { + try + { + Predicate filter = QUERY_HELPER.getQueryFilter( searchTerm ); + Comparator ordering = QUERY_HELPER.getComparator( orderBy, QUERY_HELPER.isAscending( order ) ); + int totalCount = Math.toIntExact( repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).count( ) ); + List result = repositoryRegistry.getRepositoryGroups( ).stream( ).filter( filter ).sorted( ordering ).skip( offset ).limit( limit ).map( + RepositoryGroup::of + ).collect( Collectors.toList( ) ); + return new PagedResult<>( totalCount, offset, limit, result ); + } + catch ( ArithmeticException e ) + { + log.error( "Could not convert total count: {}", e.getMessage( ) ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) ); + } + + } + + @Override + public RepositoryGroup getRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException + { + if ( StringUtils.isEmpty( repositoryGroupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); + return RepositoryGroup.of( group ); + } + + private RepositoryGroupConfiguration toConfig( RepositoryGroup group ) + { + RepositoryGroupConfiguration result = new RepositoryGroupConfiguration( ); + result.setId( group.getId( ) ); + result.setName( group.getName() ); + result.setLocation( group.getLocation( ) ); + result.setRepositories( group.getRepositories( ) ); + MergeConfiguration mergeConfig = group.getMergeConfiguration( ); + if ( mergeConfig != null ) + { + result.setMergedIndexPath( mergeConfig.getMergedIndexPath( ) ); + result.setMergedIndexTtl( mergeConfig.getMergedIndexTtlMinutes( ) ); + result.setCronExpression( mergeConfig.getIndexMergeSchedule( ) ); + } + return result; + } + + @Override + public RepositoryGroup addRepositoryGroup( RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException + { + final String groupId = repositoryGroup.getId( ); + if ( StringUtils.isEmpty( groupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, groupId ), 422 ); + } + if ( repositoryRegistry.hasRepositoryGroup( groupId ) ) + { + httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( groupId ).build( ).toString( ) ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, groupId ), 303 ); + } + try + { + + RepositoryGroupConfiguration configuration = toConfig( repositoryGroup ); + CheckedResult>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration ); + if ( validationResult.isValid( ) ) + { + httpServletResponse.setStatus( 201 ); + return RepositoryGroup.of( validationResult.getRepository( ) ); + } + else + { + throw ValidationException.of( validationResult.getResult( ) ); + } + } + catch ( RepositoryException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_ADD_FAILED ) ); + } + } + + @Override + public RepositoryGroup updateRepositoryGroup( final String repositoryGroupId, final RepositoryGroup repositoryGroup ) throws ArchivaRestServiceException + { + if ( StringUtils.isEmpty( repositoryGroupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + if ( !repositoryRegistry.hasRepositoryGroup( repositoryGroupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND ), 404 ); + } + repositoryGroup.setId( repositoryGroupId ); + try + { + RepositoryGroupConfiguration configuration = toConfig( repositoryGroup ); + CheckedResult>> validationResult = repositoryRegistry.putRepositoryGroupAndValidate( configuration ); + if ( validationResult.isValid( ) ) + { + httpServletResponse.setStatus( 201 ); + return RepositoryGroup.of( validationResult.getRepository( ) ); + } + else + { + throw ValidationException.of( validationResult.getResult( ) ); + } + } + catch ( RepositoryException e ) + { + log.error( "Exception during repository group update: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ) ); + + } + } + + @Override + public Response deleteRepositoryGroup( String repositoryGroupId ) throws ArchivaRestServiceException + { + if ( StringUtils.isEmpty( repositoryGroupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + try + { + org.apache.archiva.repository.RepositoryGroup group = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); + if ( group == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + repositoryRegistry.removeRepositoryGroup( group ); + return Response.ok( ).build( ); + } + catch ( RepositoryException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_DELETE_FAILED ) ); + } + } + + @Override + public RepositoryGroup addRepositoryToGroup( String repositoryGroupId, String repositoryId ) throws ArchivaRestServiceException + { + if ( StringUtils.isEmpty( repositoryGroupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + if ( StringUtils.isEmpty( repositoryId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 ); + } + try + { + org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); + if ( repositoryGroup == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + if ( !( repositoryGroup instanceof EditableRepositoryGroup ) ) + { + log.error( "This group instance is not editable: {}", repositoryGroupId ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 ); + } + EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup; + if ( editableRepositoryGroup.getRepositories( ).stream( ).anyMatch( repo -> repositoryId.equals( repo.getId( ) ) ) ) + { + log.info( "Repository {} is already member of group {}", repositoryId, repositoryGroupId ); + return RepositoryGroup.of( editableRepositoryGroup ); + } + org.apache.archiva.repository.ManagedRepository managedRepo = repositoryRegistry.getManagedRepository( repositoryId ); + if ( managedRepo == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, "" ), 404 ); + } + editableRepositoryGroup.addRepository( managedRepo ); + org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup ); + return RepositoryGroup.of( newGroup ); + } + catch ( RepositoryException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 ); + } + } + + @Override + public RepositoryGroup deleteRepositoryFromGroup( final String repositoryGroupId, final String repositoryId ) throws ArchivaRestServiceException + { + if ( StringUtils.isEmpty( repositoryGroupId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, repositoryGroupId ), 404 ); + } + if ( StringUtils.isEmpty( repositoryId ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); + } + try + { + org.apache.archiva.repository.RepositoryGroup repositoryGroup = repositoryRegistry.getRepositoryGroup( repositoryGroupId ); + if ( repositoryGroup == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_NOT_FOUND, "" ), 404 ); + } + if ( repositoryGroup.getRepositories( ).stream( ).noneMatch( r -> repositoryId.equals( r.getId( ) ) ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 ); + } + if ( !( repositoryGroup instanceof EditableRepositoryGroup ) ) + { + log.error( "This group instance is not editable: {}", repositoryGroupId ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, "" ), 500 ); + } + EditableRepositoryGroup editableRepositoryGroup = (EditableRepositoryGroup) repositoryGroup; + editableRepositoryGroup.removeRepository( repositoryId ); + org.apache.archiva.repository.RepositoryGroup newGroup = repositoryRegistry.putRepositoryGroup( editableRepositoryGroup ); + return RepositoryGroup.of( newGroup ); + } + catch ( RepositoryException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_GROUP_UPDATE_FAILED, e.getMessage( ) ), 500 ); + } + } + + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryService.java new file mode 100644 index 000000000..bf1e13654 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultRepositoryService.java @@ -0,0 +1,244 @@ +package org.apache.archiva.rest.v2.svc; +/* + * 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.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.util.QueryHelper; +import org.apache.archiva.components.rest.util.RestUtil; +import org.apache.archiva.metadata.repository.MetadataRepositoryException; +import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager; +import org.apache.archiva.repository.RemoteRepository; +import org.apache.archiva.repository.RepositoryRegistry; +import org.apache.archiva.repository.scanner.RepositoryScanner; +import org.apache.archiva.repository.scanner.RepositoryScannerException; +import org.apache.archiva.rest.api.v2.model.Repository; +import org.apache.archiva.rest.api.v2.model.RepositoryStatistics; +import org.apache.archiva.rest.api.v2.model.ScanStatus; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; +import org.apache.archiva.rest.api.v2.svc.ErrorKeys; +import org.apache.archiva.rest.api.v2.svc.ErrorMessage; +import org.apache.archiva.rest.api.v2.svc.RepositoryService; +import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException; +import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.inject.Named; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * @author Martin Stockhammer + * @since 3.0 + */ +@Service( "v2.repositoryService#rest" ) +public class DefaultRepositoryService implements RepositoryService +{ + + final + RepositoryRegistry repositoryRegistry; + + final + RepositoryStatisticsManager repositoryStatisticsManager; + + private final RepositoryTaskAdministration repositoryTaskAdministration; + + private final RepositoryScanner repoScanner; + + private final DownloadRemoteIndexScheduler downloadRemoteIndexScheduler; + + private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryService.class ); + private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} ); + + static + { + QUERY_HELPER.addStringFilter( "id", org.apache.archiva.repository.Repository::getId ); + QUERY_HELPER.addStringFilter( "name", org.apache.archiva.repository.Repository::getName ); + QUERY_HELPER.addStringFilter( "description", org.apache.archiva.repository.Repository::getDescription ); + QUERY_HELPER.addStringFilter( "type", repo -> repo.getType( ).name( ) ); + QUERY_HELPER.addBooleanFilter( "scanned", org.apache.archiva.repository.Repository::isScanned ); + QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.repository.Repository::getId ); + QUERY_HELPER.addNullsafeFieldComparator( "name", org.apache.archiva.repository.Repository::getName ); + QUERY_HELPER.addNullsafeFieldComparator( "type", repo -> repo.getType( ).name( ) ); + QUERY_HELPER.addNullsafeFieldComparator( "boolean", org.apache.archiva.repository.Repository::isScanned ); + } + + public DefaultRepositoryService( RepositoryRegistry repositoryRegistry, RepositoryStatisticsManager repositoryStatisticsManager, + @Named( value = "repositoryTaskAdministration#default") RepositoryTaskAdministration repositoryTaskAdministration, + RepositoryScanner repoScanner, DownloadRemoteIndexScheduler downloadRemoteIndexScheduler ) + { + this.repositoryRegistry = repositoryRegistry; + this.repositoryStatisticsManager = repositoryStatisticsManager; + this.repoScanner = repoScanner; + this.repositoryTaskAdministration = repositoryTaskAdministration; + this.downloadRemoteIndexScheduler = downloadRemoteIndexScheduler; + } + + private void handleAdminException( RepositoryAdminException e ) throws ArchivaRestServiceException + { + log.error( "Repository admin error: {}", e.getMessage( ), e ); + if ( e.keyExists( ) ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PREFIX + e.getKey( ), e.getParameters( ) ) ); + } + else + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + } + + + @Override + public PagedResult getRepositories( String searchTerm, Integer offset, Integer limit, List orderBy, String order, + String localeString ) throws ArchivaRestServiceException + { + final Locale locale = StringUtils.isNotEmpty( localeString ) ? Locale.forLanguageTag( localeString ) : Locale.getDefault( ); + boolean isAscending = QUERY_HELPER.isAscending( order ); + Predicate filter = QUERY_HELPER.getQueryFilter( searchTerm ); + Comparator comparator = QUERY_HELPER.getComparator( orderBy, isAscending ); + try + { + int totalCount = Math.toIntExact( repositoryRegistry.getRepositories( ).stream( ).filter( filter ).count( ) ); + return new PagedResult<>( totalCount, offset, limit, repositoryRegistry.getRepositories( ).stream( ) + .filter( filter ).skip( offset ).limit( limit ).sorted( comparator ).map( repo -> Repository.of( repo, locale ) ) + .collect( Collectors.toList( ) ) ); + } + catch ( ArithmeticException e ) + { + log.error( "Invalid integer conversion for totalCount" ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) ); + } + } + + @Override + public RepositoryStatistics getManagedRepositoryStatistics( String repositoryId ) throws ArchivaRestServiceException + { + if ( repositoryRegistry.getManagedRepository( repositoryId ) == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_MANAGED_NOT_FOUND, repositoryId ), 404 ); + } + try + { + return RepositoryStatistics.of( repositoryStatisticsManager.getLastStatistics( repositoryId ) ); + } + catch ( MetadataRepositoryException e ) + { + log.error( "Metadata error: {} ", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_METADATA_ERROR, e.getMessage( ) ) ); + } + } + + @Override + public Response scheduleRepositoryScan( String repositoryId, boolean fullScan ) throws ArchivaRestServiceException + { + try + { + repositoryTaskAdministration.scheduleFullScan( repositoryId ); + return Response.ok( ).build( ); + } + catch ( RepositoryAdminException e ) + { + handleAdminException( e ); + return Response.serverError( ).build( ); + } + } + + @Override + public RepositoryStatistics scanRepositoryImmediately( String repositoryId ) throws ArchivaRestServiceException + { + long sinceWhen = RepositoryScanner.FRESH_SCAN; + try + { + return RepositoryStatistics.of( repoScanner.scan( repositoryRegistry.getManagedRepository( repositoryId ), sinceWhen ) ); + } + catch ( RepositoryScannerException e ) + { + log.error( e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_SCAN_FAILED, e.getMessage( ) ) ); + } + } + + @Override + public ScanStatus getScanStatus( String repositoryId ) throws ArchivaRestServiceException + { + try + { + return ScanStatus.of( repositoryTaskAdministration.getCurrentScanStatus( ) ); + } + catch ( RepositoryAdminException e ) + { + handleAdminException( e ); + return new ScanStatus(); + } + } + + @Override + public Response removeScanningTaskFromQueue( String repositoryId ) throws ArchivaRestServiceException + { + try + { + repositoryTaskAdministration.cancelTasks( repositoryId ); + return Response.ok( ).build( ); + } + catch ( RepositoryAdminException e ) + { + handleAdminException( e ); + return Response.serverError( ).build( ); + } + } + + + @Override + public Response scheduleDownloadRemoteIndex( String repositoryId, boolean immediately, boolean full, + UriInfo uriInfo ) throws ArchivaRestServiceException + { + boolean immediateSet = RestUtil.isFlagSet( uriInfo, "immediate" ); + boolean fullSet = RestUtil.isFlagSet( uriInfo, "full" ); + RemoteRepository repo = repositoryRegistry.getRemoteRepository( repositoryId ); + if (repo==null) { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_NOT_FOUND, repositoryId ), 404 ); + } + try + { + downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, immediateSet, fullSet ); + return Response.ok( ).build( ); + } + catch ( DownloadRemoteIndexException e ) + { + log.error( "Could not schedule index download for repository {}: {}", repositoryId, e.getMessage(), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED, e.getMessage( ) ) ); + } + } + + + + @Override + public List getRunningRemoteDownloads( ) + { + return downloadRemoteIndexScheduler.getRunningRemoteDownloadIds( ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultSecurityConfigurationService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultSecurityConfigurationService.java new file mode 100644 index 000000000..6e6a157a4 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/DefaultSecurityConfigurationService.java @@ -0,0 +1,677 @@ +package org.apache.archiva.rest.v2.svc;/* + * 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. + */ + +/* + * 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.archiva.admin.model.RepositoryAdminException; +import org.apache.archiva.admin.model.beans.RedbackRuntimeConfiguration; +import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.model.PropertyEntry; +import org.apache.archiva.components.rest.util.QueryHelper; +import org.apache.archiva.redback.authentication.Authenticator; +import org.apache.archiva.redback.common.ldap.connection.LdapConnection; +import org.apache.archiva.redback.common.ldap.connection.LdapConnectionConfiguration; +import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory; +import org.apache.archiva.redback.common.ldap.connection.LdapException; +import org.apache.archiva.redback.common.ldap.user.LdapUserMapper; +import org.apache.archiva.redback.policy.CookieSettings; +import org.apache.archiva.redback.policy.PasswordRule; +import org.apache.archiva.redback.rbac.RBACManager; +import org.apache.archiva.redback.role.RoleManager; +import org.apache.archiva.redback.users.UserManager; +import org.apache.archiva.rest.api.v2.model.BeanInformation; +import org.apache.archiva.rest.api.v2.model.CacheConfiguration; +import org.apache.archiva.rest.api.v2.model.LdapConfiguration; +import org.apache.archiva.rest.api.v2.model.SecurityConfiguration; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; +import org.apache.archiva.rest.api.v2.svc.ErrorKeys; +import org.apache.archiva.rest.api.v2.svc.ErrorMessage; +import org.apache.archiva.rest.api.v2.svc.SecurityConfigurationService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.inject.Named; +import javax.naming.AuthenticationException; +import javax.naming.AuthenticationNotSupportedException; +import javax.naming.CommunicationException; +import javax.naming.InvalidNameException; +import javax.naming.NamingException; +import javax.naming.NoPermissionException; +import javax.naming.ServiceUnavailableException; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static org.apache.archiva.rest.api.v2.svc.ErrorKeys.INVALID_RESULT_SET_ERROR; +import static org.apache.archiva.rest.api.v2.svc.ErrorKeys.REPOSITORY_ADMIN_ERROR; + +/** + * @author Martin Stockhammer + */ +@Service( "v2.defaultSecurityConfigurationService" ) +public class DefaultSecurityConfigurationService implements SecurityConfigurationService +{ + private static final Logger log = LoggerFactory.getLogger( DefaultSecurityConfigurationService.class ); + + private static final String[] KNOWN_LDAP_CONTEXT_PROVIDERS = {"com.sun.jndi.ldap.LdapCtxFactory","com.ibm.jndi.LDAPCtxFactory"}; + private final List availableContextProviders = new ArrayList<>( ); + + private static final QueryHelper PROP_QUERY_HELPER = new QueryHelper<>( new String[]{"key"} ); + + static + { + PROP_QUERY_HELPER.addStringFilter( "key", PropertyEntry::getKey ); + PROP_QUERY_HELPER.addStringFilter( "value", PropertyEntry::getValue ); + PROP_QUERY_HELPER.addNullsafeFieldComparator( "key", PropertyEntry::getKey ); + PROP_QUERY_HELPER.addNullsafeFieldComparator( "value", PropertyEntry::getValue ); + + } + + private ResourceBundle bundle; + + + @Inject + private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin; + + @Inject + private ApplicationContext applicationContext; + + @Inject + @Named( value = "userManager#default" ) + private UserManager userManager; + + @Inject + @Named( value = "rbacManager#default" ) + private RBACManager rbacManager; + + @Inject + private RoleManager roleManager; + + @Inject + @Named( value = "ldapConnectionFactory#configurable" ) + private LdapConnectionFactory ldapConnectionFactory; + + @Inject + private LdapUserMapper ldapUserMapper; + + + @PostConstruct + void init( ) + { + bundle = ResourceBundle.getBundle( "org.apache.archiva.rest.RestBundle" ); + for (String ldapClass : KNOWN_LDAP_CONTEXT_PROVIDERS) { + if (isContextFactoryAvailable( ldapClass )) { + availableContextProviders.add( ldapClass ); + } + } + } + + @Override + public SecurityConfiguration getConfiguration( ) throws ArchivaRestServiceException + { + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfiguration ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + } + + private void updateConfig( SecurityConfiguration newConfig, RedbackRuntimeConfiguration rbConfig ) + { + rbConfig.setUserManagerImpls( newConfig.getActiveUserManagers( ) ); + rbConfig.setRbacManagerImpls( newConfig.getActiveRbacManagers( ) ); + rbConfig.setUseUsersCache( newConfig.isUserCacheEnabled( ) ); + Map props = rbConfig.getConfigurationProperties( ); + for ( Map.Entry newProp : newConfig.getProperties( ).entrySet( ) ) + { + props.put( newProp.getKey( ), newProp.getValue( ) ); + } + } + + private void updateConfig( LdapConfiguration newConfig, RedbackRuntimeConfiguration rbConfig ) + { + org.apache.archiva.admin.model.beans.LdapConfiguration ldapConfig = rbConfig.getLdapConfiguration( ); + ldapConfig.setBaseDn( newConfig.getBaseDn( ) ); + ldapConfig.setAuthenticationMethod( newConfig.getAuthenticationMethod( ) ); + ldapConfig.setBindAuthenticatorEnabled( newConfig.isBindAuthenticatorEnabled( ) ); + ldapConfig.setBindDn( newConfig.getBindDn( ) ); + ldapConfig.setSsl( newConfig.isSslEnabled( ) ); + ldapConfig.setBaseGroupsDn( newConfig.getGroupsBaseDn( ) ); + ldapConfig.setHostName( newConfig.getHostName( ) ); + ldapConfig.setPort( newConfig.getPort( ) ); + ldapConfig.setPassword( newConfig.getBindPassword( ) ); + ldapConfig.setUseRoleNameAsGroup( newConfig.isUseRoleNameAsGroup( ) ); + ldapConfig.setWritable( newConfig.isWritable( ) ); + ldapConfig.setContextFactory( newConfig.getContextFactory( ) ); + + Map props = ldapConfig.getExtraProperties( ); + for ( Map.Entry newProp : newConfig.getProperties( ).entrySet( ) ) + { + props.put( newProp.getKey( ), newProp.getValue( ) ); + } + } + + private void updateConfig( CacheConfiguration newConfig, RedbackRuntimeConfiguration rbConfig ) + { + org.apache.archiva.admin.model.beans.CacheConfiguration cacheConfig = rbConfig.getUsersCacheConfiguration( ); + cacheConfig.setMaxElementsInMemory( newConfig.getMaxEntriesInMemory( ) ); + cacheConfig.setMaxElementsOnDisk( newConfig.getMaxEntriesOnDisk( ) ); + cacheConfig.setTimeToLiveSeconds( newConfig.getTimeToLiveSeconds( ) ); + cacheConfig.setTimeToIdleSeconds( newConfig.getTimeToIdleSeconds( ) ); + } + + @Override + public SecurityConfiguration updateConfiguration( SecurityConfiguration newConfiguration ) throws ArchivaRestServiceException + { + if ( newConfiguration == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 ); + } + try + { + RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + boolean userManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveUserManagers( ), conf.getUserManagerImpls( ) ); + boolean rbacManagerChanged = !CollectionUtils.isEqualCollection( newConfiguration.getActiveRbacManagers( ), conf.getRbacManagerImpls( ) ); + + boolean ldapConfigured = newConfiguration.getActiveUserManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) ); + if ( !ldapConfigured ) + { + ldapConfigured= newConfiguration.getActiveRbacManagers( ).stream( ).anyMatch( um -> um.contains( "ldap" ) ); + } + + updateConfig( newConfiguration, conf ); + redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf ); + + if ( userManagerChanged ) + { + log.info( "user managerImpls changed to {} so reload it", + newConfiguration.getActiveUserManagers( ) ); + userManager.initialize( ); + } + + if ( rbacManagerChanged ) + { + log.info( "rbac manager changed to {} so reload it", + newConfiguration.getActiveRbacManagers( ) ); + rbacManager.initialize( ); + roleManager.initialize( ); + } + + if ( ldapConfigured ) + { + try + { + ldapConnectionFactory.initialize( ); + } + catch ( Exception e ) + { + log.error( "Could not initialize LDAP connection factory: {}", e.getMessage( ) ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_CF_INIT_FAILED, e.getMessage( ) ) ); + } + } + Collection passwordRules = applicationContext.getBeansOfType( PasswordRule.class ).values( ); + + for ( PasswordRule passwordRule : passwordRules ) + { + passwordRule.initialize( ); + } + + Collection cookieSettingsList = + applicationContext.getBeansOfType( CookieSettings.class ).values( ); + + for ( CookieSettings cookieSettings : cookieSettingsList ) + { + cookieSettings.initialize( ); + } + + Collection authenticators = + applicationContext.getBeansOfType( Authenticator.class ).values( ); + + for ( Authenticator authenticator : authenticators ) + { + try + { + log.debug( "Initializing authenticatior " + authenticator.getId( ) ); + authenticator.initialize( ); + } + catch ( Exception e ) + { + log.error( "Initialization of authenticator failed " + authenticator.getId( ), e ); + } + } + + if ( ldapConfigured ) + { + try + { + ldapUserMapper.initialize( ); + } + catch ( Exception e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_USER_MAPPER_INIT_FAILED, e.getMessage( ) ) ); + } + } + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + try + { + return SecurityConfiguration.ofRedbackConfiguration( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ) ); + } + catch ( RepositoryAdminException e ) + { + log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) ); + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + } + + @Override + public PagedResult getConfigurationProperties( String searchTerm, Integer offset, Integer limit, List orderBy, String order ) throws ArchivaRestServiceException + { + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + boolean ascending = PROP_QUERY_HELPER.isAscending( order ); + Predicate filter = PROP_QUERY_HELPER.getQueryFilter( searchTerm ); + Comparator comparator = PROP_QUERY_HELPER.getComparator( orderBy, ascending ); + Map props = redbackRuntimeConfiguration.getConfigurationProperties( ); + int totalCount = Math.toIntExact( props.entrySet( ).stream( ).map( + entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) ) + ).filter( filter ).count( ) ); + List result = props.entrySet( ).stream( ).map( + entry -> new PropertyEntry( entry.getKey( ), entry.getValue( ) ) + ).filter( filter ) + .sorted( comparator ) + .skip( offset ).limit( limit ) + .collect( Collectors.toList( ) ); + return new PagedResult<>( totalCount, offset, limit, result ); + } catch (ArithmeticException e) { + log.error( "The total count of the result properties is higher than max integer value!" ); + throw new ArchivaRestServiceException( ErrorMessage.of( INVALID_RESULT_SET_ERROR ) ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + } + + @Override + public PropertyEntry getConfigurationProperty( String propertyName ) throws ArchivaRestServiceException + { + try + { + RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + if ( conf.getConfigurationProperties( ).containsKey( propertyName ) ) + { + String value = conf.getConfigurationProperties( ).get( propertyName ); + return new PropertyEntry( propertyName, value ); + } + else + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 ); + } + + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + + } + + @Override + public Response updateConfigurationProperty( String propertyName, PropertyEntry propertyValue ) throws ArchivaRestServiceException + { + if ( propertyValue == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 ); + } + try + { + RedbackRuntimeConfiguration conf = redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + if ( conf.getConfigurationProperties( ).containsKey( propertyName ) ) + { + conf.getConfigurationProperties( ).put( propertyName, propertyValue.getValue( ) ); + redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( conf ); + return Response.ok( ).build( ); + } + else + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PROPERTY_NOT_FOUND ), 404 ); + } + + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + } + + @Override + public LdapConfiguration getLdapConfiguration( ) throws ArchivaRestServiceException + { + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + LdapConfiguration ldapConfig = LdapConfiguration.of( redbackRuntimeConfiguration.getLdapConfiguration( ) ); + ldapConfig.setAvailableContextFactories( availableContextProviders ); + return ldapConfig; + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + + } + + @Override + public LdapConfiguration updateLdapConfiguration( LdapConfiguration configuration ) throws ArchivaRestServiceException + { + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + updateConfig( configuration, redbackRuntimeConfiguration ); + + redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration ); + ldapConnectionFactory.initialize( ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + + try + { + return LdapConfiguration.of( redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ).getLdapConfiguration() ); + } + catch ( RepositoryAdminException e ) + { + log.error( "Error while retrieve updated configuration: {}", e.getMessage( ) ); + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + } + + } + + static Properties toProperties( Map values ) + { + Properties result = new Properties( ); + for ( Map.Entry entry : values.entrySet( ) ) + { + result.setProperty( entry.getKey( ), entry.getValue( ) ); + } + return result; + } + + private static boolean isContextFactoryAvailable( final String factoryClass) + { + try + { + return Thread.currentThread().getContextClassLoader().loadClass( factoryClass ) + != null; + } + catch ( ClassNotFoundException e ) + { + return false; + } + } + + + @Override + public Response verifyLdapConfiguration( LdapConfiguration ldapConfiguration ) throws ArchivaRestServiceException + { + LdapConnection ldapConnection = null; + try + { + LdapConnectionConfiguration ldapConnectionConfiguration = + new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ), + ldapConfiguration.getBaseDn( ), ldapConfiguration.getContextFactory( ), + ldapConfiguration.getBindDn( ), ldapConfiguration.getBindPassword( ), + ldapConfiguration.getAuthenticationMethod( ), + toProperties( ldapConfiguration.getProperties( ) ) ); + ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) ); + + ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration ); + } + catch ( InvalidNameException e ) + { + log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 ); + } + catch ( LdapException e ) + { + handleLdapException( e ); + } + finally + { + if ( ldapConnection != null ) + { + try + { + ldapConnection.close( ); + } + catch ( NamingException e ) + { + log.error( "Could not close connection: {}", e.getMessage( ) ); + } + } + ldapConnection = null; + } + + try + { + // verify groups dn value too + + LdapConnectionConfiguration ldapConnectionConfiguration = new LdapConnectionConfiguration( ldapConfiguration.getHostName( ), ldapConfiguration.getPort( ), + ldapConfiguration.getGroupsBaseDn( ), + ldapConfiguration.getContextFactory( ), ldapConfiguration.getBindDn( ), + ldapConfiguration.getBindPassword( ), + ldapConfiguration.getAuthenticationMethod( ), + toProperties( ldapConfiguration.getProperties( ) ) ); + + ldapConnectionConfiguration.setSsl( ldapConfiguration.isSslEnabled( ) ); + + ldapConnection = ldapConnectionFactory.getConnection( ldapConnectionConfiguration ); + } + catch ( InvalidNameException e ) + { + log.warn( "LDAP connection check failed with invalid name : {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_INVALID_NAME, e.getMessage( ) ), 400 ); + } + catch ( LdapException e ) + { + handleLdapException( e ); + } + finally + { + if ( ldapConnection != null ) + { + try + { + ldapConnection.close( ); + } + catch ( NamingException e ) + { + log.error( "Could not close connection: {}", e.getMessage( ), e ); + } + } + } + + return Response.ok( ).build( ); + } + + private void handleLdapException( LdapException e ) throws ArchivaRestServiceException + { + Throwable rootCause = e.getRootCause( ); + if ( rootCause instanceof CommunicationException ) + { + log.warn( "LDAP connection check failed with CommunicationException: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_COMMUNICATION_ERROR, e.getMessage( ) ), 400 ); + } else if (rootCause instanceof ServiceUnavailableException ) { + log.warn( "LDAP connection check failed with ServiceUnavailableException: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_UNAVAILABLE, e.getMessage( ) ), 400 ); + } else if (rootCause instanceof AuthenticationException ) { + log.warn( "LDAP connection check failed with AuthenticationException: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_FAILED, e.getMessage( ) ), 400 ); + } else if (rootCause instanceof AuthenticationNotSupportedException ) { + log.warn( "LDAP connection check failed with AuthenticationNotSupportedException: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_AUTHENTICATION_NOT_SUPPORTED, e.getMessage( ) ), 400 ); + } else if (rootCause instanceof NoPermissionException ) { + log.warn( "LDAP connection check failed with NoPermissionException: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_SERVICE_NO_PERMISSION, e.getMessage( ) ), 400 ); + } + log.warn( "LDAP connection check failed: {} - {}", e.getClass().getName(), e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.LDAP_GENERIC_ERROR, e.getMessage( ) ), 400 ); + } + + @Override + public CacheConfiguration getCacheConfiguration( ) throws ArchivaRestServiceException + { + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + + return CacheConfiguration.of( redbackRuntimeConfiguration.getUsersCacheConfiguration( ) ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + + } + + @Override + public CacheConfiguration updateCacheConfiguration( CacheConfiguration cacheConfiguration ) throws ArchivaRestServiceException + { + if ( cacheConfiguration == null ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.MISSING_DATA ), 400 ); + } + try + { + RedbackRuntimeConfiguration redbackRuntimeConfiguration = + redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration( ); + + log.debug( "getRedbackRuntimeConfiguration -> {}", redbackRuntimeConfiguration ); + updateConfig( cacheConfiguration, redbackRuntimeConfiguration ); + redbackRuntimeConfigurationAdmin.updateRedbackRuntimeConfiguration( redbackRuntimeConfiguration ); + return getCacheConfiguration( ); + } + catch ( RepositoryAdminException e ) + { + throw new ArchivaRestServiceException( ErrorMessage.of( REPOSITORY_ADMIN_ERROR ) ); + } + } + + @Override + public List getAvailableUserManagers( ) + { + Map beans = applicationContext.getBeansOfType( UserManager.class ); + + if ( beans.isEmpty( ) ) + { + return Collections.emptyList( ); + } + + return beans.entrySet( ).stream( ) + .filter( entry -> entry.getValue( ).isFinalImplementation( ) ) + .map( ( Map.Entry entry ) -> { + UserManager um = entry.getValue( ); + String id = StringUtils.substringAfter( entry.getKey( ), "#" ); + String displayName = bundle.getString( "user_manager." + id + ".display_name" ); + String description = bundle.getString( "user_manager." + id + ".description" ); + return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, um.getDescriptionKey( ), description, um.isReadOnly( ) ); + } ).collect( Collectors.toList( ) ); + } + + @Override + public List getAvailableRbacManagers( ) + { + Map beans = applicationContext.getBeansOfType( RBACManager.class ); + + if ( beans.isEmpty( ) ) + { + return Collections.emptyList( ); + } + + return beans.entrySet( ).stream( ) + .filter( entry -> entry.getValue( ).isFinalImplementation( ) ) + .map( ( Map.Entry entry ) -> { + RBACManager rm = entry.getValue( ); + String id = StringUtils.substringAfter( entry.getKey( ), "#" ); + String displayName = bundle.getString( "rbac_manager." + id + ".display_name" ); + String description = bundle.getString( "rbac_manager." + id + ".description" ); + return new BeanInformation( StringUtils.substringAfter( entry.getKey( ), "#" ), displayName, rm.getDescriptionKey( ), description, rm.isReadOnly( ) ); + } ).collect( Collectors.toList( ) ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml index 46dbc499a..6f5f1fc1f 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml @@ -34,7 +34,7 @@ + base-package="org.apache.archiva.rest.services,org.apache.archiva.redback.rest.services,org.apache.archiva.rest.v2"/> diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java deleted file mode 100644 index 9a9b7e829..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/AbstractNativeRestServices.java +++ /dev/null @@ -1,512 +0,0 @@ -package org.apache.archiva.rest.services.v2; - -/* - * 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.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import io.restassured.RestAssured; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.config.ObjectMapperConfig; -import io.restassured.config.RestAssuredConfig; -import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; -import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants; -import org.apache.archiva.redback.rest.services.BaseSetup; -import org.apache.archiva.redback.role.RoleManager; -import org.apache.archiva.redback.role.RoleManagerException; -import org.apache.archiva.redback.users.User; -import org.apache.archiva.redback.users.UserManager; -import org.apache.archiva.redback.users.UserManagerException; -import org.apache.archiva.redback.users.UserNotFoundException; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.SystemUtils; -import org.apache.cxf.transport.servlet.CXFServlet; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.junit.jupiter.api.Tag; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.context.ContextLoaderListener; - -import java.lang.reflect.Type; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.LocalTime; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static io.restassured.RestAssured.*; -import static io.restassured.http.ContentType.JSON; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** - * Native REST tests do not use the JAX-RS client and can be used with a remote - * REST API service. The tests - * - * @author Martin Stockhammer - */ -@Tag( "rest-native" ) -@Tag( "rest-v2" ) -public abstract class AbstractNativeRestServices -{ - private AtomicReference projectDir = new AtomicReference<>(); - private AtomicReference appServerBase = new AtomicReference<>( ); - private AtomicReference basePath = new AtomicReference<>( ); - - public static final int STOPPED = 0; - public static final int STOPPING = 1; - public static final int STARTING = 2; - public static final int STARTED = 3; - public static final int ERROR = 4; - private final boolean startServer; - private final String serverPort; - private final String baseUri; - - private RequestSpecification requestSpec; - protected Logger log = LoggerFactory.getLogger( getClass( ) ); - - private static AtomicReference server = new AtomicReference<>( ); - private static AtomicReference serverConnector = new AtomicReference<>( ); - private static AtomicInteger serverStarted = new AtomicInteger( STOPPED ); - private UserManager userManager; - private RoleManager roleManager; - - private final boolean remoteService; - - private String adminToken; - private String adminRefreshToken; - - - public AbstractNativeRestServices( ) - { - this.startServer = BaseSetup.startServer( ); - this.serverPort = BaseSetup.getServerPort( ); - this.baseUri = BaseSetup.getBaseUri( ); - - if ( startServer ) - { - this.remoteService = false; - } else { - this.remoteService = true; - } - } - - protected abstract String getServicePath( ); - - protected String getSpringConfigLocation( ) - { - return "classpath*:META-INF/spring-context.xml,classpath:META-INF/spring-context-native-test.xml"; - } - - protected RequestSpecification getRequestSpec( ) - { - return this.requestSpec; - } - - protected String getContextRoot( ) - { - return "/api"; - } - - - protected String getServiceBasePath( ) - { - return "/v2/archiva"; - } - - protected String getRedbackServiceBasePath( ) - { - return "/v2/redback"; - } - - - protected String getBasePath( ) - { - return new StringBuilder( ) - .append( getContextRoot( ) ) - .append( getServiceBasePath( ) ) - .append( getServicePath( ) ).toString( ); - } - - /** - * Returns the server that was started, or null if not initialized before. - * - * @return - */ - public Server getServer( ) - { - return this.server.get( ); - } - - public int getServerPort( ) - { - ServerConnector connector = serverConnector.get( ); - if ( connector != null ) - { - return connector.getLocalPort( ); - } - else - { - return 0; - } - } - - /** - * Returns true, if the server does exist and is running. - * - * @return true, if server does exist and is running. - */ - public boolean isServerRunning( ) - { - return serverStarted.get( ) == STARTED && this.server.get( ) != null && this.server.get( ).isRunning( ); - } - - private UserManager getUserManager( ) - { - if ( this.userManager == null ) - { - UserManager userManager = ContextLoaderListener.getCurrentWebApplicationContext( ) - .getBean( "userManager#default", UserManager.class ); - assertNotNull( userManager ); - this.userManager = userManager; - } - return this.userManager; - } - - private RoleManager getRoleManager( ) - { - if ( this.roleManager == null ) - { - RoleManager roleManager = ContextLoaderListener.getCurrentWebApplicationContext( ) - .getBean( "roleManager", RoleManager.class ); - assertNotNull( roleManager ); - this.roleManager = roleManager; - } - return this.roleManager; - } - - protected String getAdminPwd( ) - { - return BaseSetup.getAdminPwd( ); - } - - protected String getAdminUser( ) - { - return RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME; - } - - private void setupAdminUser( ) throws UserManagerException, RoleManagerException - { - - UserManager um = getUserManager( ); - - User adminUser = null; - try - { - adminUser = um.findUser( getAdminUser( ) ); - } - catch ( UserNotFoundException e ) - { - // ignore - } - adminUser = um.createUser( getAdminUser( ), "Administrator", "admin@local.home" ); - adminUser.setUsername( getAdminUser( ) ); - adminUser.setPassword( getAdminPwd( ) ); - adminUser.setFullName( "the admin user" ); - adminUser.setEmail( "toto@toto.fr" ); - adminUser.setPermanent( true ); - adminUser.setValidated( true ); - adminUser.setLocked( false ); - adminUser.setPasswordChangeRequired( false ); - if ( adminUser == null ) - { - um.addUser( adminUser ); - } - else - { - um.updateUser( adminUser, false ); - } - getRoleManager( ).assignRole( "system-administrator", adminUser.getUsername( ) ); - } - - protected Path getProjectDirectory() { - if ( projectDir.get()==null) { - String propVal = System.getProperty("mvn.project.base.dir"); - Path newVal; - if (StringUtils.isEmpty(propVal)) { - newVal = Paths.get("").toAbsolutePath(); - } else { - newVal = Paths.get(propVal).toAbsolutePath(); - } - projectDir.compareAndSet(null, newVal); - } - return projectDir.get(); - } - - public Path getBasedir() - { - if (basePath.get()==null) { - String baseDir = System.getProperty( "basedir" ); - final Path baseDirPath; - if (StringUtils.isNotEmpty( baseDir )) { - baseDirPath = Paths.get( baseDir ); - } else { - baseDirPath = getProjectDirectory( ); - } - basePath.compareAndSet( null, baseDirPath ); - } - return basePath.get( ); - } - - Path getAppserverBase() { - if (appServerBase.get()==null) { - String basePath = System.getProperty( "appserver.base" ); - final Path appserverPath; - if (StringUtils.isNotEmpty( basePath )) { - appserverPath = Paths.get( basePath ).toAbsolutePath( ); - } else { - appserverPath = getBasedir( ).resolve( "target" ).resolve( "appserver-base-" + LocalTime.now( ).toSecondOfDay( ) ); - } - appServerBase.compareAndSet( null, appserverPath ); - } - return appServerBase.get(); - } - - private void removeAppsubFolder( Path appServerBase, String folder ) - throws Exception - { - Path directory = appServerBase.resolve( folder ); - if ( Files.exists(directory) ) - { - org.apache.archiva.common.utils.FileUtils.deleteDirectory( directory ); - } - } - - public void startServer( ) - throws Exception - { - if ( serverStarted.compareAndSet( STOPPED, STARTING ) ) - { - try - { - log.info( "Starting server" ); - Path appServerBase = getAppserverBase( ); - - removeAppsubFolder(appServerBase, "jcr"); - removeAppsubFolder(appServerBase, "conf"); - removeAppsubFolder(appServerBase, "data"); - - - Server myServer = new Server( ); - this.server.set( myServer ); - this.serverConnector.set( new ServerConnector( myServer, new HttpConnectionFactory( ) ) ); - myServer.addConnector( serverConnector.get( ) ); - - ServletHolder servletHolder = new ServletHolder( new CXFServlet( ) ); - ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS ); - context.setResourceBase( SystemUtils.JAVA_IO_TMPDIR ); - context.setSessionHandler( new SessionHandler( ) ); - context.addServlet( servletHolder, getContextRoot( ) + "/*" ); - context.setInitParameter( "contextConfigLocation", getSpringConfigLocation( ) ); - context.addEventListener( new ContextLoaderListener( ) ); - - getServer( ).setHandler( context ); - getServer( ).start( ); - - if ( log.isDebugEnabled( ) ) - { - log.debug( "Jetty dump: {}", getServer( ).dump( ) ); - } - - setupAdminUser( ); - log.info( "Started server on port {}", getServerPort( ) ); - serverStarted.set( STARTED ); - } - finally - { - // In case, if the last statement was not reached - serverStarted.compareAndSet( STARTING, ERROR ); - } - } - - } - - public void stopServer( ) - throws Exception - { - if ( this.serverStarted.compareAndSet( STARTED, STOPPING ) ) - { - try - { - final Server myServer = getServer( ); - if ( myServer != null ) - { - log.info( "Stopping server" ); - myServer.stop( ); - } - serverStarted.set( STOPPED ); - } - finally - { - serverStarted.compareAndSet( STOPPING, ERROR ); - } - } - else - { - log.error( "Server is not in STARTED state!" ); - } - } - - - protected void setupNative( ) throws Exception - { - if ( this.startServer ) - { - startServer( ); - } - - if ( StringUtils.isNotEmpty( serverPort ) ) - { - RestAssured.port = Integer.parseInt( serverPort ); - } - else - { - RestAssured.port = getServerPort( ); - } - if ( StringUtils.isNotEmpty( baseUri ) ) - { - RestAssured.baseURI = baseUri; - } - else - { - RestAssured.baseURI = "http://localhost"; - } - String basePath = getBasePath( ); - this.requestSpec = getRequestSpecBuilder( ).build( ); - RestAssured.basePath = basePath; - RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory( - ( cls, charset ) -> { - ObjectMapper om = new ObjectMapper().findAndRegisterModules(); - om.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - om.setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE ); - return om; - } - )); - } - - protected RequestSpecBuilder getRequestSpecBuilder( ) { - return getRequestSpecBuilder( null ); - } - - protected RequestSpecBuilder getRequestSpecBuilder( String basePath ) - { - String myBasePath = basePath == null ? getBasePath( ) : basePath; - return new RequestSpecBuilder( ).setBaseUri( baseURI ) - .setPort( port ) - .setBasePath( myBasePath ) - .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port ); - } - - protected RequestSpecBuilder getAuthRequestSpecBuilder( ) - { - return new RequestSpecBuilder( ).setBaseUri( baseURI ) - .setPort( port ) - .setBasePath( new StringBuilder( ) - .append( getContextRoot( ) ) - .append( getRedbackServiceBasePath() ).append("/auth").toString() ) - .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port ); - } - - protected RequestSpecification getRequestSpec( String bearerToken ) - { - return getRequestSpecBuilder( ).addHeader( "Authorization", "Bearer " + bearerToken ).build( ); - } - - protected RequestSpecification getRequestSpec( String bearerToken, String path) - { - return getRequestSpecBuilder( path ).addHeader( "Authorization", "Bearer " + bearerToken ).build( ); - } - - protected void shutdownNative( ) throws Exception - { - if (startServer) - { - stopServer( ); - } - } - - protected org.apache.archiva.redback.rest.api.model.User addRemoteUser(String userid, String password, String fullName, String mail) { - - return null; - } - - protected void initAdminToken() { - Map jsonAsMap = new HashMap<>(); - jsonAsMap.put( "grant_type", "authorization_code" ); - jsonAsMap.put("user_id", getAdminUser()); - jsonAsMap.put("password", getAdminPwd() ); - Response result = given( ).spec( getAuthRequestSpecBuilder().build() ) - .contentType( JSON ) - .body( jsonAsMap ) - .when( ).post( "/authenticate").then( ).statusCode( 200 ) - .extract( ).response( ); - this.adminToken = result.body( ).jsonPath( ).getString( "access_token" ); - this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" ); - } - - protected String getUserToken(String userId, String password) { - Map jsonAsMap = new HashMap<>(); - jsonAsMap.put( "grant_type", "authorization_code" ); - jsonAsMap.put("user_id", userId); - jsonAsMap.put("password", password ); - Response result = given( ).spec( getAuthRequestSpecBuilder().build() ) - .contentType( JSON ) - .body( jsonAsMap ) - .when( ).post( "/authenticate").then( ).statusCode( 200 ) - .extract( ).response( ); - return result.body( ).jsonPath( ).getString( "access_token" ); - } - protected String getAdminToken() { - if (this.adminToken == null) { - initAdminToken(); - } - return this.adminToken; - } - - - protected String getAdminRefreshToken() { - if (this.adminRefreshToken == null) { - initAdminToken(); - } - return this.adminRefreshToken; - } - - public boolean isRemoteService() { - return this.remoteService; - } -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java deleted file mode 100644 index f7d137f56..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeMavenManagedRepositoryServiceTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.apache.archiva.rest.services.v2; - -/* - * 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 io.restassured.path.json.JsonPath; -import io.restassured.response.Response; -import io.restassured.response.ResponseBody; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.model.PropertyEntry; -import org.apache.archiva.rest.api.model.v2.BeanInformation; -import org.apache.archiva.rest.api.model.v2.CacheConfiguration; -import org.apache.archiva.rest.api.model.v2.LdapConfiguration; -import org.apache.archiva.rest.api.model.v2.MavenManagedRepository; -import org.apache.archiva.rest.api.services.v2.RestConfiguration; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.TestMethodOrder; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Martin Stockhammer - */ -@TestInstance( TestInstance.Lifecycle.PER_CLASS ) -@Tag( "rest-native" ) -@TestMethodOrder( MethodOrderer.OrderAnnotation.class ) -@DisplayName( "Native REST tests for V2 ManagedRepositoryService" ) -public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestServices -{ - @Override - protected String getServicePath( ) - { - return "/repositories/maven/managed"; - } - - @BeforeAll - void setup( ) throws Exception - { - super.setupNative( ); - } - - @AfterAll - void destroy( ) throws Exception - { - super.shutdownNative( ); - } - - @Test - @Order( 1 ) - void testGetRepositories( ) - { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - JsonPath json = response.getBody( ).jsonPath( ); - assertEquals( 2, json.getInt( "pagination.total_count" ) ); - assertEquals( 0, json.getInt( "pagination.offset" ) ); - assertEquals( Integer.valueOf( RestConfiguration.DEFAULT_PAGE_LIMIT ), json.getInt( "pagination.limit" ) ); - List repositories = json.getList( "data", MavenManagedRepository.class ); - assertEquals( "internal", repositories.get( 0 ).getId( ) ); - assertEquals( "snapshots", repositories.get( 1 ).getId( ) ); - } - - - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java deleted file mode 100644 index 033a4a060..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryGroupServiceTest.java +++ /dev/null @@ -1,471 +0,0 @@ -package org.apache.archiva.rest.services.v2; - -/* - * 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 io.restassured.response.Response; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.rest.api.model.v2.RepositoryGroup; -import org.apache.archiva.rest.api.services.v2.ArchivaRestError; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.TestMethodOrder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static org.easymock.EasyMock.contains; -import static org.hamcrest.Matchers.endsWith; -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Martin Stockhammer - */ -@TestInstance( TestInstance.Lifecycle.PER_CLASS ) -@Tag( "rest-native" ) -@TestMethodOrder( MethodOrderer.Random.class ) -@DisplayName( "Native REST tests for V2 RepositoryGroupService" ) -public class NativeRepositoryGroupServiceTest extends AbstractNativeRestServices -{ - @Override - protected String getServicePath( ) - { - return "/repository_groups"; - } - - @BeforeAll - void setup( ) throws Exception - { - super.setupNative( ); - } - - @AfterAll - void destroy( ) throws Exception - { - super.shutdownNative( ); - } - - @Test - void testGetEmptyList( ) - { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 0, result.getPagination( ).getTotalCount( ) ); - - } - - @Test - void testAddGroup( ) - { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", "group_001" ); - jsonAsMap.put( "name", "group_001" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); - } finally - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ) - .then( ).statusCode( 200 ); - } - } - - @Test - void testAddExistingGroup( ) - { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", "group_001" ); - jsonAsMap.put( "name", "group_001" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .prettyPeek() - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .redirects().follow( false ) - .body( jsonAsMap ) - .post( "" ) - .prettyPeek() - .then( ).statusCode( 303 ) - .assertThat() - .header( "Location", endsWith("group_001") ).extract( ).response( ); - } finally - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ); - } - } - - - @Test - void testAddMultipleGroups( ) - { - String token = getAdminToken( ); - List groups = new ArrayList<>( ); - try - { - for ( int i=0; i<10; i++) - { - String groupName = String.format( "group_%03d", i ); - groups.add( groupName ); - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", groupName ); - jsonAsMap.put( "name", groupName ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - } - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 10, resultList.getPagination( ).getTotalCount( ) ); - } finally - { - for (String groupName : groups) - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( groupName ); - } - } - } - - @Test - void testRemoveRepositoryGroup( ) - { - String token = getAdminToken( ); - List groups = new ArrayList<>( ); - try - { - for ( int i=0; i<10; i++) - { - String groupName = String.format( "group_%03d", i ); - groups.add( groupName ); - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", groupName ); - jsonAsMap.put( "name", groupName ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - } - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 9, resultList.getPagination( ).getTotalCount( ) ); - - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_005" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 8, resultList.getPagination( ).getTotalCount( ) ); - - } finally - { - for (String groupName : groups) - { - if (!("group_001".equals(groupName) || "group_005".equals(groupName) ) ) - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( groupName ); - } - } - } - } - - - @Test - void testAddRepositoryToGroup( ) - { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", "group_001" ); - jsonAsMap.put( "name", "group_001" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .prettyPeek() - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .put( "group_001/repositories/internal" ) - .prettyPeek() - .then( ).statusCode( 200 ).extract( ).response( ); - - assertNotNull( response ); - result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - assertEquals( 1, result.getRepositories( ).size( ) ); - assertTrue( result.getRepositories( ).contains( "internal" ) ); - - } finally - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ); - } - } - - @Test - void testAddRepositoryToGroupIdempotency( ) - { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", "group_001" ); - jsonAsMap.put( "name", "group_001" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .prettyPeek() - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .put( "group_001/repositories/internal" ) - .prettyPeek() - .then( ).statusCode( 200 ).extract( ).response( ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .put( "group_001/repositories/internal" ) - .prettyPeek() - .then( ).statusCode( 200 ).extract( ).response( ); - - assertNotNull( response ); - result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - assertEquals( 1, result.getRepositories( ).size( ) ); - assertTrue( result.getRepositories( ).contains( "internal" ) ); - - } finally - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ) - .then( ).statusCode( 200 ); - } - } - - - @Test - void testRemoveRepositoryFromGroup( ) - { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", "group_001" ); - jsonAsMap.put( "name", "group_001" ); - jsonAsMap.put( "repositories", Arrays.asList( "internal" ) ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .prettyPeek() - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); - - assertNotNull( result.getRepositories( ) ); - assertEquals( 1, result.getRepositories( ).size( ) ); - assertTrue( result.getRepositories( ).contains( "internal" ) ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .delete( "group_001/repositories/internal" ) - .prettyPeek() - .then( ).statusCode( 200 ).extract( ).response( ); - - assertNotNull( response ); - result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - assertEquals( 0, result.getRepositories( ).size( ) ); - - } finally - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ) - .then( ).statusCode( 200 ); - } - } - - @Test - void testRemoveRepositoryFromGroup404( ) - { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "id", "group_001" ); - jsonAsMap.put( "name", "group_001" ); - jsonAsMap.put( "repositories", Arrays.asList( "internal" ) ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .post( "" ) - .prettyPeek() - .then( ).statusCode( 201 ).extract( ).response( ); - assertNotNull( response ); - RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); - assertNotNull( result ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); - - assertNotNull( result.getRepositories( ) ); - assertEquals( 1, result.getRepositories( ).size( ) ); - assertTrue( result.getRepositories( ).contains( "internal" ) ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .delete( "group_001/repositories/internalxx" ) - .prettyPeek() - .then( ).statusCode( 404 ).extract( ).response( ); - - assertNotNull( response ); - ArchivaRestError error = response.getBody( ).jsonPath( ).getObject( "", ArchivaRestError.class ); - assertNotNull( error ); - } finally - { - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .delete( "group_001" ); - } - } - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java deleted file mode 100644 index 1976fa1f0..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java +++ /dev/null @@ -1,185 +0,0 @@ -package org.apache.archiva.rest.services.v2; - -/* - * 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 io.restassured.response.Response; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.rest.api.model.v2.Repository; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.TestMethodOrder; - -import java.util.List; - -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Martin Stockhammer - */ -@TestInstance( TestInstance.Lifecycle.PER_CLASS ) -@Tag( "rest-native" ) -@TestMethodOrder( MethodOrderer.Random.class ) -@DisplayName( "Native REST tests for V2 RepositoryService" ) -public class NativeRepositoryServiceTest extends AbstractNativeRestServices -{ - @Override - protected String getServicePath( ) - { - return "/repositories"; - } - - @BeforeAll - void setup( ) throws Exception - { - super.setupNative( ); - } - - @AfterAll - void destroy( ) throws Exception - { - super.shutdownNative( ); - } - - @Test - void testGetRepositories() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult repositoryPagedResult = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 3, repositoryPagedResult.getPagination( ).getTotalCount( ) ); - List data = response.getBody( ).jsonPath( ).getList( "data", Repository.class ); - assertTrue( data.stream( ).anyMatch( p -> "central".equals( p.getId( ) ) ) ); - assertTrue( data.stream( ).anyMatch( p -> "internal".equals( p.getId( ) ) ) ); - assertTrue( data.stream( ).anyMatch( p -> "snapshots".equals( p.getId( ) ) ) ); - Repository snapshotRepo = data.stream( ).filter( p -> "snapshots".equals( p.getId( ) ) ).findFirst( ).get( ); - assertEquals( "Archiva Managed Snapshot Repository", snapshotRepo.getName( ) ); - assertEquals( "MAVEN", snapshotRepo.getType() ); - assertEquals( "managed", snapshotRepo.getCharacteristic() ); - assertEquals( "default", snapshotRepo.getLayout() ); - assertTrue( snapshotRepo.isScanned( ) ); - assertTrue( snapshotRepo.isIndex( ) ); - - Repository centralRepo = data.stream( ).filter( p -> "central".equals( p.getId( ) ) ).findFirst( ).get( ); - assertEquals( "Central Repository", centralRepo.getName( ) ); - assertEquals( "MAVEN", centralRepo.getType() ); - assertEquals( "remote", centralRepo.getCharacteristic() ); - assertEquals( "default", centralRepo.getLayout() ); - - - } - - @Test - void testGetFilteredRepositories() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .queryParam( "q", "central" ) - .get( "" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult repositoryPagedResult = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 1, repositoryPagedResult.getPagination( ).getTotalCount( ) ); - List data = response.getBody( ).jsonPath( ).getList( "data", Repository.class ); - assertTrue( data.stream( ).anyMatch( p -> "central".equals( p.getId( ) ) ) ); - } - - - @Test - void getStatistics() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "managed/internal/statistics" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - } - - @Test - void scheduleScan() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .post( "managed/internal/scan/schedule" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - } - - @Test - void immediateScan() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .post( "managed/internal/scan/now" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - } - - @Test - void scanStatus() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "managed/internal/scan/status" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - } - - @Test - void scheduleIndexDownload() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .post( "remote/central/index/download/start" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - } - - @Test - void getIndexDownloadList() { - String token = getAdminToken( ); - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .queryParam( "immediate", "true" ) - .post( "remote/central/index/download/start" ) - .then( ).statusCode( 200 ).extract( ).response( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "remote/index/downloads" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - List downloads = response.getBody( ).jsonPath( ).getList( "", String.class ); - assertEquals( 1, downloads.size() ); - assertEquals( "central", downloads.get( 0 ) ); - } - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java deleted file mode 100644 index 13b0a3e5b..000000000 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeSecurityConfigurationServiceTest.java +++ /dev/null @@ -1,351 +0,0 @@ -package org.apache.archiva.rest.services.v2; - -/* - * 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 io.restassured.response.Response; -import org.apache.archiva.components.rest.model.PagedResult; -import org.apache.archiva.components.rest.model.PropertyEntry; -import org.apache.archiva.rest.api.model.v2.BeanInformation; -import org.apache.archiva.rest.api.model.v2.CacheConfiguration; -import org.apache.archiva.rest.api.model.v2.LdapConfiguration; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Martin Stockhammer - */ -@TestInstance( TestInstance.Lifecycle.PER_CLASS ) -@Tag( "rest-native" ) -@TestMethodOrder( MethodOrderer.Random.class ) -@DisplayName( "Native REST tests for V2 SecurityConfigurationService" ) -public class NativeSecurityConfigurationServiceTest extends AbstractNativeRestServices -{ - @Override - protected String getServicePath( ) - { - return "/security"; - } - - @BeforeAll - void setup( ) throws Exception - { - super.setupNative( ); - } - - @AfterAll - void destroy( ) throws Exception - { - super.shutdownNative( ); - } - - @Test - void testGetConfiguration() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_user_managers[0]" ) ); - assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_rbac_managers[0]" ) ); - assertEquals( "memory", response.getBody( ).jsonPath( ).getString( "properties.\"authentication.jwt.keystoreType\"" ) ); - assertEquals("10",response.getBody( ).jsonPath( ).getString( "properties.\"security.policy.allowed.login.attempt\"")); - assertTrue( response.getBody( ).jsonPath( ).getBoolean( "user_cache_enabled" ) ); - assertFalse( response.getBody( ).jsonPath( ).getBoolean( "ldap_active" ) ); - } - - @Test - void testGetConfigurationProperties() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/properties" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - PagedResult result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - List propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class ); - assertEquals( 10, result.getPagination( ).getLimit( ) ); - assertEquals( 0, result.getPagination( ).getOffset( ) ); - assertEquals( 47, result.getPagination( ).getTotalCount( ) ); - assertEquals( "authentication.jwt.keystoreType", propList.get( 0 ).getKey() ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .queryParam( "offset", "3" ) - .queryParam( "limit", "5" ) - .get( "config/properties" ) - .then( ).statusCode( 200 ).extract( ).response( ); - - assertNotNull( response ); - result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); - assertEquals( 5, result.getPagination( ).getLimit( ) ); - assertEquals( 47, result.getPagination( ).getTotalCount( ) ); - propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class ); - assertEquals( "authentication.jwt.refreshLifetimeMs", propList.get( 0 ).getKey() ); - } - - @Test - void testGetLdapConfiguration() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/ldap" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - assertEquals( "", response.getBody( ).jsonPath( ).get( "host_name" ) ); - assertEquals( 0, response.getBody( ).jsonPath( ).getMap( "properties" ).size( ) ); - } - - - @Test - void testUpdateLdapConfiguration() { - String token = getAdminToken( ); - try - { - Map jsonMap = new HashMap<>( ); - jsonMap.put( "host_name", "localhost" ); - jsonMap.put( "port", 389 ); - jsonMap.put( "ssl_enabled", false ); - jsonMap.put( "writable", true ); - jsonMap.put( "base_dn", "dc=apache,dc=org" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonMap ) - .put( "config/ldap" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/ldap" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - LdapConfiguration config = response.getBody( ).jsonPath( ).getObject( "", LdapConfiguration.class ); - assertEquals( "localhost", config.getHostName( ) ); - assertEquals( 389, config.getPort( ) ); - assertFalse( config.isSslEnabled( ) ); - assertTrue( config.isWritable( ) ); - assertEquals( "dc=apache,dc=org", config.getBaseDn( ) ); - } finally - { - Map jsonMap = new HashMap<>( ); - jsonMap.put( "host_name", "" ); - jsonMap.put( "port", -1 ); - jsonMap.put( "ssl_enabled", false ); - jsonMap.put( "base_dn", "" ); - jsonMap.put( "writable", false ); - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonMap ) - .put( "config/ldap" ) - .then( ).statusCode( 200 ); - - } - } - - - @Test - void testGetCacheConfiguration() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/cache" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - } - - @Test - void testUpdateCacheConfiguration() { - String token = getAdminToken( ); - - try - { - Map jsonMap = new HashMap<>( ); - jsonMap.put( "time_to_idle_seconds", 1600 ); - jsonMap.put( "time_to_live_seconds", 12000 ); - jsonMap.put( "max_entries_in_memory", 500 ); - jsonMap.put( "max_entries_on_disk", 400 ); - - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonMap ) - .put( "config/cache" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/cache" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - CacheConfiguration config = response.getBody( ).jsonPath( ).getObject( "", CacheConfiguration.class ); - assertEquals( 1600, config.getTimeToIdleSeconds( ) ); - assertEquals( 12000, config.getTimeToLiveSeconds( ) ); - assertEquals( 500, config.getMaxEntriesInMemory( ) ); - assertEquals( 400, config.getMaxEntriesOnDisk( ) ); - } finally - { - Map jsonMap = new HashMap<>( ); - jsonMap.put( "time_to_idle_seconds", 1800 ); - jsonMap.put( "time_to_live_seconds", 14400 ); - jsonMap.put( "max_entries_in_memory", 1000 ); - jsonMap.put( "max_entries_on_disk", 0 ); - - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonMap ) - .put( "config/cache" ) - .then( ).statusCode( 200 ); - - } - } - - - @Test - void testGetUserManagers() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "user_managers" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - List usrList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class ); - assertEquals( 2, usrList.size( ) ); - assertTrue( usrList.stream( ).anyMatch( bi -> "LDAP User Manager".equals( bi.getDisplayName( ) ) ) ); - assertTrue( usrList.stream( ).anyMatch( bi -> "Database User Manager".equals( bi.getDisplayName( ) ) ) ); - } - - @Test - void testGetRbacManagers() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "rbac_managers" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - List rbacList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class ); - assertEquals( 2, rbacList.size( ) ); - assertTrue( rbacList.stream( ).anyMatch( bi -> "Database RBAC Manager".equals( bi.getDisplayName( ) ) ) ); - assertTrue( rbacList.stream( ).anyMatch( bi -> "LDAP RBAC Manager".equals( bi.getDisplayName( ) ) ) ); - } - - @Test - void testUpdateConfiguration() { - String token = getAdminToken( ); - try - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa", "ldap" ) ); - jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) ); - jsonAsMap.put( "user_cache_enabled", false ); - jsonAsMap.put( "ldap_active", false ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .put( "config" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - assertEquals( 2, response.getBody( ).jsonPath( ).getList( "active_user_managers" ).size( ) ); - } finally - { - Map jsonAsMap = new HashMap<>( ); - jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa" ) ); - jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) ); - jsonAsMap.put( "user_cache_enabled", true ); - jsonAsMap.put( "ldap_active", false ); - given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonAsMap ) - .put( "config" ) - .then( ).statusCode( 200 ); - - } - - } - - @Test - void testGetConfigProperty() { - String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/properties/rest.csrffilter.absentorigin.deny" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - assertEquals( "true", response.getBody( ).jsonPath( ).getString( "value" ) ); - } - - @Test - void testUpdateConfigProperty() { - String token = getAdminToken( ); - - try - { - Map jsonMap = new HashMap<>( ); - jsonMap.put( "value", "false" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonMap ) - .put( "config/properties/rest.csrffilter.absentorigin.deny" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - - - response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .get( "config/properties/rest.csrffilter.absentorigin.deny" ) - .then( ).statusCode( 200 ).extract( ).response( ); - assertNotNull( response ); - assertEquals( "false", response.getBody( ).jsonPath( ).getString( "value" ) ); - } finally - { - Map jsonMap = new HashMap<>( ); - jsonMap.put( "value", "true" ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) - .when( ) - .body( jsonMap ) - .put( "config/properties/rest.csrffilter.absentorigin.deny" ) - .then( ).statusCode( 200 ).extract( ).response( ); - } - } - - -} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/AbstractNativeRestServices.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/AbstractNativeRestServices.java new file mode 100644 index 000000000..4949e55a7 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/AbstractNativeRestServices.java @@ -0,0 +1,512 @@ +package org.apache.archiva.rest.v2.svc; + +/* + * 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.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.config.RestAssuredConfig; +import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory; +import io.restassured.response.Response; +import io.restassured.specification.RequestSpecification; +import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants; +import org.apache.archiva.redback.rest.services.BaseSetup; +import org.apache.archiva.redback.role.RoleManager; +import org.apache.archiva.redback.role.RoleManagerException; +import org.apache.archiva.redback.users.User; +import org.apache.archiva.redback.users.UserManager; +import org.apache.archiva.redback.users.UserManagerException; +import org.apache.archiva.redback.users.UserNotFoundException; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemUtils; +import org.apache.cxf.transport.servlet.CXFServlet; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.junit.jupiter.api.Tag; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.ContextLoaderListener; + +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static io.restassured.RestAssured.*; +import static io.restassured.http.ContentType.JSON; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * Native REST tests do not use the JAX-RS client and can be used with a remote + * REST API service. The tests + * + * @author Martin Stockhammer + */ +@Tag( "rest-native" ) +@Tag( "rest-v2" ) +public abstract class AbstractNativeRestServices +{ + private AtomicReference projectDir = new AtomicReference<>(); + private AtomicReference appServerBase = new AtomicReference<>( ); + private AtomicReference basePath = new AtomicReference<>( ); + + public static final int STOPPED = 0; + public static final int STOPPING = 1; + public static final int STARTING = 2; + public static final int STARTED = 3; + public static final int ERROR = 4; + private final boolean startServer; + private final String serverPort; + private final String baseUri; + + private RequestSpecification requestSpec; + protected Logger log = LoggerFactory.getLogger( getClass( ) ); + + private static AtomicReference server = new AtomicReference<>( ); + private static AtomicReference serverConnector = new AtomicReference<>( ); + private static AtomicInteger serverStarted = new AtomicInteger( STOPPED ); + private UserManager userManager; + private RoleManager roleManager; + + private final boolean remoteService; + + private String adminToken; + private String adminRefreshToken; + + + public AbstractNativeRestServices( ) + { + this.startServer = BaseSetup.startServer( ); + this.serverPort = BaseSetup.getServerPort( ); + this.baseUri = BaseSetup.getBaseUri( ); + + if ( startServer ) + { + this.remoteService = false; + } else { + this.remoteService = true; + } + } + + protected abstract String getServicePath( ); + + protected String getSpringConfigLocation( ) + { + return "classpath*:META-INF/spring-context.xml,classpath:META-INF/spring-context-native-test.xml"; + } + + protected RequestSpecification getRequestSpec( ) + { + return this.requestSpec; + } + + protected String getContextRoot( ) + { + return "/api"; + } + + + protected String getServiceBasePath( ) + { + return "/v2/archiva"; + } + + protected String getRedbackServiceBasePath( ) + { + return "/v2/redback"; + } + + + protected String getBasePath( ) + { + return new StringBuilder( ) + .append( getContextRoot( ) ) + .append( getServiceBasePath( ) ) + .append( getServicePath( ) ).toString( ); + } + + /** + * Returns the server that was started, or null if not initialized before. + * + * @return + */ + public Server getServer( ) + { + return this.server.get( ); + } + + public int getServerPort( ) + { + ServerConnector connector = serverConnector.get( ); + if ( connector != null ) + { + return connector.getLocalPort( ); + } + else + { + return 0; + } + } + + /** + * Returns true, if the server does exist and is running. + * + * @return true, if server does exist and is running. + */ + public boolean isServerRunning( ) + { + return serverStarted.get( ) == STARTED && this.server.get( ) != null && this.server.get( ).isRunning( ); + } + + private UserManager getUserManager( ) + { + if ( this.userManager == null ) + { + UserManager userManager = ContextLoaderListener.getCurrentWebApplicationContext( ) + .getBean( "userManager#default", UserManager.class ); + assertNotNull( userManager ); + this.userManager = userManager; + } + return this.userManager; + } + + private RoleManager getRoleManager( ) + { + if ( this.roleManager == null ) + { + RoleManager roleManager = ContextLoaderListener.getCurrentWebApplicationContext( ) + .getBean( "roleManager", RoleManager.class ); + assertNotNull( roleManager ); + this.roleManager = roleManager; + } + return this.roleManager; + } + + protected String getAdminPwd( ) + { + return BaseSetup.getAdminPwd( ); + } + + protected String getAdminUser( ) + { + return RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME; + } + + private void setupAdminUser( ) throws UserManagerException, RoleManagerException + { + + UserManager um = getUserManager( ); + + User adminUser = null; + try + { + adminUser = um.findUser( getAdminUser( ) ); + } + catch ( UserNotFoundException e ) + { + // ignore + } + adminUser = um.createUser( getAdminUser( ), "Administrator", "admin@local.home" ); + adminUser.setUsername( getAdminUser( ) ); + adminUser.setPassword( getAdminPwd( ) ); + adminUser.setFullName( "the admin user" ); + adminUser.setEmail( "toto@toto.fr" ); + adminUser.setPermanent( true ); + adminUser.setValidated( true ); + adminUser.setLocked( false ); + adminUser.setPasswordChangeRequired( false ); + if ( adminUser == null ) + { + um.addUser( adminUser ); + } + else + { + um.updateUser( adminUser, false ); + } + getRoleManager( ).assignRole( "system-administrator", adminUser.getUsername( ) ); + } + + protected Path getProjectDirectory() { + if ( projectDir.get()==null) { + String propVal = System.getProperty("mvn.project.base.dir"); + Path newVal; + if (StringUtils.isEmpty(propVal)) { + newVal = Paths.get("").toAbsolutePath(); + } else { + newVal = Paths.get(propVal).toAbsolutePath(); + } + projectDir.compareAndSet(null, newVal); + } + return projectDir.get(); + } + + public Path getBasedir() + { + if (basePath.get()==null) { + String baseDir = System.getProperty( "basedir" ); + final Path baseDirPath; + if (StringUtils.isNotEmpty( baseDir )) { + baseDirPath = Paths.get( baseDir ); + } else { + baseDirPath = getProjectDirectory( ); + } + basePath.compareAndSet( null, baseDirPath ); + } + return basePath.get( ); + } + + Path getAppserverBase() { + if (appServerBase.get()==null) { + String basePath = System.getProperty( "appserver.base" ); + final Path appserverPath; + if (StringUtils.isNotEmpty( basePath )) { + appserverPath = Paths.get( basePath ).toAbsolutePath( ); + } else { + appserverPath = getBasedir( ).resolve( "target" ).resolve( "appserver-base-" + LocalTime.now( ).toSecondOfDay( ) ); + } + appServerBase.compareAndSet( null, appserverPath ); + } + return appServerBase.get(); + } + + private void removeAppsubFolder( Path appServerBase, String folder ) + throws Exception + { + Path directory = appServerBase.resolve( folder ); + if ( Files.exists(directory) ) + { + org.apache.archiva.common.utils.FileUtils.deleteDirectory( directory ); + } + } + + public void startServer( ) + throws Exception + { + if ( serverStarted.compareAndSet( STOPPED, STARTING ) ) + { + try + { + log.info( "Starting server" ); + Path appServerBase = getAppserverBase( ); + + removeAppsubFolder(appServerBase, "jcr"); + removeAppsubFolder(appServerBase, "conf"); + removeAppsubFolder(appServerBase, "data"); + + + Server myServer = new Server( ); + this.server.set( myServer ); + this.serverConnector.set( new ServerConnector( myServer, new HttpConnectionFactory( ) ) ); + myServer.addConnector( serverConnector.get( ) ); + + ServletHolder servletHolder = new ServletHolder( new CXFServlet( ) ); + ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS ); + context.setResourceBase( SystemUtils.JAVA_IO_TMPDIR ); + context.setSessionHandler( new SessionHandler( ) ); + context.addServlet( servletHolder, getContextRoot( ) + "/*" ); + context.setInitParameter( "contextConfigLocation", getSpringConfigLocation( ) ); + context.addEventListener( new ContextLoaderListener( ) ); + + getServer( ).setHandler( context ); + getServer( ).start( ); + + if ( log.isDebugEnabled( ) ) + { + log.debug( "Jetty dump: {}", getServer( ).dump( ) ); + } + + setupAdminUser( ); + log.info( "Started server on port {}", getServerPort( ) ); + serverStarted.set( STARTED ); + } + finally + { + // In case, if the last statement was not reached + serverStarted.compareAndSet( STARTING, ERROR ); + } + } + + } + + public void stopServer( ) + throws Exception + { + if ( this.serverStarted.compareAndSet( STARTED, STOPPING ) ) + { + try + { + final Server myServer = getServer( ); + if ( myServer != null ) + { + log.info( "Stopping server" ); + myServer.stop( ); + } + serverStarted.set( STOPPED ); + } + finally + { + serverStarted.compareAndSet( STOPPING, ERROR ); + } + } + else + { + log.error( "Server is not in STARTED state!" ); + } + } + + + protected void setupNative( ) throws Exception + { + if ( this.startServer ) + { + startServer( ); + } + + if ( StringUtils.isNotEmpty( serverPort ) ) + { + RestAssured.port = Integer.parseInt( serverPort ); + } + else + { + RestAssured.port = getServerPort( ); + } + if ( StringUtils.isNotEmpty( baseUri ) ) + { + RestAssured.baseURI = baseUri; + } + else + { + RestAssured.baseURI = "http://localhost"; + } + String basePath = getBasePath( ); + this.requestSpec = getRequestSpecBuilder( ).build( ); + RestAssured.basePath = basePath; + RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory( + ( cls, charset ) -> { + ObjectMapper om = new ObjectMapper().findAndRegisterModules(); + om.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + om.setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE ); + return om; + } + )); + } + + protected RequestSpecBuilder getRequestSpecBuilder( ) { + return getRequestSpecBuilder( null ); + } + + protected RequestSpecBuilder getRequestSpecBuilder( String basePath ) + { + String myBasePath = basePath == null ? getBasePath( ) : basePath; + return new RequestSpecBuilder( ).setBaseUri( baseURI ) + .setPort( port ) + .setBasePath( myBasePath ) + .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port ); + } + + protected RequestSpecBuilder getAuthRequestSpecBuilder( ) + { + return new RequestSpecBuilder( ).setBaseUri( baseURI ) + .setPort( port ) + .setBasePath( new StringBuilder( ) + .append( getContextRoot( ) ) + .append( getRedbackServiceBasePath() ).append("/auth").toString() ) + .addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port ); + } + + protected RequestSpecification getRequestSpec( String bearerToken ) + { + return getRequestSpecBuilder( ).addHeader( "Authorization", "Bearer " + bearerToken ).build( ); + } + + protected RequestSpecification getRequestSpec( String bearerToken, String path) + { + return getRequestSpecBuilder( path ).addHeader( "Authorization", "Bearer " + bearerToken ).build( ); + } + + protected void shutdownNative( ) throws Exception + { + if (startServer) + { + stopServer( ); + } + } + + protected org.apache.archiva.redback.rest.api.model.User addRemoteUser(String userid, String password, String fullName, String mail) { + + return null; + } + + protected void initAdminToken() { + Map jsonAsMap = new HashMap<>(); + jsonAsMap.put( "grant_type", "authorization_code" ); + jsonAsMap.put("user_id", getAdminUser()); + jsonAsMap.put("password", getAdminPwd() ); + Response result = given( ).spec( getAuthRequestSpecBuilder().build() ) + .contentType( JSON ) + .body( jsonAsMap ) + .when( ).post( "/authenticate").then( ).statusCode( 200 ) + .extract( ).response( ); + this.adminToken = result.body( ).jsonPath( ).getString( "access_token" ); + this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" ); + } + + protected String getUserToken(String userId, String password) { + Map jsonAsMap = new HashMap<>(); + jsonAsMap.put( "grant_type", "authorization_code" ); + jsonAsMap.put("user_id", userId); + jsonAsMap.put("password", password ); + Response result = given( ).spec( getAuthRequestSpecBuilder().build() ) + .contentType( JSON ) + .body( jsonAsMap ) + .when( ).post( "/authenticate").then( ).statusCode( 200 ) + .extract( ).response( ); + return result.body( ).jsonPath( ).getString( "access_token" ); + } + protected String getAdminToken() { + if (this.adminToken == null) { + initAdminToken(); + } + return this.adminToken; + } + + + protected String getAdminRefreshToken() { + if (this.adminRefreshToken == null) { + initAdminToken(); + } + return this.adminRefreshToken; + } + + public boolean isRemoteService() { + return this.remoteService; + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeMavenManagedRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeMavenManagedRepositoryServiceTest.java new file mode 100644 index 000000000..d078b454e --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeMavenManagedRepositoryServiceTest.java @@ -0,0 +1,88 @@ +package org.apache.archiva.rest.v2.svc; + +/* + * 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 io.restassured.path.json.JsonPath; +import io.restassured.response.Response; +import org.apache.archiva.rest.api.v2.model.MavenManagedRepository; +import org.apache.archiva.rest.api.v2.svc.RestConfiguration; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.List; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Martin Stockhammer + */ +@TestInstance( TestInstance.Lifecycle.PER_CLASS ) +@Tag( "rest-native" ) +@TestMethodOrder( MethodOrderer.OrderAnnotation.class ) +@DisplayName( "Native REST tests for V2 ManagedRepositoryService" ) +public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestServices +{ + @Override + protected String getServicePath( ) + { + return "/repositories/maven/managed"; + } + + @BeforeAll + void setup( ) throws Exception + { + super.setupNative( ); + } + + @AfterAll + void destroy( ) throws Exception + { + super.shutdownNative( ); + } + + @Test + @Order( 1 ) + void testGetRepositories( ) + { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + JsonPath json = response.getBody( ).jsonPath( ); + assertEquals( 2, json.getInt( "pagination.total_count" ) ); + assertEquals( 0, json.getInt( "pagination.offset" ) ); + assertEquals( Integer.valueOf( RestConfiguration.DEFAULT_PAGE_LIMIT ), json.getInt( "pagination.limit" ) ); + List repositories = json.getList( "data", MavenManagedRepository.class ); + assertEquals( "internal", repositories.get( 0 ).getId( ) ); + assertEquals( "snapshots", repositories.get( 1 ).getId( ) ); + } + + + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryGroupServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryGroupServiceTest.java new file mode 100644 index 000000000..9abb5e437 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryGroupServiceTest.java @@ -0,0 +1,470 @@ +package org.apache.archiva.rest.v2.svc; + +/* + * 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 io.restassured.response.Response; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.rest.api.v2.model.RepositoryGroup; +import org.apache.archiva.rest.api.v2.svc.ArchivaRestError; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static org.hamcrest.Matchers.endsWith; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Martin Stockhammer + */ +@TestInstance( TestInstance.Lifecycle.PER_CLASS ) +@Tag( "rest-native" ) +@TestMethodOrder( MethodOrderer.Random.class ) +@DisplayName( "Native REST tests for V2 RepositoryGroupService" ) +public class NativeRepositoryGroupServiceTest extends AbstractNativeRestServices +{ + @Override + protected String getServicePath( ) + { + return "/repository_groups"; + } + + @BeforeAll + void setup( ) throws Exception + { + super.setupNative( ); + } + + @AfterAll + void destroy( ) throws Exception + { + super.shutdownNative( ); + } + + @Test + void testGetEmptyList( ) + { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 0, result.getPagination( ).getTotalCount( ) ); + + } + + @Test + void testAddGroup( ) + { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", "group_001" ); + jsonAsMap.put( "name", "group_001" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); + } finally + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ) + .then( ).statusCode( 200 ); + } + } + + @Test + void testAddExistingGroup( ) + { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", "group_001" ); + jsonAsMap.put( "name", "group_001" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .prettyPeek() + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .redirects().follow( false ) + .body( jsonAsMap ) + .post( "" ) + .prettyPeek() + .then( ).statusCode( 303 ) + .assertThat() + .header( "Location", endsWith("group_001") ).extract( ).response( ); + } finally + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ); + } + } + + + @Test + void testAddMultipleGroups( ) + { + String token = getAdminToken( ); + List groups = new ArrayList<>( ); + try + { + for ( int i=0; i<10; i++) + { + String groupName = String.format( "group_%03d", i ); + groups.add( groupName ); + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", groupName ); + jsonAsMap.put( "name", groupName ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + } + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 10, resultList.getPagination( ).getTotalCount( ) ); + } finally + { + for (String groupName : groups) + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( groupName ); + } + } + } + + @Test + void testRemoveRepositoryGroup( ) + { + String token = getAdminToken( ); + List groups = new ArrayList<>( ); + try + { + for ( int i=0; i<10; i++) + { + String groupName = String.format( "group_%03d", i ); + groups.add( groupName ); + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", groupName ); + jsonAsMap.put( "name", groupName ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + } + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 9, resultList.getPagination( ).getTotalCount( ) ); + + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_005" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 8, resultList.getPagination( ).getTotalCount( ) ); + + } finally + { + for (String groupName : groups) + { + if (!("group_001".equals(groupName) || "group_005".equals(groupName) ) ) + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( groupName ); + } + } + } + } + + + @Test + void testAddRepositoryToGroup( ) + { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", "group_001" ); + jsonAsMap.put( "name", "group_001" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .prettyPeek() + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .put( "group_001/repositories/internal" ) + .prettyPeek() + .then( ).statusCode( 200 ).extract( ).response( ); + + assertNotNull( response ); + result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + assertEquals( 1, result.getRepositories( ).size( ) ); + assertTrue( result.getRepositories( ).contains( "internal" ) ); + + } finally + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ); + } + } + + @Test + void testAddRepositoryToGroupIdempotency( ) + { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", "group_001" ); + jsonAsMap.put( "name", "group_001" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .prettyPeek() + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .put( "group_001/repositories/internal" ) + .prettyPeek() + .then( ).statusCode( 200 ).extract( ).response( ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .put( "group_001/repositories/internal" ) + .prettyPeek() + .then( ).statusCode( 200 ).extract( ).response( ); + + assertNotNull( response ); + result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + assertEquals( 1, result.getRepositories( ).size( ) ); + assertTrue( result.getRepositories( ).contains( "internal" ) ); + + } finally + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ) + .then( ).statusCode( 200 ); + } + } + + + @Test + void testRemoveRepositoryFromGroup( ) + { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", "group_001" ); + jsonAsMap.put( "name", "group_001" ); + jsonAsMap.put( "repositories", Arrays.asList( "internal" ) ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .prettyPeek() + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); + + assertNotNull( result.getRepositories( ) ); + assertEquals( 1, result.getRepositories( ).size( ) ); + assertTrue( result.getRepositories( ).contains( "internal" ) ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .delete( "group_001/repositories/internal" ) + .prettyPeek() + .then( ).statusCode( 200 ).extract( ).response( ); + + assertNotNull( response ); + result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + assertEquals( 0, result.getRepositories( ).size( ) ); + + } finally + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ) + .then( ).statusCode( 200 ); + } + } + + @Test + void testRemoveRepositoryFromGroup404( ) + { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "id", "group_001" ); + jsonAsMap.put( "name", "group_001" ); + jsonAsMap.put( "repositories", Arrays.asList( "internal" ) ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .post( "" ) + .prettyPeek() + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + RepositoryGroup result = response.getBody( ).jsonPath( ).getObject( "", RepositoryGroup.class ); + assertNotNull( result ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult resultList = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 1, resultList.getPagination( ).getTotalCount( ) ); + + assertNotNull( result.getRepositories( ) ); + assertEquals( 1, result.getRepositories( ).size( ) ); + assertTrue( result.getRepositories( ).contains( "internal" ) ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .delete( "group_001/repositories/internalxx" ) + .prettyPeek() + .then( ).statusCode( 404 ).extract( ).response( ); + + assertNotNull( response ); + ArchivaRestError error = response.getBody( ).jsonPath( ).getObject( "", ArchivaRestError.class ); + assertNotNull( error ); + } finally + { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "group_001" ); + } + } + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryServiceTest.java new file mode 100644 index 000000000..783047c95 --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeRepositoryServiceTest.java @@ -0,0 +1,185 @@ +package org.apache.archiva.rest.v2.svc; + +/* + * 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 io.restassured.response.Response; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.rest.api.v2.model.Repository; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.List; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Martin Stockhammer + */ +@TestInstance( TestInstance.Lifecycle.PER_CLASS ) +@Tag( "rest-native" ) +@TestMethodOrder( MethodOrderer.Random.class ) +@DisplayName( "Native REST tests for V2 RepositoryService" ) +public class NativeRepositoryServiceTest extends AbstractNativeRestServices +{ + @Override + protected String getServicePath( ) + { + return "/repositories"; + } + + @BeforeAll + void setup( ) throws Exception + { + super.setupNative( ); + } + + @AfterAll + void destroy( ) throws Exception + { + super.shutdownNative( ); + } + + @Test + void testGetRepositories() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult repositoryPagedResult = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 3, repositoryPagedResult.getPagination( ).getTotalCount( ) ); + List data = response.getBody( ).jsonPath( ).getList( "data", Repository.class ); + assertTrue( data.stream( ).anyMatch( p -> "central".equals( p.getId( ) ) ) ); + assertTrue( data.stream( ).anyMatch( p -> "internal".equals( p.getId( ) ) ) ); + assertTrue( data.stream( ).anyMatch( p -> "snapshots".equals( p.getId( ) ) ) ); + Repository snapshotRepo = data.stream( ).filter( p -> "snapshots".equals( p.getId( ) ) ).findFirst( ).get( ); + assertEquals( "Archiva Managed Snapshot Repository", snapshotRepo.getName( ) ); + assertEquals( "MAVEN", snapshotRepo.getType() ); + assertEquals( "managed", snapshotRepo.getCharacteristic() ); + assertEquals( "default", snapshotRepo.getLayout() ); + assertTrue( snapshotRepo.isScanned( ) ); + assertTrue( snapshotRepo.isIndex( ) ); + + Repository centralRepo = data.stream( ).filter( p -> "central".equals( p.getId( ) ) ).findFirst( ).get( ); + assertEquals( "Central Repository", centralRepo.getName( ) ); + assertEquals( "MAVEN", centralRepo.getType() ); + assertEquals( "remote", centralRepo.getCharacteristic() ); + assertEquals( "default", centralRepo.getLayout() ); + + + } + + @Test + void testGetFilteredRepositories() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .queryParam( "q", "central" ) + .get( "" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult repositoryPagedResult = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 1, repositoryPagedResult.getPagination( ).getTotalCount( ) ); + List data = response.getBody( ).jsonPath( ).getList( "data", Repository.class ); + assertTrue( data.stream( ).anyMatch( p -> "central".equals( p.getId( ) ) ) ); + } + + + @Test + void getStatistics() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "managed/internal/statistics" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + } + + @Test + void scheduleScan() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .post( "managed/internal/scan/schedule" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + } + + @Test + void immediateScan() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .post( "managed/internal/scan/now" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + } + + @Test + void scanStatus() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "managed/internal/scan/status" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + } + + @Test + void scheduleIndexDownload() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .post( "remote/central/index/download/start" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + } + + @Test + void getIndexDownloadList() { + String token = getAdminToken( ); + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .queryParam( "immediate", "true" ) + .post( "remote/central/index/download/start" ) + .then( ).statusCode( 200 ).extract( ).response( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "remote/index/downloads" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List downloads = response.getBody( ).jsonPath( ).getList( "", String.class ); + assertEquals( 1, downloads.size() ); + assertEquals( "central", downloads.get( 0 ) ); + } + +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeSecurityConfigurationServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeSecurityConfigurationServiceTest.java new file mode 100644 index 000000000..0eadb676e --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/NativeSecurityConfigurationServiceTest.java @@ -0,0 +1,348 @@ +package org.apache.archiva.rest.v2.svc; + +/* + * 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 io.restassured.response.Response; +import org.apache.archiva.components.rest.model.PagedResult; +import org.apache.archiva.components.rest.model.PropertyEntry; +import org.apache.archiva.rest.api.v2.model.BeanInformation; +import org.apache.archiva.rest.api.v2.model.CacheConfiguration; +import org.apache.archiva.rest.api.v2.model.LdapConfiguration; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Martin Stockhammer + */ +@TestInstance( TestInstance.Lifecycle.PER_CLASS ) +@Tag( "rest-native" ) +@TestMethodOrder( MethodOrderer.Random.class ) +@DisplayName( "Native REST tests for V2 SecurityConfigurationService" ) +public class NativeSecurityConfigurationServiceTest extends AbstractNativeRestServices +{ + @Override + protected String getServicePath( ) + { + return "/security"; + } + + @BeforeAll + void setup( ) throws Exception + { + super.setupNative( ); + } + + @AfterAll + void destroy( ) throws Exception + { + super.shutdownNative( ); + } + + @Test + void testGetConfiguration() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_user_managers[0]" ) ); + assertEquals( "jpa", response.getBody( ).jsonPath( ).getString( "active_rbac_managers[0]" ) ); + assertEquals( "memory", response.getBody( ).jsonPath( ).getString( "properties.\"authentication.jwt.keystoreType\"" ) ); + assertEquals("10",response.getBody( ).jsonPath( ).getString( "properties.\"security.policy.allowed.login.attempt\"")); + assertTrue( response.getBody( ).jsonPath( ).getBoolean( "user_cache_enabled" ) ); + assertFalse( response.getBody( ).jsonPath( ).getBoolean( "ldap_active" ) ); + } + + @Test + void testGetConfigurationProperties() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/properties" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + PagedResult result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + List propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class ); + assertEquals( 10, result.getPagination( ).getLimit( ) ); + assertEquals( 0, result.getPagination( ).getOffset( ) ); + assertEquals( 47, result.getPagination( ).getTotalCount( ) ); + assertEquals( "authentication.jwt.keystoreType", propList.get( 0 ).getKey() ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .queryParam( "offset", "3" ) + .queryParam( "limit", "5" ) + .get( "config/properties" ) + .then( ).statusCode( 200 ).extract( ).response( ); + + assertNotNull( response ); + result = response.getBody( ).jsonPath( ).getObject( "", PagedResult.class ); + assertEquals( 5, result.getPagination( ).getLimit( ) ); + assertEquals( 47, result.getPagination( ).getTotalCount( ) ); + propList = response.getBody( ).jsonPath( ).getList( "data", PropertyEntry.class ); + assertEquals( "authentication.jwt.refreshLifetimeMs", propList.get( 0 ).getKey() ); + } + + @Test + void testGetLdapConfiguration() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/ldap" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( "", response.getBody( ).jsonPath( ).get( "host_name" ) ); + assertEquals( 0, response.getBody( ).jsonPath( ).getMap( "properties" ).size( ) ); + } + + + @Test + void testUpdateLdapConfiguration() { + String token = getAdminToken( ); + try + { + Map jsonMap = new HashMap<>( ); + jsonMap.put( "host_name", "localhost" ); + jsonMap.put( "port", 389 ); + jsonMap.put( "ssl_enabled", false ); + jsonMap.put( "writable", true ); + jsonMap.put( "base_dn", "dc=apache,dc=org" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonMap ) + .put( "config/ldap" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/ldap" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + LdapConfiguration config = response.getBody( ).jsonPath( ).getObject( "", LdapConfiguration.class ); + assertEquals( "localhost", config.getHostName( ) ); + assertEquals( 389, config.getPort( ) ); + assertFalse( config.isSslEnabled( ) ); + assertTrue( config.isWritable( ) ); + assertEquals( "dc=apache,dc=org", config.getBaseDn( ) ); + } finally + { + Map jsonMap = new HashMap<>( ); + jsonMap.put( "host_name", "" ); + jsonMap.put( "port", -1 ); + jsonMap.put( "ssl_enabled", false ); + jsonMap.put( "base_dn", "" ); + jsonMap.put( "writable", false ); + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonMap ) + .put( "config/ldap" ) + .then( ).statusCode( 200 ); + + } + } + + + @Test + void testGetCacheConfiguration() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/cache" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + } + + @Test + void testUpdateCacheConfiguration() { + String token = getAdminToken( ); + + try + { + Map jsonMap = new HashMap<>( ); + jsonMap.put( "time_to_idle_seconds", 1600 ); + jsonMap.put( "time_to_live_seconds", 12000 ); + jsonMap.put( "max_entries_in_memory", 500 ); + jsonMap.put( "max_entries_on_disk", 400 ); + + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonMap ) + .put( "config/cache" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/cache" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + CacheConfiguration config = response.getBody( ).jsonPath( ).getObject( "", CacheConfiguration.class ); + assertEquals( 1600, config.getTimeToIdleSeconds( ) ); + assertEquals( 12000, config.getTimeToLiveSeconds( ) ); + assertEquals( 500, config.getMaxEntriesInMemory( ) ); + assertEquals( 400, config.getMaxEntriesOnDisk( ) ); + } finally + { + Map jsonMap = new HashMap<>( ); + jsonMap.put( "time_to_idle_seconds", 1800 ); + jsonMap.put( "time_to_live_seconds", 14400 ); + jsonMap.put( "max_entries_in_memory", 1000 ); + jsonMap.put( "max_entries_on_disk", 0 ); + + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonMap ) + .put( "config/cache" ) + .then( ).statusCode( 200 ); + + } + } + + + @Test + void testGetUserManagers() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "user_managers" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List usrList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class ); + assertEquals( 2, usrList.size( ) ); + assertTrue( usrList.stream( ).anyMatch( bi -> "LDAP User Manager".equals( bi.getDisplayName( ) ) ) ); + assertTrue( usrList.stream( ).anyMatch( bi -> "Database User Manager".equals( bi.getDisplayName( ) ) ) ); + } + + @Test + void testGetRbacManagers() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "rbac_managers" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List rbacList = response.getBody( ).jsonPath( ).getList( "", BeanInformation.class ); + assertEquals( 2, rbacList.size( ) ); + assertTrue( rbacList.stream( ).anyMatch( bi -> "Database RBAC Manager".equals( bi.getDisplayName( ) ) ) ); + assertTrue( rbacList.stream( ).anyMatch( bi -> "LDAP RBAC Manager".equals( bi.getDisplayName( ) ) ) ); + } + + @Test + void testUpdateConfiguration() { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa", "ldap" ) ); + jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) ); + jsonAsMap.put( "user_cache_enabled", false ); + jsonAsMap.put( "ldap_active", false ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .put( "config" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( 2, response.getBody( ).jsonPath( ).getList( "active_user_managers" ).size( ) ); + } finally + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "active_user_managers", Arrays.asList( "jpa" ) ); + jsonAsMap.put( "active_rbac_managers", Arrays.asList( "jpa" ) ); + jsonAsMap.put( "user_cache_enabled", true ); + jsonAsMap.put( "ldap_active", false ); + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonAsMap ) + .put( "config" ) + .then( ).statusCode( 200 ); + + } + + } + + @Test + void testGetConfigProperty() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/properties/rest.csrffilter.absentorigin.deny" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( "true", response.getBody( ).jsonPath( ).getString( "value" ) ); + } + + @Test + void testUpdateConfigProperty() { + String token = getAdminToken( ); + + try + { + Map jsonMap = new HashMap<>( ); + jsonMap.put( "value", "false" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonMap ) + .put( "config/properties/rest.csrffilter.absentorigin.deny" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "config/properties/rest.csrffilter.absentorigin.deny" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( "false", response.getBody( ).jsonPath( ).getString( "value" ) ); + } finally + { + Map jsonMap = new HashMap<>( ); + jsonMap.put( "value", "true" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body( jsonMap ) + .put( "config/properties/rest.csrffilter.absentorigin.deny" ) + .then( ).statusCode( 200 ).extract( ).response( ); + } + } + + +}