Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #27 from ikedam/feature/JENKINS-20398_CopyPermission
[JENKINS-20398] Job Property to define projects that can copy artifacts
- Loading branch information
Showing
14 changed files
with
691 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
260 changes: 260 additions & 0 deletions
260
src/main/java/hudson/plugins/copyartifact/CopyArtifactPermissionProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,260 @@ | ||
/* | ||
* The MIT License | ||
* | ||
* Copyright (c) 2013 IKEDA Yasuyuki | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
package hudson.plugins.copyartifact; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.regex.Pattern; | ||
|
||
import jenkins.model.Jenkins; | ||
import net.sf.json.JSONObject; | ||
|
||
import org.apache.commons.lang.StringUtils; | ||
import org.kohsuke.stapler.AncestorInPath; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
import org.kohsuke.stapler.QueryParameter; | ||
import org.kohsuke.stapler.StaplerRequest; | ||
|
||
import com.google.common.base.Function; | ||
import com.google.common.collect.Lists; | ||
|
||
import hudson.Extension; | ||
import hudson.model.AutoCompletionCandidates; | ||
import hudson.model.Item; | ||
import hudson.model.ItemGroup; | ||
import hudson.model.JobProperty; | ||
import hudson.model.JobPropertyDescriptor; | ||
import hudson.model.AbstractProject; | ||
import hudson.util.FormValidation; | ||
|
||
/** | ||
* Job Property to define projects that can copy artifacts of this project. | ||
*/ | ||
public class CopyArtifactPermissionProperty extends JobProperty<AbstractProject<?,?>> { | ||
public static final String PROPERTY_NAME = "copy-artifact-permission-property"; | ||
|
||
private final List<String> projectNameList; | ||
|
||
/** | ||
* @return list of project names that can copy artifacts of this project. | ||
*/ | ||
public List<String> getProjectNameList() { | ||
return projectNameList; | ||
} | ||
|
||
/** | ||
* @return comma-separated project names that can copy artifacts of this project. | ||
*/ | ||
public String getProjectNames() { | ||
return StringUtils.join(projectNameList, ','); | ||
} | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param projectNames comma-separated project names that can copy artifacts of this project. | ||
*/ | ||
@DataBoundConstructor | ||
public CopyArtifactPermissionProperty(String projectNames) { | ||
List<String> rawProjectNameList = Arrays.asList((projectNames != null)?StringUtils.split(projectNames, ','):new String[0]); | ||
projectNameList = new ArrayList<String>(rawProjectNameList.size()); | ||
for (String rawProjectName: rawProjectNameList) { | ||
if (StringUtils.isBlank(rawProjectName)) { | ||
continue; | ||
} | ||
projectNameList.add(StringUtils.trim(rawProjectName)); | ||
} | ||
} | ||
|
||
/** | ||
* @param copier a project who wants to copy artifacts of this project. | ||
* @return whether copier is allowed to copy artifacts of this project. | ||
*/ | ||
public boolean canCopiedBy(AbstractProject<?,?> copier) { | ||
String copierName = copier.getRelativeNameFrom(owner.getParent()); | ||
for (String projectName: getProjectNameList()) { | ||
if (isNameMatch(copierName, projectName)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* package scope for testing purpose. | ||
* | ||
* @param name | ||
* @param pattern | ||
* @return whether name matches pattern. | ||
*/ | ||
/*package*/ static boolean isNameMatch(String name, String pattern) { | ||
if (pattern == null || name == null) { | ||
return false; | ||
} | ||
if (!pattern.contains("*")) { | ||
// if no wild card, simply complete match. | ||
return pattern.equals(name); | ||
} | ||
|
||
List<String> literals = Arrays.asList(pattern.split("\\*", -1)); | ||
String regex = StringUtils.join(Lists.transform(literals, new Function<String, String>() { | ||
public String apply(String input) { | ||
return Pattern.quote(input); | ||
} | ||
}), ".*"); | ||
return name.matches(regex); | ||
} | ||
|
||
/** | ||
* Convenient wrapper for {@link CopyArtifactPermissionProperty#canCopiedBy(AbstractProject)} | ||
* | ||
* @param copier a project that wants to copy artifacts of copiee. | ||
* @param copiee a owner of artifacts. | ||
* @return whether copier can copy artifacts of copiee. | ||
*/ | ||
public static boolean canCopyArtifact(AbstractProject<?,?> copier, AbstractProject<?,?> copiee) { | ||
CopyArtifactPermissionProperty prop = copiee.getProperty(CopyArtifactPermissionProperty.class); | ||
if (prop == null) { | ||
return false; | ||
} | ||
return prop.canCopiedBy(copier); | ||
} | ||
|
||
/** | ||
* Descriptor for {@link CopyArtifactPermissionProperty}. | ||
*/ | ||
@Extension | ||
public static class DescriptorImpl extends JobPropertyDescriptor { | ||
/** | ||
* @return name displayed in the project configuration page. | ||
* @see hudson.model.Descriptor#getDisplayName() | ||
*/ | ||
@Override | ||
public String getDisplayName() { | ||
return Messages.CopyArtifactPermissionProperty_DisplayName(); | ||
} | ||
|
||
/** | ||
* @return key name used in the configuration form. | ||
*/ | ||
public String getPropertyName() { | ||
return PROPERTY_NAME; | ||
} | ||
|
||
/** | ||
* @param req | ||
* @param formData | ||
* @return | ||
* @throws hudson.model.Descriptor.FormException | ||
* @see hudson.model.JobPropertyDescriptor#newInstance(org.kohsuke.stapler.StaplerRequest, net.sf.json.JSONObject) | ||
*/ | ||
@Override | ||
public CopyArtifactPermissionProperty newInstance(StaplerRequest req, JSONObject formData) | ||
throws hudson.model.Descriptor.FormException { | ||
if(formData == null || formData.isNullObject()) { | ||
return null; | ||
} | ||
JSONObject form = formData.getJSONObject(getPropertyName()); | ||
if(form == null || form.isNullObject()) { | ||
return null; | ||
} | ||
|
||
return (CopyArtifactPermissionProperty)super.newInstance(req, form); | ||
} | ||
|
||
/** | ||
* package scope for testing purpose. | ||
* | ||
* @param projectNames | ||
* @param context | ||
* @return | ||
*/ | ||
/*package*/ List<String> checkNotFoundProjects(String projectNames, ItemGroup<?> context) { | ||
if (StringUtils.isBlank(projectNames)) { | ||
return Collections.emptyList(); | ||
} | ||
List<String> notFound = new ArrayList<String>(); | ||
for (String projectName: StringUtils.split(projectNames, ',')) { | ||
if (StringUtils.isBlank(projectName)) { | ||
continue; | ||
} | ||
projectName = StringUtils.trim(projectName); | ||
if (projectName.contains("*")) { | ||
// no check for pattern | ||
continue; | ||
} | ||
AbstractProject<?,?> proj = Jenkins.getInstance().getItem(projectName, context, AbstractProject.class); | ||
if (proj == null || proj.getRootProject() != proj || !proj.hasPermission(Item.READ)) { | ||
// permission check is done only for root project. | ||
notFound.add(projectName); | ||
continue; | ||
} | ||
} | ||
return notFound; | ||
} | ||
|
||
/** | ||
* @param projectNames | ||
* @return | ||
*/ | ||
public FormValidation doCheckProjectNames(@QueryParameter String projectNames, @AncestorInPath ItemGroup<?> context) { | ||
List<String> notFound = checkNotFoundProjects(projectNames, context); | ||
if (!notFound.isEmpty()) { | ||
return FormValidation.warning(Messages.CopyArtifactPermissionProperty_MissingProject(StringUtils.join(notFound, ","))); | ||
} | ||
return FormValidation.ok(); | ||
} | ||
|
||
/** | ||
* @param value | ||
* @param context | ||
* @return | ||
*/ | ||
public AutoCompletionCandidates doAutoCompleteProjectNames(@QueryParameter String value, @AncestorInPath ItemGroup<?> context) { | ||
AutoCompletionCandidates candidates = new AutoCompletionCandidates(); | ||
if (StringUtils.isBlank(value)) { | ||
return candidates; | ||
} | ||
value = StringUtils.trim(value); | ||
for (AbstractProject<?,?> project: Jenkins.getInstance().getAllItems(AbstractProject.class)) { | ||
if (project.getRootProject() != project) { | ||
// permission check is done only for root project. | ||
continue; | ||
} | ||
if (!project.hasPermission(Item.READ)) { | ||
continue; | ||
} | ||
|
||
String relativeName = project.getRelativeNameFrom(context); | ||
if (relativeName.startsWith(value)) { | ||
candidates.add(relativeName); | ||
} | ||
} | ||
return candidates; | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/resources/hudson/plugins/copyartifact/CopyArtifactPermissionProperty/config.jelly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<!-- | ||
The MIT License | ||
Copyright (c) 2013 IKEDA Yasuyuki | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
--> | ||
<?jelly escape-by-default='true'?> | ||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> | ||
<f:optionalBlock name="${descriptor.propertyName}" title="${descriptor.displayName}" checked="${instance != null}"> | ||
<f:entry title="${%Projects to allow copy artifacts}" field="projectNames"> | ||
<f:textbox autoCompleteDelimChar="," /> | ||
</f:entry> | ||
</f:optionalBlock> | ||
</j:jelly> |
24 changes: 24 additions & 0 deletions
24
...resources/hudson/plugins/copyartifact/CopyArtifactPermissionProperty/config_ja.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# The MIT License | ||
# | ||
# Copyright (c) 2013 IKEDA Yasuyuki | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), to deal | ||
# in the Software without restriction, including without limitation the rights | ||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
# copies of the Software, and to permit persons to whom the Software is | ||
# furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
# THE SOFTWARE. | ||
|
||
# Projects\ to\ allow\ copy\ artifacts=成果物のコピーを許可するプロジェクト | ||
Projects\ to\ allow\ copy\ artifacts=\u6210\u679c\u7269\u306e\u30b3\u30d4\u30fc\u3092\u8a31\u53ef\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8 |
4 changes: 4 additions & 0 deletions
4
...sources/hudson/plugins/copyartifact/CopyArtifactPermissionProperty/help-projectNames.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<div> | ||
Comma seperated list of projects that can copy artifacts of this project. | ||
Wild card character ('*') is available. | ||
</div> |
4 changes: 4 additions & 0 deletions
4
...rces/hudson/plugins/copyartifact/CopyArtifactPermissionProperty/help-projectNames_ja.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<div> | ||
このプロジェクトの成果物をコピーできるプロジェクトをカンマ区切りで指定します。 | ||
ワイルドカード ('*') を使用できます。 | ||
</div> |
3 changes: 3 additions & 0 deletions
3
src/main/resources/hudson/plugins/copyartifact/CopyArtifactPermissionProperty/help.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<div> | ||
Define projects that can copy artifacts of this project without authentication. | ||
</div> |
3 changes: 3 additions & 0 deletions
3
src/main/resources/hudson/plugins/copyartifact/CopyArtifactPermissionProperty/help_ja.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<div> | ||
このプロジェクトの成果物を、認証を必要とせずにコピーできるプロジェクトを指定します。 | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.