diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..3a626c3a
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: monthly
diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml
new file mode 100644
index 00000000..9b134d5c
--- /dev/null
+++ b/.github/workflows/cd.yaml
@@ -0,0 +1,54 @@
+# Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins
+#
+# Please find additional hints for individual trigger use case
+# configuration options inline this script below.
+#
+---
+name: cd
+on:
+ workflow_dispatch:
+ inputs:
+ validate_only:
+ required: false
+ type: boolean
+ description: |
+ Run validation with release drafter only
+ → Skip the release job
+ # Note: Change this default to true,
+ # if the checkbox should be checked by default.
+ default: false
+ # If you don't want any automatic trigger in general, then
+ # the following check_run trigger lines should all be commented.
+ # Note: Consider the use case #2 config for 'validate_only' below
+ # as an alternative option!
+ check_run:
+ types:
+ - completed
+
+permissions:
+ checks: read
+ contents: write
+
+jobs:
+ maven-cd:
+ uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
+ with:
+ # Comment / uncomment the validate_only config appropriate to your preference:
+ #
+ # Use case #1 (automatic release):
+ # - Let any successful Jenkins build trigger another release,
+ # if there are merged pull requests of interest
+ # - Perform a validation only run with drafting a release note,
+ # if manually triggered AND inputs.validate_only has been checked.
+ #
+ validate_only: ${{ inputs.validate_only == true }}
+ #
+ # Alternative use case #2 (no automatic release):
+ # - Same as use case #1 - but:
+ # - Let any check_run trigger a validate_only run.
+ # => enforce the release job to be skipped.
+ #
+ #validate_only: ${{ inputs.validate_only == true || github.event_name == 'check_run' }}
+ secrets:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
diff --git a/.github/workflows/jenkins-security-scan.yml b/.github/workflows/jenkins-security-scan.yml
new file mode 100644
index 00000000..c7b41fc2
--- /dev/null
+++ b/.github/workflows/jenkins-security-scan.yml
@@ -0,0 +1,21 @@
+name: Jenkins Security Scan
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ types: [ opened, synchronize, reopened ]
+ workflow_dispatch:
+
+permissions:
+ security-events: write
+ contents: read
+ actions: read
+
+jobs:
+ security-scan:
+ uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2
+ with:
+ java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate.
+ # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default.
diff --git a/.gitignore b/.gitignore
index 11dcc1a7..f5c95b0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,7 @@ work/
.settings/
# Coverity
/cov-int
+
+#IDEA
+ownership.iml
+.idea/
diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml
new file mode 100644
index 00000000..c2350859
--- /dev/null
+++ b/.mvn/extensions.xml
@@ -0,0 +1,8 @@
+
+
+
+ io.jenkins.tools.incrementals
+ incrementals-maven-plugin
+ 1.13
+
+
diff --git a/.mvn/maven.config b/.mvn/maven.config
new file mode 100644
index 00000000..f7daf60d
--- /dev/null
+++ b/.mvn/maven.config
@@ -0,0 +1,3 @@
+-Pconsume-incrementals
+-Pmight-produce-incrementals
+-Dchangelist.format=%d.v%s
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..37d9fa55
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,276 @@
+Changelog
+-----
+
+| WARNING: Changelogs have been moved to [GitHub Releases](https://github.com/jenkinsci/ownership/releases) |
+| --- |
+
+### New releases
+
+See [GitHub Releases](https://github.com/jenkinsci/ownership/releases).
+
+### 0.12.1
+
+Release date: Apr 30, 2018
+
+* [JENKINS-49744](https://issues.jenkins-ci.org/browse/JENKINS-49744) -
+Users with `Manage Ownership` permissions were unable to change Foler ownership from CLI/REST API without `Jenkins/Administer` persiossion.
+* [JENKINS-50807](https://issues.jenkins-ci.org/browse/JENKINS-50807) -
+Add missing implementations for [OwnershipHelperLocator](https://jenkins.io/doc/developer/extensions/ownership/#ownershiphelperlocator)
+extension point.
+Now the API can be used to retrieve ownership info for any object.
+
+### 0.12.0
+
+Release date: Feb 26, 2018
+
+* [SECURITY-498](https://jenkins.io/security/advisory/2018-02-26/#SECURITY-498) -
+Users with _Item/Configure_ and _Computer/Configure_ permissions were able to change ownership from CLI or REST API without the _Manage Ownership_ permissions.
+
+Compatibility notes:
+
+* External configuration management logic may fail if the client user has no _Overall/Administer_ or _Manage Ownership_ permission.
+* Folder ownership modifications from REST/CLI will fail for users who have no _Overall/Administer_ perission.
+Re-enabling functionality for users with _Manage Ownership_ permission is tracked as [JENKINS-49744](https://issues.jenkins-ci.org/browse/JENKINS-49744).
+
+### 0.11.0
+
+Release date: Jan 14, 2018
+
+* [JENKINS-20832](https://issues.jenkins-ci.org/browse/JENKINS-20832) -
+Use case sensitivity strategies from security realms when comparing user IDs.
+* [JENKINS-48707](https://issues.jenkins-ci.org/browse/JENKINS-48707) -
+Speedup user fetching operations in the plugin.
+* [PR #65](https://github.com/jenkinsci/ownership-plugin/pull/65) -
+Add Russian localization to UI components.
+
+### 0.10.0
+
+Release date: May 07, 2017
+
+Improvements:
+
+* [PR #56](https://github.com/jenkinsci/ownership-plugin/pull/56) -
+Add new Preserve Ownership Item Policy.
+It allows retaining ownership in plugins like JobDSL.
+* [PR #58](https://github.com/jenkinsci/ownership-plugin/pull/58) -
+Add permissions report for items being owned by the specified user. Powered by the [Security Inspector Plugin](https://plugins.jenkins.io/security-inspector).
+* [PR #57](https://github.com/jenkinsci/ownership-plugin/pull/57),
+[PR #60](https://github.com/jenkinsci/ownership-plugin/pull/60) -
+Extend plugin documentation and move it to GitHub.
+* Update Jenkins core minimal version requirement to `1.651.3`.
+
+
+Fixed issues:
+
+* [JENKINS-42908](https://issues.jenkins-ci.org/browse/JENKINS-42908) -
+When contributing ownership environment variables, check jobs by the generic `BuildableItemWithBuildWrappers` interface.
+
+
+### 0.9.1
+
+Release date: Jan 08, 2017
+
+Fixed issues:
+
+* [JENKINS-38353](https://issues.jenkins-ci.org/browse/JENKINS-38353) -
+Fix handling of Multi-branch Pipeline and other computed folders in the ownership management logic.
+* [JENKINS-38513](https://issues.jenkins-ci.org/browse/JENKINS-38513) -
+Prevent `ClassNotFoundException` in `FolderItemListener` when Folders plugin is not installed or disabled.
+
+### 0.9.0
+
+Release date: Sep 17, 2016
+
+Improvements:
+
+* [JENKINS-28881](https://issues.jenkins-ci.org/browse/JENKINS-28881) -
+Integration with Folders Plugin.
+ * Ownership info can be defined for folders
+ * Ownership info can be inherited by jobs and folders from upper folder levels
+ * All Ownership-Based security features got integration with folders
+* [JENKINS-32353](https://issues.jenkins-ci.org/browse/JENKINS-32353) -
+Integration with Pipeline Plugin (see [this page](doc/PipelineIntegration.md) for more info).
+ * Ownership can be now configured for Jenkins Pipeline
+ * `ownership` global variable, which provides information about job and node ownership within Pipeline runs
+* [JENKINS-28258](https://issues.jenkins-ci.org/browse/JENKINS-28258) -
+Add support of non-AbstractProject job types in the [Authorize Project](https://plugins.jenkins.io/authorize-project) extension.
+* [JENKINS-36946](https://issues.jenkins-ci.org/browse/JENKINS-36946) -
+Ownership summary boxes: Add hint for disabling empty ownership summaries.
+* [PR #46](https://github.com/jenkinsci/ownership-plugin/pull/46) -
+Update to the new plugin parent POM 2.x.
+* [PR #47](https://github.com/jenkinsci/ownership-plugin/pull/47) -
+No more "Slave Ownership" in the UI, "Node ownership" is a correct term.
+
+Fixed issues:
+
+* [PR #46](https://github.com/jenkinsci/ownership-plugin/pull/46) -
+Cleanup of issues reported by FindBugs.
+* [JENKINS-37405](https://issues.jenkins-ci.org/browse/JENKINS-37405) -
+Ownership job filter now supports all item types with ownership info.
+* [JENKINS-38236](https://issues.jenkins-ci.org/browse/JENKINS-38236) -
+Prevent `NullPointerException` in Item Listeners if the policy form submission provides `null` policy.
+
+### 0.8
+
+Release date: Oct 27, 2015
+
+Improvements:
+
+* [JENKINS-28714](https://issues.jenkins-ci.org/browse/JENKINS-28714) -
+Add option to hide ownership summary boxes for Runs.
+* [JENKINS-28712](https://issues.jenkins-ci.org/browse/JENKINS-28712) -
+Add option to hide ownership summary boxes if owners are not assigned.
+* [JENKINS-30254](https://issues.jenkins-ci.org/browse/JENKINS-30254) -
+Allow hiding user e-mails in summary boxes.
+* Better help text in ownership summary boxes for items with unassigned Ownership
+
+Fixed issues:
+
+* [JENKINS-30818](https://issues.jenkins-ci.org/browse/JENKINS-30818) -
+Prevent `NullPointerException` in `JobOwnerJobProperty::toString()` if ownership is not configured.
+
+### 0.7
+
+Release date: Jun 03, 2015
+
+Improvements:
+
+* [JENKINS-26768](https://issues.jenkins-ci.org/browse/JENKINS-26768) -
+Contact Owners and Contact Admins links can be disabled.
+* [PR #35](https://github.com/jenkinsci/ownership-plugin/pull/35) -
+Remove unnecessary `//` from the `mailto:` hyperlink.
+
+Fixed issues:
+
+* [JENKINS-28713](https://issues.jenkins-ci.org/browse/JENKINS-28713) -
+Improper permission checks in several API methods.
+* [JENKINS-27715](https://issues.jenkins-ci.org/browse/JENKINS-27715) -
+Properly inject owner user IDs into `JOB_COOWNERS` and `NODE_COOWNERS` environment variables.
+
+### 0.6
+
+Release date: Jan 18, 2015
+
+* [JENKINS-28713](https://issues.jenkins-ci.org/browse/JENKINS-26283) -
+ Add "Contact item owners" and "Contact service owners" links to ownership summary boxes.
+ * Links automatically generate a e-mail stub with configurable subject and body templates
+ * Owners and co-owners are being automatically added to recipients
+* [JENKINS-23947](https://issues.jenkins-ci.org/browse/JENKINS-23947) -
+Jenkins admins can enable the global injection of ownership variables.
+* [JENKINS-26320](https://issues.jenkins-ci.org/browse/JENKINS-26320) -
+Display ownership info for builds.
+* [PR #28](https://github.com/jenkinsci/ownership-plugin/pull/28) -
+Avoid confusing node property shown on config screen.
+
+Fixed issues:
+
+* [JENKINS-23926](https://issues.jenkins-ci.org/browse/JENKINS-23926) -
+Inject ownership variables even if the build fails before build steps execution.
+* [JENKINS-19433](https://issues.jenkins-ci.org/browse/JENKINS-19433) -
+Update Mailer plugin dependency to mailer-0.9 to support user properties.
+
+### 0.5.1
+
+Release date: Sep 30, 2014
+
+Fixed issues:
+
+* [JENKINS-24475](https://issues.jenkins-ci.org/browse/JENKINS-24475) -
+Managing ownership fails in Jenkins 1.565.1+.
+* [JENKINS-24921](https://issues.jenkins-ci.org/browse/JENKINS-24921) -
+Remove the obsolete `Assign ownership on create` configuration entry.
+* [JENKINS-23657](https://issues.jenkins-ci.org/browse/JENKINS-23657) -
+Use transparent PNG icons instead of GIFs.
+
+### 0.5
+
+Release date: Sep 09, 2014
+
+Improvements:
+
+* [JENKINS-21904](https://issues.jenkins-ci.org/browse/JENKINS-21904) -
+Add new Ownership policy extension point: different ownership assignment behaviors can be specified.
+* [JENKINS-21838](https://issues.jenkins-ci.org/browse/JENKINS-21838) -
+Add Ownership authorization strategy for the Authorize Project plugin.
+* Improve Ownership summary box layouts.
+
+Fixed issues:
+
+* [JENKINS-24370](https://issues.jenkins-ci.org/browse/JENKINS-24370) -
+Fixed the issue with redirects to absolute URLs after the ownership modification.
+
+
+### 0.4
+
+Release date: Jan 18, 2014
+
+Improvements:
+
+* [JENKINS-18977](https://issues.jenkins-ci.org/browse/JENKINS-18977) -
+Display node ownership info in the Computer list.
+* [JENKINS-21358](https://issues.jenkins-ci.org/browse/JENKINS-21358) -
+Show Job ownership actions in the side panel instead of the Jenkins default panel.
+* [JENKINS-20908](https://issues.jenkins-ci.org/browse/JENKINS-20908) -
+Remove custom fast mail resolution handlers. Now the plugin uses native handlers from Mailer Plugin 1.6+.
+
+Fixed issues:
+
+* [JENKINS-20488](https://issues.jenkins-ci.org/browse/JENKINS-20488) -
+Prevent possible issue during the concurrent nodes renaming and modification.
+
+### 0.3.1
+
+Release date: Oct 25, 2013
+
+Fixed issues:
+
+* [JENKINS-28713](https://issues.jenkins-ci.org/browse/JENKINS-28713),
+[JENKINS-20213](https://issues.jenkins-ci.org/browse/JENKINS-20213),
+[JENKINS-20181](https://issues.jenkins-ci.org/browse/JENKINS-20181) -
+Fix handling of Multi-configuration (Matrix) jobs.
+* [JENKINS-19993](https://issues.jenkins-ci.org/browse/JENKINS-19993) -
+Fix propagation of default item-specific permissions to jobs after the reconfiguration.
+
+### 0.3
+
+Release date: Sep 08, 2013
+
+Improvements:
+
+* Allow restricting execution of jobs on agents according to ownership configuration (Extension for Job Restrictions Plugin)
+* Support of item-specific access rights for jobs (Extension for Role Strategy Plugin)
+ * `@ItemSpecific` macro - Check the SID against entries from the item-specific security
+ * `@ItemSpecificWithUserId` macro - if SID is "authenticated", checks current user's ID
+* Support of Token Macros (`${OWNERSHIP,var=varname}`)
+
+### 0.2.1
+
+Release date: Aug 08, 2013
+
+Fixed issues:
+
+* Hotfix: Added support of the fast e-mail resolver to fix the UI performance issue.
+(copy of default resolver from Mailer 1.5)
+
+### 0.2
+
+Release date: Aug 02, 2013
+
+Enhancements:
+
+* Integration with Role Strategy Plugin via macros.
+* Added a build wrapper, which exposes ownership variables to environment.
+* Added support of co-owners.
+* Replaced built-in e-mail suffix resolver by configurable selector of `MailAddressResolver` extension.
+* Ownership management has been migrated to a separate `Manage Ownership` page.
+
+Known compatibility issues:
+
+:exclamation:
+Update from `0.1` to `0.2` corrupts plugin's data structure (issue #19078). You will need to manually cleanup data in the ownership.xml after the update.
+
+### 0.1
+
+Release date: Jul 12, 2013
+
+* Initial release: ownership management and visualization
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..fdc46fac
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,7 @@
+Contributing
+====
+
+If you want to propose a change, just create a pull request to the main repository within the `jenkinsci` organization.
+Bugs and feature requests can be reported to the [Jenkins issue tracker](https://issues.jenkins-ci.org/secure/Dashboard.jspa) with the `ownership-plugin` component ID.
+
+Jenkins contribution guidelines and developer resources are aggregated [here](https://jenkins.io/participate/).
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 00000000..8e666b01
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,6 @@
+buildPlugin(
+ useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests
+ configurations: [
+ [platform: 'linux', jdk: 21],
+ [platform: 'windows', jdk: 17],
+])
diff --git a/LICENSE b/LICENSE
index 32977329..181da981 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License
-Copyright (c) 2013 Oleg Nenashev , Synopsys Inc.
+Copyright (c) 2013-2017 Oleg Nenashev, Synopsys Inc. and Jenkins contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 0cb376d9..8269dcc3 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,60 @@
-Ownership Plugin
+Ownership Plugin for Jenkins
================
-[Jenkins CI][3] plugin. Provides explicit ownership of jobs and slaves.
-See [Ownership Plugin][4] wiki page for more info.
+[](https://gitter.im/jenkinsci/ownership-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[](https://plugins.jenkins.io/ownership)
+[](https://github.com/jenkinsci/ownership-plugin/releases/latest)
+[](https://plugins.jenkins.io/ownership)
-Contributors
---------
-1. [Oleg Nenashev][2] (maintainer), Synopsys Inc., www.synopsys.com
+This plugin provides an ownership engine for [Jenkins](https://jenkins.io/) automation server.
-License
---------
-[MIT License][1]
+# Supported features
-[1]: http://www.opensource.org/licenses/mit-license.php
-[2]: https://github.com/oleg-nenashev
-[3]: https://jenkins-ci.org/
-[4]: https://wiki.jenkins-ci.org/display/JENKINS/Ownership+Plugin
+* Ownership management for jobs, folders, runs and nodes (Summary boxes, ListView columns, etc.)
+* Injection of ownership variables into the build environment
+* Easy MailTo links for "Contact owners" and "Contact admins" with pre-formatted messages
+* [Ownership-Based Security](doc/OwnershipBasedSecurity.md) (Role Strategy, Job Restrictions, Authorize Project, etc.)
+* Integration with Jenkins Pipeline
+* Ownership Filter for List Views
+
+# Documentation
+
+* [Configuration](doc/Configuration.md)
+* [Ownership-Based Security](doc/OwnershipBasedSecurity.md)
+* [AbstractProject Integration](doc/AbstractProjectSupport.md)
+* [Pipeline Integration](doc/PipelineIntegration.md)
+* [Contributing](CONTRIBUTING.md)
+* [Changelog](CHANGELOG.md)
+
+# Examples
+
+Below you can find several Ownership Plugin UI examples.
+
+Ownership Info Summary box:
+
+
+
+Ownership Column:
+
+
+
+# Plugin Integrations
+
+Ownership Plugin provides integration with multiple Jenkins plugins:
+
+* Role Strategy - see [Ownership-Based Security](doc/OwnershipBasedSecurity.md)
+* Job Restrictions - see [Ownership-Based Security](doc/OwnershipBasedSecurity.md)
+* Authorize Project - see [Ownership-Based Security](doc/OwnershipBasedSecurity.md)
+* Token Macro - see [AbstractProject Integration](doc/AbstractProjectSupport.md)
+* Pipeline - see [Pipeline Integration](doc/PipelineIntegration.md)
+
+The plugin also contributes extension points, which can be used by other plugins.
+
+# License
+
+[MIT License](http://www.opensource.org/licenses/mit-license.php)
+
+# Changelog
+
+See [GitHub releases](https://github.com/jenkinsci/ownership-plugin/releases) for recent releases.
+Changelog for 0.12.1 and older versions is available [here](CHANGELOG.md).
diff --git a/doc/AbstractProjectSupport.md b/doc/AbstractProjectSupport.md
new file mode 100644
index 00000000..89224e2f
--- /dev/null
+++ b/doc/AbstractProjectSupport.md
@@ -0,0 +1,35 @@
+Integration with AbstractProject job types
+===
+
+`AbstractProject` is one of the most widely used abstraction layers of Jenkins.
+Most of the common job types implement it (Freestyle, Matrix, JobDSL, etc.).
+
+### Environment variables
+
+Ownership plugin may contribute Build Environment variables,
+which can be used in custom logic.
+These variables are available from all build steps, including SCM checkout.
+
+Job-specific settings can be configured in the `Build Environment` section of the job configuration.
+In [Global Ownership Settings](Configuration.md) it is possible to enable injection of the ownership variables by default.
+
+On the screenshot below you can find the list of injected environment variables:
+
+
+
+Usage example:
+
+
+
+### Token macro
+
+Particular Jenkins plugins (e.g. Copy Artifact) use [Token Macro](https://plugins.jenkins.io/token-macro) expressions instead of environment variables.
+Though all ownership environment variables are accessible through the `${ENV}` macro, there is also a specialized `${OWNERSHIP}` macro.
+
+Usage: `${OWNERSHIP,var="TODO:varname"}`.
+Possible `varname` values and behavior are similar to the Build Environment variables described above.
+
+Usage example:
+
+
+
diff --git a/doc/Configuration.md b/doc/Configuration.md
new file mode 100644
index 00000000..ef9d8484
--- /dev/null
+++ b/doc/Configuration.md
@@ -0,0 +1,60 @@
+Ownership Plugin Configuration
+=====
+
+Ownership plugin can be flexibly configured via global settings.
+These settings can be found in _`Manage Jenkins`/ `Configure` / `Ownership section`_.
+
+## Top-level settings
+
+This section defines global settings for the plugin.
+The
+
+
+
+Available settings:
+
+* `Require Configure rights` - allows to restrict owner assignment options by the `Item.CONFIGURE` permission.
+If [Ownership-Based Security](OwnershipBasedSecurity.md) is enabled, this control should be unchecked.
+* `Service Owners e-mail` - Email of the service owners.
+It will be used for generation of _Contact service owners_ control in the Ownership Summary Box.
+* `Ownership Management policy` - This option can be used to automatically set up ownership for newly created and copied items.
+ * By default, the ownership won't be set up
+ * `Assign job creators as owners` automatically assigns owners (useful for Ownership-Based security)
+* `Globally Inject ownership variables` - If enabled,
+ownership variables will be automatically injected to all classic job types (Freestyle, Matrix, etc.).
+For Jenkins Pipeline the [`ownership` global variable](PipelineIntegration.md) will be always enabled independently of this setting.
+* `Use a specific e-mail address resolver` - If enabled,
+the plugin will be using only a limited set of email resolvers to determine the user email.
+ * The option may be used to optimize the resolution when plugins with heavy email resolvers are installed (e.g. Subversion or Perforce plugins).
+ * `Fast UI resolver` uses built-in routines of the [Mailer plugin](https://plugins.jenkins.io/mailer) => user e-mails will be resolved by user properties and e-mail suffixes
+* `Setup default permissions for item-specific security` - If enabled,
+ [Ownership-Based Security](OwnershipBasedSecurity.md) will have a custom default settings when the job owner specifies or resets _Item-specific security_ .
+
+## Advanced e-mail options
+
+This section manages the generation of `mailto:/` hyperlinks in Ownership summary boxes.
+
+You can do the following:
+* Enable/Disable visualization of the hyperlinks
+* Specify the email subject and body templates using the `${VALUE}` macros.
+Full list of available macros is specified in the built-in documentation.
+* Change the default email recipient separator
+
+
+
+Below you can find a sample email generated by the plugin:
+
+
+
+## Ownership Display options
+
+This section allows to hide Ownership summary boxes in particular cases.
+Some additional visualization settings are also available in previous sections (e.g. `Advanced e-mail options` allows hiding email links).
+
+
+
+## Ownership Inheritance options
+
+This section contains settings, which allow optimizing ownership inheritance to get a better performance on large-scale instances.
+
+
\ No newline at end of file
diff --git a/doc/OwnershipBasedSecurity.md b/doc/OwnershipBasedSecurity.md
new file mode 100644
index 00000000..af9b457e
--- /dev/null
+++ b/doc/OwnershipBasedSecurity.md
@@ -0,0 +1,93 @@
+Ownership-Based Security
+====
+
+Ownership plugin is heavily focused on the security aspects of Jenkins.
+For such purpose the plugin is integrated with many security-related plugins,
+which effectively create an "Ownership-based" security ecosystem in Jenkins.
+
+This page describes the available integrations with the following plugins:
+
+* [Role-Based Authorization Strategy](https://plugins.jenkins.io/role-strategy)
+* [Job Restrictions](https://plugins.jenkins.io/job-restrictions)
+* [Authorize Project](https://plugins.jenkins.io/authorize-project)
+
+## Role-Based strategy integration
+
+Although it does not offer a special Authorization Strategy,
+it offers a deep integration with the [Role-Strategy Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Role+Strategy+Plugin) via the macro engine.
+
+This macro engine greatly reduces the complexity of the configuration and also greatly improves its performance by avoiding massive regular expression checks for multiple roles.
+
+The documentation below provides details regarding the configuration approach.
+
+### Global Roles
+
+In global roles for almost any instance you have to define the roles for Jenkins administrators and other authenticated users.
+
+Performance notes: Having a globally enabled role for a user greatly improves Role Strategy performance,
+ so it is recommended to do so unless there are any security implications on your instance.
+On the screenshot below the `authenticated` role has no read access to jobs (`Job.Read`).
+
+
+
+### Item and Node roles
+
+The most of the security management goes through the Item and Role nodes.
+There are `@CurrentUserIsOwner` and `CurrentUserIsPrimaryOwner` macros, which are defined in the Role name.
+
+The example below provides a sample configuration, where primary owners have a full access to the job.
+Secondary owners are being managed by the `@CurrentUserIsOwner` macro, and they get less permissions.
+Note that the primary owners are eligible to assign secondary owners and transfer ownership on their own, hence there is no need in involving Jenkins admins for such local changes.
+
+
+
+In the case of advanced setups you can create multiple role macros with different patterns by using an ID parameter, e.g. `@CurrentUserIsOwner(1)` and then `CurrentUserIsOwner(2)` with different regular expressions.
+
+### Role Assignments
+
+For Ownership-Based Strategy Role Assignments just contain mapping of `admin` and `authenticated roles`.
+In order to specify all time- and node- specific permissions,
+ in this setup you just need to specify a single role assignment.
+
+
+
+### Item-Specific Permissions
+
+:exclamation: This is an advanced feature, which allows going beyond two roles.
+Use with caution.
+
+Item-specific permissions can be configured in the `Manage Ownership` action for jobs.
+These permissions may be granted by job owners to particular users (Similar to [Matrix Authorization Strategy](https://plugins.jenkins.io/matrix-auth)).
+
+In order to enable this functionality, use the `@ItemSpecificWithUserID` in item Role definitions.
+
+## Job Restrictions
+
+### Restricting executions on agents
+
+
+
+### Restricting execution on the master
+
+It is a common use-case to restrict job runs on the master for security reasons. Script build steps in on-master builds may get access to Jenkins system files with the Jenkins user account, hence there is a risk of data corruption in the case of erroneous or malicious scripts.
+On the other hand, it may be a valid case for the backend jobs being owned by admins.
+
+:exclamation: The example below restricts all executions.
+Particular job types (e.g. Pipeline) may require executions of particular tasks on the master.
+For this purpose you can use Class Restrictions in the plugin.
+
+
+
+## Authorize Project Plugin
+
+[Authorize Project Plugin](TODO) allows managing authentication for running builds.
+It is pretty important from the Ownership-Based Security strategy point of view, because it allows preventing
+interaction with jobs if the owner has no access to the job.
+
+For this purpose Ownership plugin offers the `Run as Job Owner` Authorize strategy, which can be enabled
+globally or for a particular job.
+
+:exclamation: Please note that not all plugins are properly integrated with the `QueueItemAuthenticator` extension point,
+which is being used in Authorize Project.
+
+
diff --git a/doc/PipelineIntegration.md b/doc/PipelineIntegration.md
new file mode 100644
index 00000000..558d9e03
--- /dev/null
+++ b/doc/PipelineIntegration.md
@@ -0,0 +1,69 @@
+Pipeline Integration
+====
+
+Ownership plugin is integrated with [Jenkins Pipeline](https://jenkins.io/doc/book/pipeline/).
+
+The following features are available:
+
+* Ownership Management in both Pipeline and Multi-branch Pipeline jobs.
+* Inheritance of ownership info from folders by Pipeline and Multi-branch Pipeline jobs.
+* Access to the ownership information via the `ownership` global variable.
+
+## Managing Ownership in Pipeline jobs
+
+Ownership management in Pipeline is similar to other job types.
+All operations can be done in the `Manage Ownership` action if the user has appropriate permissions.
+
+In Multi-Branch Pipeline it is possible to manage ownership only on the top level.
+Fine-grain ownership management for branches is not supported.
+
+## Ownership Global variable
+
+If the Plugin is install, the `ownership` global variable will be available in all jobs.
+The `ownership` variable contains `job` and `node` fields, which represent the required info.
+Both fields are **read-only**, it is not possible to modify the Ownership info from Pipeline.
+
+The `node` variable is available only within the `node()` block scope.
+If it is called outside this block, the behavior is undefined.
+
+### Examples
+
+
+
+The example below demonstrates usage of the `ownership`global variable
+
+```groovy
+stage 'Print Job Ownership Info';
+def primaryOwnerEmail = ownership.job.primaryOwnerEmail
+if (ownership.job.ownershipEnabled) {
+ println "Primary owner ID: ${ownership.job.primaryOwnerId}"
+ println "Primary owner e-mail: ${primaryOwnerEmail}"
+ println "Secondary owner IDs: ${ownership.job.secondaryOwnerIds}"
+ println "Secondary owner e-mails: ${ownership.job.secondaryOwnerEmails}"
+} else {
+ println "Ownership is disabled";
+}
+
+stage 'Send e-mail to the job owner'
+mail to: primaryOwnerEmail,
+ subject: "Job '${env.JOB_NAME}' (${env.BUILD_NUMBER}) is waiting for input",
+ body: "Please go to ${env.BUILD_URL} and verify the build"
+
+```
+
+This example demonstrates usage of the Node ownership info:
+
+```groovy
+stage 'Print Node Ownership Info'
+node('requiredLabel') {
+ echo "Current NODE_NAME = ${env.NODE_NAME}";
+ if (ownership.node.ownershipEnabled) {
+ println "Owner ID: ${ownership.node.primaryOwnerId}"
+ println "Owner e-mail: ${ownership.node.primaryOwnerEmail}"
+ println "Co-owner IDs: ${ownership.node.secondaryOwnerIds}"
+ println "Co-owner e-mails: ${ownership.node.secondaryOwnerEmails}"
+ } else {
+ println "Ownership of ${env.NODE_NAME} is disabled";
+ }
+}
+```
\ No newline at end of file
diff --git a/doc/images/abstractProject/buildWrapper.png b/doc/images/abstractProject/buildWrapper.png
new file mode 100644
index 00000000..a204c426
Binary files /dev/null and b/doc/images/abstractProject/buildWrapper.png differ
diff --git a/doc/images/abstractProject/example_buildStep.png b/doc/images/abstractProject/example_buildStep.png
new file mode 100644
index 00000000..ad668d30
Binary files /dev/null and b/doc/images/abstractProject/example_buildStep.png differ
diff --git a/doc/images/abstractProject/example_tokenMacro.png b/doc/images/abstractProject/example_tokenMacro.png
new file mode 100644
index 00000000..9546915a
Binary files /dev/null and b/doc/images/abstractProject/example_tokenMacro.png differ
diff --git a/doc/images/configuration/displayOptions.png b/doc/images/configuration/displayOptions.png
new file mode 100644
index 00000000..048c95ff
Binary files /dev/null and b/doc/images/configuration/displayOptions.png differ
diff --git a/doc/images/configuration/emailOptions.png b/doc/images/configuration/emailOptions.png
new file mode 100644
index 00000000..e92fc0d2
Binary files /dev/null and b/doc/images/configuration/emailOptions.png differ
diff --git a/doc/images/configuration/inheritanceOptions.png b/doc/images/configuration/inheritanceOptions.png
new file mode 100644
index 00000000..e88d7a8e
Binary files /dev/null and b/doc/images/configuration/inheritanceOptions.png differ
diff --git a/doc/images/configuration/topLevel.png b/doc/images/configuration/topLevel.png
new file mode 100644
index 00000000..35c0d067
Binary files /dev/null and b/doc/images/configuration/topLevel.png differ
diff --git a/doc/images/generatedEmailTemplate.png b/doc/images/generatedEmailTemplate.png
new file mode 100644
index 00000000..7987fc77
Binary files /dev/null and b/doc/images/generatedEmailTemplate.png differ
diff --git a/doc/images/ownerColumn.png b/doc/images/ownerColumn.png
new file mode 100644
index 00000000..e2f5f6f5
Binary files /dev/null and b/doc/images/ownerColumn.png differ
diff --git a/doc/images/ownershipBasedSecurity/authorizeProject_globalConfig.png b/doc/images/ownershipBasedSecurity/authorizeProject_globalConfig.png
new file mode 100644
index 00000000..95095c26
Binary files /dev/null and b/doc/images/ownershipBasedSecurity/authorizeProject_globalConfig.png differ
diff --git a/doc/images/ownershipBasedSecurity/jobrestrictions_commonNode.png b/doc/images/ownershipBasedSecurity/jobrestrictions_commonNode.png
new file mode 100644
index 00000000..fbc3578d
Binary files /dev/null and b/doc/images/ownershipBasedSecurity/jobrestrictions_commonNode.png differ
diff --git a/doc/images/ownershipBasedSecurity/jobrestrictions_masterNode.png b/doc/images/ownershipBasedSecurity/jobrestrictions_masterNode.png
new file mode 100644
index 00000000..4cc0e649
Binary files /dev/null and b/doc/images/ownershipBasedSecurity/jobrestrictions_masterNode.png differ
diff --git a/doc/images/ownershipBasedSecurity/roleStrategy_globalRoles.png b/doc/images/ownershipBasedSecurity/roleStrategy_globalRoles.png
new file mode 100644
index 00000000..378dfe5a
Binary files /dev/null and b/doc/images/ownershipBasedSecurity/roleStrategy_globalRoles.png differ
diff --git a/doc/images/ownershipBasedSecurity/roleStrategy_itemNodeRoles.png b/doc/images/ownershipBasedSecurity/roleStrategy_itemNodeRoles.png
new file mode 100644
index 00000000..337c224c
Binary files /dev/null and b/doc/images/ownershipBasedSecurity/roleStrategy_itemNodeRoles.png differ
diff --git a/doc/images/ownershipBasedSecurity/roleStrategy_roleAssignments.png b/doc/images/ownershipBasedSecurity/roleStrategy_roleAssignments.png
new file mode 100644
index 00000000..87333008
Binary files /dev/null and b/doc/images/ownershipBasedSecurity/roleStrategy_roleAssignments.png differ
diff --git a/doc/images/summaryBox.png b/doc/images/summaryBox.png
new file mode 100644
index 00000000..7731e69b
Binary files /dev/null and b/doc/images/summaryBox.png differ
diff --git a/pom.xml b/pom.xml
index 2fd00394..0f76c6fb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,141 +1,215 @@
-
- 4.0.0
-
- org.jenkins-ci.plugins
- plugin
- 1.509.3
-
-
- com.synopsys.jenkinsci
- ownership
- 0.6-SNAPSHOT
- Job and Slave ownership plugin
- hpi
- Provides explicit ownership of jobs and slaves
- https://wiki.jenkins-ci.org/display/JENKINS/Ownership+Plugin
-
-
-
- MIT License
- http://www.opensource.org/licenses/mit-license.php
- repo
-
-
-
-
- UTF-8
-
-
-
-
- oleg_nenashev
- Oleg Nenashev
- nenashev@synopsys.com; o.v.nenashev@gmail.com
- http://www.synopsys.com
- Synopsys Inc.
-
- maintainer
-
- +4
-
-
-
-
- scm:git:ssh://github.com/jenkinsci/${project.artifactId}-plugin.git
- scm:git:ssh://git@github.com/jenkinsci/${project.artifactId}-plugin.git
- https://github.com/jenkinsci/${project.artifactId}-plugin
- HEAD
-
-
-
-
- repo.jenkins-ci.org
- http://repo.jenkins-ci.org/public/
-
-
-
-
-
- repo.jenkins-ci.org
- http://repo.jenkins-ci.org/public/
-
-
-
-
-
- org.jenkins-ci.plugins
- role-strategy
- 2.1.0
- true
-
-
- org.jenkins-ci.plugins
- token-macro
- 1.6
- true
- jar
-
-
- com.synopsys.arc.jenkinsci.plugins
- job-restrictions
- 0.1
- true
-
-
- org.jenkins-ci.plugins
- authorize-project
- 1.0.2
- true
- jar
-
-
- org.jenkins-ci.plugins
- mailer
- 1.6
- jar
-
-
- org.apache.httpcomponents
- httpclient
- 4.3.4
- jar
-
-
-
-
-
-
-
- maven-deploy-plugin
- 2.8.1
-
-
- maven-release-plugin
- 2.5
-
-
-
-
-
-
-
- m2e
-
-
- m2e.version
-
-
-
-
-
- maven-compiler-plugin
-
- 1.6
- 1.6
-
-
-
-
-
-
-
+
+ 4.0.0
+
+
+ org.jenkins-ci.plugins
+ plugin
+ 5.28
+
+
+
+ com.synopsys.jenkinsci
+ ownership
+ ${changelist}
+ Job and Node ownership plugin
+ hpi
+ Provides explicit ownership of jobs and nodes
+ https://github.com/jenkinsci/ownership-plugin
+
+
+ 999999-SNAPSHOT
+ 2.479.3
+ UTF-8
+
+ Max
+
+
+
+
+ MIT License
+ http://www.opensource.org/licenses/mit-license.php
+ repo
+
+
+
+
+
+
+ oleg_nenashev
+ Oleg Nenashev
+ o.v.nenashev@gmail.com
+
+ maintainer
+
+
+
+
+
+ scm:git:https://github.com/jenkinsci/${project.artifactId}-plugin.git
+ scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git
+ https://github.com/jenkinsci/${project.artifactId}-plugin
+ HEAD
+
+
+
+
+
+ io.jenkins.tools.bom
+ bom-2.479.x
+ 4228.v0a_71308d905b_
+ pom
+ import
+
+
+
+
+
+
+ org.jenkins-ci.plugins
+ role-strategy
+
+ true
+
+
+ org.jenkins-ci.plugins
+ token-macro
+ true
+
+
+ com.synopsys.arc.jenkinsci.plugins
+ job-restrictions
+
+ true
+
+
+ org.jenkins-ci.plugins
+ script-security
+ true
+
+
+ org.jenkins-ci.plugins
+ cloudbees-folder
+ true
+
+
+ org.jenkins-ci.plugins
+ authorize-project
+
+ true
+
+
+ org.jenkins-ci.plugins
+ security-inspector
+ 0.4
+ true
+
+
+ org.kohsuke
+ access-modifier-suppressions
+ 1.34
+ provided
+
+
+
+ org.jenkins-ci.plugins
+ matrix-project
+
+
+ org.jenkins-ci.plugins
+ matrix-auth
+
+
+ org.jenkins-ci.plugins
+ mailer
+
+
+ org.jenkins-ci.plugins
+ apache-httpcomponents-client-4-api
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-cps
+
+
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-step-api
+ tests
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-job
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-basic-steps
+ test
+
+
+ org.jenkins-ci.plugins
+ credentials
+ test
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.11
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ report
+ verify
+
+ report
+
+
+
+ jacoco-check
+
+ check
+
+
+
+
+ PACKAGE
+
+
+ LINE
+ COVEREDRATIO
+ 0.00
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipHelper.java
index 40ca7fa1..702fe23c 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,7 @@
* Adapter for typical ownership operations with different item types.
* Every IOwnership item should provide ownership helper.
* @param Type of object, for which ownership should be resolved
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.0.2
* @see IOwnershipItem
* @see JobOwnerHelper
@@ -95,7 +95,7 @@ public interface IOwnershipHelper {
public boolean isOwnerExists(@Nonnull TObjectType item);
/**
- * Get Display string of the owner (and coowners).
+ * Get Display string of the owner.
* @param item Item to be described
* @return User description string
*/
@@ -106,7 +106,7 @@ public interface IOwnershipHelper {
* Gets ownership description of the requested item.
* @param item Item to be described
* @return Ownership description. The method returns a
- * {@link OwnershipDescription.DISABLED}
+ * {@link OwnershipDescription#DISABLED_DESCR}
* @since 0.0.3
*/
@Nonnull
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipItem.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipItem.java
index 6347261e..6d8736be 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipItem.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/IOwnershipItem.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,7 @@
/**
* Class provides basic methods for ownership handling.
* @param Type of the described object
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.0.3
*/
public interface IOwnershipItem {
@@ -48,7 +48,7 @@ public interface IOwnershipItem {
/**
* Gets ownership description.
- * By default, returns {@link #OwnershipDescription.DISABLED_DESCR}
+ * By default, returns {@link OwnershipDescription#DISABLED_DESCR}
* @return Ownership Description (not null)
*/
@Nonnull
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/ItemOwnershipAction.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/ItemOwnershipAction.java
index e425ba56..47638435 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/ItemOwnershipAction.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/ItemOwnershipAction.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
/**
* Abstract class for ownership actions, which describes item at the floating box.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @param A class, for which action is being created
* @since 0.0.2
*/
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipAction.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipAction.java
index caff65af..d9681855 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipAction.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipAction.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,7 @@
/**
* Provides Floating box with ownership description.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @see ItemOwnershipAction
* @see NodeOwnershipAction
*/
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipDescription.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipDescription.java
index 5ad95a53..75001cbc 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipDescription.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipDescription.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,27 +23,49 @@
*/
package com.synopsys.arc.jenkins.plugins.ownership;
+import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
+import com.synopsys.arc.jenkins.plugins.ownership.util.IdStrategyComparator;
+import com.synopsys.arc.jenkins.plugins.ownership.util.OwnershipDescriptionHelper;
+import com.synopsys.arc.jenkins.plugins.ownership.nodes.OwnerNodeProperty;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Util;
import hudson.model.Descriptor;
+import hudson.model.ModelObject;
import hudson.model.User;
+import hudson.security.ACL;
+import hudson.security.AccessControlled;
+import hudson.security.Permission;
+import java.io.InvalidObjectException;
+import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
+import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
+import org.acegisecurity.AccessDeniedException;
+import org.acegisecurity.Authentication;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted;
+import org.kohsuke.stapler.Stapler;
+import org.kohsuke.stapler.StaplerRequest;
/**
* Contains description of item's ownership.
* This class is a main information entry for all ownership features.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.0.3
*/
public class OwnershipDescription implements Serializable {
+
+ private static final Logger LOGGER = Logger.getLogger(OwnershipDescription.class.getName());
+
/**
* Disabled description, which means that ownership is disabled
*/
@@ -52,6 +74,7 @@ public class OwnershipDescription implements Serializable {
/**
* Indicates if ownership is enabled
*/
+ @Whitelisted
boolean ownershipEnabled;
/**
@@ -60,17 +83,19 @@ public class OwnershipDescription implements Serializable {
String primaryOwnerId;
/**
- * Sids of the co-Owners.
+ * Sids of the secondary owners (fka co-owners).
* Sids can include users and groups.
*/
+ @Whitelisted
Set coownersIds;
/**
* Constructor.
* @param ownershipEnabled indicates that the ownership is enabled
* @param primaryOwnerId userId of primary owner
- * @deprecated Use constructor with co-owners specification
+ * @deprecated Use constructor with secondary owners specification
*/
+ @Deprecated
public OwnershipDescription(boolean ownershipEnabled, @Nonnull String primaryOwnerId) {
this(ownershipEnabled, primaryOwnerId, null);
}
@@ -80,12 +105,12 @@ public OwnershipDescription(boolean ownershipEnabled, @Nonnull String primaryOwn
* Class is being used as DataBound in {@link OwnerNodeProperty}.
* @param ownershipEnabled Indicates that the ownership is enabled.
* @param primaryOwnerId userId of primary owner. Use null if there is no owner
- * @param coownersIds userIds of secondary owners. Use null if there is no co-owners.
+ * @param secondaryOwnerIds userIds of secondary owners. Use {@code null} if there is no secondary owners.
*/
- public OwnershipDescription(boolean ownershipEnabled, @Nullable String primaryOwnerId, @Nullable Collection coownersIds) {
+ public OwnershipDescription(boolean ownershipEnabled, @Nullable String primaryOwnerId, @Nullable Collection secondaryOwnerIds) {
this.ownershipEnabled = ownershipEnabled;
this.primaryOwnerId = primaryOwnerId;
- this.coownersIds = coownersIds != null ? new TreeSet(coownersIds) : new TreeSet();
+ this.coownersIds = secondaryOwnerIds != null ? new TreeSet<>(secondaryOwnerIds) : new TreeSet();
}
public void assign(@Nonnull OwnershipDescription descr) {
@@ -101,10 +126,10 @@ public String toString() {
}
StringBuilder builder = new StringBuilder();
- builder.append("owner=");
+ builder.append("primary owner=");
builder.append(primaryOwnerId);
if (!coownersIds.isEmpty()) {
- builder.append(" co-owners:[");
+ builder.append(" secondary owners:[");
for (String coownerId : coownersIds) {
builder.append(coownerId);
builder.append(' ');
@@ -118,6 +143,7 @@ public String toString() {
* Check if ownership is enabled.
* @return true if ownership is enabled
*/
+ @Whitelisted
public boolean isOwnershipEnabled() {
return ownershipEnabled;
}
@@ -127,6 +153,7 @@ public boolean isOwnershipEnabled() {
* @return userId of the primary owner. The result will be "unknown" if the
* user is not specified.
*/
+ @Whitelisted
public @Nonnull String getPrimaryOwnerId() {
return ownershipEnabled ? primaryOwnerId : User.getUnknown().getId();
}
@@ -138,15 +165,28 @@ public boolean isOwnershipEnabled() {
*/
@CheckForNull
public User getPrimaryOwner() {
- return User.get(primaryOwnerId, false, null);
+ return ownershipEnabled ? User.getById(primaryOwnerId, false) : null;
}
/**
- * Gets list of co-owners.
- * @return Collection of co-owners
+ * Gets list of secondary owners (fka co-owners).
+ * @return Collection of secondary owners
+ * @deprecated use {@link #getSecondaryOwnerIds()}
*/
@Nonnull
+ @Deprecated
public Set getCoownersIds() {
+ return getSecondaryOwnerIds();
+ }
+
+ /**
+ * Gets list of secondary owners.
+ * @return Collection of secondary owners
+ * @since 0.9
+ */
+ @Nonnull
+ @Whitelisted
+ public Set getSecondaryOwnerIds() {
return coownersIds;
}
@@ -154,15 +194,17 @@ public Set getCoownersIds() {
* @deprecated Use {@link #parseJSON(net.sf.json.JSONObject)} instead.
*/
@Nonnull
+ @Deprecated
+ @SuppressFBWarnings(value = "NM_METHOD_NAMING_CONVENTION", justification = "deprecated")
public static OwnershipDescription Parse(JSONObject formData)
throws Descriptor.FormException {
return parseJSON(formData);
}
/**
- * Parse a JSON input to construct {@link OwershipDescription}.
+ * Parse a JSON input to construct the ownership description.
* @param formData Object with a data
- * @return OwnershipDescription
+ * @return Ownership Description
* @throws hudson.model.Descriptor.FormException Parsing error
*/
@Nonnull
@@ -170,25 +212,25 @@ public static OwnershipDescription parseJSON(JSONObject formData)
throws Descriptor.FormException
{
// Read primary owner
- String primaryOwner = formData.getString( "primaryOwner" );
+ String primaryOwnerId = formData.getString( "primaryOwner" );
// Read coowners
- Set coOwnersSet = new TreeSet();
+ Set secondaryOwnerIds = new TreeSet<>();
if (formData.has("coOwners")) {
JSONObject coOwners = formData.optJSONObject("coOwners");
if (coOwners == null) {
for (Object obj : formData.getJSONArray("coOwners")) {
- addUser(coOwnersSet, (JSONObject)obj);
+ addUser(secondaryOwnerIds, (JSONObject)obj);
}
} else {
- addUser(coOwnersSet, coOwners);
+ addUser(secondaryOwnerIds, coOwners);
}
}
- return new OwnershipDescription(true, primaryOwner, coOwnersSet);
+ return new OwnershipDescription(true, primaryOwnerId, secondaryOwnerIds);
}
private static void addUser(Set target, JSONObject userObj) throws Descriptor.FormException {
- String userId = Util.fixEmptyAndTrim(((JSONObject)userObj).getString("coOwner"));
+ String userId = Util.fixEmptyAndTrim(userObj.getString("coOwner"));
//TODO: validate user string
if (userId != null) {
@@ -199,30 +241,206 @@ private static void addUser(Set target, JSONObject userObj) throws Descr
/**
* Check if User is an owner.
* @param user User to be checked
- * @param acceptCoowners Check if user belongs to co-owners
- * @return true if User belongs to primary owners (and/or co-owners)
+ * @param includeSecondaryOwners Check if user belongs to secondary owners
+ * @return {@code true} if the user belongs to primary owners (and/or secondary owners)
*/
- public boolean isOwner(User user, boolean acceptCoowners) {
+ public boolean isOwner(User user, boolean includeSecondaryOwners) {
if (user == null) {
return false;
}
if (isPrimaryOwner(user)) {
return true;
}
- return acceptCoowners ? coownersIds.contains(user.getId()) : false;
+ if (includeSecondaryOwners) {
+ Set coowners = new TreeSet<>(new IdStrategyComparator());
+ coowners.addAll(coownersIds);
+ return coowners.contains(user.getId());
+ }
+ return false;
}
+ @Whitelisted
public boolean hasPrimaryOwner() {
return ownershipEnabled && getPrimaryOwner() != null;
}
-
- public boolean isPrimaryOwner(User user) {
+ /**
+ * Checks if the specified user is a primary owner.
+ * @param user User to be checked
+ * @return {@code true} if the user is a primary owner
+ */
+ public boolean isPrimaryOwner(@CheckForNull User user) {
return user != null && user == getPrimaryOwner();
}
+ /**
+ * Gets ID of the primary owner.
+ * @return userId of the primary owner. The result will be "unknown" if the
+ * user is not specified.
+ * @since 0.9
+ * @deprecated Use {@link #getPrimaryOwnerId()}
+ */
+ @Deprecated
+ public @Nonnull String getOwnerId() {
+ return getPrimaryOwnerId();
+ }
+
+ /**
+ * Gets primary owner's e-mail.
+ * This method utilizes {@link OwnershipPlugin} global configuration to resolve emails.
+ * @return Primary owner's e-mail or empty string if it is not available
+ * @since 0.9
+ * @deprecated Use {@link #getPrimaryOwnerEmail()}
+ */
+ @Nonnull
+ @Deprecated
+ public String getOwnerEmail() {
+ return getPrimaryOwnerEmail();
+ }
+
+ /**
+ * Gets primary owner's e-mail.
+ * This method utilizes {@link OwnershipPlugin} global configuration to resolve emails.
+ * @return Primary owner's e-mail or empty string if it is not available
+ * @since 0.9
+ */
+ @Nonnull
+ @Whitelisted
+ public String getPrimaryOwnerEmail() {
+ return OwnershipDescriptionHelper.getOwnerEmail(this);
+ }
+
+ /**
+ * Gets a comma-separated list of co-owners.
+ * @return List of co-owner user IDs
+ * @deprecated use {@link #getSecondaryOwnerIds()}
+ */
+ @Deprecated
+ public @Nonnull Set getCoOwnerIds() {
+ return coownersIds;
+ }
+
+ /**
+ * Gets e-mails of secondary owners.
+ * This method utilizes {@link OwnershipPlugin} global configuration to resolve emails.
+ * @return List of secondary owner e-mails (may be empty)
+ * @deprecated use {@link #getSecondaryOwnerEmails()}
+ */
+ @Deprecated
+ public @Nonnull Set getCoOwnerEmails() {
+ return OwnershipDescriptionHelper.getSecondaryOwnerEmails(this, false);
+ }
+
+ /**
+ * Gets e-mails of secondary owners.
+ * This method utilizes {@link OwnershipPlugin} global configuration to resolve emails.
+ * @return List of secondary owner e-mails (may be empty)
+ * @since 0.9
+ */
+ @Whitelisted
+ public @Nonnull Set getSecondaryOwnerEmails() {
+ return OwnershipDescriptionHelper.getSecondaryOwnerEmails(this, false);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 41 * hash + (this.ownershipEnabled ? 1 : 0);
+ hash = 41 * hash + (this.primaryOwnerId != null ? this.primaryOwnerId.hashCode() : 0);
+ hash = 41 * hash + (this.coownersIds != null ? this.coownersIds.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final OwnershipDescription other = (OwnershipDescription) obj;
+ if (this.ownershipEnabled != other.ownershipEnabled) {
+ return false;
+ } else if (!this.ownershipEnabled) {
+ // Treat disabled ownership configurations as equal ones
+ return true;
+ }
+
+ if ((this.primaryOwnerId == null) ? (other.primaryOwnerId != null) : !this.primaryOwnerId.equals(other.primaryOwnerId)) {
+ return false;
+ }
+ if (this.coownersIds != other.coownersIds && (this.coownersIds == null || !this.coownersIds.equals(other.coownersIds))) {
+ return false;
+ }
+ return true;
+ }
+
+ protected Object readResolve() throws ObjectStreamException {
+ checkUnsecuredConfiguration();
+ return this;
+ }
+
+ /**
+ * If the ownership is being deserialized because of a REST call or CLI command, we need to
+ * make sure that either the ownership is unchanged, or that the user performing the command
+ * has permission to manage ownership for the object attached to this {@link OwnershipDescription}.
+ */
+ private void checkUnsecuredConfiguration() throws ObjectStreamException {
+ Authentication authentication = Jenkins.getAuthentication();
+ if (authentication == ACL.SYSTEM) {
+ return;
+ }
+ StaplerRequest request = Stapler.getCurrentRequest();
+ if (request != null) {
+ AccessControlled context = request.findAncestorObject(AccessControlled.class);
+ if (context != null) {
+ final AbstractOwnershipHelper helper = OwnershipHelperLocator.locate(context);
+ if (helper != null) {
+ final OwnershipDescription d = helper.getOwnershipDescription(context);
+ if (!helper.hasLocallyDefinedOwnership(context) || !Objects.equals(d, this)) {
+ throwIfMissingPermission(context, helper.getRequiredPermission());
+ }
+ return;
+ } else {
+ LOGGER.log(Level.WARNING, "Cannot locate OwnershipHelperClass for object {0}. " +
+ "Jenkins.ADMINISTER permissions will be required to change ownership", context);
+ }
+ } else {
+ //TODO: maybe it should rejected, because there is no use-cases for it so far AFAIK
+ LOGGER.log(Level.WARNING, "Ownership Description is used outside the object context. " +
+ "Jenkins.ADMINISTER permissions will be required to change ownership");
+ }
+ }
+ // We don't know what object this OwnershipDescription belongs to, so we require Overall/Administer permissions.
+ // CLI commands always use this check.
+ throwIfMissingPermission(Jenkins.get(), Jenkins.ADMINISTER);
+ }
+
+ private void throwIfMissingPermission(@Nonnull AccessControlled context, Permission permission) throws ObjectStreamException {
+ try {
+ context.checkPermission(permission);
+ } catch (AccessDeniedException e) {
+ final String name;
+ if (context instanceof ModelObject) {
+ name = ((ModelObject)context).getDisplayName();
+ } else {
+ name = context.toString();
+ }
+
+ InvalidObjectException ex = new InvalidObjectException(
+ String.format("Cannot modify permissions of %s of type %s: %s", name,
+ context.getClass(), e.getMessage()));
+ ex.addSuppressed(e);
+ throw ex;
+ }
+ }
+
/**
* Check if ownership is enabled.
- * @param descr Ownership description (can be null)
+ * @param descr Ownership description (can be {@code null})
* @return True if the ownership is enabled
* @since 0.1
*/
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPlugin.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPlugin.java
index 9b42b079..bcf1e796 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPlugin.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPlugin.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,11 +28,11 @@
import com.synopsys.arc.jenkins.plugins.ownership.extensions.item_ownership_policy.AssignCreatorPolicy;
import com.synopsys.arc.jenkins.plugins.ownership.extensions.item_ownership_policy.DropOwnershipPolicy;
import com.synopsys.arc.jenkins.plugins.ownership.security.itemspecific.ItemSpecificSecurity;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.ExtensionList;
import hudson.Plugin;
import hudson.Util;
import hudson.model.Descriptor;
-import hudson.model.Hudson;
import hudson.model.User;
import hudson.security.Permission;
import hudson.security.PermissionGroup;
@@ -55,7 +55,7 @@
/**
* Contains global actions and configurations.
* @since 0.0.1
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public class OwnershipPlugin extends Plugin {
@@ -73,22 +73,25 @@ public class OwnershipPlugin extends Plugin {
/**
* @deprecated Replaced by {@link ItemOwnershipPolicy}
*/
+ @Deprecated
private transient boolean assignOnCreate;
- private final List pluginActions = new ArrayList();
- public String mailResolverClassName;
+ private final List pluginActions = new ArrayList<>();
+ private String mailResolverClassName;
private ItemSpecificSecurity defaultJobsSecurity;
private OwnershipPluginConfiguration configuration;
/**
* @deprecated Use {@link #getInstance()} instead
*/
+ @Deprecated
+ @SuppressFBWarnings(value = "NM_METHOD_NAMING_CONVENTION", justification = "deprecated")
public static OwnershipPlugin Instance() {
return getInstance();
}
public static OwnershipPlugin getInstance() {
- Jenkins j = Jenkins.getInstance();
- OwnershipPlugin plugin = j != null ? j.getPlugin(OwnershipPlugin.class) : null;
+ Jenkins j = Jenkins.get();
+ OwnershipPlugin plugin = j.getPlugin(OwnershipPlugin.class);
if (plugin == null) { // Fail horribly
// TODO: throw a graceful error
throw new IllegalStateException("Cannot get the plugin's instance. Jenkins or the plugin have not been initialized yet");
@@ -100,11 +103,11 @@ public static OwnershipPlugin getInstance() {
public void start() throws Exception {
load();
reinitActionsList();
- Hudson.getInstance().getActions().addAll(pluginActions);
+ Jenkins.get().getActions().addAll(pluginActions);
}
@Override
- protected void load() throws IOException {
+ public void load() throws IOException {
super.load();
// Migration to 1.5.0: Check ItemOwnershipPolicy
@@ -124,9 +127,10 @@ public boolean isRequiresConfigureRights() {
/**
* @deprecated This method is deprecated since 0.5
- * @return true if the {@link #itemOwnershipPolicy} is an instance of
+ * @return {@code true} if the Item ownership policy is an instance of
* {@link AssignCreatorPolicy}.
*/
+ @Deprecated
public boolean isAssignOnCreate() {
return (getConfiguration().getItemOwnershipPolicy() instanceof AssignCreatorPolicy);
}
@@ -168,13 +172,13 @@ public void configure(boolean requiresConfigureRights, String mailResolverClassN
reinitActionsList();
save();
- Hudson.getInstance().getActions().addAll(pluginActions);
+ Jenkins.get().getActions().addAll(pluginActions);
}
@Override
public void configure(StaplerRequest req, JSONObject formData)
throws IOException, ServletException, Descriptor.FormException {
- Hudson.getInstance().getActions().removeAll(pluginActions);
+ Jenkins.get().getActions().removeAll(pluginActions);
requiresConfigureRights = formData.getBoolean("requiresConfigureRights");
// Configurations
@@ -193,7 +197,7 @@ public void configure(StaplerRequest req, JSONObject formData)
reinitActionsList();
save();
- Hudson.getInstance().getActions().addAll(pluginActions);
+ Jenkins.get().getActions().addAll(pluginActions);
}
private void reinitActionsList() {
@@ -232,7 +236,7 @@ public FormValidation doCheckUser(@QueryParameter String userId) {
return FormValidation.error("Field is empty. Field will be ignored");
}
- User usr = User.get(userId, false, null);
+ User usr = User.getById(userId, false);
if (usr == null) {
return FormValidation.warning("User " + userId + " is not registered in Jenkins");
}
@@ -254,12 +258,16 @@ public String resolveEmail(User user) {
} else {
Class resolverClass = (Class)Class.forName(mailResolverClassName);
MailAddressResolver res = MailAddressResolver.all().get(resolverClass);
- return res.findMailAddressFor(user);
+ if (res != null) {
+ return res.findMailAddressFor(user);
+ }
}
}
} catch (ClassNotFoundException ex) {
// Do nothing - fallback do default handler
}
+ //TODO: ClassCastException (bug)
+ //TODO: methods above should log errors
return MailAddressResolver.resolve(user);
}
@@ -267,7 +275,7 @@ public String resolveEmail(User user) {
@Nonnull
public Collection getPossibleMailResolvers() {
ExtensionList extensions = MailAddressResolver.all();
- List items =new ArrayList(extensions.size());
+ List items = new ArrayList<>(extensions.size());
items.add(FAST_RESOLVER_ID);
for (MailAddressResolver resolver : extensions) {
items.add(resolver.getClass().getCanonicalName());
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPluginConfiguration.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPluginConfiguration.java
index 91aacb3f..6b4fff45 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPluginConfiguration.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/OwnershipPluginConfiguration.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,13 +31,15 @@
import hudson.model.Descriptor;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import org.jenkinsci.plugins.ownership.config.DisplayOptions;
+import org.jenkinsci.plugins.ownership.config.InheritanceOptions;
import org.jenkinsci.plugins.ownership.model.runs.OwnershipRunListener;
import org.jenkinsci.plugins.ownership.util.environment.EnvSetupOptions;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* Configuration of {@link OwnershipPlugin}.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.5
*/
public class OwnershipPluginConfiguration
@@ -45,6 +47,9 @@ public class OwnershipPluginConfiguration
private final ItemOwnershipPolicy itemOwnershipPolicy;
private final @CheckForNull MailOptions mailOptions;
+ private final @CheckForNull DisplayOptions displayOptions;
+ private final @CheckForNull InheritanceOptions inheritanceOptions;
+
/**
* Enforces the injection of ownership variables in {@link OwnershipRunListener}.
* Null means the injection is disabled.
@@ -52,27 +57,57 @@ public class OwnershipPluginConfiguration
*/
private final @CheckForNull EnvSetupOptions globalEnvSetupOptions;
+ @Deprecated
+ public OwnershipPluginConfiguration(@Nonnull ItemOwnershipPolicy itemOwnershipPolicy,
+ @Nonnull MailOptions mailOptions, EnvSetupOptions globalEnvSetupOptions,
+ @Nonnull DisplayOptions displayOptions) {
+ this(itemOwnershipPolicy, mailOptions, globalEnvSetupOptions, displayOptions, InheritanceOptions.DEFAULT);
+ }
+
@DataBoundConstructor
public OwnershipPluginConfiguration(@Nonnull ItemOwnershipPolicy itemOwnershipPolicy,
- @Nonnull MailOptions mailOptions, EnvSetupOptions globalEnvSetupOptions) {
+ @Nonnull MailOptions mailOptions, EnvSetupOptions globalEnvSetupOptions,
+ @Nonnull DisplayOptions displayOptions, @Nonnull InheritanceOptions inheritanceOptions) {
this.itemOwnershipPolicy = itemOwnershipPolicy;
this.mailOptions = mailOptions;
this.globalEnvSetupOptions = globalEnvSetupOptions;
+ this.displayOptions = displayOptions;
+ this.inheritanceOptions = inheritanceOptions;
}
@Deprecated
public OwnershipPluginConfiguration(@Nonnull ItemOwnershipPolicy itemOwnershipPolicy) {
this (itemOwnershipPolicy, MailOptions.DEFAULT, null);
}
+
+ @Deprecated
+ public OwnershipPluginConfiguration(@Nonnull ItemOwnershipPolicy itemOwnershipPolicy,
+ @Nonnull MailOptions mailOptions, EnvSetupOptions globalEnvSetupOptions) {
+ this(itemOwnershipPolicy, mailOptions, globalEnvSetupOptions, DisplayOptions.DEFAULT);
+ }
public @Nonnull ItemOwnershipPolicy getItemOwnershipPolicy() {
- return itemOwnershipPolicy;
+ return itemOwnershipPolicy != null ? itemOwnershipPolicy : ItemOwnershipPolicy.getDefault();
}
public @Nonnull MailOptions getMailOptions() {
return mailOptions != null ? mailOptions : MailOptions.DEFAULT;
}
+ /**
+ * Gets {@link OwnershipPlugin}'s display options.
+ * @return Display options. If the configuration has not been specified after the plugin update,
+ * {@link DisplayOptions#DEFAULT} will be returned.
+ * @since 0.8
+ */
+ public @Nonnull DisplayOptions getDisplayOptions() {
+ return displayOptions != null ? displayOptions : DisplayOptions.DEFAULT;
+ }
+
+ public InheritanceOptions getInheritanceOptions() {
+ return inheritanceOptions != null ? inheritanceOptions : InheritanceOptions.DEFAULT;
+ }
+
/**
* @return Global environment inject options. Null - global setup is disabled
* @since 0.6
@@ -97,4 +132,14 @@ public String getDisplayName() {
}
}
+
+ /**
+ * Gets the {@link OwnershipPlugin} configuration.
+ * @return The plugin configuration if available.
+ * @throws IllegalStateException Jenkins instance is not ready
+ * @since 0.8
+ */
+ public static OwnershipPluginConfiguration get() {
+ return OwnershipPlugin.getInstance().getConfiguration();
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicy.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicy.java
index dfc06a50..e03361cc 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicy.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicy.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,7 @@
package com.synopsys.arc.jenkins.plugins.ownership.extensions;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import com.synopsys.arc.jenkins.plugins.ownership.extensions.item_ownership_policy.DropOwnershipPolicy;
import hudson.DescriptorExtensionList;
import hudson.ExtensionPoint;
import hudson.model.Describable;
@@ -33,15 +34,29 @@
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Implements an ownership changes policy for {@link Item}s.
* This policy defines actions to be implemented if specific changes in jobs occur.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public abstract class ItemOwnershipPolicy
implements ExtensionPoint, Describable {
+ private static final ItemOwnershipPolicy DEFAULT = new DropOwnershipPolicy();
+
+ /**
+ * Returns default Item Ownership Policy, which should be assigned on first startup.
+ * @return Ownership policy
+ */
+ @Nonnull
+ @Restricted(NoExternalUse.class)
+ public static ItemOwnershipPolicy getDefault() {
+ return DEFAULT;
+ }
+
/**
* A handler for newly created items.
* By default, the ownership won't be set.
@@ -67,7 +82,8 @@ public abstract class ItemOwnershipPolicy
@Override
public ItemOwnershipPolicyDescriptor getDescriptor() {
- return (ItemOwnershipPolicyDescriptor) Jenkins.getInstance().getDescriptorOrDie(getClass());
+ return (ItemOwnershipPolicyDescriptor) Jenkins.get()
+ .getDescriptorOrDie(getClass());
}
/**
@@ -75,8 +91,8 @@ public ItemOwnershipPolicyDescriptor getDescriptor() {
* @return List of {@link ItemOwnershipPolicy}s.
*/
public static DescriptorExtensionList all() {
- return Jenkins.getInstance().
- getDescriptorList(ItemOwnershipPolicy.class);
+ //TODO: rework to Extension list Lookup
+ return Jenkins.get().getDescriptorList(ItemOwnershipPolicy.class);
}
/**
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicyDescriptor.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicyDescriptor.java
index 3fbe54fe..c6efea6f 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicyDescriptor.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/ItemOwnershipPolicyDescriptor.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,7 @@
/**
* Defines a descriptor for {@link ItemOwnershipPolicy}.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public abstract class ItemOwnershipPolicyDescriptor
extends Descriptor {
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/OwnershipLayoutFormatterProvider.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/OwnershipLayoutFormatterProvider.java
index 4b0adb90..cea8ee55 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/OwnershipLayoutFormatterProvider.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/OwnershipLayoutFormatterProvider.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev .
+ * Copyright 2014 Oleg Nenashev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -35,25 +35,25 @@
/**
* The extension creates {@link OwnershipLayoutFormatter}s for various object types.
* @since 0.5
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
@Restricted(NoExternalUse.class)
public abstract class OwnershipLayoutFormatterProvider {
public static final OwnershipLayoutFormatterProvider DEFAULT_PROVIDER = new DefaultProvider();
- private static final OwnershipLayoutFormatter> DEFAULT_JOB_FORMATTER = new OwnershipLayoutFormatter.DefaultJobFormatter>();
- private static final OwnershipLayoutFormatter DEFAULT_NODE_FORMATTER = new OwnershipLayoutFormatter.DefaultJobFormatter();
- private static final OwnershipLayoutFormatter DEFAULT_RUN_FORMATTER = new OwnershipLayoutFormatter.DefaultJobFormatter();
+ private static final OwnershipLayoutFormatter> DEFAULT_JOB_FORMATTER = new OwnershipLayoutFormatter.DefaultJobFormatter<>();
+ private static final OwnershipLayoutFormatter DEFAULT_NODE_FORMATTER = new OwnershipLayoutFormatter.DefaultJobFormatter<>();
+ private static final OwnershipLayoutFormatter DEFAULT_RUN_FORMATTER = new OwnershipLayoutFormatter.DefaultJobFormatter<>();
- public @Nonnull OwnershipLayoutFormatter> getLayoutFormatter(@Nonnull Job,?> job) {
+ public @Nonnull OwnershipLayoutFormatter> getLayoutFormatter(Job,?> job) {
return DEFAULT_JOB_FORMATTER;
}
- public @Nonnull OwnershipLayoutFormatter getLayoutFormatter(@Nonnull Node node) {
+ public @Nonnull OwnershipLayoutFormatter getLayoutFormatter(Node node) {
return DEFAULT_NODE_FORMATTER;
}
- public @Nonnull OwnershipLayoutFormatter getLayoutFormatter(@Nonnull Run run) {
+ public @Nonnull OwnershipLayoutFormatter getLayoutFormatter(Run run) {
return DEFAULT_RUN_FORMATTER;
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/AssignCreatorPolicy.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/AssignCreatorPolicy.java
index 8da79d69..2109dc62 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/AssignCreatorPolicy.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/AssignCreatorPolicy.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,13 +30,12 @@
import com.synopsys.arc.jenkins.plugins.ownership.extensions.ItemOwnershipPolicyDescriptor;
import hudson.Extension;
import hudson.model.Item;
-import hudson.model.Job;
import hudson.model.User;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* A policy, which sets the item creator as an owner.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.5
*/
public class AssignCreatorPolicy extends ItemOwnershipPolicy {
@@ -48,7 +47,7 @@ public AssignCreatorPolicy() {
@Override
public OwnershipDescription onCreated(Item item) {
User creator = User.current();
- if (creator != null && creator != User.getUnknown() && item instanceof Job) {
+ if (creator != null && creator != User.getUnknown()) {
return new OwnershipDescription(true, creator.getId(), null);
}
@@ -60,7 +59,7 @@ public static class DescriptorImpl extends ItemOwnershipPolicyDescriptor {
@Override
public String getDisplayName() {
- return Messages.ItemOwnershipPolicy_AssignCreatorPolicy_dipslayName();
+ return Messages.ItemOwnershipPolicy_AssignCreatorPolicy_displayName();
}
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/CopyOwnerPolicy.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/CopyOwnerPolicy.java
index edf83a9b..1b2c33e6 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/CopyOwnerPolicy.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/CopyOwnerPolicy.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,12 +24,15 @@
package com.synopsys.arc.jenkins.plugins.ownership.extensions.item_ownership_policy;
-import com.synopsys.arc.jenkins.plugins.ownership.extensions.ItemOwnershipPolicy;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
- *
- * @author Oleg Nenashev
+ * @deprecated Not implemented
+ * @author Oleg Nenashev
*/
+@Restricted(NoExternalUse.class)
+@Deprecated
public class CopyOwnerPolicy {
//TODO: implement
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/DropOwnershipPolicy.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/DropOwnershipPolicy.java
index 9fa2009f..262de454 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/DropOwnershipPolicy.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/extensions/item_ownership_policy/DropOwnershipPolicy.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,7 +34,7 @@
/**
* A policy, which drops the project's ownership.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.5
*/
public class DropOwnershipPolicy extends ItemOwnershipPolicy {
@@ -58,7 +58,7 @@ public static class DescriptorImpl extends ItemOwnershipPolicyDescriptor {
@Override
public String getDisplayName() {
- return Messages.ItemOwnershipPolicy_DropOwnershipPolicy_dipslayName();
+ return Messages.ItemOwnershipPolicy_DropOwnershipPolicy_displayName();
}
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerColumn.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerColumn.java
index 8cce3dc9..5bc5b784 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerColumn.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerColumn.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,15 +24,21 @@
package com.synopsys.arc.jenkins.plugins.ownership.jobs;
import com.synopsys.arc.jenkins.plugins.ownership.Messages;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
import org.kohsuke.stapler.DataBoundConstructor;
import hudson.Extension;
-import hudson.model.Job;
+import hudson.model.Item;
+import hudson.model.User;
import hudson.views.ListViewColumnDescriptor;
import hudson.views.ListViewColumn;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
/**
* Provides Ownership column for the list view.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.1
*/
public class JobOwnerColumn extends ListViewColumn {
@@ -42,12 +48,25 @@ public JobOwnerColumn() {
super();
}
- public String getJobOwner(@SuppressWarnings("rawtypes") Job job) {
- return JobOwnerHelper.Instance.getOwner(job);
+ @Nonnull
+ public String getJobOwner(Item item) {
+ final OwnershipDescription description = getDescription(item);
+ return description != null ? description.getPrimaryOwnerId() : User.getUnknown().getId();
}
- public boolean isOwnerExists(@SuppressWarnings("rawtypes") Job job) {
- return JobOwnerHelper.Instance.isOwnerExists(job);
+ public boolean isOwnerExists(Item item) {
+ final OwnershipDescription description = getDescription(item);
+ return description != null ? description.hasPrimaryOwner(): false;
+ }
+
+ @CheckForNull
+ private OwnershipDescription getDescription(Item item) {
+ AbstractOwnershipHelper- helper = OwnershipHelperLocator.locate(item);
+ if (helper == null) {
+ // We cannot retrieve helper for the object => keep moving
+ return null;
+ }
+ return helper.getOwnershipDescription(item);
}
@Extension
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerHelper.java
index 73f09769..2ee65a46 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,39 +25,48 @@
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPluginConfiguration;
import com.synopsys.arc.jenkins.plugins.ownership.security.itemspecific.ItemSpecificSecurity;
import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
import com.synopsys.arc.jenkins.plugins.ownership.util.UserCollectionFilter;
import com.synopsys.arc.jenkins.plugins.ownership.util.userFilters.AccessRightsFilter;
import com.synopsys.arc.jenkins.plugins.ownership.util.userFilters.IUserFilter;
-import com.synopsys.arc.jenkins.plugins.ownership.wrappers.OwnershipBuildWrapper;
+import hudson.Extension;
import hudson.matrix.MatrixConfiguration;
-import hudson.model.AbstractBuild;
+import hudson.model.Item;
+import hudson.model.ItemGroup;
import hudson.model.Job;
import hudson.model.JobProperty;
-import hudson.model.Project;
import hudson.model.User;
import java.io.IOException;
import java.util.Collection;
-import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.jenkinsci.plugins.ownership.model.OwnershipInfo;
+import org.jenkinsci.plugins.ownership.model.jobs.JobOwnershipDescriptionSource;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+
/**
* Helper for Jobs Ownership.
* @since 0.0.3
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public class JobOwnerHelper extends AbstractOwnershipHelper> {
public final static JobOwnerHelper Instance = new JobOwnerHelper();
/**
- * Gets JobOwnerProperty from job if possible.
+ * Gets {@link JobOwnerJobProperty} from the job if possible.
* The function also handles multi-configuration jobs, so it should be used
* wherever it is possible.
+ * This method should not be used to retrieve Ownership descriptions,
+ * because it does not take inheritance into account.
* @param job Job
- * @return JobOwnerJobProperty or null if it is not configured
+ * @return JobOwnerJobProperty or {@code null} if it is not configured
*/
@CheckForNull
public static JobOwnerJobProperty getOwnerProperty(@Nonnull Job,?> job) {
@@ -80,14 +89,57 @@ public static boolean isUserExists(@Nonnull User user) {
}
public static boolean isUserExists(@Nonnull String userIdOrFullName) {
- assert (userIdOrFullName != null);
- return User.get(userIdOrFullName, false, null) != null;
+ return User.getById(userIdOrFullName, false) != null;
}
@Override
public @Nonnull OwnershipDescription getOwnershipDescription(@Nonnull Job, ?> job) {
+ // TODO: Maybe makes sense to unwrap the method to get a better performance (esp. for Security)
+ return getOwnershipInfo(job).getDescription();
+ }
+
+ @Override
+ public Permission getRequiredPermission() {
+ return OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP;
+ }
+
+ @Override
+ public boolean hasLocallyDefinedOwnership(@Nonnull Job, ?> job) {
+ return getOwnerProperty(job) != null;
+ }
+
+ @Override
+ public OwnershipInfo getOwnershipInfo(Job, ?> job) {
JobOwnerJobProperty prop = getOwnerProperty(job);
- return (prop != null) ? prop.getOwnership() : OwnershipDescription.DISABLED_DESCR;
+ if (prop != null) {
+ OwnershipDescription d = prop.getOwnership();
+ if (d.isOwnershipEnabled()) {
+ // If Ownership on this level is enabled, we return it
+ return new OwnershipInfo(d, new JobOwnershipDescriptionSource(job));
+ }
+ }
+
+ // We go to upper items in order to get the ownership description
+ if (!OwnershipPluginConfiguration.get().getInheritanceOptions().isBlockInheritanceFromItemGroups()) {
+ ItemGroup parent = job.getParent();
+ AbstractOwnershipHelper located = OwnershipHelperLocator.locate(parent);
+ while (located != null) {
+ OwnershipInfo fromParent = located.getOwnershipInfo(parent);
+ if (fromParent.getDescription().isOwnershipEnabled()) {
+ return fromParent;
+ }
+ if (parent instanceof Item) {
+ Item parentItem = (Item)parent;
+ parent = parentItem.getParent();
+ located = OwnershipHelperLocator.locate(parent);
+ } else {
+ located = null;
+ }
+ }
+ }
+
+ // Fallback: we have not found the Ownership using known approaches
+ return OwnershipInfo.DISABLED_INFO;
}
/**
@@ -146,4 +198,17 @@ public String getItemDisplayName(Job, ?> item) {
public String getItemURL(Job, ?> item) {
return item.getUrl();
}
+
+ @Extension
+ @Restricted(NoExternalUse.class)
+ public static class LocatorImpl extends OwnershipHelperLocator> {
+
+ @Override
+ public AbstractOwnershipHelper> findHelper(Object item) {
+ if (item instanceof Job,?>) {
+ return Instance;
+ }
+ return null;
+ }
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobAction.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobAction.java
index 6ada8384..07182ff4 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobAction.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobAction.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,6 +27,7 @@
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
import com.synopsys.arc.jenkins.plugins.ownership.security.itemspecific.ItemSpecificSecurity;
+import hudson.model.Item;
import hudson.model.Descriptor;
import hudson.model.Job;
@@ -45,12 +46,13 @@
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
+import org.kohsuke.stapler.interceptor.RequirePOST;
/**
* Ownership action for jobs.
* The action displays "Manage Ownership" action on the left panel.
* Actually, this action injects {@link JobOwnerJobProperty} into the project.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public class JobOwnerJobAction extends ItemOwnershipAction> {
@@ -68,6 +70,7 @@ public JobOwnerHelper helper() {
* Gets described job.
* @deprecated Just for compatibility with 0.0.1
*/
+ @Deprecated
public Job, ?> getJob() {
return getDescribedItem();
}
@@ -122,25 +125,29 @@ public ItemSpecificSecurity.ItemSpecificDescriptor getItemSpecificDescriptor() {
@Override
public boolean actionIsAvailable() {
- return getDescribedItem().hasPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
+ // Action should be available to anyone with READ permission on the item
+ // Individual methods will check MANAGE_ITEMS_OWNERSHIP and return 403 if needed
+ return getDescribedItem().hasPermission(Item.READ);
}
+ @RequirePOST
public HttpResponse doOwnersSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, UnsupportedEncodingException, ServletException, Descriptor.FormException {
- getDescribedItem().hasPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
+ getDescribedItem().checkPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
- JSONObject jsonOwnership = (JSONObject) req.getSubmittedForm().getJSONObject("owners");
+ JSONObject jsonOwnership = req.getSubmittedForm().getJSONObject("owners");
OwnershipDescription descr = OwnershipDescription.parseJSON(jsonOwnership);
JobOwnerHelper.setOwnership(getDescribedItem(), descr);
return HttpResponses.redirectViaContextPath(getDescribedItem().getUrl());
}
+ @RequirePOST
public HttpResponse doProjectSpecificSecuritySubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException {
- getDescribedItem().hasPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
+ getDescribedItem().checkPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
JSONObject form = req.getSubmittedForm();
if (form.containsKey("itemSpecificSecurity")) {
- JSONObject jsonSpecificSecurity = (JSONObject) req.getSubmittedForm().getJSONObject("itemSpecificSecurity");
+ JSONObject jsonSpecificSecurity = req.getSubmittedForm().getJSONObject("itemSpecificSecurity");
ItemSpecificSecurity specific = ItemSpecificSecurity.DESCRIPTOR.newInstance(req, jsonSpecificSecurity);
JobOwnerHelper.setProjectSpecificSecurity(getDescribedItem(), specific);
} else { // drop security
@@ -150,8 +157,9 @@ public HttpResponse doProjectSpecificSecuritySubmit(StaplerRequest req, StaplerR
return HttpResponses.redirectViaContextPath(getDescribedItem().getUrl());
}
+ @RequirePOST
public HttpResponse doRestoreDefaultSpecificSecuritySubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException {
- getDescribedItem().hasPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
+ getDescribedItem().checkPermission(OwnershipPlugin.MANAGE_ITEMS_OWNERSHIP);
// Get default security
ItemSpecificSecurity defaultJobsSecurity = OwnershipPlugin.getInstance().getDefaultJobsSecurity();
ItemSpecificSecurity val = defaultJobsSecurity != null ? defaultJobsSecurity.clone() : null;
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobProperty.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobProperty.java
index 52cf4994..06937582 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobProperty.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/JobOwnerJobProperty.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -40,30 +40,37 @@
import hudson.Extension;
import hudson.model.Descriptor;
+import hudson.model.Items;
import hudson.model.Job;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import hudson.model.User;
+import hudson.util.XStream2;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.Collection;
import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import org.kohsuke.stapler.StaplerResponse;
/**
* Ownership job property.
- * @todo Implement generic approaches from 0.0.3
- * @author Oleg Nenashev
+ * TODO: Implement generic approaches from 0.0.3
+ * @author Oleg Nenashev
* @since 0.0.1
*/
public class JobOwnerJobProperty extends JobProperty>
implements IOwnershipItem>
{
+ @CheckForNull
OwnershipDescription ownership;
- /**Additional matrix with project security*/
+ /**
+ * Additional matrix with project security
+ */
+ @CheckForNull
ItemSpecificSecurity itemSpecificSecurity;
@DataBoundConstructor
@@ -82,10 +89,10 @@ public OwnershipDescription getOwnership() {
* The function returns a default configuration if security is not
* configured. Use {@link #hasItemSpecificSecurity() hasItemSpecificSecurity}
* to check an origin of permissions.
- * @return ItemSpecific security or null if it is not configured
+ * @return ItemSpecific security or {@code null} if it is not configured
* @since 0.3
*/
- @Nonnull
+ @CheckForNull
public ItemSpecificSecurity getItemSpecificSecurity() {
return itemSpecificSecurity != null
? itemSpecificSecurity
@@ -102,7 +109,7 @@ public boolean hasItemSpecificSecurity() {
}
public String getDisplayName(User usr) {
- return JobOwnerHelper.Instance.getDisplayName(usr);
+ return JobOwnerHelper.Instance.getDisplayName(usr);
}
public Collection getUsers()
@@ -147,12 +154,16 @@ public boolean isApplicable(Class extends Job> jobType) {
@Override
public String toString() {
- return ownership.toString();
+ StringBuilder bldr = new StringBuilder();
+ bldr.append(ownership != null ? ownership.toString() : "ownership not set");
+ bldr.append(" ");
+ bldr.append(itemSpecificSecurity != null ? "with specific permissions" : "without specific permissions");
+ return bldr.toString();
}
public void doOwnersSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, UnsupportedEncodingException, ServletException, Descriptor.FormException {
JSONObject formData = req.getSubmittedForm();
- JSONObject jsonOwnership = (JSONObject) formData.getJSONObject("owners");
+ JSONObject jsonOwnership = formData.getJSONObject("owners");
setOwnershipDescription(OwnershipDescription.parseJSON(jsonOwnership));
}
@@ -165,4 +176,14 @@ public void setItemSpecificSecurity(@CheckForNull ItemSpecificSecurity security)
itemSpecificSecurity = security;
owner.save();
}
+
+ static {
+ // TODO: Remove reflection once baseline is updated past 2.85.
+ try {
+ Method m = XStream2.class.getMethod("addCriticalField", Class.class, String.class);
+ m.invoke(Items.XSTREAM2, JobOwnerJobProperty.class, "ownership");
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipActionFactory.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipActionFactory.java
index 560faeb9..8bb99133 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipActionFactory.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipActionFactory.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,28 +25,36 @@
import hudson.Extension;
import hudson.matrix.MatrixConfiguration;
-import hudson.model.AbstractProject;
import hudson.model.Action;
-import hudson.model.TransientProjectActionFactory;
+import hudson.model.Job;
import java.util.Collection;
import static java.util.Collections.singleton;
import java.util.LinkedList;
+import jenkins.model.TransientActionFactory;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Creates a "Manage Ownership" action for jobs.
* Action will be available for all top-level job items.
* Matrix configurations will be ignored.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
*/
@Extension
-public class OwnershipActionFactory extends TransientProjectActionFactory {
+@Restricted(NoExternalUse.class)
+public class OwnershipActionFactory extends TransientActionFactory {
/**Empty actions collection for invalid project type*/
private static final Collection extends Action> EMPTY_ACTIONS
- = new LinkedList();
+ = new LinkedList<>();
@Override
- public Collection extends Action> createFor(AbstractProject target) {
+ public Collection extends Action> createFor(Job target) {
return (target instanceof MatrixConfiguration)
? EMPTY_ACTIONS : singleton(new JobOwnerJobAction(target));
}
+
+ @Override
+ public Class type() {
+ return Job.class;
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipItemListener.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipItemListener.java
index b2a2978c..6f5a00a5 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipItemListener.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipItemListener.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,7 +37,7 @@
* applies and modifies its ownership info.
* By default, the plugin drops initial ownership settings.
* It can also set the current user as a new owner (can be enabled in global configs).
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
*/
@Extension
public class OwnershipItemListener extends ItemListener {
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipJobFilter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipJobFilter.java
index e455e9c4..49c7c57c 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipJobFilter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/jobs/OwnershipJobFilter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,10 +25,10 @@
import com.synopsys.arc.jenkins.plugins.ownership.Messages;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
import com.synopsys.arc.jenkins.plugins.ownership.util.userFilters.UserComparator;
import com.synopsys.arc.jenkins.plugins.ownership.util.UserWrapper;
import hudson.Extension;
-import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.TopLevelItem;
import hudson.model.User;
@@ -39,13 +39,15 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import javax.annotation.Nonnull;
import net.sf.json.JSONObject;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
/**
- * Filters owner's and co-owners.
- * @author Oleg Nenashev
+ * Filters jobs by primary and secondary owners.
+ * @author Oleg Nenashev
* @since 0.1
*/
public class OwnershipJobFilter extends ViewJobFilter {
@@ -62,9 +64,22 @@ public String getOwnerName() {
return ownerId;
}
+ /**
+ * @deprecated use {@link #isAcceptSecondaryOwners()}
+ */
+ @Deprecated
public boolean isAcceptsCoowners() {
return acceptsCoowners;
}
+
+ /**
+ * Enables checking of secondary owners
+ * @return
+ * @since TODO
+ */
+ public boolean isAcceptSecondaryOwners() {
+ return acceptsCoowners;
+ }
public boolean isSelected(UserWrapper usr) {
return ownerId.equals(usr.getId());
@@ -78,32 +93,35 @@ public OwnershipJobFilter(String ownerName, boolean acceptCoowners) {
@Override
public List filter(List added, List all, View filteringView) {
- final ArrayList newList = new ArrayList();
+ final ArrayList newList = new ArrayList<>();
final UserWrapper userWrapper = new UserWrapper(ownerId);
for (TopLevelItem item : added) {
- if (item instanceof AbstractProject) { // Ignore non-project items
- AbstractProject project = (AbstractProject) item;
- OwnershipDescription ownership = JobOwnerHelper.Instance.getOwnershipDescription(project);
- if (!ownership.isOwnershipEnabled()) {
- continue;
- }
+ AbstractOwnershipHelper helper = OwnershipHelperLocator.locate(item);
+ if (helper == null) {
+ // We cannot retrieve helper for the object => keep moving
+ continue;
+ }
+
+ OwnershipDescription ownership = helper.getOwnershipDescription(item);
+ if (!ownership.isOwnershipEnabled()) {
+ continue;
+ }
- boolean matches = false; // Check owner
- if (userWrapper.meetsMacro(ownership.getPrimaryOwnerId())) {
- matches = true;
- }
- if (acceptsCoowners && !matches) { // Check co-owners
- for (String coOwnerId : ownership.getCoownersIds()) {
- if (userWrapper.meetsMacro(coOwnerId)) {
- matches = true;
- break;
- }
+ boolean matches = false; // Check owner
+ if (userWrapper.meetsMacro(ownership.getPrimaryOwnerId())) {
+ matches = true;
+ }
+ if (acceptsCoowners && !matches) { // Check secondary owners
+ for (String coOwnerId : ownership.getSecondaryOwnerIds()) {
+ if (userWrapper.meetsMacro(coOwnerId)) {
+ matches = true;
+ break;
}
}
- if (matches) {
- newList.add(item);
- }
+ }
+ if (matches) {
+ newList.add(item);
}
}
@@ -132,14 +150,15 @@ public ViewJobFilter newInstance(StaplerRequest req, JSONObject formData) throws
*
* @return Collection of all registered users
*/
+ @Nonnull
public static Collection getAvailableUsers() {
// Sort users
UserComparator comparator = new UserComparator();
- LinkedList userList = new LinkedList(User.getAll());
+ LinkedList userList = new LinkedList<>(User.getAll());
Collections.sort(userList, comparator);
// Prepare new list
- Collection res = new ArrayList(userList.size() + 1);
+ Collection res = new ArrayList<>(userList.size() + 1);
res.add(new UserWrapper(MACRO_ME));
for (User user : userList) {
res.add(new UserWrapper(user));
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/ComputerOwnerHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/ComputerOwnerHelper.java
index 7325b8ec..c8495267 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/ComputerOwnerHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/ComputerOwnerHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,42 +24,60 @@
package com.synopsys.arc.jenkins.plugins.ownership.nodes;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
+import hudson.Extension;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.User;
import java.io.IOException;
import java.util.Collection;
+import java.util.Collections;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.jenkinsci.plugins.ownership.model.OwnershipInfo;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+
/**
* Provides ownership helper for {@link Computer}.
* The class implements a wrapper of {@link NodeOwnerHelper}.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
*/
public class ComputerOwnerHelper extends AbstractOwnershipHelper {
- static final ComputerOwnerHelper Instance = new ComputerOwnerHelper();
+ static final ComputerOwnerHelper INSTANCE = new ComputerOwnerHelper();
public static ComputerOwnerHelper getInstance() {
- return Instance;
+ return INSTANCE;
}
@Override
public OwnershipDescription getOwnershipDescription(@Nonnull Computer item) {
+ // TODO: This method impl is a performance hack. May be replaced by getOwnershipInfo() in 1.0
Node node = item.getNode();
return node != null
? NodeOwnerHelper.Instance.getOwnershipDescription(node)
: OwnershipDescription.DISABLED_DESCR; // No node - no ownership
}
-
+
+ @Override
+ public OwnershipInfo getOwnershipInfo(Computer item) {
+ Node node = item.getNode();
+ return node != null
+ ? NodeOwnerHelper.Instance.getOwnershipInfo(node)
+ : OwnershipInfo.DISABLED_INFO;
+ }
+
@Override
public Collection getPossibleOwners(@Nonnull Computer computer) {
Node node = computer.getNode();
return node != null
? NodeOwnerHelper.Instance.getPossibleOwners(node)
- : EMPTY_USERS_COLLECTION;
+ : Collections.emptyList();
}
public static void setOwnership(@Nonnull Computer computer,
@@ -72,17 +90,47 @@ public static void setOwnership(@Nonnull Computer computer,
NodeOwnerHelper.setOwnership(node, descr);
}
+ @Override
+ public Permission getRequiredPermission() {
+ return OwnershipPlugin.MANAGE_SLAVES_OWNERSHIP;
+ }
+
+ @Override
+ public boolean hasLocallyDefinedOwnership(@Nonnull Computer computer) {
+ Node node = computer.getNode();
+ if (node == null) {
+ // Node is not defined => permission is detached
+ return false;
+ }
+ return NodeOwnerHelper.Instance.hasLocallyDefinedOwnership(node);
+ }
+
@Override
public String getItemTypeName(Computer item) {
return "computer";
}
+ @Override
public String getItemDisplayName(Computer item) {
return item.getDisplayName();
}
+ @Override
public String getItemURL(Computer item) {
//TODO: Absolute URL
return item.getUrl();
}
+
+ @Extension
+ @Restricted(NoExternalUse.class)
+ public static class LocatorImpl extends OwnershipHelperLocator {
+
+ @Override
+ public AbstractOwnershipHelper findHelper(Object item) {
+ if (item instanceof Computer) {
+ return INSTANCE;
+ }
+ return null;
+ }
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerHelper.java
index 6b684981..dc59c2a1 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,20 +29,29 @@
import com.synopsys.arc.jenkins.plugins.ownership.util.UserCollectionFilter;
import com.synopsys.arc.jenkins.plugins.ownership.util.userFilters.AccessRightsFilter;
import com.synopsys.arc.jenkins.plugins.ownership.util.userFilters.IUserFilter;
+import hudson.Extension;
import hudson.model.Computer;
+import hudson.model.Job;
import hudson.model.Node;
import hudson.model.User;
-import hudson.slaves.NodeProperty;
+
import java.io.IOException;
import java.util.Collection;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.jenkinsci.plugins.ownership.model.OwnershipInfo;
+import org.jenkinsci.plugins.ownership.model.nodes.NodeOwnershipDescriptionSource;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+
/**
* Provides helper for Node owner.
- * @todo Add Bug reference
+ * TODO: Add Bug reference
* @since 0.0.3
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @see OwnerNodeProperty
*/
public class NodeOwnerHelper extends AbstractOwnershipHelper {
@@ -57,12 +66,12 @@ public class NodeOwnerHelper extends AbstractOwnershipHelper {
*/
@CheckForNull
public static OwnerNodeProperty getOwnerProperty(@Nonnull Node node) {
- NodeProperty prop = node.getNodeProperties().get(OwnerNodeProperty.class);
- return prop != null ? (OwnerNodeProperty)prop : null;
+ return node.getNodeProperties().get(OwnerNodeProperty.class);
}
@Override
- public OwnershipDescription getOwnershipDescription(Node item) {
+ public OwnershipDescription getOwnershipDescription(@CheckForNull Node item) {
+ // TODO: This method impl is a performance hack. May be replaced by getOwnershipInfo() in 1.0
if (item == null) { // Handle renames, etc.
return OwnershipDescription.DISABLED_DESCR;
}
@@ -70,7 +79,28 @@ public OwnershipDescription getOwnershipDescription(Node item) {
OwnerNodeProperty prop = getOwnerProperty(item);
return prop != null ? prop.getOwnership() : OwnershipDescription.DISABLED_DESCR;
}
-
+
+ @Override
+ public OwnershipInfo getOwnershipInfo(Node item) {
+ if (item == null) { // Handle renames, etc.
+ return OwnershipInfo.DISABLED_INFO;
+ }
+
+ OwnerNodeProperty prop = getOwnerProperty(item);
+ return prop != null ? new OwnershipInfo(OwnershipDescription.DISABLED_DESCR,
+ new NodeOwnershipDescriptionSource(item)) : OwnershipInfo.DISABLED_INFO;
+ }
+
+ @Override
+ public Permission getRequiredPermission() {
+ return OwnershipPlugin.MANAGE_SLAVES_OWNERSHIP;
+ }
+
+ @Override
+ public boolean hasLocallyDefinedOwnership(@Nonnull Node node) {
+ return getOwnerProperty(node) != null;
+ }
+
@Override
public Collection getPossibleOwners(Node item) {
if (OwnershipPlugin.getInstance().isRequiresConfigureRights()) {
@@ -111,6 +141,19 @@ public String getItemDisplayName(Node item) {
@Override
public String getItemURL(Node item) {
Computer c = item.toComputer();
- return c != null ? ComputerOwnerHelper.Instance.getItemURL(c) : null;
+ return c != null ? ComputerOwnerHelper.INSTANCE.getItemURL(c) : null;
+ }
+
+ @Extension
+ @Restricted(NoExternalUse.class)
+ public static class LocatorImpl extends OwnershipHelperLocator {
+
+ @Override
+ public AbstractOwnershipHelper findHelper(Object item) {
+ if (item instanceof Node) {
+ return Instance;
+ }
+ return null;
+ }
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerPropertyHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerPropertyHelper.java
index 7b56cfe1..b8b3c9a8 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerPropertyHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerPropertyHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,18 +27,28 @@
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
import com.synopsys.arc.jenkins.plugins.ownership.util.UserCollectionFilter;
+import hudson.Extension;
+import hudson.model.Job;
import hudson.model.Node;
import hudson.model.User;
+import hudson.security.Permission;
import hudson.slaves.NodeProperty;
import java.util.Collection;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.jenkinsci.plugins.ownership.model.OwnershipInfo;
+import org.jenkinsci.plugins.ownership.model.nodes.NodeOwnershipDescriptionSource;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+
/**
* Provides helper for Node owner
* @since 0.0.3
- * @author Oleg Nenashev
- * @see OwnerNodeProperty, NodeOwnerHelper
+ * @author Oleg Nenashev
+ * @see OwnerNodeProperty
+ * @see NodeOwnerHelper
*/
public class NodeOwnerPropertyHelper extends AbstractOwnershipHelper {
@@ -57,10 +67,20 @@ private static OwnerNodeProperty getOwnerProperty(@CheckForNull NodeProperty nod
@Nonnull
@Override
public OwnershipDescription getOwnershipDescription(@CheckForNull NodeProperty item) {
+ // TODO: This method impl is a performance hack. May be replaced by getOwnershipInfo() in 1.0
OwnerNodeProperty prop = getOwnerProperty(item);
OwnershipDescription descr = (prop != null) ? prop.getOwnership() : null;
return descr != null ? descr : OwnershipDescription.DISABLED_DESCR;
}
+
+ @Override
+ public OwnershipInfo getOwnershipInfo(NodeProperty item) {
+ OwnerNodeProperty prop = getOwnerProperty(item);
+ OwnershipDescription descr = (prop != null) ? prop.getOwnership() : null;
+ return descr != null
+ ? new OwnershipInfo(descr, new NodeOwnershipDescriptionSource(getNode(item)))
+ : OwnershipInfo.DISABLED_INFO;
+ }
@Nonnull
@Override
@@ -81,6 +101,17 @@ public Collection getPossibleOwners(NodeProperty item) {
return null;
}
+ @Override
+ public Permission getRequiredPermission() {
+ return OwnershipPlugin.MANAGE_SLAVES_OWNERSHIP;
+ }
+
+ @Override
+ public boolean hasLocallyDefinedOwnership(@Nonnull NodeProperty item) {
+ // Self-defined
+ return true;
+ }
+
@Override
public String getItemTypeName(NodeProperty item) {
return NodeOwnerHelper.ITEM_TYPE_NAME;
@@ -96,5 +127,18 @@ public String getItemDisplayName(NodeProperty item) {
public String getItemURL(NodeProperty item) {
Node node = getNode(item);
return node != null ? NodeOwnerHelper.Instance.getItemURL(node) : null;
- }
+ }
+
+ @Extension
+ @Restricted(NoExternalUse.class)
+ public static class LocatorImpl extends OwnershipHelperLocator {
+
+ @Override
+ public AbstractOwnershipHelper findHelper(Object item) {
+ if (item instanceof NodeProperty) {
+ return Instance;
+ }
+ return null;
+ }
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerWrapper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerWrapper.java
index 1c2e4a63..d7f9cabf 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerWrapper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnerWrapper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,13 +24,15 @@
package com.synopsys.arc.jenkins.plugins.ownership.nodes;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import java.util.Collections;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* Data-bound wrapper for slave ownership initialization.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @see OwnerNodeProperty
*/
public class NodeOwnerWrapper {
@@ -39,7 +41,9 @@ public class NodeOwnerWrapper {
@DataBoundConstructor
public NodeOwnerWrapper(@CheckForNull String primaryOwner) {
- description = new OwnershipDescription(primaryOwner!=null, primaryOwner);
+ description = StringUtils.isBlank(primaryOwner)
+ ? OwnershipDescription.DISABLED_DESCR
+ : new OwnershipDescription(true, primaryOwner, Collections.emptyList());
}
@Nonnull
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnershipAction.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnershipAction.java
index 42b9d0d9..08fb3bee 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnershipAction.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/NodeOwnershipAction.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -49,7 +49,7 @@
/**
* Node ownership action.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
public class NodeOwnershipAction extends ItemOwnershipAction {
@@ -75,7 +75,7 @@ public Permission getProjectSpecificPermission() {
@Override
public IOwnershipHelper helper() {
- return ComputerOwnerHelper.Instance;
+ return ComputerOwnerHelper.INSTANCE;
}
@Override
@@ -90,7 +90,7 @@ public OwnershipDescription getOwnership() {
* @return
*/
public static String getAbsoluteUrl(@Nonnull Computer computer) {
- String r = Jenkins.getInstance().getRootUrl();
+ String r = Jenkins.get().getRootUrl();
if(r==null) {
throw new IllegalStateException("Root URL isn't configured yet. Cannot compute absolute URL.");
}
@@ -98,9 +98,9 @@ public static String getAbsoluteUrl(@Nonnull Computer computer) {
}
public HttpResponse doOwnersSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, UnsupportedEncodingException, ServletException, Descriptor.FormException {
- getDescribedItem().hasPermission(OwnershipPlugin.MANAGE_SLAVES_OWNERSHIP);
+ getDescribedItem().checkPermission(OwnershipPlugin.MANAGE_SLAVES_OWNERSHIP);
- JSONObject jsonOwnership = (JSONObject) req.getSubmittedForm().getJSONObject("owners");
+ JSONObject jsonOwnership = req.getSubmittedForm().getJSONObject("owners");
OwnershipDescription descr = OwnershipDescription.parseJSON(jsonOwnership);
ComputerOwnerHelper.setOwnership(getDescribedItem(), descr);
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnerNodeProperty.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnerNodeProperty.java
index 814c29ab..c692e155 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnerNodeProperty.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnerNodeProperty.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,16 +25,20 @@
import com.synopsys.arc.jenkins.plugins.ownership.IOwnershipHelper;
import com.synopsys.arc.jenkins.plugins.ownership.IOwnershipItem;
-import com.synopsys.arc.jenkins.plugins.ownership.Messages;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
import com.synopsys.arc.jenkins.plugins.ownership.util.ui.OwnershipLayoutFormatter;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.model.Descriptor;
import hudson.model.Node;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import hudson.slaves.SlaveComputer;
+import hudson.util.XStream2;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.List;
import javax.annotation.CheckForNull;
import jenkins.model.Jenkins;
@@ -45,8 +49,7 @@
/**
* Implements owner property for Jenkins Nodes.
- * @author Oleg Nenashev
- * @deprecated Will be removed in future versions
+ * @author Oleg Nenashev
* @since 0.0.3
*/
public class OwnerNodeProperty extends NodeProperty
@@ -72,15 +75,18 @@ public OwnershipDescription getOwnership() {
return ownership != null ? ownership : OwnershipDescription.DISABLED_DESCR;
}
- public void setOwnershipDescription(OwnershipDescription descr) {
+ public void setOwnershipDescription(OwnershipDescription descr) throws IOException {
ownership = descr;
- getDescriptor().save();
+ Node node = getNode();
+ if (node != null) {
+ node.save();
+ }
}
@CheckForNull
public Node getNode() {
if (node == null) {
- setNode(Jenkins.getInstance().getNode(nodeName));
+ setNode(Jenkins.get().getNode(nodeName));
}
return node;
}
@@ -118,7 +124,7 @@ public static class DescriptorImpl extends NodePropertyDescriptor {
* @return Instance of the node, which is being configured (or null)
*
* @since 0.0.5
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
private static Node getNodePropertyOwner(StaplerRequest req)
{
@@ -138,13 +144,24 @@ private static Node getNodePropertyOwner(StaplerRequest req)
}
@Override
+ @SuppressFBWarnings(value = "NP_NONNULL_RETURN_VIOLATION", justification = "TODO: should be fixed, see jenkinsci PR #1880")
public String getDisplayName() {
return null;
}
-
+
@Override
public boolean isApplicable( Class extends Node> Type ) {
return true;
}
}
+
+ static {
+ // TODO: Remove reflection once baseline is updated past 2.85.
+ try {
+ Method m = XStream2.class.getMethod("addCriticalField", Class.class, String.class);
+ m.invoke(Jenkins.XSTREAM2, OwnerNodeProperty.class, "ownership");
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipActionFactory.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipActionFactory.java
index 11f34300..bf4d5cdd 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipActionFactory.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipActionFactory.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@
/**
* Generates ownership actions for the Jenkins nodes.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
@Extension
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipNodeMonitor.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipNodeMonitor.java
index de1ffc19..a69bc9e1 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipNodeMonitor.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/nodes/OwnershipNodeMonitor.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,7 @@
/**
* Implements monitoring of ownership.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.4
*/
public class OwnershipNodeMonitor extends NodeMonitor {
@@ -51,6 +51,12 @@ public AbstractNodeMonitorDescriptor> getDescriptor() {
public static class DescriptorImpl extends AbstractNodeMonitorDescriptor {
+ //TODO: no need to use AsyncNodeMonitor from the performance PoV, but there is no supported sync option in the core
+ DescriptorImpl() {
+ // Check every 10 minutes
+ super(1000*60*10L);
+ }
+
@Override
protected Data monitor(Computer c) throws IOException, InterruptedException {
OwnershipDescription ownership = ComputerOwnerHelper.getInstance().getOwnershipDescription(c);
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/authorizeproject/OwnershipAuthorizeProjectStrategy.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/authorizeproject/OwnershipAuthorizeProjectStrategy.java
index dbb13c3a..d50910fb 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/authorizeproject/OwnershipAuthorizeProjectStrategy.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/authorizeproject/OwnershipAuthorizeProjectStrategy.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2014 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,13 +28,12 @@
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerHelper;
import hudson.Extension;
-import hudson.model.AbstractProject;
+import hudson.model.Job;
import hudson.model.Queue;
import hudson.model.User;
-import java.util.Collections;
import jenkins.model.Jenkins;
-import org.acegisecurity.Authentication;
-import org.acegisecurity.userdetails.UsernameNotFoundException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.jenkinsci.plugins.authorizeproject.AuthorizeProjectStrategy;
import org.jenkinsci.plugins.authorizeproject.AuthorizeProjectStrategyDescriptor;
import org.kohsuke.stapler.DataBoundConstructor;
@@ -44,7 +43,7 @@
* This strategy authenticates as a job's owner if it is specified.
* Otherwise, the anonymous user will be used.
* @since 0.5
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public class OwnershipAuthorizeProjectStrategy extends AuthorizeProjectStrategy {
@@ -53,20 +52,19 @@ public OwnershipAuthorizeProjectStrategy() {
}
@Override
- public Authentication authenticate(AbstractProject, ?> ap, Queue.Item item) {
- OwnershipDescription d = JobOwnerHelper.Instance.getOwnershipDescription(ap);
+ public Authentication authenticate(Job, ?> job, Queue.Item item) {
+ OwnershipDescription d = JobOwnerHelper.Instance.getOwnershipDescription(job);
if (!d.hasPrimaryOwner()) { // fallback to anonymous
- return Jenkins.ANONYMOUS;
+ return Jenkins.ANONYMOUS2;
}
- User owner = User.get(d.getPrimaryOwnerId(), false, Collections.emptyMap());
+ User owner = User.getById(d.getPrimaryOwnerId(), false);
if (owner == null) { // fallback to anonymous
- return Jenkins.ANONYMOUS;
+ return Jenkins.ANONYMOUS2;
}
try {
- Authentication auth = owner.impersonate();
- return (auth != null) ? auth : Jenkins.ANONYMOUS;
+ return owner.impersonate2();
} catch (UsernameNotFoundException ex) { // fallback to anonymous
- return Jenkins.ANONYMOUS;
+ return Jenkins.ANONYMOUS2;
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/itemspecific/ItemSpecificSecurity.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/itemspecific/ItemSpecificSecurity.java
index 9608857c..3da8db18 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/itemspecific/ItemSpecificSecurity.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/itemspecific/ItemSpecificSecurity.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,8 @@
import hudson.model.Descriptor;
import hudson.security.AuthorizationMatrixProperty;
import hudson.security.Permission;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
@@ -36,13 +38,14 @@
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
+import org.jenkinsci.plugins.matrixauth.PermissionEntry;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
/**
* Implements item-specific property map.
* This class relies on {@link AuthorizationMatrixProperty} from Jenkins core.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.3
*/
public class ItemSpecificSecurity implements Describable, Cloneable {
@@ -71,7 +74,18 @@ public ItemSpecificSecurity clone() {
ItemSpecificSecurity newItem;
try {
newItem = (ItemSpecificSecurity)super.clone();
- newItem.permissionsMatrix = new AuthorizationMatrixProperty(this.permissionsMatrix.getGrantedPermissions());
+ // Use getGrantedPermissionEntries() instead of deprecated getGrantedPermissions()
+ Map> permissionEntries = this.permissionsMatrix.getGrantedPermissionEntries();
+ // Convert PermissionEntry to String (SID) for the constructor
+ Map> permissions = new TreeMap<>();
+ for (Map.Entry> entry : permissionEntries.entrySet()) {
+ Set sids = new HashSet<>();
+ for (PermissionEntry permEntry : entry.getValue()) {
+ sids.add(permEntry.getSid());
+ }
+ permissions.put(entry.getKey(), sids);
+ }
+ newItem.permissionsMatrix = new AuthorizationMatrixProperty(permissions);
return newItem;
} catch (CloneNotSupportedException ex) {
Logger.getLogger(ItemSpecificSecurity.class.getName()).log(Level.SEVERE, null, ex);
@@ -92,8 +106,10 @@ public String getDisplayName() {
public ItemSpecificSecurity newInstance(StaplerRequest req, JSONObject formData) throws FormException {
AuthorizationMatrixProperty prop = null;
if (formData.containsKey("permissionsMatrix")) {
- Descriptor d= Jenkins.getInstance().getDescriptor(AuthorizationMatrixProperty.class);
- prop = (AuthorizationMatrixProperty)d.newInstance(req, formData.getJSONObject("permissionsMatrix"));
+ Descriptor> d= Jenkins.get().getDescriptor(AuthorizationMatrixProperty.class);
+ if (d != null) {
+ prop = (AuthorizationMatrixProperty)d.newInstance(req, formData.getJSONObject("permissionsMatrix"));
+ }
}
return new ItemSpecificSecurity(prop);
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/jobrestrictions/OwnersListJobRestriction.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/jobrestrictions/OwnersListJobRestriction.java
index 4c61cb2f..95d3ece3 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/jobrestrictions/OwnersListJobRestriction.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/jobrestrictions/OwnersListJobRestriction.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,9 +26,11 @@
import com.synopsys.arc.jenkins.plugins.ownership.Messages;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerHelper;
+import com.synopsys.arc.jenkins.plugins.ownership.util.IdStrategyComparator;
import com.synopsys.arc.jenkins.plugins.ownership.util.ui.UserSelector;
import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.JobRestriction;
import com.synopsys.arc.jenkinsci.plugins.jobrestrictions.restrictions.JobRestrictionDescriptor;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.model.Job;
import hudson.model.Queue;
@@ -40,9 +42,11 @@
/**
* Allows to restrict job executions by ownership.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
+@SuppressFBWarnings(value = "SE_NO_SERIALVERSIONID",
+ justification = "JobRestriction should not be serializable, not required for Xstream")
public class OwnersListJobRestriction extends JobRestriction {
private static final JobOwnerHelper helper = new JobOwnerHelper();
@@ -60,7 +64,7 @@ public OwnersListJobRestriction(List usersList, boolean acceptsCoO
protected synchronized final void updateUsersMap() {
if (usersMap == null) {
// Update users map
- usersMap = new TreeSet();
+ usersMap = new TreeSet<>(new IdStrategyComparator());
for (UserSelector selector : usersList) {
String userId = hudson.Util.fixEmptyAndTrim(selector.getSelectedUserId());
if (userId != null && !usersMap.contains(userId)) {
@@ -74,10 +78,23 @@ public List getUsersList() {
return usersList;
}
+ /**
+ * @deprecated use {@link #isAcceptSecondaryOwners() }
+ */
+ @Deprecated
public boolean isAcceptsCoOwners() {
return acceptsCoOwners;
}
+ /**
+ * Checks if the filter accepts secondary owners.
+ * @return {@code true} if secondary owners should be accepted
+ * @since 0.9
+ */
+ public boolean isAcceptSecondaryOwners() {
+ return acceptsCoOwners;
+ }
+
@Override
public boolean canTake(Queue.BuildableItem item) {
if (item.task instanceof Job) {
@@ -101,22 +118,25 @@ private boolean canTake(OwnershipDescription descr) {
return false;
}
- updateUsersMap();
- if (usersMap.contains(descr.getPrimaryOwnerId())) {
- return true;
- }
-
- // Handle co-owners if required
- Set itemCoOwners = descr.getCoownersIds();
- if (acceptsCoOwners && !itemCoOwners.isEmpty()) {
- for (String userID : usersMap) {
- if (itemCoOwners.contains(userID)) {
- return true;
+ synchronized(this) {
+ updateUsersMap();
+ if (usersMap.contains(descr.getPrimaryOwnerId())) {
+ return true;
+ }
+
+ // Handle secondary owners if required
+ Set itemCoOwners = new TreeSet<>(new IdStrategyComparator());
+ itemCoOwners.addAll(descr.getSecondaryOwnerIds());
+ if (acceptsCoOwners && !itemCoOwners.isEmpty()) {
+ for (String userID : usersMap) {
+ if (itemCoOwners.contains(userID)) {
+ return true;
+ }
}
}
}
- // Default fallback - user is not owner or co-owner
+ // Default fallback - user is not a primary or secondary owner
return false;
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/AbstractOwnershipRoleMacro.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/AbstractOwnershipRoleMacro.java
index 89295ed8..61ddba31 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/AbstractOwnershipRoleMacro.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/AbstractOwnershipRoleMacro.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,33 +23,38 @@
*/
package com.synopsys.arc.jenkins.plugins.ownership.security.rolestrategy;
-import com.synopsys.arc.jenkins.plugins.ownership.IOwnershipItem;
+import com.synopsys.arc.jenkins.plugins.ownership.IOwnershipHelper;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
-import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerHelper;
-import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerJobProperty;
-import com.synopsys.arc.jenkins.plugins.ownership.nodes.OwnerNodeProperty;
+import com.synopsys.arc.jenkins.plugins.ownership.nodes.NodeOwnerHelper;
+import com.michelin.cio.hudson.plugins.rolestrategy.PermissionEntry;
import com.synopsys.arc.jenkins.plugins.rolestrategy.Macro;
import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleMacroExtension;
import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
import static com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType.Project;
import static com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType.Slave;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.model.Computer;
-import hudson.model.Job;
+import hudson.model.Item;
import hudson.model.Node;
import hudson.model.User;
import hudson.security.AccessControlled;
+import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+
+import javax.annotation.CheckForNull;
/**
* An abstract class for {@link RoleMacroExtension}s provided by the ownership plugin.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.1
*/
-abstract class AbstractOwnershipRoleMacro extends RoleMacroExtension {
+public abstract class AbstractOwnershipRoleMacro extends RoleMacroExtension {
public static final String NO_SID_SUFFIX="NoSid";
protected static final String AUTHENTICATED_SID = "authenticated";
@Override
+ @SuppressFBWarnings(value = "NM_METHOD_NAMING_CONVENTION", justification = "Part of other plugin API")
public boolean IsApplicable(RoleType roleType) {
switch (roleType) {
case Project:
@@ -62,15 +67,12 @@ public boolean IsApplicable(RoleType roleType) {
}
public static OwnershipDescription getOwnership(RoleType type, AccessControlled item) {
- IOwnershipItem ownership = null;
+ //TODO refactor the code to use OwnershipHelperLocator
switch(type) {
case Project:
- if (item instanceof Job) {
- Job prj = (Job)item;
- JobOwnerJobProperty prop = JobOwnerHelper.getOwnerProperty(prj);
- if (prop != null) {
- ownership = prop;
- }
+ if (item instanceof Item) {
+ IOwnershipHelper helper = OwnershipHelperLocator.locate(item);
+ return helper != null ? helper.getOwnershipDescription(item) : OwnershipDescription.DISABLED_DESCR;
}
break;
case Slave:
@@ -78,21 +80,68 @@ public static OwnershipDescription getOwnership(RoleType type, AccessControlled
Computer comp = (Computer)item;
Node node = comp.getNode();
if (node != null) {
- ownership = node.getNodeProperties().get(OwnerNodeProperty.class);
+ return NodeOwnerHelper.Instance.getOwnershipDescription(node);
}
}
break;
default:
//do nothing => Ownership is disabled
}
- return ownership != null ? ownership.getOwnership() : OwnershipDescription.DISABLED_DESCR;
+
+ // Fallback to the disabled Ownership description
+ return OwnershipDescription.DISABLED_DESCR;
+ }
+
+ /**
+ * Checks if a user has the permission defined for this macro.
+ * @param user User
+ * @param type Role type
+ * @param item Item, for which permissions are being checked
+ * @param macro Macro expression
+ * @param acceptSecondaryOwners {@code true} if secondary owners should be considered
+ * @return {@code true} if the macro provides a permission.
+ * Always {@code false} if the user is {@code null}.
+ */
+ public static boolean hasPermission(@CheckForNull User user, RoleType type, AccessControlled item,
+ Macro macro, boolean acceptSecondaryOwners) {
+ return user != null && getOwnership(type, item).isOwner(user, acceptSecondaryOwners);
}
- public static boolean hasPermission(User user, RoleType type, AccessControlled item, Macro macro, boolean acceptCoowners) {
- //TODO: implement
- if (user == null) {
+ /**
+ * New API method with PermissionEntry.
+ * Extracts SID from PermissionEntry and delegates to the old method.
+ */
+ @Override
+ public boolean hasPermission(PermissionEntry entry, Permission p, RoleType type, AccessControlled item, Macro macro) {
+ // Extract SID from PermissionEntry
+ // Check for null entry first
+ if (entry == null) {
return false;
- }
- return getOwnership(type, item).isOwner(user, acceptCoowners);
+ }
+
+ String sid = entry.getSid();
+ // Check for null or empty SID - deny access in such cases
+ if (sid == null || sid.trim().isEmpty()) {
+ return false;
+ }
+
+ return hasPermission(sid, p, type, item, macro);
+ }
+
+ /**
+ * Legacy method signature - kept for backward compatibility.
+ * Subclasses should override this method.
+ */
+ public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
+ // Check for null or empty SID - deny access in such cases
+ if (sid == null) {
+ return false;
+ }
+ if (sid.trim().isEmpty()) {
+ return false;
+ }
+
+ User user = User.getById(sid, false);
+ return hasPermission(user, type, item, macro, false);
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacro.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacro.java
index 0e9ee835..764a0fd1 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacro.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacro.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,11 +33,11 @@
import hudson.security.Permission;
/**
- * Checks if the user belongs to owners or co-owners of the item.
- * @author Oleg Nenashev , Synopsys Inc.
+ * Checks if the user belongs to primary or secondary owners of the item.
+ * @author Oleg Nenashev
* @since 0.2
*/
-@Extension(optional = true)
+@Extension(optional = true, ordinal = -1000)
public class CoOwnerRoleMacro extends AbstractOwnershipRoleMacro {
@Override
@@ -51,8 +51,16 @@ public String getDescription() {
}
@Override
- public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
- User user = User.get(sid, false, null);
+ public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
+ // Check for null or empty SID - deny access in such cases
+ if (sid == null) {
+ return false;
+ }
+ if (sid.trim().isEmpty()) {
+ return false;
+ }
+
+ User user = User.getById(sid, false);
return hasPermission(user, type, item, macro, true);
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacroNoSid.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacroNoSid.java
index 3fa66495..e32b23aa 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacroNoSid.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/CoOwnerRoleMacroNoSid.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,13 +31,16 @@
import hudson.model.User;
import hudson.security.AccessControlled;
import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.integrations.rolestrategy.macros.CurrentUserIsOwnerMacro;
/**
- * Checks if the current user belongs to owners or co-owners of the item (w/o sid control).
- * @author Oleg Nenashev , Synopsys Inc.
+ * Checks if the current user is a primary or secondary owner of the item (w/o sid control).
+ * @author Oleg Nenashev
* @since 0.2
+ * @deprecated Use {@link CurrentUserIsOwnerMacro}
*/
-@Extension(optional = true)
+@Deprecated
+@Extension(optional = true, ordinal = -1000)
public class CoOwnerRoleMacroNoSid extends AbstractOwnershipRoleMacro{
@Override
@@ -52,7 +55,7 @@ public String getDescription() {
@Override
public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
- User user = User.current();
+ User user = User.current();
return hasPermission(user, type, item, macro, true);
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacro.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacro.java
index 8d0588be..3ba08afe 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacro.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacro.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@
import com.synopsys.arc.jenkins.plugins.ownership.security.itemspecific.ItemSpecificSecurity;
import com.synopsys.arc.jenkins.plugins.rolestrategy.Macro;
import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.model.Job;
import hudson.security.AccessControlled;
@@ -36,10 +37,10 @@
/**
* Macro invokes evaluation of item-specific access rights.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.4
*/
-@Extension(optional = true)
+@Extension(optional = true, ordinal = -5)
public class ItemSpecificRoleMacro extends AbstractOwnershipRoleMacro {
@Override
@@ -53,6 +54,7 @@ public String getDescription() {
}
@Override
+ @SuppressFBWarnings(value = "NM_METHOD_NAMING_CONVENTION", justification = "Part of other plugin API")
public boolean IsApplicable(RoleType roleType) {
return roleType == RoleType.Project;
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacroWithUserID.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacroWithUserID.java
index 85c754c3..998142a0 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacroWithUserID.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/ItemSpecificRoleMacroWithUserID.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,10 +33,10 @@
/**
* Macro invokes evaluation of item-specific access rights for the current user.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.4
*/
-@Extension(optional = true)
+@Extension(optional = true, ordinal = -5)
public class ItemSpecificRoleMacroWithUserID extends ItemSpecificRoleMacro {
@Override
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/NoOwnerRoleMacro.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/NoOwnerRoleMacro.java
index 28552abe..2d49092a 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/NoOwnerRoleMacro.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/NoOwnerRoleMacro.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,7 +33,7 @@
/**
* Checks if item has no ownership.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
@Extension(optional = true)
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacro.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacro.java
index 1f8451c9..43978f16 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacro.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacro.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,10 +33,10 @@
/**
* Provides owner RoleMacro for the role-based strategy.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
-@Extension(optional = true)
+@Extension(optional = true, ordinal = -1000)
public class OwnerRoleMacro extends AbstractOwnershipRoleMacro {
@Override
@@ -50,8 +50,16 @@ public String getDescription() {
}
@Override
- public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
- User user = User.get(sid, false, null);
+ public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
+ // Check for null or empty SID - deny access in such cases
+ if (sid == null) {
+ return false;
+ }
+ if (sid.trim().isEmpty()) {
+ return false;
+ }
+
+ User user = User.getById(sid, false);
return hasPermission(user, type, item, macro, false);
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacroNoSid.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacroNoSid.java
index b724187b..f76002d0 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacroNoSid.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/security/rolestrategy/OwnerRoleMacroNoSid.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,20 +24,22 @@
package com.synopsys.arc.jenkins.plugins.ownership.security.rolestrategy;
import com.synopsys.arc.jenkins.plugins.ownership.Messages;
-import static com.synopsys.arc.jenkins.plugins.ownership.security.rolestrategy.AbstractOwnershipRoleMacro.hasPermission;
import com.synopsys.arc.jenkins.plugins.rolestrategy.Macro;
import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
import hudson.Extension;
import hudson.model.User;
import hudson.security.AccessControlled;
import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.integrations.rolestrategy.macros.CurrentUserIsPrimaryOwnerMacro;
/**
* Provides owner RoleMacro for the role-based strategy (w/o Sid check).
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
+ * @deprecated Use {@link CurrentUserIsPrimaryOwnerMacro}
*/
-@Extension(optional = true)
+@Deprecated
+@Extension(optional = true, ordinal = -1000)
public class OwnerRoleMacroNoSid extends AbstractOwnershipRoleMacro {
@Override
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/AbstractOwnershipHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/AbstractOwnershipHelper.java
index 8124f86d..6fc9903b 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/AbstractOwnershipHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/AbstractOwnershipHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,34 +24,27 @@
package com.synopsys.arc.jenkins.plugins.ownership.util;
import com.synopsys.arc.jenkins.plugins.ownership.IOwnershipHelper;
-import com.synopsys.arc.jenkins.plugins.ownership.Messages;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
-import org.jenkinsci.plugins.ownership.util.mail.MailFormatter;
import hudson.model.User;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import java.util.Collections;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+
+import hudson.security.Permission;
import jenkins.model.Jenkins;
+import org.jenkinsci.plugins.ownership.model.OwnershipInfo;
/**
* Provides basic operations for ownership helpers.
* @param An item type, which is supported by the class.
* @since 0.0.4
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public abstract class AbstractOwnershipHelper
implements IOwnershipHelper {
- /**An empty collection of users*/
- protected final static Collection EMPTY_USERS_COLLECTION = new ArrayList(0);
-
-
@Override
public final @Nonnull String getDisplayName(@CheckForNull User usr) {
return UserStringFormatter.format(usr);
@@ -87,6 +80,52 @@ public final boolean isOwnerExists(@Nonnull TObjectType item) {
@Override
public Collection getPossibleOwners(TObjectType item) {
- return EMPTY_USERS_COLLECTION;
+ return Collections.emptyList();
+ }
+
+ //TODO: promote to interface
+ /**
+ * Checks if the summary box should be displayed.
+ * @param item Current item
+ * @return {@code true} if the summary box should be displayed (even if there is no data);
+ * @since 0.8
+ */
+ public boolean isDisplayOwnershipSummaryBox(@Nonnull TObjectType item) {
+ // If there is no data, check global options
+ if (!getOwnershipDescription(item).isOwnershipEnabled()) {
+ return !OwnershipPlugin.getInstance().getConfiguration().getDisplayOptions().isHideOwnershipIfNoData();
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets ownership info of the requested item.
+ * @param item Item to be described
+ * @return Ownership description. The method returns a
+ * {@link OwnershipDescription#DISABLED_DESCR}
+ * @since 0.9
+ */
+ @Nonnull
+ public abstract OwnershipInfo getOwnershipInfo(@Nonnull TObjectType item);
+
+ /**
+ * Gets permission required to manage ownership for the item.
+ * {@link Jenkins#ADMINISTER} by default if not overridden.
+ * @return Permission which is needed to change ownership.
+ * @since TODO
+ */
+ @Nonnull
+ public Permission getRequiredPermission() {
+ return Jenkins.ADMINISTER;
}
+
+ /**
+ * Check if the objeck has locally defined ownership info.
+ * @param item Item
+ * @return {@code true} if the object has ownership defined locally.
+ * {@code false} will be returned otherwise, even if ownership is inherited.
+ * @since TODO
+ */
+ public boolean hasLocallyDefinedOwnership(@Nonnull TObjectType item) { return false; }
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/HTMLFormatter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/HTMLFormatter.java
index 29c08963..c16e70f3 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/HTMLFormatter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/HTMLFormatter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,16 +23,20 @@
*/
package com.synopsys.arc.jenkins.plugins.ownership.util;
+import hudson.Functions;
import hudson.model.User;
+
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+
import jenkins.model.Jenkins;
+
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Provides additional formatters for jelly layout.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
@Restricted(NoExternalUse.class)
@@ -44,9 +48,9 @@ public class HTMLFormatter {
* @return User e-mail in the following format: <user@doma.in>
*/
public static @CheckForNull String formatEmailURI(@Nonnull String userId) {
- String email = UserStringFormatter.formatEmail(userId);
+ String email = Functions.escape(UserStringFormatter.formatEmail(userId));
if (email != null) {
- return "<"+email+">";
+ return "<"+email+">";
} else {
return null;
}
@@ -61,12 +65,19 @@ public class HTMLFormatter {
}
public static @Nonnull String formatUserURI(@Nonnull String userId, boolean useLongFormat) {
- User usr = User.get(userId, false, null);
+ User usr = User.getById(userId, false);
if (usr != null) {
String userStr = useLongFormat
? usr.getDisplayName()
: UserStringFormatter.formatShort(usr.getId());
- return ""+userStr+"";
+ // URL-encoding for the URL part, HTML-escaping for the link text
+ try {
+ String encodedUserId = java.net.URLEncoder.encode(userId, "UTF-8");
+ return ""+Functions.escape(userStr)+"";
+ } catch (java.io.UnsupportedEncodingException e) {
+ // Fallback to original behavior if encoding fails
+ return ""+Functions.escape(userStr)+"";
+ }
} else { // just return name w/o hyperlink
return userId + " (unregistered)";
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/IdStrategyComparator.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/IdStrategyComparator.java
new file mode 100644
index 00000000..af51e58e
--- /dev/null
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/IdStrategyComparator.java
@@ -0,0 +1,28 @@
+package com.synopsys.arc.jenkins.plugins.ownership.util;
+
+import hudson.security.SecurityRealm;
+import java.util.Comparator;
+import jenkins.model.IdStrategy;
+import jenkins.model.Jenkins;
+
+
+public class IdStrategyComparator implements Comparator {
+
+ private final SecurityRealm securityRealm;
+ private final IdStrategy groupIdStrategy;
+ private final IdStrategy userIdStrategy;
+
+ public IdStrategyComparator() {
+ securityRealm = Jenkins.get().getSecurityRealm();
+ groupIdStrategy = securityRealm.getGroupIdStrategy();
+ userIdStrategy = securityRealm.getUserIdStrategy();
+ }
+
+ public int compare(String o1, String o2) {
+ int r = userIdStrategy.compare(o1, o2);
+ if (r == 0) {
+ r = groupIdStrategy.compare(o1, o2);
+ }
+ return r;
+ }
+}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/OwnershipDescriptionHelper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/OwnershipDescriptionHelper.java
index a359770d..f24ab958 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/OwnershipDescriptionHelper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/OwnershipDescriptionHelper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,34 +24,70 @@
package com.synopsys.arc.jenkins.plugins.ownership.util;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import java.util.Set;
+import java.util.TreeSet;
import javax.annotation.Nonnull;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+//TODO: Do we really need this helper class now?
+//TODO co-owners have not been renamed to secondary owners, but it's an internal-only class
/**
* Provides handlers for ownership description.
- * @author Oleg Nenashev , Synopsys Inc.
- * @since 0.4
+ * @author Oleg Nenashev
+ * @since 0.4 - Public API class
+ * @since TODO - Class API is restricted, use OwnershipDescription instead
* @see OwnershipDescription
*/
+@Restricted(NoExternalUse.class)
public class OwnershipDescriptionHelper {
private OwnershipDescriptionHelper() {}
/**
- * Gets id of the owner.
+ * Gets ID of the primary owner.
* @param descr Ownership description
* @return userId of the primary owner. The result will be "unknown" if the
* user is not specified.
+ * @deprecated Use {@link #getPrimaryOwnerId(com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription)}
*/
- public static @Nonnull String getOwnerID(@Nonnull OwnershipDescription descr) {
+ @Nonnull
+ @Deprecated
+ public static String getOwnerID(@Nonnull OwnershipDescription descr) {
+ return getPrimaryOwnerId(descr);
+ }
+
+ /**
+ * Gets id of the primary owner.
+ * @param descr Ownership description
+ * @return userId of the primary owner. The result will be "unknown" if the
+ * user is not specified.
+ */
+ @Nonnull
+ public static String getPrimaryOwnerId(@Nonnull OwnershipDescription descr) {
return descr.getPrimaryOwnerId();
}
/**
* Gets owner's e-mail.
* @param descr Ownership description
- * @return Owner's e-mail or empty string if it is not available
+ * @return Owner's e-mail or empty string if it is not available
+ * @deprecated Use {@link #getPrimaryOwnerEmail(com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription)}
*/
+ @Nonnull
+ @Deprecated
public static String getOwnerEmail(@Nonnull OwnershipDescription descr) {
+ return getPrimaryOwnerEmail(descr);
+ }
+
+ /**
+ * Gets e-mail of the primary owner.
+ * @param descr Ownership description
+ * @return Owner's e-mail or empty string if it is not available
+ * @since 0.9
+ */
+ @Nonnull
+ public static String getPrimaryOwnerEmail(@Nonnull OwnershipDescription descr) {
String ownerEmail = UserStringFormatter.formatEmail(descr.getPrimaryOwnerId());
return ownerEmail != null ? ownerEmail : "";
}
@@ -59,12 +95,46 @@ public static String getOwnerEmail(@Nonnull OwnershipDescription descr) {
/**
* Gets a comma-separated list of co-owners.
* @param descr Ownership description
+ * @param includeOwner Include owner to the list
+ * @return Set of co-owner user IDs
+ * @since 0.9
+ */
+ @Nonnull
+ public static Set getSecondaryOwnerIds(@Nonnull OwnershipDescription descr, boolean includeOwner) {
+ Set res = new TreeSet<>();
+ if (includeOwner) {
+ res.add(getPrimaryOwnerId(descr));
+ }
+ for (String userId : descr.getSecondaryOwnerIds()) {
+ res.add(userId);
+ }
+ return res;
+ }
+
+ /**
+ * Gets a comma-separated list of co-owners.
+ * Owner will be also considered as co-owner.
+ * @param descr Ownership description
* @return List of co-owner user IDs
+ * @deprecated Use {@link #getAllOwnerIdsString(com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription)}
+ */
+ @Deprecated
+ @Nonnull
+ public static String getCoOwnerIDs(@Nonnull OwnershipDescription descr) {
+ return getAllOwnerEmailsString(descr);
+ }
+
+ /**
+ * Gets a comma-separated list of primary and secondary owners.
+ * @param descr Ownership description
+ * @return String containing comma-separated list of owner user IDs
+ * @since 0.9
*/
- public static @Nonnull String getCoOwnerIDs(@Nonnull OwnershipDescription descr) {
- StringBuilder coowners= new StringBuilder(getOwnerID(descr));
- for (String userId : descr.getCoownersIds()) {
- if (coowners.length() == 0) {
+ @Nonnull
+ public static String getAllOwnerIdsString(@Nonnull OwnershipDescription descr) {
+ StringBuilder coowners= new StringBuilder();
+ for (String userId : getSecondaryOwnerIds(descr, true)) {
+ if (coowners.length() != 0) {
coowners.append(",");
}
coowners.append(userId);
@@ -73,21 +143,41 @@ public static String getOwnerEmail(@Nonnull OwnershipDescription descr) {
}
/**
- * Gets e-mails of co-owners.
+ * Gets e-mails of secondary owners (including owner if required).
* @param descr Ownership description
- * @return Comma-separated list of co-owner e-mails (may be empty)
+ * @param includeOwner Include owner to the list
+ * @return Set of secondary owner emails
+ * @since 0.9
*/
- public static String getCoOwnerEmails(@Nonnull OwnershipDescription descr) {
- StringBuilder coownerEmails=new StringBuilder(getOwnerEmail(descr));
- for (String userId : descr.getCoownersIds()) {
+ public static Set getSecondaryOwnerEmails(@Nonnull OwnershipDescription descr, boolean includeOwner) {
+ Set res = new TreeSet<>();
+
+ if (includeOwner) {
+ res.add(getOwnerEmail(descr));
+ }
+ for (String userId : descr.getSecondaryOwnerIds()) {
String coownerEmail = UserStringFormatter.formatEmail(userId);
if (coownerEmail != null) {
- if (coownerEmails.length() != 0) {
- coownerEmails.append(",");
- }
- coownerEmails.append(coownerEmail);
+ res.add(coownerEmail);
}
}
+ return res;
+ }
+
+ /**
+ * Gets e-mails of secondary owners (including primary owner).
+ * @param descr Ownership description
+ * @return Comma-separated list of secondary owner e-mails (may be empty)
+ * @since 0.9
+ */
+ public static String getAllOwnerEmailsString(@Nonnull OwnershipDescription descr) {
+ StringBuilder coownerEmails=new StringBuilder();
+ for (String coownerEmail : getSecondaryOwnerEmails(descr, true)) {
+ if (coownerEmails.length() != 0) {
+ coownerEmails.append(",");
+ }
+ coownerEmails.append(coownerEmail);
+ }
return coownerEmails.toString();
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserCollectionFilter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserCollectionFilter.java
index e528d949..7d72710c 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserCollectionFilter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserCollectionFilter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,7 @@
/**
* Filters {@link Collection}s of {@link User}s.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.1
*/
@Restricted(NoExternalUse.class)
@@ -46,13 +46,13 @@ public class UserCollectionFilter {
public static Collection filterUsers(@Nonnull Collection input, boolean enableSort, @Nonnull IUserFilter... filters) {
// Sort users
UserComparator comparator = new UserComparator();
- LinkedList userList = new LinkedList(User.getAll());
+ LinkedList userList = new LinkedList<>(User.getAll());
if (enableSort) {
Collections.sort(userList, comparator);
}
// Prepare new list
- Collection res = new ArrayList();
+ Collection res = new ArrayList<>();
for (User user : userList) {
if (user == null) {
continue;
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserStringFormatter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserStringFormatter.java
index 861e5050..86a1b6a8 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserStringFormatter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserStringFormatter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@
/**
* Helper for User string formatting.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
@Restricted(NoExternalUse.class)
public class UserStringFormatter {
@@ -49,7 +49,7 @@ public class UserStringFormatter {
}
public static @Nonnull String format(@Nonnull String userId) {
- return format(User.get(userId, false, null));
+ return format(User.getById(userId, false));
}
public static @Nonnull String formatShort(@CheckForNull String userId) {
@@ -63,7 +63,7 @@ public class UserStringFormatter {
* @since 0.2
*/
public static @CheckForNull String formatEmail(@Nonnull String userId) {
- return formatEmail(User.get(userId, false, null));
+ return formatEmail(User.getById(userId, false));
}
public static @CheckForNull String formatEmail(@CheckForNull User user) {
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserValidator.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserValidator.java
index ae52eac8..916f3c2d 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserValidator.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserValidator.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,12 +23,11 @@
*/
package com.synopsys.arc.jenkins.plugins.ownership.util;
-import hudson.util.FormValidation;
-
/**
* @deprecated Old non-used stuff, which will be deleted in further versions
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
*/
+@Deprecated
public class UserValidator {
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserWrapper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserWrapper.java
index 2ef18f36..58721d4b 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserWrapper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/UserWrapper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,7 @@
*/
package com.synopsys.arc.jenkins.plugins.ownership.util;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.model.User;
import javax.annotation.Nonnull;
import org.kohsuke.accmod.Restricted;
@@ -30,7 +31,7 @@
/**
* Implements a wrapper, which allows to implement the "non-existent" user macro.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.1
*/
@Restricted(NoExternalUse.class)
@@ -59,20 +60,29 @@ public UserWrapper(@Nonnull String userMacro) {
this.macro = userMacro;
} else {
this.isUser = true;
- this.user = User.get(userMacro, false, null);
+ this.user = User.getById(userMacro, false);
// throw new UnsupportedOperationException("User macro must start with prefix '"+USER_MACRO_PREFIX+"'");
}
}
+ /**
+ * @deprecated Use {@link #isUser() }
+ */
+ @Deprecated
+ @SuppressFBWarnings(value = "NM_METHOD_NAMING_CONVENTION")
public boolean IsUser() {
return isUser;
}
+
+ public boolean isUser() {
+ return isUser;
+ }
/**
* Gets id of the user (calls User.getId() or returns macro).
*
- * @return
+ * @return ID or macro
*/
public String getId() {
return isUser ? user.getId() : macro;
@@ -84,7 +94,7 @@ public String toString() {
}
public boolean meetsMacro(String userId) {
- // Handle macroses and get effective user's id
+ // Handle macros and get effective user's id
String comparedId;
if (isUser) {
if (user == null) {
@@ -100,7 +110,7 @@ public boolean meetsMacro(String userId) {
}
// Check
- return comparedId.equals(userId);
+ return User.idStrategy().equals(comparedId, userId);
}
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/OwnershipLayoutFormatter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/OwnershipLayoutFormatter.java
index f1c25037..febb2b4e 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/OwnershipLayoutFormatter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/OwnershipLayoutFormatter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2014 Oleg Nenashev .
+ * Copyright 2014 Oleg Nenashev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,29 +25,62 @@
package com.synopsys.arc.jenkins.plugins.ownership.util.ui;
import com.synopsys.arc.jenkins.plugins.ownership.IOwnershipHelper;
-import com.synopsys.arc.jenkins.plugins.ownership.Messages;
import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPluginConfiguration;
import com.synopsys.arc.jenkins.plugins.ownership.util.HTMLFormatter;
import org.jenkinsci.plugins.ownership.util.mail.OwnershipMailHelper;
import javax.annotation.Nonnull;
/**
* Formats layouts for UI interfaces.
- * This extension is being used by {@link OwnershipLayoutFormatterProvider}.
* @param Type of object, for which ownership should be resolved
- * @see OwnershipLayoutFormatterProvider
* @since 0.5
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
*/
public abstract class OwnershipLayoutFormatter {
- public abstract String formatUser(@Nonnull TObjectType item, String userId);
+ @Nonnull
+ public abstract String formatUser(@Nonnull TObjectType item, @Nonnull String userId);
- public String formatOwner(@Nonnull TObjectType item, String userId) {
+ /**
+ * Formats primary owner.
+ * @param item Item, for which the formatting is being performed
+ * @param userId User ID
+ * @return Raw HTML with user format
+ * @since 0.9
+ */
+ @Nonnull
+ public String formatPrimaryOwner(@Nonnull TObjectType item, @Nonnull String userId) {
+ return formatOwner(item, userId);
+ }
+
+ /**
+ * @deprecated Use {@link #formatPrimaryOwner(java.lang.Object, java.lang.String)}
+ */
+ @Deprecated
+ @Nonnull
+ public String formatOwner(@Nonnull TObjectType item, @Nonnull String userId) {
return formatUser(item, userId);
}
- public String formatCoOwner(@Nonnull TObjectType item, String userId) {
+ /**
+ * Formats secondary owner.
+ * @param item Item, for which the formatting is being performed
+ * @param userId User ID
+ * @return Raw HTML with user format
+ * @since 0.9
+ */
+ @Nonnull
+ public String formatSecondaryOwner(@Nonnull TObjectType item, @Nonnull String userId) {
+ return formatCoOwner(item, userId);
+ }
+
+ /**
+ * @deprecated Use {@link #formatSecondaryOwner(java.lang.Object, java.lang.String)}
+ */
+ @Deprecated
+ @Nonnull
+ public String formatCoOwner(@Nonnull TObjectType item, @Nonnull String userId) {
return formatUser(item, userId);
}
@@ -77,10 +110,19 @@ public static class DefaultJobFormatter extends OwnershipLayoutForm
@Override
public String formatUser(TObjectType item, String userId) {
- final String userURI = HTMLFormatter.formatUserURI(userId, true);
- final String userEmail = HTMLFormatter.formatEmailURI(userId);
- final String userInfoHTML = userURI + (userEmail != null ? " " + userEmail : "");
- return userInfoHTML;
+ StringBuilder rawHtmlBuilder = new StringBuilder();
+ rawHtmlBuilder.append(HTMLFormatter.formatUserURI(userId, true));
+
+ // Append e-mail to the output if it is not prohibited.
+ if (!OwnershipPluginConfiguration.get().getMailOptions().isHideOwnerAndCoOwnerEmails()) {
+ final String userEmail = HTMLFormatter.formatEmailURI(userId);
+ if (userEmail != null) {
+ rawHtmlBuilder.append(' ');
+ rawHtmlBuilder.append(userEmail);
+ }
+ }
+
+ return rawHtmlBuilder.toString();
}
@Override
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/UserSelector.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/UserSelector.java
index 59e11f79..b93b57a3 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/UserSelector.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/ui/UserSelector.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,13 +31,16 @@
import hudson.util.FormValidation;
import java.io.Serializable;
import javax.annotation.CheckForNull;
+
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
/**
* Describable Item, which allows to configure user.
* Features: validation
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
*/
//TODO: Autocompletion
public class UserSelector implements Describable, Serializable {
@@ -84,14 +87,15 @@ public static class DescriptorImpl extends Descriptor {
public String getDisplayName() {
return "N/A";
}
-
+
+ @Restricted(NoExternalUse.class)
public FormValidation doCheckSelectedUserId(@QueryParameter String selectedUserId) {
selectedUserId = Util.fixEmptyAndTrim(selectedUserId);
if (selectedUserId == null) {
return FormValidation.error("Field is empty. Field will be ignored");
}
- User usr = User.get(selectedUserId, false, null);
+ User usr = User.getById(selectedUserId, false);
if (usr == null) {
return FormValidation.warning("User " + selectedUserId + " is not registered in Jenkins");
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/AccessRightsFilter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/AccessRightsFilter.java
index 03df226f..ab80096d 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/AccessRightsFilter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/AccessRightsFilter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,7 +34,7 @@
/**
* Filters user according to access rights to specified item.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.1
*/
public class AccessRightsFilter implements IUserFilter {
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/IUserFilter.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/IUserFilter.java
index 3db91e31..fab31669 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/IUserFilter.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/IUserFilter.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +28,7 @@
/**
* Provides filtering of users.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.1
*/
public interface IUserFilter {
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/UserComparator.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/UserComparator.java
index d69690a2..f7db36ac 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/UserComparator.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/util/userFilters/UserComparator.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
/**
* Compares two {@link User}s by their full names.
- * @author Oleg Nenashev
+ * @author Oleg Nenashev
* @since 0.1
*/
public class UserComparator implements java.util.Comparator, Serializable
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipBuildWrapper.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipBuildWrapper.java
index 0a825473..e175ddb7 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipBuildWrapper.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipBuildWrapper.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Oleg Nenashev , Synopsys Inc.
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,7 @@
package com.synopsys.arc.jenkins.plugins.ownership.wrappers;
import com.synopsys.arc.jenkins.plugins.ownership.Messages;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
@@ -39,19 +40,19 @@
/**
* Provides wrapper, which injects ownership variables into the build environment.
* The wrapper support both slave and node ownership information.
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.2
*/
public class OwnershipBuildWrapper extends BuildWrapper {
private @Nonnull EnvSetupOptions envSetupOptions;
@Deprecated
- private transient final boolean injectNodeOwnership = false;
+ private static final transient boolean injectNodeOwnership = false;
@Deprecated
- private transient final boolean injectJobOwnership = false;
+ private static final transient boolean injectJobOwnership = false;
@DataBoundConstructor
- public OwnershipBuildWrapper(EnvSetupOptions envSetupOptions) {
+ public OwnershipBuildWrapper(@Nonnull EnvSetupOptions envSetupOptions) {
this.envSetupOptions = envSetupOptions;
}
@@ -59,6 +60,7 @@ public OwnershipBuildWrapper(boolean injectJobOwnership, boolean injectNodeOwner
this(new EnvSetupOptions(injectJobOwnership, injectNodeOwnership));
}
+ @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE", justification = "Migration of the old data")
public Object readResolve() {
if (envSetupOptions == null) {
envSetupOptions = new EnvSetupOptions(injectJobOwnership, injectNodeOwnership);
@@ -69,7 +71,7 @@ public Object readResolve() {
@Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
return new Environment() {
- // Empty instantination. The entire code has been moved to OwnershipRunListener
+ // Empty instantiation. The entire code has been moved to OwnershipRunListener
};
}
diff --git a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipTokenMacro.java b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipTokenMacro.java
index 43f92107..5fafd788 100644
--- a/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipTokenMacro.java
+++ b/src/main/java/com/synopsys/arc/jenkins/plugins/ownership/wrappers/OwnershipTokenMacro.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
- * Copyright 2013 Synopsys Inc., Oleg Nenashev
+ * Copyright 2013 Synopsys Inc., Oleg Nenashev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,6 +29,7 @@
import com.synopsys.arc.jenkins.plugins.ownership.util.OwnershipDescriptionHelper;
import hudson.Extension;
import hudson.model.AbstractBuild;
+import hudson.model.Node;
import hudson.model.TaskListener;
import java.io.IOException;
import org.jenkinsci.plugins.tokenmacro.DataBoundTokenMacro;
@@ -39,7 +40,7 @@
* This macro allows to extract information about ownership.
* An information type can be specified by additional var parameter
* (see {@link OwnershipFunction} to get a list of supported operations).
- * @author Oleg Nenashev , Synopsys Inc.
+ * @author Oleg Nenashev
* @since 0.4
*/
@Extension(optional = true)
@@ -72,10 +73,19 @@ public String evaluate(AbstractBuild, ?> ab, TaskListener tl, String string) t
}
OwnershipDescription job = JobOwnerHelper.Instance.getOwnershipDescription(ab.getProject());
- OwnershipDescription node = NodeOwnerHelper.Instance.getOwnershipDescription(ab.getBuiltOn());
- return func.evaluate(job, node);
+
+ // Get data for node
+ final Node node = ab.getBuiltOn();
+ OwnershipDescription nodeDescription = node != null
+ ? NodeOwnerHelper.Instance.getOwnershipDescription(node)
+ : OwnershipDescription.DISABLED_DESCR;
+
+ // Evaluate the macro
+ return func.evaluate(job, nodeDescription);
}
-
+
+ // TODO: This implementation needs some polishing in order to address naming changes
+ // in primary and secondary owners
private static enum OwnershipFunction {
JOB_OWNER(true),
JOB_OWNER_EMAIL(true),
@@ -86,7 +96,7 @@ private static enum OwnershipFunction {
NODE_COOWNERS(false),
NODE_COOWNERS_EMAILS(false);
- private boolean isJob;
+ private final boolean isJob;
private OwnershipFunction(boolean isJob) {
this.isJob = isJob;
@@ -110,21 +120,21 @@ public String evaluate(OwnershipDescription job, OwnershipDescription node) thro
switch(this) {
case JOB_OWNER:
- return OwnershipDescriptionHelper.getOwnerID(job);
+ return OwnershipDescriptionHelper.getPrimaryOwnerId(job);
case JOB_OWNER_EMAIL:
- return OwnershipDescriptionHelper.getOwnerEmail(job);
+ return OwnershipDescriptionHelper.getPrimaryOwnerEmail(job);
case JOB_COOWNERS:
- return OwnershipDescriptionHelper.getCoOwnerIDs(job);
+ return OwnershipDescriptionHelper.getAllOwnerIdsString(job);
case JOB_COOWNERS_EMAILS:
- return OwnershipDescriptionHelper.getCoOwnerEmails(job);
+ return OwnershipDescriptionHelper.getAllOwnerEmailsString(job);
case NODE_OWNER:
- return OwnershipDescriptionHelper.getOwnerID(node);
+ return OwnershipDescriptionHelper.getPrimaryOwnerId(node);
case NODE_OWNER_EMAIL:
- return OwnershipDescriptionHelper.getOwnerEmail(node);
+ return OwnershipDescriptionHelper.getPrimaryOwnerEmail(node);
case NODE_COOWNERS:
- return OwnershipDescriptionHelper.getCoOwnerIDs(node);
+ return OwnershipDescriptionHelper.getAllOwnerIdsString(node);
case NODE_COOWNERS_EMAILS:
- return OwnershipDescriptionHelper.getCoOwnerEmails(node);
+ return OwnershipDescriptionHelper.getAllOwnerEmailsString(node);
default:
throw new IOException(this+" ownership function is not implemented");
}
diff --git a/src/main/java/org/jenkinsci/plugins/ownership/config/DisplayOptions.java b/src/main/java/org/jenkinsci/plugins/ownership/config/DisplayOptions.java
new file mode 100644
index 00000000..857b1a70
--- /dev/null
+++ b/src/main/java/org/jenkinsci/plugins/ownership/config/DisplayOptions.java
@@ -0,0 +1,86 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2015 Oleg Nenashev
+ *
+ * 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 org.jenkinsci.plugins.ownership.config;
+
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPluginConfiguration;
+import hudson.Extension;
+import hudson.model.Describable;
+import hudson.model.Descriptor;
+
+import org.jenkinsci.plugins.ownership.model.runs.RunOwnershipAction;
+import org.kohsuke.stapler.DataBoundConstructor;
+
+/**
+ * Stores display options for {@link OwnershipPlugin}.
+ * This section is attached as an advanced section to {@link OwnershipPluginConfiguration}.
+ * @author Oleg Nenashev
+ * @since 0.8
+ */
+public class DisplayOptions implements Describable {
+
+ public static final DisplayOptions DEFAULT = new DisplayOptions(false, false);
+
+ private final boolean hideRunOwnership;
+ private final boolean hideOwnershipIfNoData;
+
+ @DataBoundConstructor
+ public DisplayOptions(boolean hideRunOwnership, boolean hideOwnershipIfNoData) {
+ this.hideRunOwnership = hideRunOwnership;
+ this.hideOwnershipIfNoData = hideOwnershipIfNoData;
+ }
+
+ /**
+ * Disables Run summary boxes in {@link RunOwnershipAction}.
+ * @return {@code true} if {@link RunOwnershipAction}'s summary box should not be displayed.
+ */
+ public boolean isHideRunOwnership() {
+ return hideRunOwnership;
+ }
+
+ /**
+ * Does not display Ownership summary boxes if Ownership is not configured.
+ * @return {@code true} to hide empty Ownership summary boxes.
+ */
+ public boolean isHideOwnershipIfNoData() {
+ return hideOwnershipIfNoData;
+ }
+
+ @Extension
+ public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
+
+ @Override
+ public DescriptorImpl getDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ public static class DescriptorImpl extends Descriptor {
+
+ @Override
+ public String getDisplayName() {
+ return "N/A";
+ }
+ }
+}
diff --git a/src/main/java/org/jenkinsci/plugins/ownership/config/InheritanceOptions.java b/src/main/java/org/jenkinsci/plugins/ownership/config/InheritanceOptions.java
new file mode 100644
index 00000000..eb9ca998
--- /dev/null
+++ b/src/main/java/org/jenkinsci/plugins/ownership/config/InheritanceOptions.java
@@ -0,0 +1,81 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2016 Oleg Nenashev
+ *
+ * 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 org.jenkinsci.plugins.ownership.config;
+
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipPluginConfiguration;
+import com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerHelper;
+import hudson.Extension;
+import hudson.model.Describable;
+import hudson.model.Descriptor;
+import hudson.model.ItemGroup;
+import org.jenkinsci.plugins.ownership.model.folders.FolderOwnershipHelper;
+import org.kohsuke.stapler.DataBoundConstructor;
+
+/**
+ * Stores inheritance options for {@link OwnershipPlugin}.
+ * This section is attached as an advanced section to {@link OwnershipPluginConfiguration}.
+ * These options has been created
+ * @author Oleg Nenashev
+ * @since 0.9
+ */
+public class InheritanceOptions implements Describable {
+
+ public static final InheritanceOptions DEFAULT = new InheritanceOptions(false);
+
+ private final boolean blockInheritanceFromItemGroups;
+
+ @DataBoundConstructor
+ public InheritanceOptions(boolean blockInheritanceFromItemGroups) {
+ this.blockInheritanceFromItemGroups = blockInheritanceFromItemGroups;
+ }
+
+ /**
+ * Blocks ownership inheritance from {@link ItemGroup}s.
+ * This inheritance is used in {@link JobOwnerHelper} and {@link FolderOwnershipHelper}
+ * in order to retrieve the info from parent folders.
+ * Such inheritance may impact the performance of Jenkins instance, hence it is possible to disable it.
+ * @return {@code true} if ownership inheritance should be blocked.
+ */
+ public boolean isBlockInheritanceFromItemGroups() {
+ return blockInheritanceFromItemGroups;
+ }
+
+ @Extension
+ public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
+
+ @Override
+ public DescriptorImpl getDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ public static class DescriptorImpl extends Descriptor {
+
+ @Override
+ public String getDisplayName() {
+ return "N/A";
+ }
+ }
+}
diff --git a/src/main/java/org/jenkinsci/plugins/ownership/config/PreserveOwnershipPolicy.java b/src/main/java/org/jenkinsci/plugins/ownership/config/PreserveOwnershipPolicy.java
new file mode 100644
index 00000000..641a6aa2
--- /dev/null
+++ b/src/main/java/org/jenkinsci/plugins/ownership/config/PreserveOwnershipPolicy.java
@@ -0,0 +1,42 @@
+package org.jenkinsci.plugins.ownership.config;
+
+import com.synopsys.arc.jenkins.plugins.ownership.Messages;
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import com.synopsys.arc.jenkins.plugins.ownership.extensions.ItemOwnershipPolicy;
+import com.synopsys.arc.jenkins.plugins.ownership.extensions.ItemOwnershipPolicyDescriptor;
+import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
+import hudson.Extension;
+import hudson.model.Item;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.kohsuke.stapler.DataBoundConstructor;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A policy, which keeps the previous job's ownership.
+ * @author cpuydebois
+ * @since TODO
+ */
+public class PreserveOwnershipPolicy extends ItemOwnershipPolicy {
+
+ @DataBoundConstructor
+ public PreserveOwnershipPolicy() {
+ }
+
+ @Override
+ public OwnershipDescription onCreated(@Nonnull Item item) {
+ AbstractOwnershipHelper
- helper = OwnershipHelperLocator.locate(item);
+ if (helper != null) {
+ return helper.getOwnershipDescription(item);
+ }
+ return null;
+ }
+
+ @Extension
+ public static class DescriptorImpl extends ItemOwnershipPolicyDescriptor {
+ @Override
+ public String getDisplayName() {
+ return Messages.ItemOwnershipPolicy_PreserveOwnershipPolicy_displayName();
+ }
+ }
+}
diff --git a/src/main/java/org/jenkinsci/plugins/ownership/integrations/rolestrategy/macros/CurrentUserIsOwnerMacro.java b/src/main/java/org/jenkinsci/plugins/ownership/integrations/rolestrategy/macros/CurrentUserIsOwnerMacro.java
new file mode 100644
index 00000000..33cc11c0
--- /dev/null
+++ b/src/main/java/org/jenkinsci/plugins/ownership/integrations/rolestrategy/macros/CurrentUserIsOwnerMacro.java
@@ -0,0 +1,59 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
+ *
+ * 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 org.jenkinsci.plugins.ownership.integrations.rolestrategy.macros;
+
+import com.synopsys.arc.jenkins.plugins.ownership.security.rolestrategy.AbstractOwnershipRoleMacro;
+import com.synopsys.arc.jenkins.plugins.rolestrategy.Macro;
+import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
+import hudson.Extension;
+import hudson.model.User;
+import hudson.security.AccessControlled;
+import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.integrations.rolestrategy.Messages;
+
+/**
+ * Checks if the current user is an owner.
+ * Primary and secondary owners are fine.
+ * @author Oleg Nenashev
+ * @since 0.9
+ */
+@Extension(optional = true)
+public class CurrentUserIsOwnerMacro extends AbstractOwnershipRoleMacro {
+
+ @Override
+ public String getName() {
+ return "CurrentUserIsOwner";
+ }
+
+ @Override
+ public String getDescription() {
+ return Messages.CurrentUserIsOwnerMacro_description();
+ }
+
+ @Override
+ public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
+ User user = User.current();
+ return hasPermission(user, type, item, macro, true);
+ }
+}
diff --git a/src/main/java/org/jenkinsci/plugins/ownership/integrations/rolestrategy/macros/CurrentUserIsPrimaryOwnerMacro.java b/src/main/java/org/jenkinsci/plugins/ownership/integrations/rolestrategy/macros/CurrentUserIsPrimaryOwnerMacro.java
new file mode 100644
index 00000000..a45ade2f
--- /dev/null
+++ b/src/main/java/org/jenkinsci/plugins/ownership/integrations/rolestrategy/macros/CurrentUserIsPrimaryOwnerMacro.java
@@ -0,0 +1,58 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2013 Oleg Nenashev, Synopsys Inc.
+ *
+ * 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 org.jenkinsci.plugins.ownership.integrations.rolestrategy.macros;
+
+import com.synopsys.arc.jenkins.plugins.ownership.security.rolestrategy.AbstractOwnershipRoleMacro;
+import com.synopsys.arc.jenkins.plugins.rolestrategy.Macro;
+import com.synopsys.arc.jenkins.plugins.rolestrategy.RoleType;
+import hudson.Extension;
+import hudson.model.User;
+import hudson.security.AccessControlled;
+import hudson.security.Permission;
+import org.jenkinsci.plugins.ownership.integrations.rolestrategy.Messages;
+
+/**
+ * Checks if the current user is a primary owner of the item.
+ * @author Oleg Nenashev
+ * @since 0.9
+ */
+@Extension(optional = true)
+public class CurrentUserIsPrimaryOwnerMacro extends AbstractOwnershipRoleMacro {
+
+ @Override
+ public String getName() {
+ return "CurrentUserIsPrimaryOwner";
+ }
+
+ @Override
+ public String getDescription() {
+ return Messages.CurrentUserIsPrimaryOwnerMacro_description();
+ }
+
+ @Override
+ public boolean hasPermission(String sid, Permission p, RoleType type, AccessControlled item, Macro macro) {
+ User user = User.current();
+ return hasPermission(user, type, item, macro, false);
+ }
+}
diff --git a/src/main/java/org/jenkinsci/plugins/ownership/integrations/securityinspector/OwnerFilter.java b/src/main/java/org/jenkinsci/plugins/ownership/integrations/securityinspector/OwnerFilter.java
new file mode 100644
index 00000000..3f4b378d
--- /dev/null
+++ b/src/main/java/org/jenkinsci/plugins/ownership/integrations/securityinspector/OwnerFilter.java
@@ -0,0 +1,174 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2017 Ksenia Nenasheva .
+ *
+ * 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 org.jenkinsci.plugins.ownership.integrations.securityinspector;
+
+import com.synopsys.arc.jenkins.plugins.ownership.OwnershipDescription;
+import com.synopsys.arc.jenkins.plugins.ownership.util.AbstractOwnershipHelper;
+import hudson.Util;
+import hudson.model.Descriptor;
+import hudson.model.Item;
+import hudson.model.ItemGroup;
+import hudson.model.TopLevelItem;
+import hudson.model.User;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.servlet.ServletException;
+import jenkins.model.Jenkins;
+import org.jenkinsci.plugins.ownership.model.OwnershipHelperLocator;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+import org.kohsuke.stapler.StaplerRequest;
+
+class OwnerFilter {
+
+ private static final Logger LOGGER = Logger.getLogger(OwnerFilter.class.getName());
+
+ /**
+ * Include regex string.
+ */
+ @CheckForNull
+ private final String includeRegex;
+
+ /**
+ * Compiled include pattern from the includeRegex string.
+ */
+ @CheckForNull
+ private final Pattern includePattern;
+
+ /**
+ * Folder name for report
+ */
+ @CheckForNull
+ private final String report4folder;
+
+ /**
+ * Constructs empty filter.
+ */
+ public OwnerFilter() {
+ this.includeRegex = null;
+ this.includePattern = null;
+ this.report4folder = null;
+ }
+
+ @Restricted(NoExternalUse.class)
+ public OwnerFilter(@Nonnull StaplerRequest req)
+ throws Descriptor.FormException, ServletException {
+ if (req.getParameter("useincluderegex") != null) {
+ includeRegex = Util.nullify(req.getParameter("_.includeRegex"));
+ if (includeRegex == null) {
+ includePattern = null;
+ } else {
+ try {
+ includePattern = Pattern.compile(includeRegex);
+ } catch(PatternSyntaxException ex) {
+ throw new Descriptor.FormException(ex, "includeRegex");
+ }
+ }
+ } else {
+ includeRegex = null;
+ includePattern = null;
+ }
+
+ if (req.getParameter("usefolder") != null) {
+ report4folder = req.getParameter("selectedFolder");
+ } else {
+ report4folder = null;
+ }
+ }
+
+ @Nonnull
+ @Restricted(NoExternalUse.class)
+ public List doFilter(User owner) {
+
+ final Jenkins jenkins = Jenkins.get();
+ final List
- allItems;
+
+ if (report4folder != null) {
+ Item folder = jenkins.getItem(report4folder);
+ if (folder instanceof ItemGroup) {
+ Collection
- items = ((ItemGroup)folder).getItems();
+ allItems = new ArrayList<>(items.size());
+ for (Item item : items) {
+ allItems.add(item);
+ }
+ allItems.add(folder);
+ } else {
+ LOGGER.log(Level.WARNING, report4folder + " is not an ItemGroup");
+ return Collections.emptyList();
+ }
+ } else {
+ allItems = jenkins.getAllItems(Item.class);
+ }
+
+ String itemName;
+
+ List items = new ArrayList<>();
+ OwnershipDescription ownershipDescription;
+ AbstractOwnershipHelper