]> source.dussan.org Git - archiva.git/blob
a34c1e6d853762619825e0dc0e073e71c285fa35
[archiva.git] /
1 package org.apache.maven.archiva.web.action.admin.repositories;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import com.opensymphony.xwork.ActionContext;
23 import com.opensymphony.xwork.Preparable;
24 import org.apache.commons.io.FileUtils;
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.maven.archiva.common.utils.PathUtil;
27 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
28 import org.apache.maven.archiva.configuration.Configuration;
29 import org.apache.maven.archiva.configuration.IndeterminateConfigurationException;
30 import org.apache.maven.archiva.configuration.InvalidConfigurationException;
31 import org.apache.maven.archiva.configuration.RepositoryConfiguration;
32 import org.apache.maven.archiva.security.ArchivaRoleConstants;
33 import org.codehaus.plexus.redback.authorization.AuthorizationException;
34 import org.codehaus.plexus.redback.authorization.AuthorizationResult;
35 import org.codehaus.plexus.redback.rbac.Resource;
36 import org.codehaus.plexus.redback.role.RoleManager;
37 import org.codehaus.plexus.redback.role.RoleManagerException;
38 import org.codehaus.plexus.redback.system.SecuritySession;
39 import org.codehaus.plexus.redback.system.SecuritySystem;
40 import org.codehaus.plexus.redback.xwork.interceptor.SecureAction;
41 import org.codehaus.plexus.redback.xwork.interceptor.SecureActionBundle;
42 import org.codehaus.plexus.redback.xwork.interceptor.SecureActionException;
43 import org.codehaus.plexus.registry.RegistryException;
44 import org.codehaus.plexus.scheduler.CronExpressionValidator;
45 import org.codehaus.plexus.xwork.action.PlexusActionSupport;
46
47 import java.io.File;
48 import java.io.IOException;
49
50 /**
51  * Configures the application repositories.
52  *
53  * @plexus.component role="com.opensymphony.xwork.Action" role-hint="configureRepositoryAction"
54  */
55 public class ConfigureRepositoryAction
56     extends PlexusActionSupport
57     implements Preparable, SecureAction
58 {
59     /**
60      * @plexus.requirement role-hint="default"
61      */
62     private RoleManager roleManager;
63
64     /**
65      * @plexus.requirement
66      */
67     private SecuritySystem securitySystem;
68
69     /**
70      * @plexus.requirement
71      */
72     private ArchivaConfiguration archivaConfiguration;
73
74     private String repoid;
75
76     private String mode;
77
78     /**
79      * The model for this action.
80      */
81     private AdminRepositoryConfiguration repository;
82
83     public String add()
84     {
85         getLogger().info( ".add()" );
86         this.mode = "add";
87
88         return INPUT;
89     }
90
91     public String confirm()
92     {
93         getLogger().info( ".confirm()" );
94
95         if ( operationAllowed( ArchivaRoleConstants.OPERATION_DELETE_REPOSITORY, getRepoid() ) )
96         {
97             addActionError(
98                 "You do not have the appropriate permissions to delete the " + getRepoid() + " repository." );
99             return ERROR;
100         }
101
102         return INPUT;
103     }
104
105     public String delete()
106     {
107         getLogger().info( ".delete()" );
108
109         if ( operationAllowed( ArchivaRoleConstants.OPERATION_DELETE_REPOSITORY, getRepoid() ) )
110         {
111             addActionError(
112                 "You do not have the appropriate permissions to delete the " + getRepoid() + " repository." );
113             return ERROR;
114         }
115
116         String result = SUCCESS;
117         if ( StringUtils.equals( mode, "delete-entry" ) || StringUtils.equals( mode, "delete-contents" ) )
118         {
119             AdminRepositoryConfiguration existingRepository = getRepository();
120             if ( existingRepository == null )
121             {
122                 addActionError( "A repository with that id does not exist" );
123                 return ERROR;
124             }
125
126             // TODO: remove from index too!
127
128             try
129             {
130                 removeRepository( getRepoid() );
131                 result = saveConfiguration();
132
133                 if ( result.equals( SUCCESS ) )
134                 {
135                     removeRepositoryRoles( existingRepository );
136                     if ( StringUtils.equals( mode, "delete-contents" ) )
137                     {
138                         removeContents( existingRepository );
139                     }
140                 }
141             }
142             catch ( IOException e )
143             {
144                 addActionError( "Unable to delete repository: " + e.getMessage() );
145                 result = INPUT;
146             }
147             catch ( RoleManagerException e )
148             {
149                 addActionError( "Unable to delete repository: " + e.getMessage() );
150                 result = INPUT;
151             }
152             catch ( InvalidConfigurationException e )
153             {
154                 addActionError( "Unable to delete repository: " + e.getMessage() );
155                 result = INPUT;
156             }
157             catch ( RegistryException e )
158             {
159                 addActionError( "Unable to delete repository: " + e.getMessage() );
160                 result = INPUT;
161             }
162         }
163
164         return result;
165     }
166
167     public String edit()
168     {
169         getLogger().info( ".edit()" );
170         this.mode = "edit";
171
172         if ( operationAllowed( ArchivaRoleConstants.OPERATION_EDIT_REPOSITORY, getRepoid() ) )
173         {
174             addActionError( "You do not have the appropriate permissions to edit the " + getRepoid() + " repository." );
175             return ERROR;
176         }
177
178         return INPUT;
179     }
180
181     public String getMode()
182     {
183         return this.mode;
184     }
185
186     public String getRepoid()
187     {
188         return repoid;
189     }
190
191     public AdminRepositoryConfiguration getRepository()
192     {
193         return repository;
194     }
195
196     public SecureActionBundle getSecureActionBundle()
197         throws SecureActionException
198     {
199         SecureActionBundle bundle = new SecureActionBundle();
200
201         bundle.setRequiresAuthentication( true );
202         bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION, Resource.GLOBAL );
203
204         return bundle;
205     }
206
207     public void prepare()
208         throws Exception
209     {
210         String id = getRepoid();
211         if ( id == null )
212         {
213             this.repository = new AdminRepositoryConfiguration();
214         }
215
216         RepositoryConfiguration repoconfig = archivaConfiguration.getConfiguration().findRepositoryById( id );
217         if ( repoconfig != null )
218         {
219             this.repository = new AdminRepositoryConfiguration( repoconfig );
220         }
221     }
222
223     public String save()
224     {
225         String mode = getMode();
226         String repoId = getRepository().getId();
227         boolean containsError = false;
228
229         getLogger().info( ".save(" + mode + ":" + repoId + ")" );
230
231         containsError = validateFields( mode );
232
233         if ( containsError && StringUtils.equalsIgnoreCase( "add", mode ) )
234         {
235             return INPUT;
236         }
237         else if ( containsError && StringUtils.equalsIgnoreCase( "edit", mode ) )
238         {
239             return ERROR;
240         }
241
242         if ( StringUtils.equalsIgnoreCase( "edit", mode ) )
243         {
244             removeRepository( repoId );
245         }
246
247         String result;
248         try
249         {
250             addRepository( getRepository() );
251             result = saveConfiguration();
252         }
253         catch ( IOException e )
254         {
255             addActionError( "I/O Exception: " + e.getMessage() );
256             result = INPUT;
257         }
258         catch ( RoleManagerException e )
259         {
260             addActionError( "Role Manager Exception: " + e.getMessage() );
261             result = INPUT;
262         }
263         catch ( InvalidConfigurationException e )
264         {
265             addActionError( "Invalid Configuration Exception: " + e.getMessage() );
266             result = INPUT;
267         }
268         catch ( RegistryException e )
269         {
270             addActionError( "Configuration Registry Exception: " + e.getMessage() );
271             result = INPUT;
272         }
273
274         return result;
275     }
276
277     private boolean validateFields( String mode )
278     {
279         boolean containsError = false;
280         CronExpressionValidator validator = new CronExpressionValidator();
281         Configuration config = archivaConfiguration.getConfiguration();
282         String repoId = getRepository().getId();
283
284         if ( StringUtils.isBlank( repoId ) )
285         {
286             addFieldError( "repository.id", "You must enter a repository identifier." );
287             containsError = true;
288         }
289         //if edit mode, do not validate existence of repoId
290         else if ( config.findRepositoryById( repoId ) != null && !StringUtils.equalsIgnoreCase( mode, "edit" ) )
291         {
292             addFieldError( "repository.id",
293                            "Unable to add new repository with id [" + repoId + "], that id already exists." );
294             containsError = true;
295         }
296
297         if ( StringUtils.isBlank( repository.getUrl() ) )
298         {
299
300             addFieldError( "repository.url", "You must enter a directory or url." );
301             containsError = true;
302         }
303         if ( StringUtils.isBlank( repository.getName() ) )
304         {
305             addFieldError( "repository.name", "You must enter a repository name." );
306             containsError = true;
307         }
308         if ( !validator.validate( repository.getRefreshCronExpression() ) )
309         {
310             addFieldError( "repository.refreshCronExpression", "Invalid cron expression." );
311             containsError = true;
312         }
313
314         return containsError;
315     }
316
317     public void setMode( String mode )
318     {
319         this.mode = mode;
320     }
321
322     public void setRepoid( String repoid )
323     {
324         this.repoid = repoid;
325     }
326
327     public void setRepository( AdminRepositoryConfiguration repository )
328     {
329         this.repository = repository;
330     }
331
332     private void addRepository( AdminRepositoryConfiguration repository )
333         throws IOException, RoleManagerException
334     {
335         getLogger().info( ".addRepository(" + repository + ")" );
336
337         // Fix the URL entry (could possibly be a filesystem path)
338         String rawUrlEntry = repository.getUrl();
339         if ( !rawUrlEntry.startsWith( "http://" ) )
340         {
341             repository.setUrl( PathUtil.toUrl( rawUrlEntry ) );
342         }
343
344         if ( repository.isManaged() )
345         {
346             // Normalize the path
347             File file = new File( repository.getDirectory() );
348             repository.setDirectory( file.getCanonicalPath() );
349             if ( !file.exists() )
350             {
351                 file.mkdirs();
352                 // TODO: error handling when this fails, or is not a directory!
353             }
354         }
355
356         archivaConfiguration.getConfiguration().addRepository( repository );
357
358         // TODO: double check these are configured on start up
359         roleManager.createTemplatedRole( "archiva-repository-manager", repository.getId() );
360
361         roleManager.createTemplatedRole( "archiva-repository-observer", repository.getId() );
362
363     }
364
365     private boolean operationAllowed( String permission, String repoid )
366     {
367         ActionContext context = ActionContext.getContext();
368         SecuritySession securitySession = (SecuritySession) context.get( SecuritySession.ROLE );
369
370         AuthorizationResult authzResult;
371         try
372         {
373             authzResult = securitySystem.authorize( securitySession, permission, repoid );
374
375             return authzResult.isAuthorized();
376         }
377         catch ( AuthorizationException e )
378         {
379             getLogger().info( "Unable to authorize permission: " + permission + " against repo: " + repoid +
380                 " due to: " + e.getMessage() );
381             return false;
382         }
383     }
384
385     private void removeContents( AdminRepositoryConfiguration existingRepository )
386         throws IOException
387     {
388         if ( existingRepository.isManaged() )
389         {
390             getLogger().info( "Removing " + existingRepository.getDirectory() );
391             FileUtils.deleteDirectory( new File( existingRepository.getDirectory() ) );
392         }
393     }
394
395     private void removeRepository( String repoId )
396     {
397         getLogger().info( ".removeRepository()" );
398
399         RepositoryConfiguration toremove = archivaConfiguration.getConfiguration().findRepositoryById( repoId );
400         if ( toremove != null )
401         {
402             archivaConfiguration.getConfiguration().removeRepository( toremove );
403         }
404     }
405
406     private void removeRepositoryRoles( RepositoryConfiguration existingRepository )
407         throws RoleManagerException
408     {
409         roleManager.removeTemplatedRole( "archiva-repository-manager", existingRepository.getId() );
410         roleManager.removeTemplatedRole( "archiva-repository-observer", existingRepository.getId() );
411
412         getLogger().info( "removed user roles associated with repository " + existingRepository.getId() );
413     }
414
415     private String saveConfiguration()
416         throws IOException, InvalidConfigurationException, RegistryException
417     {
418         getLogger().info( ".saveConfiguration()" );
419
420         try
421         {
422             archivaConfiguration.save( archivaConfiguration.getConfiguration() );
423             addActionMessage( "Successfully saved configuration" );
424         }
425         catch ( IndeterminateConfigurationException e )
426         {
427             addActionError( e.getMessage() );
428             return INPUT;
429         }
430
431         return SUCCESS;
432     }
433 }