From 7e34fb5f4e3486a7e72b35a2f6be9a7cde14ece0 Mon Sep 17 00:00:00 2001 From: wusisu Date: Fri, 18 May 2018 15:44:16 +0800 Subject: [PATCH 1/8] Add Coding Auth --- README.md | 3 + build.gradle | 49 +- gradle/wrapper/gradle-wrapper.properties | 4 +- src/main/java/net/coding/api/Coding.java | 224 +++++ .../java/net/coding/api/CodingBuilder.java | 80 ++ src/main/java/net/coding/api/CodingEmail.java | 63 ++ .../java/net/coding/api/CodingMyself.java | 155 ++++ .../java/net/coding/api/CodingObject.java | 68 ++ .../net/coding/api/CodingOrganization.java | 58 ++ .../java/net/coding/api/CodingPerson.java | 120 +++ .../java/net/coding/api/CodingPersonSet.java | 57 ++ .../java/net/coding/api/CodingRepository.java | 68 ++ src/main/java/net/coding/api/CodingTeam.java | 55 ++ src/main/java/net/coding/api/CodingUser.java | 23 + .../java/net/coding/api/HttpConnector.java | 51 ++ .../java/net/coding/api/HttpException.java | 44 + .../java/net/coding/api/PagedIterable.java | 71 ++ .../java/net/coding/api/PagedIterator.java | 83 ++ src/main/java/net/coding/api/Requester.java | 527 +++++++++++ .../java/net/coding/api/SkipFromToString.java | 30 + .../api/extras/ImpatientHttpConnector.java | 72 ++ .../coding/api/extras/OkHttpConnector.java | 39 + .../oauth/CodingAccessTokenProperty.java | 63 ++ .../oauth/CodingAuthenticationToken.java | 553 ++++++++++++ .../oauth/CodingAuthorizationStrategy.java | 254 ++++++ .../plugin/oauth/CodingLogoutAction.java | 80 ++ .../plugin/oauth/CodingOAuthGroupDetails.java | 71 ++ .../plugin/oauth/CodingOAuthScope.java | 36 + .../plugin/oauth/CodingOAuthUserDetails.java | 73 ++ .../plugin/oauth/CodingRepositoryName.java | 126 +++ ...odingRequireOrganizationMembershipACL.java | 448 ++++++++++ .../plugin/oauth/CodingSecretStorage.java | 58 ++ .../plugin/oauth/CodingSecurityRealm.java | 823 ++++++++++++++++++ .../jenkins/plugin/oauth/CodingUtil.java | 32 + .../jenkins/plugin/webhook/CodingWebHook.java | 34 +- .../plugin/webhook/WebHookHelperV1.java | 10 +- src/main/resources/index.jelly | 2 +- .../plugin/CodingPushTrigger/help.properties | 4 +- .../CodingPushTrigger/help_zh_CN.properties | 4 +- .../CodingAuthorizationStrategy/config.jelly | 49 ++ .../config.properties | 30 + .../config_zh_CN.properties | 30 + .../oauth/CodingLogoutAction/index.jelly | 42 + .../oauth/CodingLogoutAction/index.properties | 25 + .../CodingLogoutAction/index_zh_CN.properties | 25 + .../oauth/CodingSecurityRealm/config.jelly | 29 + .../CodingSecurityRealm/config.properties | 26 + .../config_zh_CN.properties | 26 + .../jenkins/plugin/oauth/Messages.properties | 22 + .../plugin/oauth/Messages_zh_CN.properties | 22 + .../help/help-webhook-api-personal-token.html | 2 +- ...help-webhook-api-personal-token_zh_CN.html | 2 +- .../webapp/help/help-webhook-apitoken.html | 2 +- .../help/help-webhook-apitoken_zh_CN.html | 2 +- src/main/webapp/help/oauth/aaa.sh | 7 + .../oauth/auth/admin-user-names-help.html | 3 + .../auth/admin-user-names-help_zh_CN.html | 3 + ...rant-create-job-to-authenticated-help.html | 3 + ...reate-job-to-authenticated-help_zh_CN.html | 3 + .../auth/grant-read-to-anonymous-help.html | 3 + .../grant-read-to-anonymous-help_zh_CN.html | 3 + .../grant-read-to-authenticated-help.html | 3 + ...rant-read-to-authenticated-help_zh_CN.html | 3 + .../oauth/auth/grant-read-to-cctray-help.html | 7 + .../auth/grant-read-to-cctray-help_zh_CN.html | 5 + .../grant-read-to-coding-webhook-help.html | 6 + ...ant-read-to-coding-webhook-help_zh_CN.html | 6 + .../grant-viewstatus-to-anonymous-help.html | 4 + ...nt-viewstatus-to-anonymous-help_zh_CN.html | 4 + .../oauth/auth/organization-names-help.html | 3 + .../auth/organization-names-help_zh_CN.html | 3 + .../auth/use-repository-permissions-help.html | 7 + ...use-repository-permissions-help_zh_CN.html | 7 + .../oauth/help-authorization-strategy.html | 13 + .../help-authorization-strategy_zh_CN.html | 14 + .../help/oauth/help-security-realm.html | 23 + .../help/oauth/help-security-realm_zh_CN.html | 23 + .../help/oauth/realm/client-id-help.html | 3 + .../oauth/realm/client-id-help_zh_CN.html | 3 + .../help/oauth/realm/client-secret-help.html | 3 + .../oauth/realm/client-secret-help_zh_CN.html | 3 + .../help/oauth/realm/coding-api-uri-help.html | 15 + .../realm/coding-api-uri-help_zh_CN.html | 15 + .../help/oauth/realm/coding-web-uri-help.html | 14 + .../realm/coding-web-uri-help_zh_CN.html | 14 + .../help/oauth/realm/oauth-scopes-help.html | 3 + .../oauth/realm/oauth-scopes-help_zh_CN.html | 3 + 87 files changed, 5151 insertions(+), 30 deletions(-) create mode 100644 src/main/java/net/coding/api/Coding.java create mode 100644 src/main/java/net/coding/api/CodingBuilder.java create mode 100644 src/main/java/net/coding/api/CodingEmail.java create mode 100644 src/main/java/net/coding/api/CodingMyself.java create mode 100644 src/main/java/net/coding/api/CodingObject.java create mode 100644 src/main/java/net/coding/api/CodingOrganization.java create mode 100644 src/main/java/net/coding/api/CodingPerson.java create mode 100644 src/main/java/net/coding/api/CodingPersonSet.java create mode 100644 src/main/java/net/coding/api/CodingRepository.java create mode 100644 src/main/java/net/coding/api/CodingTeam.java create mode 100644 src/main/java/net/coding/api/CodingUser.java create mode 100644 src/main/java/net/coding/api/HttpConnector.java create mode 100644 src/main/java/net/coding/api/HttpException.java create mode 100644 src/main/java/net/coding/api/PagedIterable.java create mode 100644 src/main/java/net/coding/api/PagedIterator.java create mode 100644 src/main/java/net/coding/api/Requester.java create mode 100644 src/main/java/net/coding/api/SkipFromToString.java create mode 100644 src/main/java/net/coding/api/extras/ImpatientHttpConnector.java create mode 100644 src/main/java/net/coding/api/extras/OkHttpConnector.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java create mode 100644 src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.jelly create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config_zh_CN.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.jelly create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index_zh_CN.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.jelly create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config_zh_CN.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/Messages.properties create mode 100644 src/main/resources/net/coding/jenkins/plugin/oauth/Messages_zh_CN.properties create mode 100644 src/main/webapp/help/oauth/aaa.sh create mode 100644 src/main/webapp/help/oauth/auth/admin-user-names-help.html create mode 100644 src/main/webapp/help/oauth/auth/admin-user-names-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help.html create mode 100644 src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-cctray-help.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-cctray-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help.html create mode 100644 src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help.html create mode 100644 src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/organization-names-help.html create mode 100644 src/main/webapp/help/oauth/auth/organization-names-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/auth/use-repository-permissions-help.html create mode 100644 src/main/webapp/help/oauth/auth/use-repository-permissions-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/help-authorization-strategy.html create mode 100644 src/main/webapp/help/oauth/help-authorization-strategy_zh_CN.html create mode 100644 src/main/webapp/help/oauth/help-security-realm.html create mode 100644 src/main/webapp/help/oauth/help-security-realm_zh_CN.html create mode 100644 src/main/webapp/help/oauth/realm/client-id-help.html create mode 100644 src/main/webapp/help/oauth/realm/client-id-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/realm/client-secret-help.html create mode 100644 src/main/webapp/help/oauth/realm/client-secret-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/realm/coding-api-uri-help.html create mode 100644 src/main/webapp/help/oauth/realm/coding-api-uri-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/realm/coding-web-uri-help.html create mode 100644 src/main/webapp/help/oauth/realm/coding-web-uri-help_zh_CN.html create mode 100644 src/main/webapp/help/oauth/realm/oauth-scopes-help.html create mode 100644 src/main/webapp/help/oauth/realm/oauth-scopes-help_zh_CN.html diff --git a/README.md b/README.md index 34be4cc..0586e68 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,12 @@ You may want to disable debug options to get faster page load time: ## Acknowledgements This project is started and based on the [gitlab-plugin][3], thanks for the great project. +The coding-api module follows [github-api-plugin][6], and coding-auth module follows [github-oauth-plugin][7], thanks for them. [1]: https://coding.net [2]: https://open.coding.net/webhooks [3]: https://github.com/jenkinsci/gitlab-plugin [4]: https://plugins.jenkins.io [5]: https://jenkins.io/doc/book/managing/plugins + [6]: https://github.com/jenkinsci/github-api-plugin + [7]: https://github.com/jenkinsci/github-oauth-plugin diff --git a/build.gradle b/build.gradle index c353162..0243bca 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,5 @@ plugins { - id 'org.jenkins-ci.jpi' version '0.18.1' - id 'me.tatarka.retrolambda' version '3.6.0' + id 'org.jenkins-ci.jpi' version '0.25.0' id "com.github.hierynomus.license" version "0.14.0" id 'idea' } @@ -12,8 +11,8 @@ repositories { url "http://repo.jenkins-ci.org/public/" } } - dependencies { + jenkinsPlugins 'org.jenkins-ci.plugins:git:2.4.1@jar' jenkinsPlugins 'org.jenkins-ci.plugins:git-client:1.19.0@jar' @@ -22,11 +21,51 @@ dependencies { compile 'org.eclipse.jgit:org.eclipse.jgit:3.5.2.201411120430-r' compile 'org.apache.httpcomponents:httpclient:4.5' compile 'commons-codec:commons-codec:1.10' + + // below are for coding oauth + jenkinsPlugins 'org.jenkins-ci.plugins:mailer:1.18@jar' + jenkinsPlugins 'org.jenkins-ci.plugins:matrix-project:1.7@jar' + jenkinsPlugins 'org.jenkins-ci.plugins:github-branch-source:1.9@jar' + + compile 'org.jenkins-ci.plugins.workflow:workflow-multibranch:2.9@jar' + compile 'org.jenkins-ci.plugins:branch-api:1.11@jar' + compile 'org.jenkins-ci.plugins:scm-api:1.3@jar' + compile 'org.jenkins-ci.plugins:cloudbees-folder:5.12@jar' + compile 'org.jenkins-ci.plugins.workflow:workflow-api:2.3@jar' + compile 'org.jenkins-ci.plugins.workflow:workflow-job:2.6@jar' + + compile 'com.fasterxml.jackson.core:jackson-databind:2.2.3' + compile 'com.squareup.okhttp:okhttp-urlconnection:2.5.0' + + compile group: 'com.google.code.gson', name: 'gson', version:'2.8.4' + compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.7' + testCompile group: 'org.powermock', name: 'powermock-api-mockito', version:'1.6.5' + testCompile group: 'org.powermock', name: 'powermock-module-junit4', version:'1.6.5' + testCompile group: 'junit', name: 'junit', version:'4.12' + testCompile group: 'org.jenkins-ci.plugins', name: 'external-monitor-job', version:'1.6' + testCompile group: 'javax.servlet', name: 'javax.servlet-api', version:'3.1.0' + testCompile group: 'org.jenkins-ci.main', name: 'jenkins-war', version:'2.7.1', classifier:'war-for-test' + testCompile group: 'org.jenkins-ci.main', name: 'jenkins-war', version:'2.7.1' + testCompile(group: 'org.jenkins-ci.main', name: 'jenkins-test-harness', version:'2.15') { + exclude(module: 'junit-dep') + } + testCompile group: 'org.jenkins-ci', name: 'test-annotations', version:'1.2' + testCompile group: 'org.slf4j', name: 'log4j-over-slf4j', version:'1.7.7' + testCompile group: 'org.slf4j', name: 'jcl-over-slf4j', version:'1.7.7' + testCompile group: 'org.slf4j', name: 'slf4j-jdk14', version:'1.7.7' + compileOnly group: 'com.google.code.findbugs', name: 'annotations', version:'3.0.0' + compileOnly group: 'net.jcip', name: 'jcip-annotations', version:'1.0' + compileOnly group: 'org.codehaus.mojo', name: 'animal-sniffer-annotations', version:'1.14' + compileOnly group: 'javax.servlet', name: 'servlet-api', version:'2.4' + compileOnly group: 'org.jenkins-ci.main', name: 'jenkins-core', version:'2.7.1' } group = 'org.jenkins-ci.plugins' description = 'Webhook trigger for Coding (https://coding.net)' -version = '1.2.2' +version = '1.3.0-alpha.1' + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 task wrapper(type: Wrapper) { gradleVersion = '2.14' @@ -38,7 +77,7 @@ license { } jenkinsPlugin { - coreVersion = '1.625.3' + coreVersion = '2.7.1' shortName = 'coding-webhook' displayName = 'Coding Webhook Plugin' url = 'https://wiki.jenkins.io/display/JENKINS/Coding+Webhook+Plugin' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e80b17b..8ba2eee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Feb 15 20:12:54 CST 2018 +#Tue May 15 15:33:00 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip diff --git a/src/main/java/net/coding/api/Coding.java b/src/main/java/net/coding/api/Coding.java new file mode 100644 index 0000000..f6071a1 --- /dev/null +++ b/src/main/java/net/coding/api/Coding.java @@ -0,0 +1,224 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.VisibilityChecker; +import com.infradna.tool.bridge_method_injector.WithBridgeMethods; +import org.apache.commons.codec.Charsets; +import org.apache.commons.codec.binary.Base64; + +import java.io.IOException; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; + +public class Coding { + /*package*/ final String login; + + private final Map users = new Hashtable(); + private final Map orgs = new Hashtable(); + + private final String apiUrl; + private HttpConnector connector = HttpConnector.DEFAULT; + /*package*/ final String encodedAuthorization; + + Coding(String apiUrl, String login, String oauthAccessToken, String password, HttpConnector connector) throws IOException { + if (apiUrl.endsWith("/")) apiUrl = apiUrl.substring(0, apiUrl.length() - 1); // normalize + this.apiUrl = apiUrl; + if (null != connector) this.connector = connector; + + if (oauthAccessToken != null) { + encodedAuthorization = oauthAccessToken; + } else { + if (password != null) { + String authorization = (login + ':' + password); + String charsetName = Charsets.UTF_8.name(); + encodedAuthorization = "Basic " + new String(Base64.encodeBase64(authorization.getBytes(charsetName)), charsetName); + } else {// anonymous access + encodedAuthorization = null; + } + } + + if (login == null && encodedAuthorization != null) + login = getMyself().getLogin(); + this.login = login; + } + + /** + * This method returns a shallowly populated organizations. + * + * To retrieve full organization details, you need to call {@link #getOrganization(String)} + * TODO: make this automatic. + */ + public Map getMyOrganizations() throws IOException { + if ("https://coding.net".equals(apiUrl)) { + return Collections.singletonMap("coding_dot_net", null); + } + return Collections.singletonMap("coding_dot_net", null); +// CodingOrganization[] orgs = retrieve().to("/user/orgs", CodingOrganization[].class); +// Map r = new HashMap(); +// for (CodingOrganization o : orgs) { +// // don't put 'o' into orgs because they are shallow +// r.put(o.getLogin(),o.wrapUp(this)); +// } +// return r; + } + + public CodingOrganization getOrganization(String name) throws IOException { + CodingOrganization o = new CodingOrganization(); + o.global_key = "coding_dot_net"; + return o; +// CodingOrganization o = orgs.get(name); +// if (o==null) { +// o = retrieve().to("/orgs/" + name, CodingOrganization.class).wrapUp(this); +// orgs.put(name,o); +// } +// return o; + } + + /** + * Gets the repository object from 'user/reponame' string that GitHub calls as "repository name" + * + * @see CodingRepository#getName() + */ + public CodingRepository getRepository(String name) throws IOException { + String[] tokens = name.split("/"); + return retrieve().to("/repos/" + tokens[0] + '/' + tokens[1], CodingRepository.class).wrap(this); + } + + /** + * Gets complete map of organizations/teams that current user belongs to. + * + * Leverages the new GitHub API /user/teams made available recently to + * get in a single call the complete set of organizations, teams and permissions + * in a single call. + */ + public Map> getMyTeams() throws IOException { + Map> allMyTeams = new HashMap<>(); + for (CodingTeam team : retrieve().to("/api/team/joined", CodingTeam[].class)) { + team.wrapUp(this); + String orgLogin = team.getOrganization().getLogin(); + Set teamsPerOrg = allMyTeams.get(orgLogin); + if (teamsPerOrg == null) { + teamsPerOrg = new HashSet<>(); + } + teamsPerOrg.add(team); + allMyTeams.put(orgLogin, teamsPerOrg); + } + return allMyTeams; + } + + /** + * Obtains the object that represents the named user. + */ + public CodingUser getUser(String login) throws IOException { + if ("MANAGE_DOMAINS".equals(login)) { + LOGGER.log(Level.INFO, "ignore fetch user info for MANAGE_DOMAINS"); + return null; + } + CodingUser u = users.get(login); + if (u == null) { + u = retrieve().to("/api/user/key/" + login, CodingUser.class); + if (u == null) { + return null; + } + u.root = this; + users.put(u.getLogin(), u); + } + return u; + } + + + /** + * Gets the {@link CodingUser} that represents yourself. + */ + @WithBridgeMethods(CodingUser.class) + public CodingMyself getMyself() throws IOException { + requireCredential(); + + CodingMyself u = retrieve().to("/api/current_user", CodingMyself.class); + LOGGER.log(Level.FINE, "fetch current_user " + u); + + u.root = this; + users.put(u.getLogin(), u); + + return u; + } + + /*package*/ void requireCredential() { + if (isAnonymous()) + throw new IllegalStateException("This operation requires a credential but none is given to the GitHub constructor"); + } + + /** + * Is this an anonymous connection + * @return {@code true} if operations that require authentication will fail. + */ + public boolean isAnonymous() { + return login == null && encodedAuthorization == null; + } + + Requester retrieve() { + return new Requester(this).method("GET"); + } + + public HttpConnector getConnector() { + return connector; + } + + /*package*/ URL getApiURL(String tailApiUrl) throws IOException { + if (tailApiUrl.startsWith("/")) { + return new URL(apiUrl + tailApiUrl); + } else { + return new URL(tailApiUrl); + } + } + + /*package*/ + static String printDate(Date dt) { + return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(dt); + } + + /*package*/ static final ObjectMapper MAPPER = new ObjectMapper(); + + private static final String[] TIME_FORMATS = {"yyyy/MM/dd HH:mm:ss ZZZZ", "yyyy-MM-dd'T'HH:mm:ss'Z'"}; + + static { + MAPPER.setVisibilityChecker(new VisibilityChecker.Std(NONE, NONE, NONE, NONE, ANY)); + MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + /* package */ static final String CODING_URL = "https://coding.net"; + + private static final Logger LOGGER = Logger.getLogger(Coding.class.getName()); +} diff --git a/src/main/java/net/coding/api/CodingBuilder.java b/src/main/java/net/coding/api/CodingBuilder.java new file mode 100644 index 0000000..aee8623 --- /dev/null +++ b/src/main/java/net/coding/api/CodingBuilder.java @@ -0,0 +1,80 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.io.IOException; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; + +public class CodingBuilder { + + /* private */ String endpoint = Coding.CODING_URL; + /* private */ String user; + /* private */ String password; + /* private */ String oauthToken; + + private HttpConnector connector; + + public static CodingBuilder fromEnvironment() throws IOException { + Properties props = new Properties(); + for (Map.Entry e : System.getenv().entrySet()) { + String name = e.getKey().toLowerCase(Locale.ENGLISH); + if (name.startsWith("github_")) name=name.substring(7); + props.put(name,e.getValue()); + } + return fromProperties(props); + } + + public static CodingBuilder fromProperties(Properties props) { + CodingBuilder self = new CodingBuilder(); + self.withOAuthToken(props.getProperty("net/coding/jenkins/plugin/oauth"), props.getProperty("login")); + self.withPassword(props.getProperty("login"), props.getProperty("password")); + self.withEndpoint(props.getProperty("endpoint", Coding.CODING_URL)); + return self; + } + + public CodingBuilder withEndpoint(String endpoint) { + this.endpoint = endpoint; + return this; + } + public CodingBuilder withPassword(String user, String password) { + this.user = user; + this.password = password; + return this; + } + public CodingBuilder withOAuthToken(String oauthToken) { + return withOAuthToken(oauthToken, null); + } + public CodingBuilder withOAuthToken(String oauthToken, String user) { + this.oauthToken = oauthToken; + this.user = user; + return this; + } + + public CodingBuilder withConnector(HttpConnector connector) { + this.connector = connector; + return this; + } + + public Coding build() throws IOException { + return new Coding(endpoint, user, oauthToken, password, connector); + } +} diff --git a/src/main/java/net/coding/api/CodingEmail.java b/src/main/java/net/coding/api/CodingEmail.java new file mode 100644 index 0000000..a9e59f8 --- /dev/null +++ b/src/main/java/net/coding/api/CodingEmail.java @@ -0,0 +1,63 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", + "NP_UNWRITTEN_FIELD", "NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD"}, justification = "JSON API") +public class CodingEmail { + + protected String email; + protected boolean primary; + protected boolean verified; + + public String getEmail() { + return email; + } + + public boolean isPrimary() { + return primary; + } + + public boolean isVerified() { + return verified; + } + + + @Override + public String toString() { + return "Email:"+email; + } + + @Override + public int hashCode() { + return email.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CodingEmail) { + CodingEmail that = (CodingEmail) obj; + return this.email.equals(that.email); + } + return false; + } +} diff --git a/src/main/java/net/coding/api/CodingMyself.java b/src/main/java/net/coding/api/CodingMyself.java new file mode 100644 index 0000000..be50e5d --- /dev/null +++ b/src/main/java/net/coding/api/CodingMyself.java @@ -0,0 +1,155 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class CodingMyself extends CodingUser { + + /** + * Type of repositories returned during listing. + */ + public enum RepositoryListFilter { + /** + * All public and private repositories that current user has access or collaborates to + */ + ALL, + /** + * Public and private repositories owned by current user + */ + OWNER, + /** + * Public repositories that current user has access or collaborates to + */ + PUBLIC, + /** + * Private repositories that current user has access or collaborates to + */ + PRIVATE, + /** + * Public and private repositories that current user is a member + */ + MEMBER; + } + + /** + * Lists up all repositories this user owns (public and private). + * + * Unlike {@link #getAllRepositories()}, this does not wait until all the repositories are returned. + * Repositories are returned by GitHub API with a 30 items per page. + */ + @Override + public PagedIterable listRepositories() { + return listRepositories(30); + } + + /** + * Gets the all repositories this user owns (public and private). + */ + public synchronized Map getAllRepositories() throws IOException { + Map repositories = new TreeMap(); + for (CodingRepository r : listAllRepositories()) { + repositories.put(r.getName(),r); + } + return Collections.unmodifiableMap(repositories); + } + + /** + * @deprecated + * Use {@link #listRepositories()} + */ + public PagedIterable listAllRepositories() { + return listRepositories(); + } + + /** + * Gets the organization that this user belongs to. + */ + public CodingPersonSet getAllOrganizations() throws IOException { + CodingPersonSet orgs = new CodingPersonSet(); +// Set names = new HashSet(); +// for (CodingOrganization o : root.retrieve().to("/user/orgs", CodingOrganization[].class)) { +// if (names.add(o.getLogin())) // in case of rumoured duplicates in the data +// orgs.add(root.getOrganization(o.getLogin())); +// } + + orgs.add(root.getOrganization(null)); + return orgs; + } + + /** + * List repositories that are accessible to the authenticated user (public and private) using the specified page size. + * + * This includes repositories owned by the authenticated user, repositories that belong to other users + * where the authenticated user is a collaborator, and other organizations' repositories that the authenticated + * user has access to through an organization membership. + * + * @param pageSize size for each page of items returned by GitHub. Maximum page size is 100. + * + * Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned. + */ + public PagedIterable listRepositories(final int pageSize) { + return listRepositories(pageSize, RepositoryListFilter.ALL); + } + + /** + * List repositories of a certain type that are accessible by current authenticated user using the specified page size. + * + * @param pageSize size for each page of items returned by GitHub. Maximum page size is 100. + * @param repoType type of repository returned in the listing + */ + public PagedIterable listRepositories(final int pageSize, final RepositoryListFilter repoType) { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().with("type",repoType).asIterator("/user/repos", CodingRepository[].class, pageSize)) { + @Override + protected void wrapUp(CodingRepository[] page) { + for (CodingRepository c : page) + c.wrap(root); + } + }; + } + }.withPageSize(pageSize); + } + + /** + * Returns the read-only list of e-mail addresses configured for you. + * + * This corresponds to the stuff you configure in https://github.com/settings/emails, + * and not to be confused with {@link #getEmail()} that shows your public e-mail address + * set in https://github.com/settings/profile + * + * @return + * Always non-null. + */ + public List getEmails2() throws IOException { + String fetchEmail = root.retrieve().to("/api/account/email", String.class); + email = fetchEmail; + CodingEmail codingEmail = new CodingEmail(); + codingEmail.email = fetchEmail; + codingEmail.primary = true; + return Collections.unmodifiableList(Collections.singletonList(codingEmail)); + } + +} diff --git a/src/main/java/net/coding/api/CodingObject.java b/src/main/java/net/coding/api/CodingObject.java new file mode 100644 index 0000000..578221d --- /dev/null +++ b/src/main/java/net/coding/api/CodingObject.java @@ -0,0 +1,68 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +import java.lang.reflect.Field; + +public class CodingObject { + + protected String url; + protected int id; + protected String created_at; + protected String updated_at; + + /** + * String representation to assist debugging and inspection. The output format of this string + * is not a committed part of the API and is subject to change. + */ + @Override + public String toString() { + return new ReflectionToStringBuilder(this, TOSTRING_STYLE, null, null, false, false) { + @Override + protected boolean accept(Field field) { + return super.accept(field) && !field.isAnnotationPresent(SkipFromToString.class); + } + }.toString(); + } + + private static final ToStringStyle TOSTRING_STYLE = new ToStringStyle() { + { + this.setUseShortClassName(true); + } + + @Override + public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) { + // skip unimportant properties. '_' is a heuristics as important properties tend to have short names + if (fieldName.contains("_")) + return; + // avoid recursing other GHObject + if (value instanceof CodingObject) + return; + // likewise no point in showing root + if (value instanceof Coding) + return; + + super.append(buffer,fieldName,value,fullDetail); + } + }; +} diff --git a/src/main/java/net/coding/api/CodingOrganization.java b/src/main/java/net/coding/api/CodingOrganization.java new file mode 100644 index 0000000..63403cb --- /dev/null +++ b/src/main/java/net/coding/api/CodingOrganization.java @@ -0,0 +1,58 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.io.IOException; + +public class CodingOrganization extends CodingPerson { + protected String avatar_url, gravatar_id; + + /*package*/ CodingOrganization wrapUp(Coding root) { + return (CodingOrganization)super.wrapUp(root); + } + + /** + * Finds a team that has the given name in its {@link CodingTeam#getName()} + */ + public CodingTeam getTeamByName(String name) throws IOException { + for (CodingTeam t : listTeams()) { + if(t.getName().equals(name)) + return t; + } + return null; + } + + /** + * List up all the teams. + */ + public PagedIterable listTeams() throws IOException { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/teams", getLogin()), CodingTeam[].class, pageSize)) { + @Override + protected void wrapUp(CodingTeam[] page) { + for (CodingTeam c : page) + c.wrapUp(CodingOrganization.this); + } + }; + } + }; + } +} diff --git a/src/main/java/net/coding/api/CodingPerson.java b/src/main/java/net/coding/api/CodingPerson.java new file mode 100644 index 0000000..23cbb69 --- /dev/null +++ b/src/main/java/net/coding/api/CodingPerson.java @@ -0,0 +1,120 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +public class CodingPerson extends CodingObject { + + /*package almost final*/ Coding root; + + protected String avatar_url, global_key; + + protected String location,blog,email,name,company; + + protected String html_url; + + /** + * Gets the login ID of this user, like 'kohsuke' + */ + public String getLogin() { + return global_key; + } + + /*package*/ CodingPerson wrapUp(Coding root) { + this.root = root; + return this; + } + + /** + * Gets the e-mail address of the user. + */ + public String getEmail() throws IOException { + populate(); + return email; + } + + /** + * Fully populate the data by retrieving missing data. + * + * Depending on the original API call where this object is created, it may not contain everything. + */ + protected synchronized void populate() throws IOException { + if (created_at!=null) return; // already populated + + root.retrieve().to(url, this); + } + + /** + * Lists up all the repositories using a 30 items page size. + * + * Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned. + */ + public PagedIterable listRepositories() { + return listRepositories(30); + } + + /** + * Lists up all the repositories using the specified page size. + * + * @param pageSize size for each page of items returned by GitHub. Maximum page size is 100. + * + * Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned. + */ + public PagedIterable listRepositories(final int pageSize) { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator("/users/" + getLogin() + "/repos?per_page=" + pageSize, CodingRepository[].class, pageSize)) { + @Override + protected void wrapUp(CodingRepository[] page) { + for (CodingRepository c : page) + c.wrap(root); + } + }; + } + }; + } + + /** + * Gets the public repositories this user owns. + * + *

+ * To list your own repositories, including private repositories, + * use {@link CodingMyself#listRepositories()} + */ + public synchronized Map getRepositories() throws IOException { + Map repositories = new TreeMap(); + for (CodingRepository r : listRepositories()) { + repositories.put(r.getName(),r); + } + return Collections.unmodifiableMap(repositories); + } + + /** + * Gets the human-readable name of the user, like "Kohsuke Kawaguchi" + */ + public String getName() throws IOException { + populate(); + return name; + } +} diff --git a/src/main/java/net/coding/api/CodingPersonSet.java b/src/main/java/net/coding/api/CodingPersonSet.java new file mode 100644 index 0000000..d602ee0 --- /dev/null +++ b/src/main/java/net/coding/api/CodingPersonSet.java @@ -0,0 +1,57 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; + +public class CodingPersonSet extends HashSet { + private static final long serialVersionUID = 1L; + + public CodingPersonSet() { + } + + public CodingPersonSet(Collection c) { + super(c); + } + + public CodingPersonSet(T... c) { + super(Arrays.asList(c)); + } + + public CodingPersonSet(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + public CodingPersonSet(int initialCapacity) { + super(initialCapacity); + } + + /** + * Finds the item by its login. + */ + public T byLogin(String login) { + for (T t : this) + if (t.getLogin().equals(login)) + return t; + return null; + } +} diff --git a/src/main/java/net/coding/api/CodingRepository.java b/src/main/java/net/coding/api/CodingRepository.java new file mode 100644 index 0000000..04c15c3 --- /dev/null +++ b/src/main/java/net/coding/api/CodingRepository.java @@ -0,0 +1,68 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.io.IOException; + +public class CodingRepository { + /*package almost final*/ Coding root; + + private String description, homepage, name, full_name; + private String html_url; // this is the UI + + private CodingUser owner; // not fully populated. beware. + + private boolean _private; + private boolean permissions_pull; + private boolean permissions_push; + private boolean permissions_admin; + + /** + * Short repository name without the owner. For example 'jenkins' in case of http://github.com/jenkinsci/jenkins + */ + public String getName() { + return name; + } + + /*package*/ CodingRepository wrap(Coding root) { + this.root = root; + return this; + } + + public CodingUser getOwner() throws IOException { + return root.getUser(owner.getLogin()); // because 'owner' isn't fully populated + } + + public boolean isPrivate() { + return _private; + } + + public boolean hasPullAccess() { + return permissions_pull; + } + + public boolean hasPushAccess() { + return permissions_push; + } + + public boolean hasAdminAccess() { + return permissions_admin; + } +} diff --git a/src/main/java/net/coding/api/CodingTeam.java b/src/main/java/net/coding/api/CodingTeam.java new file mode 100644 index 0000000..3a553a9 --- /dev/null +++ b/src/main/java/net/coding/api/CodingTeam.java @@ -0,0 +1,55 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +public class CodingTeam { + + private String name,permission,slug; + + private CodingOrganization organization; + + protected /*final*/ CodingOrganization org; + + private String global_key, avatar; + + private Integer id; + + public CodingOrganization getOrganization() { + return org; + } + + /*package*/ CodingTeam wrapUp(CodingOrganization owner) { + this.org = owner; + return this; + } + + /*package*/ CodingTeam wrapUp(Coding root) { // auto-wrapUp when organization is known from GET /user/teams + if (this.organization == null) { + this.organization = new CodingOrganization(); + this.organization.global_key = "coding_dot_net"; + } + this.organization.wrapUp(root); + return wrapUp(organization); + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/net/coding/api/CodingUser.java b/src/main/java/net/coding/api/CodingUser.java new file mode 100644 index 0000000..aa7b90b --- /dev/null +++ b/src/main/java/net/coding/api/CodingUser.java @@ -0,0 +1,23 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +public class CodingUser extends CodingPerson { +} diff --git a/src/main/java/net/coding/api/HttpConnector.java b/src/main/java/net/coding/api/HttpConnector.java new file mode 100644 index 0000000..24ccd88 --- /dev/null +++ b/src/main/java/net/coding/api/HttpConnector.java @@ -0,0 +1,51 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import net.coding.api.extras.ImpatientHttpConnector; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Pluggability for customizing HTTP request behaviors or using altogether different library. + * + *

+ * For example, you can implement this to st custom timeouts. + * + * @author Kohsuke Kawaguchi + */ +public interface HttpConnector { + /** + * Opens a connection to the given URL. + */ + HttpURLConnection connect(URL url) throws IOException; + + /** + * Default implementation that uses {@link URL#openConnection()}. + */ + HttpConnector DEFAULT = new ImpatientHttpConnector(new HttpConnector() { + public HttpURLConnection connect(URL url) throws IOException { + return (HttpURLConnection) url.openConnection(); + } + }); +} + diff --git a/src/main/java/net/coding/api/HttpException.java b/src/main/java/net/coding/api/HttpException.java new file mode 100644 index 0000000..c6ae00b --- /dev/null +++ b/src/main/java/net/coding/api/HttpException.java @@ -0,0 +1,44 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import javax.annotation.CheckForNull; +import java.io.IOException; +import java.net.URL; + +public class HttpException extends IOException { + + private final int responseCode; + private final String responseMessage; + private final String url; + + public HttpException(int responseCode, String responseMessage, String url, Throwable cause) { + super("Server returned HTTP response code: " + responseCode + ", message: '" + responseMessage + "'" + + " for URL: " + url); + initCause(cause); + this.responseCode = responseCode; + this.responseMessage = responseMessage; + this.url = url; + } + + public HttpException(int responseCode, String responseMessage, @CheckForNull URL url, Throwable cause) { + this(responseCode, responseMessage, url == null ? null : url.toString(), cause); + } +} diff --git a/src/main/java/net/coding/api/PagedIterable.java b/src/main/java/net/coding/api/PagedIterable.java new file mode 100644 index 0000000..f7bcbfa --- /dev/null +++ b/src/main/java/net/coding/api/PagedIterable.java @@ -0,0 +1,71 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public abstract class PagedIterable implements Iterable { + /** + * Page size. 0 is default. + */ + private int size = 0; + + /** + * Sets the pagination size. + * + *

+ * When set to non-zero, each API call will retrieve this many entries. + */ + public PagedIterable withPageSize(int size) { + this.size = size; + return this; + } + + public final PagedIterator iterator() { + return _iterator(size); + } + + public abstract PagedIterator _iterator(int pageSize); + + /** + * Eagerly walk {@link Iterable} and return the result in a list. + */ + public List asList() { + List r = new ArrayList(); + for(PagedIterator i = iterator(); i.hasNext();) { + r.addAll(i.nextPage()); + } + return r; + } + + /** + * Eagerly walk {@link Iterable} and return the result in a set. + */ + public Set asSet() { + LinkedHashSet r = new LinkedHashSet(); + for(PagedIterator i = iterator(); i.hasNext();) { + r.addAll(i.nextPage()); + } + return r; + } +} \ No newline at end of file diff --git a/src/main/java/net/coding/api/PagedIterator.java b/src/main/java/net/coding/api/PagedIterator.java new file mode 100644 index 0000000..acdf118 --- /dev/null +++ b/src/main/java/net/coding/api/PagedIterator.java @@ -0,0 +1,83 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +public abstract class PagedIterator implements Iterator { + private final Iterator base; + + /** + * Current batch that we retrieved but haven't returned to the caller. + */ + private T[] current; + private int pos; + + /*package*/ PagedIterator(Iterator base) { + this.base = base; + } + + protected abstract void wrapUp(T[] page); + + public boolean hasNext() { + fetch(); + return current!=null; + } + + public T next() { + fetch(); + if (current==null) throw new NoSuchElementException(); + return current[pos++]; + } + + private void fetch() { + while (current==null || current.length<=pos) { + if (!base.hasNext()) {// no more to retrieve + current = null; + pos = 0; + return; + } + + current = base.next(); + wrapUp(current); + pos = 0; + } + // invariant at the end: there's some data to retrieve + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * Gets the next page worth of data. + */ + public List nextPage() { + fetch(); + List r = Arrays.asList(current); + r = r.subList(pos,r.size()); + current = null; + pos = 0; + return r; + } +} \ No newline at end of file diff --git a/src/main/java/net/coding/api/Requester.java b/src/main/java/net/coding/api/Requester.java new file mode 100644 index 0000000..9810481 --- /dev/null +++ b/src/main/java/net/coding/api/Requester.java @@ -0,0 +1,527 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonSyntaxException; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.commons.io.IOUtils; + +import javax.annotation.WillClose; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; + +import static java.util.Arrays.asList; +import static net.coding.api.Coding.MAPPER; + +public class Requester { + + private final Coding root; + private final List args = new ArrayList<>(); + private final Map headers = new LinkedHashMap<>(); + + /** + * Request method. + */ + private String method = "POST"; + private String contentType = "application/x-www-form-urlencoded"; + private InputStream body; + + /** + * Current connection. + */ + private HttpURLConnection uc; + + private static class Entry { + String key; + Object value; + + private Entry(String key, Object value) { + this.key = key; + this.value = value; + } + } + + Requester(Coding root) { + this.root = root; + } + + public Requester method(String method) { + this.method = method; + return this; + } + + public void to(String tailApiUrl) throws IOException { + to(tailApiUrl,null); + } + + /** + * Like {@link #to(String, Class)} but updates an existing object instead of creating a new instance. + */ + public T to(String tailApiUrl, T existingInstance) throws IOException { + return _to(tailApiUrl, null, existingInstance); + } + + /** + * Loads pagenated resources. + * + * Every iterator call reports a new batch. + */ + /*package*/ Iterator asIterator(String tailApiUrl, Class type, int pageSize) { + method("GET"); + + if (pageSize!=0) + args.add(new Entry("per_page",pageSize)); + + StringBuilder s = new StringBuilder(tailApiUrl); + if (!args.isEmpty()) { + boolean first = true; + try { + for (Entry a : args) { + s.append(first ? '?' : '&'); + first = false; + s.append(URLEncoder.encode(a.key, "UTF-8")); + s.append('='); + s.append(URLEncoder.encode(a.value.toString(), "UTF-8")); + } + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); // UTF-8 is mandatory + } + } + + try { + return new PagingIterator(type, root.getApiURL(s.toString())); + } catch (IOException e) { + throw new Error(e); + } + } + + class PagingIterator implements Iterator { + + private final Class type; + + /** + * The next batch to be returned from {@link #next()}. + */ + private T next; + + /** + * URL of the next resource to be retrieved, or null if no more data is available. + */ + private URL url; + + PagingIterator(Class type, URL url) { + this.url = url; + this.type = type; + } + + public boolean hasNext() { + fetch(); + return next!=null; + } + + public T next() { + fetch(); + T r = next; + if (r==null) throw new NoSuchElementException(); + next = null; + return r; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + private void fetch() { + if (next!=null) return; // already fetched + if (url==null) return; // no more data to fetch + + try { + while (true) {// loop while API rate limit is hit + setupConnection(url); + try { + next = parse(type,null); + assert next!=null; + findNextURL(); + return; + } catch (IOException e) { + handleApiError(e); + } + } + } catch (IOException e) { + throw new Error(e); + } + } + + /** + * Locate the next page from the pagination "Link" tag. + */ + private void findNextURL() throws MalformedURLException { + url = null; // start defensively + String link = uc.getHeaderField("Link"); + if (link==null) return; + + for (String token : link.split(", ")) { + if (token.endsWith("rel=\"next\"")) { + // found the next page. This should look something like + // ; rel="next" + int idx = token.indexOf('>'); + url = new URL(token.substring(1,idx)); + return; + } + } + + // no more "next" link. we are done. + } + } + + /** + * Sends a request to the specified URL, and parses the response into the given type via databinding. + * + * @throws IOException + * if the server returns 4xx/5xx responses. + * @return + * {@link Reader} that reads the response. + */ + public T to(String tailApiUrl, Class type) throws IOException { + return _to(tailApiUrl, type, null); + } + + @SuppressFBWarnings("SBSC_USE_STRINGBUFFER_CONCATENATION") + private T _to(String tailApiUrl, Class type, T instance) throws IOException { + if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) { + boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; + tailApiUrl += questionMarkFound ? '&' : '?'; + for (Iterator it = args.listIterator(); it.hasNext();) { + Entry arg = it.next(); + tailApiUrl += arg.key + '=' + URLEncoder.encode(arg.value.toString(),"UTF-8"); + if (it.hasNext()) { + tailApiUrl += '&'; + } + } + } + + boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; + tailApiUrl += questionMarkFound ? '&' : '?'; + tailApiUrl += "access_token=" + root.encodedAuthorization; + + while (true) {// loop while API rate limit is hit + setupConnection(root.getApiURL(tailApiUrl)); + + buildRequest(); + + try { + T result = parse(type, instance); + if (type != null && type.isArray()) { // we might have to loop for pagination - done through recursion + final String links = uc.getHeaderField("link"); + if (links != null && links.contains("rel=\"next\"")) { + Pattern nextLinkPattern = Pattern.compile(".*<(.*)>; rel=\"next\""); + Matcher nextLinkMatcher = nextLinkPattern.matcher(links); + if (nextLinkMatcher.find()) { + final String link = nextLinkMatcher.group(1); + T nextResult = _to(link, type, instance); + + final int resultLength = Array.getLength(result); + final int nextResultLength = Array.getLength(nextResult); + T concatResult = (T) Array.newInstance(type.getComponentType(), resultLength + nextResultLength); + System.arraycopy(result, 0, concatResult, 0, resultLength); + System.arraycopy(nextResult, 0, concatResult, resultLength, nextResultLength); + result = concatResult; + } + } + } + return result; + } catch (IOException e) { + handleApiError(e); + } catch (JsonSyntaxException e) { + String msg = "not json response for api " + uc.getURL(); + LOGGER.log(Level.WARNING, msg, e); + throw new IOException(msg, e); + } + } + } + + /** + * Handle API error by either throwing it or by returning normally to retry. + */ + /*package*/ void handleApiError(IOException e) throws IOException { + int responseCode; + try { + responseCode = uc.getResponseCode(); + } catch (IOException e2) { + // likely to be a network exception (e.g. SSLHandshakeException), + // uc.getResponseCode() and any other getter on the response will cause an exception + if (LOGGER.isLoggable(Level.FINE)) + LOGGER.log(Level.FINE, "Silently ignore exception retrieving response code for '" + uc.getURL() + "'" + + " handling exception " + e, e); + throw e; + } + if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) // 401 / Unauthorized == bad creds + throw e; + + InputStream es = wrapStream(uc.getErrorStream()); + try { + if (es!=null) { + if (e instanceof FileNotFoundException) { + // pass through 404 Not Found to allow the caller to handle it intelligently + throw (IOException) new FileNotFoundException(IOUtils.toString(es, "UTF-8")).initCause(e); + } else + throw (IOException) new IOException(IOUtils.toString(es, "UTF-8")).initCause(e); + } else + throw e; + } finally { + IOUtils.closeQuietly(es); + } + } + + private T parse(Class type, T instance) throws IOException { + InputStreamReader r = null; + int responseCode = -1; + String responseMessage = null; + try { + responseCode = uc.getResponseCode(); + responseMessage = uc.getResponseMessage(); + if (responseCode == 304) { + return null; // special case handling for 304 unmodified, as the content will be "" + } + if (responseCode == 204 && type!=null && type.isArray()) { + // no content + return type.cast(Array.newInstance(type.getComponentType(),0)); + } + + r = new InputStreamReader(wrapStream(uc.getInputStream()), "UTF-8"); + String data = IOUtils.toString(r); + LOGGER.log(Level.FINEST, "api " + uc.getURL() + " reads " + data); + if (type!=null) + try { + CodingResult codingResult = new GsonBuilder().create().fromJson(data, CodingResult.class); + Integer code = codingResult.code; + if (code != 0) { + LOGGER.log(Level.WARNING, "api fails for " + uc.getURL().toString() + " coding code is " + code); + return null; + } + return MAPPER.readValue(new GsonBuilder().create().toJson(codingResult.data), type); + } catch (JsonMappingException e) { + throw (IOException)new IOException("Failed to deserialize " +data).initCause(e); + } + if (instance!=null) + try { + CodingResult codingResult = new GsonBuilder().create().fromJson(data, CodingResult.class); + Integer code = codingResult.code; + if (code != 0) { + LOGGER.log(Level.WARNING, "api fails for " + uc.getURL().toString() + " coding code is " + code); + return null; + } + return MAPPER.readerForUpdating(instance).readValue(new GsonBuilder().create().toJson(codingResult.data)); + } catch (JsonMappingException e) { + throw (IOException)new IOException("Failed to deserialize " +data).initCause(e); + } + + return null; + } catch (FileNotFoundException e) { + // java.net.URLConnection handles 404 exception has FileNotFoundException, don't wrap exception in HttpException + // to preserve backward compatibility + throw e; + } catch (IOException e) { + throw new HttpException(responseCode, responseMessage, uc.getURL(), e); + } finally { + IOUtils.closeQuietly(r); + } + } + + private static class CodingResult { + Integer code; + JsonElement data; + } + + /** + * Handles the "Content-Encoding" header. + */ + private InputStream wrapStream(InputStream in) throws IOException { + String encoding = uc.getContentEncoding(); + if (encoding==null || in==null) return in; + if (encoding.equals("gzip")) return new GZIPInputStream(in); + + throw new UnsupportedOperationException("Unexpected Content-Encoding: "+encoding); + } + + private void setupConnection(URL url) throws IOException { + uc = root.getConnector().connect(url); + + // if the authentication is needed but no credential is given, try it anyway (so that some calls + // that do work with anonymous access in the reduced form should still work.) + if (root.encodedAuthorization!=null) { +// uc.setRequestProperty("access_token", root.encodedAuthorization); + } + + + for (Map.Entry e : headers.entrySet()) { + String v = e.getValue(); + if (v!=null) + uc.setRequestProperty(e.getKey(), v); + } + + setRequestMethod(uc); + uc.setRequestProperty("Accept-Encoding", "gzip"); + } + + private void setRequestMethod(HttpURLConnection uc) throws IOException { + try { + uc.setRequestMethod(method); + } catch (ProtocolException e) { + // JDK only allows one of the fixed set of verbs. Try to override that + try { + Field $method = HttpURLConnection.class.getDeclaredField("method"); + $method.setAccessible(true); + $method.set(uc,method); + } catch (Exception x) { + throw (IOException)new IOException("Failed to set the custom verb").initCause(x); + } + // sun.net.www.protocol.https.DelegatingHttpsURLConnection delegates to another HttpURLConnection + try { + Field $delegate = uc.getClass().getDeclaredField("delegate"); + $delegate.setAccessible(true); + Object delegate = $delegate.get(uc); + if (delegate instanceof HttpURLConnection) { + HttpURLConnection nested = (HttpURLConnection) delegate; + setRequestMethod(nested); + } + } catch (NoSuchFieldException x) { + // no problem + } catch (IllegalAccessException x) { + throw (IOException)new IOException("Failed to set the custom verb").initCause(x); + } + } + if (!uc.getRequestMethod().equals(method)) + throw new IllegalStateException("Failed to set the request method to "+method); + } + + /** + * Set up the request parameters or POST payload. + */ + private void buildRequest() throws IOException { + if (isMethodWithBody()) { + uc.setDoOutput(true); + uc.setRequestProperty("Content-type", contentType); + + if (body == null) { + Map json = new HashMap(); + for (Entry e : args) { + json.put(e.key, e.value); + } + MAPPER.writeValue(uc.getOutputStream(), json); + } else { + try { + byte[] bytes = new byte[32768]; + int read = 0; + while ((read = body.read(bytes)) != -1) { + uc.getOutputStream().write(bytes, 0, read); + } + } finally { + body.close(); + } + } + } + } + + public Requester with(String key, Integer value) { + if (value!=null) + _with(key, value); + return this; + } + + public Requester with(String key, boolean value) { + return _with(key, value); + } + public Requester with(String key, Boolean value) { + return _with(key, value); + } + + public Requester with(String key, Enum e) { + if (e==null) return _with(key, null); + + // by convention Java constant names are upper cases, but github uses + // lower-case constants. GitHub also uses '-', which in Java we always + // replace by '_' + return with(key, e.toString().toLowerCase(Locale.ENGLISH).replace('_', '-')); + } + + public Requester with(String key, String value) { + return _with(key, value); + } + + public Requester with(String key, int value) { + return _with(key, value); + } + + public Requester with(String key, Collection value) { + return _with(key, value); + } + + public Requester with(String key, Map value) { + return _with(key, value); + } + + public Requester with(@WillClose/*later*/ InputStream body) { + this.body = body; + return this; + } + + public Requester _with(String key, Object value) { + if (value!=null) { + args.add(new Entry(key,value)); + } + return this; + } + + private boolean isMethodWithBody() { + return !METHODS_WITHOUT_BODY.contains(method); + } + + private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); + private static final Logger LOGGER = Logger.getLogger(Requester.class.getName()); +} diff --git a/src/main/java/net/coding/api/SkipFromToString.java b/src/main/java/net/coding/api/SkipFromToString.java new file mode 100644 index 0000000..d71fd8d --- /dev/null +++ b/src/main/java/net/coding/api/SkipFromToString.java @@ -0,0 +1,30 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@interface SkipFromToString { +} diff --git a/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java b/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java new file mode 100644 index 0000000..74a229f --- /dev/null +++ b/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java @@ -0,0 +1,72 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api.extras; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.coding.api.HttpConnector; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +public class ImpatientHttpConnector implements HttpConnector { + private final HttpConnector base; + private final int readTimeout, connectTimeout; + + /** + * @param connectTimeout + * HTTP connection timeout in milliseconds + * @param readTimeout + * HTTP read timeout in milliseconds + */ + public ImpatientHttpConnector(HttpConnector base, int connectTimeout, int readTimeout) { + this.base = base; + this.connectTimeout = connectTimeout; + this.readTimeout = readTimeout; + } + + public ImpatientHttpConnector(HttpConnector base, int timeout) { + this(base,timeout,timeout); + } + + public ImpatientHttpConnector(HttpConnector base) { + this(base,CONNECT_TIMEOUT,READ_TIMEOUT); + } + + public HttpURLConnection connect(URL url) throws IOException { + HttpURLConnection con = base.connect(url); + con.setConnectTimeout(connectTimeout); + con.setReadTimeout(readTimeout); + return con; + } + + /** + * Default connection timeout in milliseconds + */ + @SuppressFBWarnings("MS_SHOULD_BE_FINAL") + public static int CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); + + /** + * Default read timeout in milliseconds + */ + @SuppressFBWarnings("MS_SHOULD_BE_FINAL") + public static int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); +} \ No newline at end of file diff --git a/src/main/java/net/coding/api/extras/OkHttpConnector.java b/src/main/java/net/coding/api/extras/OkHttpConnector.java new file mode 100644 index 0000000..43c69c1 --- /dev/null +++ b/src/main/java/net/coding/api/extras/OkHttpConnector.java @@ -0,0 +1,39 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.api.extras; + +import com.squareup.okhttp.OkUrlFactory; +import net.coding.api.HttpConnector; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +public class OkHttpConnector implements HttpConnector { + private final OkUrlFactory urlFactory; + + public OkHttpConnector(OkUrlFactory urlFactory) { + this.urlFactory = urlFactory; + } + + public HttpURLConnection connect(URL url) throws IOException { + return urlFactory.open(url); + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java new file mode 100644 index 0000000..69b55cc --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java @@ -0,0 +1,63 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.jenkins.plugin.oauth; + +import hudson.Extension; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import hudson.util.Secret; +import org.jenkinsci.Symbol; + +import javax.annotation.Nonnull; + +/** + * Remembers the access token used to connect to the Coding server + * + * @since TODO + */ +public class CodingAccessTokenProperty extends UserProperty { + private final Secret accessToken; + + public CodingAccessTokenProperty(String accessToken) { + this.accessToken = Secret.fromString(accessToken); + } + + public @Nonnull + Secret getAccessToken() { + return accessToken; + } + + @Extension + @Symbol("codingAccessToken") + public static final class DescriptorImpl extends UserPropertyDescriptor { + @Override + public boolean isEnabled() { + // does not show elements in //configure/ + return false; + } + + @Override + public UserProperty newInstance(User user) { + // no default property + return null; + } + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java new file mode 100644 index 0000000..b9839d3 --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java @@ -0,0 +1,553 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + The MIT License + +Copyright (c) 2011 Michael O'Cleirigh + +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 net.coding.jenkins.plugin.oauth; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.OkUrlFactory; +import hudson.model.Item; +import hudson.security.Permission; +import hudson.security.SecurityRealm; +import jenkins.model.Jenkins; +import net.coding.api.Coding; +import net.coding.api.CodingBuilder; +import net.coding.api.CodingMyself; +import net.coding.api.CodingOrganization; +import net.coding.api.CodingPersonSet; +import net.coding.api.CodingRepository; +import net.coding.api.CodingTeam; +import net.coding.api.CodingUser; +import net.coding.api.extras.OkHttpConnector; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.providers.AbstractAuthenticationToken; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * @author mocleiri + * + * to hold the authentication token from the coding oauth process. + * + */ +public class CodingAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 2L; + + private final String accessToken; + private final String codingServer; + private final String userName; + + private transient Coding coding; + private transient CodingMyself me; + private transient CodingSecurityRealm myRealm = null; + + public static final TimeUnit CACHE_EXPIRY = TimeUnit.HOURS; + /** + * Cache for faster organization based security + */ + private static final Cache> userOrganizationCache = + CacheBuilder.newBuilder().expireAfterWrite(1, CACHE_EXPIRY).build(); + + private static final Cache> repositoriesByUserCache = + CacheBuilder.newBuilder().expireAfterWrite(1, CACHE_EXPIRY).build(); + + private static final Cache usersByIdCache = + CacheBuilder.newBuilder().expireAfterWrite(1, CACHE_EXPIRY).build(); + + private static final Cache usersByTokenCache = + CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + + private static final Cache>> userTeamsCache = + CacheBuilder.newBuilder().expireAfterWrite(1, CACHE_EXPIRY).build(); + + /** + * This cache is for repositories and is explicitly _not_ static because we + * want to store repo information per-user (and this class should be per-user). + * We potentially could hold a separe static cache for public repo info + * that applies to all users, but it wouldn't be able to contain user-specific + * details like exact permissions (read/write/admin). + * + * This representation of the repo holds details on whether the repo is + * public/private, as well as whether the current user has pull/push/admin + * access. + */ + private final Cache repositoryCache = + CacheBuilder.newBuilder().expireAfterWrite(1, CACHE_EXPIRY).build(); + + private final List authorities = new ArrayList<>(); + + private static final WrappedCodingUser UNKNOWN_USER = new WrappedCodingUser(null); + private static final WrappedCodingMyself UNKNOWN_TOKEN = new WrappedCodingMyself(null); + + /** Wrappers for cache **/ + static class WrappedCodingUser { + public final CodingUser user; + + public WrappedCodingUser(CodingUser user) { + this.user = user; + } + } + + static class WrappedCodingMyself { + public final CodingMyself me; + + public WrappedCodingMyself(CodingMyself me) { + this.me = me; + } + } + + static class RepoRights { + public final boolean hasAdminAccess; + public final boolean hasPullAccess; + public final boolean hasPushAccess; + public final boolean isPrivate; + + public RepoRights(CodingRepository repo) { + if (repo != null) { + this.hasAdminAccess = repo.hasAdminAccess(); + this.hasPullAccess = repo.hasPullAccess(); + this.hasPushAccess = repo.hasPushAccess(); + this.isPrivate = repo.isPrivate(); + } else { + // assume null repo means we had no rights to view it + // so must be private + this.hasAdminAccess = false; + this.hasPullAccess = false; + this.hasPushAccess = false; + this.isPrivate = true; + } + } + + public boolean hasAdminAccess() { + return this.hasAdminAccess; + } + + public boolean hasPullAccess() { + return this.hasPullAccess; + } + + public boolean hasPushAccess() { + return this.hasPushAccess; + } + + public boolean isPrivate() { + return this.isPrivate; + } + } + + public CodingAuthenticationToken(final String accessToken, final String codingServer) throws IOException { + super(new GrantedAuthority[] {}); + + this.accessToken = accessToken; + this.codingServer = codingServer; + + this.me = loadMyself(accessToken); + + LOGGER.log(Level.FINEST, "loadMyself " + this.me); + + assert this.me!=null; + + setAuthenticated(true); + + this.userName = this.me.getLogin(); + + authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY); + Jenkins jenkins = Jenkins.getInstance(); + if (jenkins == null) { + throw new IllegalStateException("Jenkins not started"); + } + if(jenkins.getSecurityRealm() instanceof CodingSecurityRealm) { + if(myRealm == null) { + myRealm = (CodingSecurityRealm) jenkins.getSecurityRealm(); + } + //Search for scopes that allow fetching team membership. This is documented online. + //https://developer.github.com/v3/orgs/#list-your-organizations + //https://developer.github.com/v3/orgs/teams/#list-user-teams +// if(myRealm.hasScope("team") || myRealm.hasScope("admin:org") || myRealm.hasScope("user") || myRealm.hasScope("project:depot")) { +// try{ +// Set myOrgs = userOrganizationCache.get(getName(), new Callable>() { +// @Override +// public Set call() throws Exception { +// return getCoding().getMyOrganizations().keySet(); +// } +// }); +// +// Map> myTeams = userTeamsCache.get(getName(), new Callable>>() { +// @Override +// public Map> call() throws Exception { +// return getCoding().getMyTeams(); +// } +// }); +// +// //fetch organization-only memberships (i.e.: groups without teams) +// for(String orgLogin : myOrgs){ +// if(!myTeams.containsKey(orgLogin)){ +// myTeams.put(orgLogin, Collections.emptySet()); +// } +// } +// +// for (Map.Entry> teamEntry : myTeams.entrySet()) { +// String orgLogin = teamEntry.getKey(); +// LOGGER.log(Level.FINE, "Fetch teams for user " + userName + " in organization " + orgLogin); +// authorities.add(new GrantedAuthorityImpl(orgLogin)); +// for (CodingTeam team : teamEntry.getValue()) { +// String role = orgLogin + CodingOAuthGroupDetails.ORG_TEAM_SEPARATOR + team.getName(); +// authorities.add(new GrantedAuthorityImpl(role)); +// LOGGER.finest(userName + " add authority " + role); +// } +// } +// } catch (ExecutionException e) { +// throw new RuntimeException("authorization failed for user = " +// + getName(), e); +// } +// } + } + } + + /** + * Necessary for testing + */ + public static void clearCaches() { + userOrganizationCache.invalidateAll(); + repositoriesByUserCache.invalidateAll(); + usersByIdCache.invalidateAll(); + usersByTokenCache.invalidateAll(); + userTeamsCache.invalidateAll(); + } + + /** + * Gets the OAuth access token, so that it can be persisted and used elsewhere. + * @return accessToken + */ + public String getAccessToken() { + return accessToken; + } + + /** + * Gets the Coding server used for this token + * @return codingServer + */ + public String getCodingServer() { + return codingServer; + } + + public Coding getCoding() throws IOException { + if (this.coding == null) { + + String host; + try { + host = new URL(this.codingServer).getHost(); + } catch (MalformedURLException e) { + throw new IOException("Invalid Coding API URL: " + this.codingServer, e); + } + + OkHttpClient client = new OkHttpClient().setProxy(getProxy(host)); + + this.coding = CodingBuilder.fromEnvironment() + .withEndpoint(this.codingServer) + .withOAuthToken(this.accessToken) +// .withRateLimitHandler(RateLimitHandler.FAIL) + .withConnector(new OkHttpConnector(new OkUrlFactory(client))) + .build(); + } + return coding; + } + + /** + * Uses proxy if configured on pluginManager/advanced page + * + * @param host Coding's hostname to build proxy to + * + * @return proxy to use it in connector. Should not be null as it can lead to unexpected behaviour + */ + @Nonnull + private static Proxy getProxy(@Nonnull String host) { + Jenkins jenkins = Jenkins.getInstance(); + + if (jenkins.proxy == null) { + return Proxy.NO_PROXY; + } else { + return jenkins.proxy.createProxy(host); + } + } + + @Override + public GrantedAuthority[] getAuthorities() { + return authorities.toArray(new GrantedAuthority[authorities.size()]); + } + + public Object getCredentials() { + return ""; // do not expose the credential + } + + /** + * Returns the login name in Coding. + * @return principal + */ + public String getPrincipal() { + return this.userName; + } + + /** + * Returns the GHMyself object from this instance. + * @return myself + */ + public CodingMyself getMyself() throws IOException { + if (me == null) { + me = getCoding().getMyself(); + } + return me; + } + + /** + * For some reason I can't get the coding api to tell me for the current + * user the groups to which he belongs. + * + * So this is a slightly larger consideration. If the authenticated user is + * part of any team within the organization then they have permission. + * + * It caches user organizations for 24 hours for faster web navigation. + * + * @param candidateName name of the candidate + * @param organization name of the organization + * @return has organization permission + */ + public boolean hasOrganizationPermission(String candidateName, + String organization) { + try { + Set v = userOrganizationCache.get(candidateName,new Callable>() { + @Override + public Set call() throws Exception { + return getCoding().getMyOrganizations().keySet(); + } + }); + + return v.contains(organization); + } catch (ExecutionException e) { + throw new RuntimeException("authorization failed for user = " + + candidateName, e); + } + } + + public boolean hasRepositoryPermission(String repositoryName, Permission permission) { + LOGGER.log(Level.FINEST, "Checking for permission: " + permission + " on repo: " + repositoryName + " for user: " + this.userName); + boolean isRepoOfMine = myRepositories().contains(repositoryName); + if (isRepoOfMine) { + return true; + } + // This is not my repository, nor is it a repository of an organization I belong to. + // Check what rights I have on the coding repo. + RepoRights repository = loadRepository(repositoryName); + if (repository == null) { + return false; + } + // let admins do anything + if (repository.hasAdminAccess()) { + return true; + } + // WRITE or READ can Read/Build/View Workspace + if (permission.equals(Item.READ) || permission.equals(Item.BUILD) || permission.equals(Item.WORKSPACE)) { + return repository.hasPullAccess() || repository.hasPushAccess(); + } + // WRITE can cancel builds or view config + if (permission.equals(Item.CANCEL) || permission.equals(Item.EXTENDED_READ)) { + return repository.hasPushAccess(); + } + // Need ADMIN rights to do rest: configure, create, delete, discover, wipeout + return false; + } + + public Set myRepositories() { + try { + return repositoriesByUserCache.get(getName(), + new Callable>() { + @Override + public Set call() throws Exception { + List userRepositoryList = getMyself().listRepositories().asList(); + Set repositoryNames = listToNames(userRepositoryList); + CodingPersonSet organizations = getMyself().getAllOrganizations(); + for (CodingOrganization organization : organizations) { + List orgRepositoryList = organization.listRepositories().asList(); + Set orgRepositoryNames = listToNames(orgRepositoryList); + repositoryNames.addAll(orgRepositoryNames); + } + return repositoryNames; + } + } + ); + } catch (ExecutionException e) { + LOGGER.log(Level.SEVERE, "an exception was thrown", e); + throw new RuntimeException("authorization failed for user = " + + getName(), e); + } + } + + public Set listToNames(Collection respositories) throws IOException { + Set names = new HashSet(); + for (CodingRepository repository : respositories) { + String ownerName = repository.getOwner().getLogin(); + String repoName = repository.getName(); + names.add(ownerName + "/" + repoName); + } + return names; + } + + public boolean isPublicRepository(String repositoryName) { + RepoRights repository = loadRepository(repositoryName); + return repository != null && !repository.isPrivate(); + } + + private static final Logger LOGGER = Logger + .getLogger(CodingAuthenticationToken.class.getName()); + + public CodingUser loadUser(String username) throws IOException { + WrappedCodingUser user; + try { + user = usersByIdCache.getIfPresent(username); + if (coding != null && user == null && isAuthenticated()) { + CodingUser ghUser = getCoding().getUser(username); + user = new WrappedCodingUser(ghUser); + usersByIdCache.put(username, user); + } + } catch (IOException e) { + LOGGER.log(Level.FINEST, e.getMessage(), e); + user = UNKNOWN_USER; + usersByIdCache.put(username, UNKNOWN_USER); + } + return user != null ? user.user : null; + } + + public CodingMyself loadMyself(String token) throws IOException { + WrappedCodingMyself me; + try { + me = usersByTokenCache.getIfPresent(token); + if (me == null) { + CodingMyself ghMyself = getCoding().getMyself(); + me = new WrappedCodingMyself(ghMyself); + usersByTokenCache.put(token, me); + } + } catch (IOException e) { + LOGGER.log(Level.FINEST, e.getMessage(), e); + me = UNKNOWN_TOKEN; + usersByTokenCache.put(token, UNKNOWN_TOKEN); + } + return me.me; + } + + public CodingOrganization loadOrganization(String organization) { + try { + if (coding != null && isAuthenticated()) +// return getCoding().getOrganization(organization); + throw new UnsupportedOperationException(""); + throw new IOException(); + } catch (IOException | RuntimeException e) { + LOGGER.log(Level.FINEST, e.getMessage(), e); + } + return null; + } + + public RepoRights loadRepository(final String repositoryName) { + try { + if (coding != null && isAuthenticated() && (myRealm.hasScope("repo") || myRealm.hasScope("public_repo"))) { + return repositoryCache.get(repositoryName, + new Callable() { + @Override + public RepoRights call() throws Exception { + throw new UnsupportedOperationException(""); +// CodingRepository repo = getCoding().getRepository(repositoryName); +// return new RepoRights(repo); + } + } + ); + } + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "an exception was thrown", e); + LOGGER.log(Level.WARNING, + "Looks like a bad Coding URL OR the Jenkins user {0} does not have access to the repository {1}. May need to add 'repo' or 'public_repo' to the list of oauth scopes requested.", + new Object[] { this.userName, repositoryName }); + } + return null; + } + + public CodingTeam loadTeam(String organization, String team) { + try { + CodingOrganization org = loadOrganization(organization); + if (org != null) { + return org.getTeamByName(team); + } + } catch (IOException e) { + LOGGER.log(Level.FINEST, e.getMessage(), e); + } + return null; + } + + public CodingOAuthUserDetails getUserDetails(String username) throws IOException { + CodingUser user = loadUser(username); + if (user != null) { + return new CodingOAuthUserDetails(user.getLogin(), this); + } + return null; + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java new file mode 100644 index 0000000..eb0dabe --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java @@ -0,0 +1,254 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + The MIT License + +Copyright (c) 2011 Michael O'Cleirigh + +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 net.coding.jenkins.plugin.oauth; + +import com.google.common.collect.ImmutableList; +import hudson.Extension; +import hudson.model.AbstractItem; +import hudson.model.Descriptor; +import hudson.model.Job; +import hudson.security.ACL; +import hudson.security.AuthorizationStrategy; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.DataBoundConstructor; + +import javax.annotation.Nonnull; +import java.util.Collection; + +/** + * @author mocleiri + * + * // TODO: 可以先注释掉这个 class,开放所有权限 + * + */ +public class CodingAuthorizationStrategy extends AuthorizationStrategy { + + @DataBoundConstructor + public CodingAuthorizationStrategy(String adminUserNames, + boolean authenticatedUserReadPermission, + boolean useRepositoryPermissions, + boolean authenticatedUserCreateJobPermission, + String organizationNames, + boolean allowCodingWebHookPermission, + boolean allowCcTrayPermission, + boolean allowAnonymousReadPermission, + boolean allowAnonymousJobStatusPermission) { + super(); + + rootACL = new CodingRequireOrganizationMembershipACL(adminUserNames, + organizationNames, + authenticatedUserReadPermission, + useRepositoryPermissions, + authenticatedUserCreateJobPermission, + allowCodingWebHookPermission, + allowCcTrayPermission, + allowAnonymousReadPermission, + allowAnonymousJobStatusPermission); + } + + private final CodingRequireOrganizationMembershipACL rootACL; + + /* + * (non-Javadoc) + * @return rootAcl + * @see hudson.security.AuthorizationStrategy#getRootACL() + */ + @Nonnull + @Override + public ACL getRootACL() { + return rootACL; + } + + @Nonnull + public ACL getACL(@Nonnull AbstractItem item) { + // skip repository right now +// if(item instanceof MultiBranchProject) { +// CodingRequireOrganizationMembershipACL codingACL = (CodingRequireOrganizationMembershipACL) getRootACL(); +// return codingACL.cloneForProject(item); +// } else { + return getRootACL(); +// } + } + + @Nonnull + public ACL getACL(@Nonnull Job job) { +// if(job instanceof WorkflowJob && job.getProperty(BranchJobProperty.class) != null || job instanceof AbstractProject) { +// CodingRequireOrganizationMembershipACL codingACL = (CodingRequireOrganizationMembershipACL) getRootACL(); +// return codingACL.cloneForProject(job); +// } else { + return getRootACL(); +// } + } + + /** + * (non-Javadoc) + * @return groups + * @see hudson.security.AuthorizationStrategy#getGroups() + */ + @Nonnull + @Override + public Collection getGroups() { + return ImmutableList.of(); + } + + private Object readResolve() { + return this; + } + + /** + * @return organizationNames + * @see CodingRequireOrganizationMembershipACL#getOrganizationNameList() + */ + public String getOrganizationNames() { + return StringUtils.join(rootACL.getOrganizationNameList().iterator(), ", "); + } + + /** + * @return adminUserNames + * @see CodingRequireOrganizationMembershipACL#getAdminUserNameList() + */ + public String getAdminUserNames() { + return StringUtils.join(rootACL.getAdminUserNameList().iterator(), ", "); + } + + /** + * @return isUseRepositoryPermissions + * @see CodingRequireOrganizationMembershipACL#isUseRepositoryPermissions() + */ + public boolean isUseRepositoryPermissions() { + return rootACL.isUseRepositoryPermissions(); + } + + /** + * @return isAuthenticatedUserCreateJobPermission + * @see CodingRequireOrganizationMembershipACL#isAuthenticatedUserCreateJobPermission() + */ + public boolean isAuthenticatedUserCreateJobPermission() { + return rootACL.isAuthenticatedUserCreateJobPermission(); + } + + /** + * @return isAuthenticatedUserReadPermission + * @see CodingRequireOrganizationMembershipACL#isAuthenticatedUserReadPermission() + */ + public boolean isAuthenticatedUserReadPermission() { + return rootACL.isAuthenticatedUserReadPermission(); + } + + /** + * @return isAllowCodingWebHookPermission + * @see CodingRequireOrganizationMembershipACL#isAllowCodingWebHookPermission() + */ + public boolean isAllowCodingWebHookPermission() { + return rootACL.isAllowCodingWebHookPermission(); + } + + /** + * @return isAllowCcTrayPermission + * @see CodingRequireOrganizationMembershipACL#isAllowCcTrayPermission() + */ + public boolean isAllowCcTrayPermission() { + return rootACL.isAllowCcTrayPermission(); + } + + + /** + * @return isAllowAnonymousReadPermission + * @see CodingRequireOrganizationMembershipACL#isAllowAnonymousReadPermission() + */ + public boolean isAllowAnonymousReadPermission() { + return rootACL.isAllowAnonymousReadPermission(); + } + + /** + * @return isAllowAnonymousJobStatusPermission + * @see CodingRequireOrganizationMembershipACL#isAllowAnonymousJobStatusPermission() + */ + public boolean isAllowAnonymousJobStatusPermission() { + return rootACL.isAllowAnonymousJobStatusPermission(); + } + + /** + * Compare an object against this instance for equivalence. + * @param object An object to campare this instance to. + * @return true if the objects are the same instance and configuration. + */ + @Override + public boolean equals(Object object){ + if(object instanceof CodingAuthorizationStrategy) { + CodingAuthorizationStrategy obj = (CodingAuthorizationStrategy) object; + return this.getOrganizationNames().equals(obj.getOrganizationNames()) && + this.getAdminUserNames().equals(obj.getAdminUserNames()) && + this.isUseRepositoryPermissions() == obj.isUseRepositoryPermissions() && + this.isAuthenticatedUserCreateJobPermission() == obj.isAuthenticatedUserCreateJobPermission() && + this.isAuthenticatedUserReadPermission() == obj.isAuthenticatedUserReadPermission() && + this.isAllowCodingWebHookPermission() == obj.isAllowCodingWebHookPermission() && + this.isAllowCcTrayPermission() == obj.isAllowCcTrayPermission() && + this.isAllowAnonymousReadPermission() == obj.isAllowAnonymousReadPermission() && + this.isAllowAnonymousJobStatusPermission() == obj.isAllowAnonymousJobStatusPermission(); + } else { + return false; + } + } + + @Override + public int hashCode() { + return rootACL != null ? rootACL.hashCode() : 0; + } + + @Extension + public static final class DescriptorImpl extends + Descriptor { + + public String getDisplayName() { + return Messages.coding_oauth_codingAuthorizationStrategy(); + } + + public String getHelpFile() { + return "/plugin/coding-webhook/help/oauth/help-authorization-strategy.html"; + } + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java new file mode 100644 index 0000000..de4a88f --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java @@ -0,0 +1,80 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.jenkins.plugin.oauth; + +import hudson.Extension; +import hudson.model.UnprotectedRootAction; +import hudson.security.SecurityRealm; +import jenkins.model.Jenkins; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +/** + * A page that shows a simple message when the user logs out. + * This prevents a logout -> login loop when using this security realm and Anonymous does not have {@code Overall.READ} permission. + */ +@Extension +public class CodingLogoutAction implements UnprotectedRootAction { + + /** The URL of the action. */ + static final String POST_LOGOUT_URL = "codingLogout"; + + @Override + public String getDisplayName() { + return "Coding Logout"; + } + + @Override + public String getIconFileName() { + // hide it + return null; + } + + @Override + public String getUrlName() { + return POST_LOGOUT_URL; + } + + @Restricted(NoExternalUse.class) // jelly only + public String getCodingURL() { + Jenkins j = Jenkins.getInstance(); + assert j != null; + SecurityRealm r = j.getSecurityRealm(); + if (r instanceof CodingSecurityRealm) { + CodingSecurityRealm ghsr = (CodingSecurityRealm) r; + return ghsr.getCodingWebUri(); + } + // only called from the Jelly if the CodingSecurityRealm is set... + return ""; + } + + @Restricted(NoExternalUse.class) // jelly only + public String getCodingText() { + Jenkins j = Jenkins.getInstance(); + assert j != null; + SecurityRealm r = j.getSecurityRealm(); + if (r instanceof CodingSecurityRealm) { + CodingSecurityRealm ghsr = (CodingSecurityRealm) r; + return (ghsr.getDescriptor().getDefaultCodingWebUri().equals(ghsr.getCodingWebUri()))? "Coding" : "Coding Enterprise"; + } + // only called from the Jelly if the CodingSecurityRealm is set... + return ""; + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java new file mode 100644 index 0000000..b4dca36 --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java @@ -0,0 +1,71 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * + */ +package net.coding.jenkins.plugin.oauth; + +import hudson.security.GroupDetails; +import net.coding.api.CodingOrganization; +import net.coding.api.CodingTeam; + +/** + * @author Mike + * + */ +public class CodingOAuthGroupDetails extends GroupDetails { + + private final CodingOrganization org; + private final CodingTeam team; + static final String ORG_TEAM_SEPARATOR = "*"; + + /** + * Group based on organization name + * @param org the coding organization + */ + public CodingOAuthGroupDetails(CodingOrganization org) { + super(); + this.org = org; + this.team = null; + } + + /** + * Group based on team name + * @param team the coding team + */ + public CodingOAuthGroupDetails(CodingTeam team) { + super(); + this.org = team.getOrganization(); + this.team = team; + } + + /* (non-Javadoc) + * @see hudson.security.GroupDetails#getName() + */ + @Override + public String getName() { + if (team != null) + return org.getLogin() + ORG_TEAM_SEPARATOR + team.getName(); + if (org != null) + return org.getLogin(); + return null; + } + +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java new file mode 100644 index 0000000..932d5cf --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java @@ -0,0 +1,36 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.jenkins.plugin.oauth; + +import hudson.ExtensionPoint; + +import java.util.Collection; + +/** + * Extension point to be implemented by plugins to request additional scopes. + * @author Kohsuke Kawaguchi + */ +public abstract class CodingOAuthScope implements ExtensionPoint { + /** + * Returns a collection of scopes to request. + * See https://open.coding.net/references/personal-access-token/#%E8%AE%BF%E9%97%AE%E4%BB%A4%E7%89%8C%E7%9A%84%E6%9D%83%E9%99%90 + */ + public abstract Collection getScopesToRequest(); +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java new file mode 100644 index 0000000..490b96b --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java @@ -0,0 +1,73 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * + */ +package net.coding.jenkins.plugin.oauth; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.coding.api.CodingUser; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.userdetails.User; +import org.acegisecurity.userdetails.UserDetails; + +import javax.annotation.Nonnull; +import java.io.IOException; + +/** + * @author Mike + * + */ +@SuppressFBWarnings("EQ_DOESNT_OVERRIDE_EQUALS") +public class CodingOAuthUserDetails extends User implements UserDetails { + + private static final long serialVersionUID = 1L; + + private boolean hasGrantedAuthorities; + + private final CodingAuthenticationToken authenticationToken; + + public CodingOAuthUserDetails(@Nonnull String login, @Nonnull GrantedAuthority[] authorities) { + super(login, "", true, true, true, true, authorities); + this.authenticationToken = null; + this.hasGrantedAuthorities = true; + } + + public CodingOAuthUserDetails(@Nonnull String login, @Nonnull CodingAuthenticationToken authenticationToken) { + super(login, "", true, true, true, true, new GrantedAuthority[0]); + this.authenticationToken = authenticationToken; + this.hasGrantedAuthorities = false; + } + + @Override + public GrantedAuthority[] getAuthorities() { + if (!hasGrantedAuthorities) { + try { + CodingUser user = authenticationToken.loadUser(getUsername()); + if(user != null) { + setAuthorities(authenticationToken.getAuthorities()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return super.getAuthorities(); + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java new file mode 100644 index 0000000..c87848d --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java @@ -0,0 +1,126 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + The MIT License + +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 net.coding.jenkins.plugin.oauth; + +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Uniquely identifies a repository on Coding. + * + * This is a simplified version of the file + * https://github.com/jenkinsci/github-plugin/blob/master/src/main/java/com/cloudbees/jenkins/GitHubRepositoryName.java + * + * It has been duplicated to avoid introducing a dependency on "coding-plugin" + * + * @author Kohsuke Kawaguchi + */ +public class CodingRepositoryName { + + private static final Pattern[] URL_PATTERNS = { + /** + * The first set of patterns extract the host, owner and repository names + * from URLs that include a '.git' suffix, removing the suffix from the + * repository name. + */ + Pattern.compile("git@(.+):([^/]+)/([^/]+)\\.git"), + Pattern.compile("https?://[^/]+@([^/]+)/([^/]+)/([^/]+)\\.git"), + Pattern.compile("https?://([^/]+)/([^/]+)/([^/]+)\\.git"), + Pattern.compile("git://([^/]+)/([^/]+)/([^/]+)\\.git"), + Pattern.compile("ssh://git@([^/]+)/([^/]+)/([^/]+)\\.git"), + /** + * The second set of patterns extract the host, owner and repository names + * from all other URLs. Note that these patterns must be processed *after* + * the first set, to avoid any '.git' suffix that may be present being included + * in the repository name. + */ + Pattern.compile("git@(.+):([^/]+)/([^/]+)/?"), + Pattern.compile("https?://[^/]+@([^/]+)/([^/]+)/([^/]+)/?"), + Pattern.compile("https?://([^/]+)/([^/]+)/([^/]+)/?"), + Pattern.compile("git://([^/]+)/([^/]+)/([^/]+)/?"), + Pattern.compile("ssh://git@([^/]+)/([^/]+)/([^/]+)/?") + }; + + /** + * Create {@link CodingRepositoryName} from URL + * + * @param url + * must be non-null + * @return parsed {@link CodingRepositoryName} or null if it cannot be + * parsed from the specified URL + */ + public static CodingRepositoryName create(final String url) { + LOGGER.log(Level.FINE, "Constructing from URL {0}", url); + for (Pattern p : URL_PATTERNS) { + Matcher m = p.matcher(url.trim()); + if (m.matches()) { + LOGGER.log(Level.FINE, "URL matches {0}", m); + CodingRepositoryName ret = new CodingRepositoryName(m.group(1), m.group(2), + m.group(3)); + LOGGER.log(Level.FINE, "Object is {0}", ret); + return ret; + } + } + LOGGER.log(Level.WARNING, "Could not match URL {0}", url); + return null; + } + + public final String host, userName, repositoryName; + + public CodingRepositoryName(String host, String userName, String repositoryName) { + this.host = host; + this.userName = userName; + this.repositoryName = repositoryName; + } + + @Override + public String toString() { + return "CodingRepository[host="+host+",username="+userName+",repository="+repositoryName+"]"; + } + + private static final Logger LOGGER = Logger.getLogger(CodingRepositoryName.class.getName()); + +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java new file mode 100644 index 0000000..fcd4646 --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java @@ -0,0 +1,448 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + The MIT License + +Copyright (c) 2011 Michael O'Cleirigh + +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 net.coding.jenkins.plugin.oauth; + +import hudson.model.AbstractItem; +import hudson.model.AbstractProject; +import hudson.model.Describable; +import hudson.model.Item; +import hudson.plugins.git.GitSCM; +import hudson.plugins.git.UserRemoteConfig; +import hudson.security.ACL; +import hudson.security.Permission; +import jenkins.branch.MultiBranchProject; +import jenkins.model.Jenkins; +import jenkins.scm.api.SCMSource; +import org.acegisecurity.Authentication; +import org.jenkinsci.plugins.github_branch_source.GitHubSCMSource; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.jenkinsci.plugins.workflow.multibranch.BranchJobProperty; +import org.kohsuke.stapler.Stapler; +import org.kohsuke.stapler.StaplerRequest; + +import javax.annotation.Nonnull; +import java.net.URI; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Logger; + +/** + * @author Mike + * + */ +public class CodingRequireOrganizationMembershipACL extends ACL { + + private static final Logger log = Logger + .getLogger(CodingRequireOrganizationMembershipACL.class.getName()); + + private final List organizationNameList; + private final List adminUserNameList; + private final boolean authenticatedUserReadPermission; + private final boolean useRepositoryPermissions; + private final boolean authenticatedUserCreateJobPermission; + private final boolean allowCodingWebHookPermission; + private final boolean allowCcTrayPermission; + private final boolean allowAnonymousReadPermission; + private final boolean allowAnonymousJobStatusPermission; + private final AbstractItem item; + + /* + * (non-Javadoc) + * + * @see hudson.security.ACL#hasPermission(org.acegisecurity.Authentication, + * hudson.security.Permission) + */ + @Override + public boolean hasPermission(@Nonnull Authentication a, @Nonnull Permission permission) { + if (a instanceof CodingAuthenticationToken) { + if (!a.isAuthenticated()) + return false; + + CodingAuthenticationToken authenticationToken = (CodingAuthenticationToken) a; + + String candidateName = a.getName(); + + if (adminUserNameList.contains(candidateName)) { + // if they are an admin then they have permission + log.finest("Granting Admin rights to user " + candidateName); + return true; + } + + if (this.item != null) { + if (useRepositoryPermissions) { + if(hasRepositoryPermission(authenticationToken, permission)) { + log.finest("Granting Authenticated User " + permission.getId() + + " permission on project " + item.getName() + + "to user " + candidateName); + return true; + } + } else { + if (authenticatedUserReadPermission) { + if (checkReadPermission(permission)) { + log.finest("Granting Authenticated User read permission " + + "on project " + item.getName() + + "to user " + candidateName); + return true; + } + } + } + } else if (authenticatedUserReadPermission) { + if (checkReadPermission(permission)) { + // if we support authenticated read and this is a read + // request we allow it + log.finest("Granting Authenticated User read permission to user " + + candidateName); + return true; + } + } + + if (authenticatedUserCreateJobPermission && permission.equals(Item.CREATE)) { + return true; + } + + for (String organizationName : this.organizationNameList) { + if (authenticationToken.hasOrganizationPermission( + candidateName, organizationName)) { + + String[] parts = permission.getId().split("\\."); + + String test = parts[parts.length - 1].toLowerCase(); + + if (checkReadPermission(permission) + || testBuildPermission(permission)) { + // check the permission + + log.finest("Granting READ and BUILD rights to user " + + candidateName + " a member of " + + organizationName); + return true; + } + } + } + + // no match. + return false; + } else { + String authenticatedUserName = a.getName(); + if (authenticatedUserName == null) { + throw new IllegalArgumentException("Authentication must have a valid name"); + } + + if (authenticatedUserName.equals(SYSTEM.getPrincipal())) { + // give system user full access + log.finest("Granting Full rights to SYSTEM user."); + return true; + } + + if (authenticatedUserName.equals("anonymous")) { + if(checkJobStatusPermission(permission) && allowAnonymousJobStatusPermission) { + return true; + } + + if (checkReadPermission(permission)) { + if (allowAnonymousReadPermission) { + return true; + } + if (allowCodingWebHookPermission && + (currentUriPathEquals("coding") || + currentUriPathEquals("coding/"))) { + log.finest("Granting READ access for coding-webhook url: " + requestURI()); + return true; + } + if (allowCcTrayPermission && currentUriPathEndsWithSegment("cc.xml")) { + log.finest("Granting READ access for cctray url: " + requestURI()); + return true; + } + log.finer("Denying anonymous READ permission to url: " + requestURI()); + } + return false; + } + + if (adminUserNameList.contains(authenticatedUserName)) { + // if they are an admin then they have all permissions + log.finest("Granting Admin rights to user " + a.getName()); + return true; + } + + // else: + // deny request + // + return false; + } + } + + private boolean currentUriPathEquals( String specificPath ) { + Jenkins jenkins = Jenkins.getInstance(); + if (jenkins == null) { + throw new IllegalStateException("Jenkins not started"); + } + String rootUrl = jenkins.getRootUrl(); + if (rootUrl == null) { + throw new IllegalStateException("Could not determine Jenkins URL"); + } + String requestUri = requestURI(); + if (requestUri != null) { + String basePath = URI.create(rootUrl).getPath(); + return URI.create(requestUri).getPath().equals(basePath + specificPath); + } else { + return false; + } + } + + private boolean currentUriPathEndsWithSegment( String segment ) { + String requestUri = requestURI(); + if (requestUri != null) { + return requestUri.substring(requestUri.lastIndexOf('/') + 1).equals(segment); + } else { + return false; + } + } + + private String requestURI() { + StaplerRequest currentRequest = Stapler.getCurrentRequest(); + return (currentRequest == null) ? null : currentRequest.getOriginalRequestURI(); + } + + private boolean testBuildPermission(Permission permission) { + if (permission.getId().equals("hudson.model.Hudson.Build") + || permission.getId().equals("hudson.model.Item.Build")) { + return true; + } else { + return false; + } + } + + private boolean checkReadPermission(Permission permission) { + if (permission.getId().equals("hudson.model.Hudson.Read") + || permission.getId().equals("hudson.model.Item.Workspace") + || permission.getId().equals("hudson.model.Item.Read")) { + return true; + } else { + return false; + } + } + + private boolean checkJobStatusPermission(Permission permission) { + return permission.getId().equals("hudson.model.Item.ViewStatus"); + } + + public boolean hasRepositoryPermission(CodingAuthenticationToken authenticationToken, Permission permission) { + String repositoryName = getRepositoryName(); + + if (repositoryName == null) { + if (authenticatedUserCreateJobPermission) { + if (permission.equals(Item.READ) || + permission.equals(Item.CONFIGURE) || + permission.equals(Item.DELETE) || + permission.equals(Item.EXTENDED_READ) || + permission.equals(Item.CANCEL)) { + return true; + } else { + return false; + } + } else { + return false; + } + } else if (checkReadPermission(permission) && + authenticationToken.isPublicRepository(repositoryName)) { + return true; + } else { + return authenticationToken.hasRepositoryPermission(repositoryName, permission); + } + } + + private String getRepositoryName() { + String repositoryName = null; + String repoUrl = null; + Describable scm = null; + if (this.item instanceof WorkflowJob) { + WorkflowJob project = (WorkflowJob) item; + scm = project.getProperty(BranchJobProperty.class).getBranch().getScm(); + } else if (this.item instanceof MultiBranchProject) { + MultiBranchProject project = (MultiBranchProject) item; + scm = (SCMSource) project.getSCMSources().get(0); + } else if (this.item instanceof AbstractProject) { + AbstractProject project = (AbstractProject) item; + scm = project.getScm(); + } + if (scm instanceof GitHubSCMSource) { + GitHubSCMSource git = (GitHubSCMSource) scm; + repoUrl = git.getRemote(); + } else if (scm instanceof GitSCM) { + GitSCM git = (GitSCM) scm; + List userRemoteConfigs = git.getUserRemoteConfigs(); + if (!userRemoteConfigs.isEmpty()) { + repoUrl = userRemoteConfigs.get(0).getUrl(); + } + } + if (repoUrl != null) { + CodingRepositoryName githubRepositoryName = + CodingRepositoryName.create(repoUrl); + if (githubRepositoryName != null) { + repositoryName = githubRepositoryName.userName + "/" + + githubRepositoryName.repositoryName; + } + } + return repositoryName; + } + + public CodingRequireOrganizationMembershipACL(String adminUserNames, + String organizationNames, + boolean authenticatedUserReadPermission, + boolean useRepositoryPermissions, + boolean authenticatedUserCreateJobPermission, + boolean allowCodingWebHookPermission, + boolean allowCcTrayPermission, + boolean allowAnonymousReadPermission, + boolean allowAnonymousJobStatusPermission) { + super(); + + this.authenticatedUserReadPermission = authenticatedUserReadPermission; + this.useRepositoryPermissions = useRepositoryPermissions; + this.authenticatedUserCreateJobPermission = authenticatedUserCreateJobPermission; + this.allowCodingWebHookPermission = allowCodingWebHookPermission; + this.allowCcTrayPermission = allowCcTrayPermission; + this.allowAnonymousReadPermission = allowAnonymousReadPermission; + this.allowAnonymousJobStatusPermission = allowAnonymousJobStatusPermission; + this.adminUserNameList = new LinkedList(); + + String[] parts = adminUserNames.split(","); + + for (String part : parts) { + adminUserNameList.add(part.trim()); + } + + this.organizationNameList = new LinkedList(); + + if (organizationNames != null) { + parts = organizationNames.split(","); + + for (String part : parts) { + organizationNameList.add(part.trim()); + } + } + + + this.item = null; + } + + public CodingRequireOrganizationMembershipACL cloneForProject(AbstractItem item) { + return new CodingRequireOrganizationMembershipACL( + this.adminUserNameList, + this.organizationNameList, + this.authenticatedUserReadPermission, + this.useRepositoryPermissions, + this.authenticatedUserCreateJobPermission, + this.allowCodingWebHookPermission, + this.allowCcTrayPermission, + this.allowAnonymousReadPermission, + this.allowAnonymousJobStatusPermission, + item); + } + + public CodingRequireOrganizationMembershipACL(List adminUserNameList, + List organizationNameList, + boolean authenticatedUserReadPermission, + boolean useRepositoryPermissions, + boolean authenticatedUserCreateJobPermission, + boolean allowCodingWebHookPermission, + boolean allowCcTrayPermission, + boolean allowAnonymousReadPermission, + boolean allowAnonymousJobStatusPermission, + AbstractItem item) { + super(); + + this.adminUserNameList = adminUserNameList; + this.organizationNameList = organizationNameList; + this.authenticatedUserReadPermission = authenticatedUserReadPermission; + this.useRepositoryPermissions = useRepositoryPermissions; + this.authenticatedUserCreateJobPermission = authenticatedUserCreateJobPermission; + this.allowCodingWebHookPermission = allowCodingWebHookPermission; + this.allowCcTrayPermission = allowCcTrayPermission; + this.allowAnonymousReadPermission = allowAnonymousReadPermission; + this.allowAnonymousJobStatusPermission = allowAnonymousJobStatusPermission; + this.item = item; + } + + public List getOrganizationNameList() { + return organizationNameList; + } + + public List getAdminUserNameList() { + return adminUserNameList; + } + + public boolean isUseRepositoryPermissions() { + return useRepositoryPermissions; + } + + public boolean isAuthenticatedUserCreateJobPermission() { + return authenticatedUserCreateJobPermission; + } + + public boolean isAuthenticatedUserReadPermission() { + return authenticatedUserReadPermission; + } + + public boolean isAllowCodingWebHookPermission() { + return allowCodingWebHookPermission; + } + + public boolean isAllowCcTrayPermission() { + return allowCcTrayPermission; + } + + /** + * @return the allowAnonymousReadPermission + */ + public boolean isAllowAnonymousReadPermission() { + return allowAnonymousReadPermission; + } + + public boolean isAllowAnonymousJobStatusPermission() { + return allowAnonymousJobStatusPermission; + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java new file mode 100644 index 0000000..2ab727b --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java @@ -0,0 +1,58 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.jenkins.plugin.oauth; + +import hudson.model.User; +import org.jfree.util.Log; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import java.io.IOException; + +public class CodingSecretStorage { + + private CodingSecretStorage(){ + // no accessible constructor + } + + public static boolean contains(@Nonnull User user) { + return user.getProperty(CodingAccessTokenProperty.class) != null; + } + + public static @CheckForNull String retrieve(@Nonnull User user) { + CodingAccessTokenProperty property = user.getProperty(CodingAccessTokenProperty.class); + if (property == null) { + Log.debug("Cache miss for username: " + user.getId()); + return null; + } else { + Log.debug("Token retrieved using cache for username: " + user.getId()); + return property.getAccessToken().getPlainText(); + } + } + + public static void put(@Nonnull User user, @Nonnull String accessToken) { + Log.debug("Populating the cache for username: " + user.getId()); + try { + user.addProperty(new CodingAccessTokenProperty(accessToken)); + } catch (IOException e) { + Log.warn("Received an exception when trying to add the Coding access token to the user: " + user.getId(), e); + } + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java new file mode 100644 index 0000000..eae3dcc --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java @@ -0,0 +1,823 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + The MIT License + +Copyright (c) 2011-2016 Michael O'Cleirigh, James Nord, CloudBees, 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 net.coding.jenkins.plugin.oauth; + +import com.google.gson.Gson; +import com.thoughtworks.xstream.converters.ConversionException; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import hudson.Extension; +import hudson.FilePath; +import hudson.ProxyConfiguration; +import hudson.Util; +import hudson.cli.CLICommand; +import hudson.model.Descriptor; +import hudson.model.User; +import hudson.security.AbstractPasswordBasedSecurityRealm; +import hudson.security.CliAuthenticator; +import hudson.security.GroupDetails; +import hudson.security.SecurityRealm; +import hudson.security.UserMayOrMayNotExistException; +import hudson.tasks.Mailer; +import hudson.util.Secret; +import jenkins.model.Jenkins; +import jenkins.security.MasterToSlaveCallable; +import jenkins.security.SecurityListener; +import net.coding.api.CodingEmail; +import net.coding.api.CodingMyself; +import net.coding.api.CodingOrganization; +import net.coding.api.CodingTeam; +import org.acegisecurity.Authentication; +import org.acegisecurity.AuthenticationException; +import org.acegisecurity.AuthenticationManager; +import org.acegisecurity.BadCredentialsException; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.acegisecurity.userdetails.UserDetails; +import org.acegisecurity.userdetails.UserDetailsService; +import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.apache.commons.httpclient.URIException; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.kohsuke.args4j.Option; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.Header; +import org.kohsuke.stapler.HttpRedirect; +import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.HttpResponses; +import org.kohsuke.stapler.StaplerRequest; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataRetrievalFailureException; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.Console; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * Implementation of the AbstractPasswordBasedSecurityRealm that uses coding + * oauth to verify the user can login. + * + * This is based on the MySQLSecurityRealm from the mysql-auth-plugin written by + * Alex Ackerman. + */ +public class CodingSecurityRealm extends AbstractPasswordBasedSecurityRealm implements UserDetailsService { + private static final String DEFAULT_WEB_URI = "https://coding.net"; + private static final String DEFAULT_API_URI = "https://coding.net"; + private static final String DEFAULT_ENTERPRISE_API_SUFFIX = "/api"; + private static final String DEFAULT_OAUTH_SCOPES = "user,user:email,team"; + + private String codingWebUri; + private String codingApiUri; + private String clientID; + private Secret clientSecret; + private String oauthScopes; + private String[] myScopes; + + /** + * @param codingWebUri The URI to the root of the web UI for Coding or Coding Enterprise, + * including the protocol (e.g. https). + * @param codingApiUri The URI to the root of the API for Coding or Coding Enterprise, + * including the protocol (e.g. https). + * @param clientID The client ID for the created OAuth Application. + * @param clientSecret The client secret for the created Coding OAuth Application. + * @param oauthScopes A comma separated list of OAuth Scopes to request access to. + */ + @DataBoundConstructor + public CodingSecurityRealm(String codingWebUri, + String codingApiUri, + String clientID, + String clientSecret, + String oauthScopes) { + super(); + + this.codingWebUri = CodingUtil.fixEndwithSlash(Util.fixEmptyAndTrim(codingWebUri)); + this.codingApiUri = CodingUtil.fixEndwithSlash(Util.fixEmptyAndTrim(codingApiUri)); + this.clientID = Util.fixEmptyAndTrim(clientID); + setClientSecret(Util.fixEmptyAndTrim(clientSecret)); + this.oauthScopes = Util.fixEmptyAndTrim(oauthScopes); + } + + private CodingSecurityRealm() { } + + /** + * Tries to automatically determine the Coding API URI based on + * a Coding Web URI. + * + * @param codingWebUri The URI to the root of the Web UI for Coding or Coding Enterprise. + * @return The expected API URI for the given Web UI + */ + private String determineApiUri(String codingWebUri) { + if(codingWebUri.equals(DEFAULT_WEB_URI)) { + return DEFAULT_API_URI; + } else { + return codingWebUri + DEFAULT_ENTERPRISE_API_SUFFIX; + } + } + + /** + * @param codingWebUri + * the string representation of the URI to the root of the Web UI for + * Coding or Coding Enterprise. + */ + private void setCodingWebUri(String codingWebUri) { + this.codingWebUri = codingWebUri; + } + + /** + * @param clientID the clientID to set + */ + private void setClientID(String clientID) { + this.clientID = clientID; + } + + /** + * @param clientSecret the clientSecret to set + */ + private void setClientSecret(String clientSecret) { + this.clientSecret = Secret.fromString(clientSecret); + } + + /** + * @param oauthScopes the oauthScopes to set + */ + private void setOauthScopes(String oauthScopes) { + this.oauthScopes = oauthScopes; + } + + /** + * Checks the security realm for a Coding OAuth scope. + * @param scope A scope to check for in the security realm. + * @return true if security realm has the scope or false if it does not. + */ + public boolean hasScope(String scope) { + if(this.myScopes == null) { + this.myScopes = this.oauthScopes.split(","); + Arrays.sort(this.myScopes); + } + return Arrays.binarySearch(this.myScopes, scope) >= 0; + } + + /** + * + * @return the URI to the API root of Coding or Coding Enterprise. + */ + public String getCodingApiUri() { + return codingWebUri; +// return codingApiUri; + } + + /** + * @param codingApiUri the URI to the API root of Coding or Coding Enterprise. + */ + private void setCodingApiUri(String codingApiUri) { + this.codingApiUri = codingApiUri; + } + + public static final class ConverterImpl implements Converter { + + public boolean canConvert(Class type) { + return type == CodingSecurityRealm.class; + } + + public void marshal(Object source, HierarchicalStreamWriter writer, + MarshallingContext context) { + CodingSecurityRealm realm = (CodingSecurityRealm) source; + + writer.startNode("codingWebUri"); + writer.setValue(realm.getCodingWebUri()); + writer.endNode(); + + writer.startNode("codingApiUri"); + writer.setValue(realm.getCodingApiUri()); + writer.endNode(); + + writer.startNode("clientID"); + writer.setValue(realm.getClientID()); + writer.endNode(); + + writer.startNode("clientSecret"); + writer.setValue(realm.getClientSecret().getEncryptedValue()); + writer.endNode(); + + writer.startNode("oauthScopes"); + writer.setValue(realm.getOauthScopes()); + writer.endNode(); + + } + + public Object unmarshal(HierarchicalStreamReader reader, + UnmarshallingContext context) { + + CodingSecurityRealm realm = new CodingSecurityRealm(); + + String node; + String value; + + while (reader.hasMoreChildren()) { + reader.moveDown(); + node = reader.getNodeName(); + value = reader.getValue(); + setValue(realm, node, value); + reader.moveUp(); + } + + if (realm.getCodingWebUri() == null) { + realm.setCodingWebUri(DEFAULT_WEB_URI); + } + + if (realm.getCodingApiUri() == null) { + realm.setCodingApiUri(DEFAULT_API_URI); + } + + return realm; + } + + private void setValue(CodingSecurityRealm realm, String node, + String value) { + if (node.toLowerCase().equals("clientid")) { + realm.setClientID(value); + } else if (node.toLowerCase().equals("clientsecret")) { + realm.setClientSecret(value); + } else if (node.toLowerCase().equals("codingweburi")) { + realm.setCodingWebUri(value); +// } else if (node.toLowerCase().equals("codinguri")) { // backwards compatibility for old field +// realm.setCodingWebUri(value); +// String apiUrl = realm.determineApiUri(value); +// realm.setCodingApiUri(apiUrl); + } else if (node.toLowerCase().equals("codingapiuri")) { + realm.setCodingApiUri(value); + } else if (node.toLowerCase().equals("oauthscopes")) { + realm.setOauthScopes(value); + } else { + throw new ConversionException("Invalid node value = " + node); + } + } + + } + + /** + * @return the uri to the web root of Coding (varies for Coding Enterprise Edition) + */ + public String getCodingWebUri() { + return codingWebUri; + } + + /** + * @return the clientID + */ + public String getClientID() { + return clientID; + } + + /** + * @return the clientSecret + */ + public Secret getClientSecret() { + return clientSecret; + } + + /** + * @return the oauthScopes + */ + public String getOauthScopes() { + return oauthScopes; + } + + public HttpResponse doCommenceLogin(StaplerRequest request, @Header("Referer") final String referer) + throws IOException { + request.getSession().setAttribute(REFERER_ATTRIBUTE,referer); + + Set scopes = new HashSet<>(); + for (CodingOAuthScope s : getJenkins().getExtensionList(CodingOAuthScope.class)) { + scopes.addAll(s.getScopesToRequest()); + } + String suffix="&response_type=code"; + + // TODO: can be removed when fix https://codingcorp.coding.net/p/coding-dev/task/85488 + String redirectUri = getJenkins().getRootUrl() + "securityRealm/finishLogin"; + suffix += "&redirect_uri=" + redirectUri; + + if (!scopes.isEmpty()) { + suffix += "&scope="+ Util.join(scopes,","); + } else { + // We need repo scope in order to access private repos + // see https://open.coding.net/references/personal-access-token/#%E8%AE%BF%E9%97%AE%E4%BB%A4%E7%89%8C%E7%9A%84%E6%9D%83%E9%99%90 + suffix += "&scope=" + oauthScopes; + } + + //redirect_uri=https%3A%2F%2Fcoding.coding.me%2FComments%2F + return new HttpRedirect(codingWebUri + "/oauth_authorize.html?client_id=" + + clientID + suffix); + } + + /** + * This is where the user comes back to at the end of the OAuth redirect + * ping-pong. + */ + public HttpResponse doFinishLogin(StaplerRequest request) + throws IOException { + String code = request.getParameter("code"); + + if (code == null || code.trim().length() == 0) { + LOGGER.info("doFinishLogin: missing code."); + return HttpResponses.redirectToContextRoot(); + } + + LOGGER.finer("get code " + code); + + String accessToken = getAccessToken(code); + + LOGGER.fine("get accessToken " + accessToken); + + if (accessToken != null && accessToken.trim().length() > 0) { + // only set the access token if it exists. + CodingAuthenticationToken auth = new CodingAuthenticationToken(accessToken, getCodingApiUri()); + SecurityContextHolder.getContext().setAuthentication(auth); + + CodingMyself self = auth.getMyself(); + User u = User.current(); + if (u == null) { + throw new IllegalStateException("Can't find user"); + } + + CodingSecretStorage.put(u, accessToken); + + u.setFullName(self.getName()); + // Set email from coding only if empty + if (!u.getProperty(Mailer.UserProperty.class).hasExplicitlyConfiguredAddress()) { + if(hasScope("user") || hasScope("user:email")) { + String primary_email = null; + for(CodingEmail e : self.getEmails2()) { + if(e.isPrimary()) { + primary_email = e.getEmail(); + } + } + if(primary_email != null) { + u.addProperty(new Mailer.UserProperty(primary_email)); + } + } else { + u.addProperty(new Mailer.UserProperty(auth.getCoding().getMyself().getEmail())); + } + } + + SecurityListener.fireAuthenticated(new CodingOAuthUserDetails(self.getLogin(), auth.getAuthorities())); + + LOGGER.finer("get user " + u); + + // While LastGrantedAuthorities are triggered by that event, we cannot trigger it there + // or modifications in organizations will be not reflected when using API Token, due to that caching + // SecurityListener.fireLoggedIn(self.getLogin()); + } else { + LOGGER.info("Coding did not return an access token."); + } + + String referer = (String)request.getSession().getAttribute(REFERER_ATTRIBUTE); + if (referer!=null) return HttpResponses.redirectTo(referer); + return HttpResponses.redirectToContextRoot(); // referer should be always there, but be defensive + } + + @Nullable + private String getAccessToken(@Nonnull String code) throws IOException { + String content; + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + // https://coding.net/api + HttpPost httpost = new HttpPost(codingWebUri + "/api/oauth/access_token?"); + ArrayList entityList = new ArrayList<>(3); + entityList.add(new BasicNameValuePair("client_id", clientID)); + entityList.add(new BasicNameValuePair("client_secret", clientSecret.getPlainText())); + entityList.add(new BasicNameValuePair("code", code)); + httpost.setEntity(new UrlEncodedFormEntity(entityList)); + HttpHost proxy = getProxy(httpost); + if (proxy != null) { + RequestConfig requestConfig = RequestConfig.custom().setProxy(proxy).build(); + httpost.setConfig(requestConfig); + } + org.apache.http.HttpResponse response = httpClient.execute(httpost); + HttpEntity entity = response.getEntity(); + content = EntityUtils.toString(entity); + + } + try { + Map json = new Gson().fromJson(content, Map.class); + return (String) json.get("access_token"); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "fail to parse json from " + content, e); + } + return null; + } + + /** + * Returns the proxy to be used when connecting to the given URI. + */ + private HttpHost getProxy(HttpUriRequest method) throws URIException { + ProxyConfiguration proxy = getJenkins().proxy; + if (proxy==null) return null; // defensive check + + Proxy p = proxy.createProxy(method.getURI().getHost()); + switch (p.type()) { + case DIRECT: + return null; // no proxy + case HTTP: + InetSocketAddress sa = (InetSocketAddress) p.address(); + return new HttpHost(sa.getHostName(),sa.getPort()); + case SOCKS: + default: + return null; // not supported yet + } + } + + /* + * (non-Javadoc) + * + * @see hudson.security.SecurityRealm#allowsSignup() + */ + @Override + public boolean allowsSignup() { + return false; + } + + @Override + public SecurityComponents createSecurityComponents() { + return new SecurityComponents(new AuthenticationManager() { + + public Authentication authenticate(Authentication authentication) + throws AuthenticationException { + if (authentication instanceof CodingAuthenticationToken) + return authentication; + if (authentication instanceof UsernamePasswordAuthenticationToken) + try { + UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication; + CodingAuthenticationToken coding = new CodingAuthenticationToken(token.getCredentials().toString(), getCodingApiUri()); + SecurityContextHolder.getContext().setAuthentication(coding); + + User user = User.getById(token.getName(), false); + if(user != null){ + CodingSecretStorage.put(user, token.getCredentials().toString()); + } + + SecurityListener.fireAuthenticated(new CodingOAuthUserDetails(token.getName(), coding.getAuthorities())); + + return coding; + } catch (IOException e) { + throw new RuntimeException(e); + } + throw new BadCredentialsException( + "Unexpected authentication type: " + authentication); + } + }, new UserDetailsService() { + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException, DataAccessException { + return CodingSecurityRealm.this.loadUserByUsername(username); + } + }); + } + + @Override + protected CodingOAuthUserDetails authenticate(String username, String password) throws AuthenticationException { + try { + CodingAuthenticationToken coding = new CodingAuthenticationToken(password, getCodingApiUri()); + if(username.equals(coding.getPrincipal())) { + SecurityContextHolder.getContext().setAuthentication(coding); + return coding.getUserDetails(username); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + throw new BadCredentialsException("Invalid Coding username or personal access token: " + username); + } + + @Override + public CliAuthenticator createCliAuthenticator(final CLICommand command) { + return new CliAuthenticator() { + @Option(name="--username",usage="Coding username to authenticate yourself to Jenkins.") + public String userName; + + @Option(name="--password",usage="Coding personal access token. Note that passing a password in arguments is insecure.") + public String password; + + @Option(name="--password-file",usage="File that contains the personal access token.") + public String passwordFile; + + public Authentication authenticate() throws AuthenticationException, IOException, InterruptedException { + if(userName == null) { + // no authentication parameter. fallback to the transport + return command.getTransportAuthentication(); + } + if(passwordFile != null) { + try { + password = new FilePath(command.channel, passwordFile).readToString().trim(); + } catch (IOException e) { + throw new BadCredentialsException("Failed to read " + passwordFile, e); + } + } + if(password == null) { + password = command.channel.call(new InteractivelyAskForPassword()); + } + + if(password == null) { + throw new BadCredentialsException("No Coding personal access token specified."); + } + CodingSecurityRealm.this.authenticate(userName, password); + return new CodingAuthenticationToken(password, getCodingApiUri()); + } + }; + } + + @Override + public String getLoginUrl() { + return "securityRealm/commenceLogin"; + } + + @Override + protected String getPostLogOutUrl(StaplerRequest req, Authentication auth) { + // if we just redirect to the root and anonymous does not have Overall read then we will start a login all over again. + // we are actually anonymous here as the security context has been cleared + Jenkins j = Jenkins.getInstance(); + assert j != null; + if (j.hasPermission(Jenkins.READ)) { + return super.getPostLogOutUrl(req, auth); + } + return req.getContextPath()+ "/" + CodingLogoutAction.POST_LOGOUT_URL; + } + + @Extension + public static final class DescriptorImpl extends Descriptor { + + @Override + public String getHelpFile() { + return "/plugin/coding-webhook/help/oauth/help-security-realm.html"; + } + + @Override + public String getDisplayName() { + return Messages.coding_oauth_codingAuthenticationPlugin(); + } + + public String getDefaultCodingWebUri() { + return DEFAULT_WEB_URI; + } + + public String getDefaultCodingApiUri() { + return DEFAULT_API_URI; + } + + public String getDefaultOauthScopes() { + return DEFAULT_OAUTH_SCOPES; + } + + public DescriptorImpl() { + super(); + // TODO Auto-generated constructor stub + } + + public DescriptorImpl(Class clazz) { + super(clazz); + // TODO Auto-generated constructor stub + } + + } + + // Overridden for better type safety. + // If your plugin doesn't really define any property on Descriptor, + // you don't have to do this. + @Override + public DescriptorImpl getDescriptor() { + return (DescriptorImpl) super.getDescriptor(); + } + + /** + * + * @param username username to lookup + * @return userDetails + * @throws UserMayOrMayNotExistException + * @throws UsernameNotFoundException + * @throws DataAccessException + */ + @Override + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException, DataAccessException { + //username is in org*team format + if(username.contains(CodingOAuthGroupDetails.ORG_TEAM_SEPARATOR)) { + throw new UsernameNotFoundException("Using org*team format instead of username: " + username); + } + + User localUser = User.getById(username, false); + + Authentication token = SecurityContextHolder.getContext().getAuthentication(); + + if (token == null) { + if(localUser != null && CodingSecretStorage.contains(localUser)){ + String accessToken = CodingSecretStorage.retrieve(localUser); + try { + token = new CodingAuthenticationToken(accessToken, getCodingApiUri()); + } catch (IOException e) { + throw new UserMayOrMayNotExistException("Could not connect to Coding API server, target URL = " + getCodingApiUri(), e); + } + SecurityContextHolder.getContext().setAuthentication(token); + }else{ + throw new UserMayOrMayNotExistException("Could not get auth token."); + } + } + + CodingAuthenticationToken authToken; + + if (token instanceof CodingAuthenticationToken) { + authToken = (CodingAuthenticationToken) token; + } else { + throw new UserMayOrMayNotExistException("Unexpected authentication type: " + token); + } + + /** + * Always lookup the local user first. If we can't resolve it then we can burn an API request to Coding for this user + * Taken from hudson.security.HudsonPrivateSecurityRealm#loadUserByUsername(java.lang.String) + */ + if (localUser != null) { + return new CodingOAuthUserDetails(username, authToken); + } + + try { + CodingOAuthUserDetails userDetails = authToken.getUserDetails(username); + if (userDetails == null) + throw new UsernameNotFoundException("Unknown user: " + username); + + // Check the username is not an homonym of an organization + CodingOrganization ghOrg = authToken.loadOrganization(username); + if (ghOrg != null) { + throw new UsernameNotFoundException("user(" + username + ") is also an organization"); + } + + return userDetails; + } catch (IOException | Error e) { + throw new DataRetrievalFailureException("loadUserByUsername (username=" + username +")", e); + } + } + + /** + * Compare an object against this instance for equivalence. + * @param object An object to campare this instance to. + * @return true if the objects are the same instance and configuration. + */ + @Override + public boolean equals(Object object){ + if(object instanceof CodingSecurityRealm) { + CodingSecurityRealm obj = (CodingSecurityRealm) object; + return this.getCodingWebUri().equals(obj.getCodingWebUri()) && + this.getCodingApiUri().equals(obj.getCodingApiUri()) && + this.getClientID().equals(obj.getClientID()) && + this.getClientSecret().equals(obj.getClientSecret()) && + this.getOauthScopes().equals(obj.getOauthScopes()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return new HashCodeBuilder() + .append(this.getCodingWebUri()) + .append(this.getCodingApiUri()) + .append(this.getClientID()) + .append(this.getClientSecret()) + .append(this.getOauthScopes()) + .toHashCode(); + } + + /** + * + * @param groupName groupName to look up + * @return groupDetails + * @throws UsernameNotFoundException + * @throws DataAccessException + */ + @Override + public GroupDetails loadGroupByGroupname(String groupName) + throws UsernameNotFoundException, DataAccessException { + CodingAuthenticationToken authToken = (CodingAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + + if(authToken == null) + throw new UsernameNotFoundException("No known group: " + groupName); + + try { + int idx = groupName.indexOf(CodingOAuthGroupDetails.ORG_TEAM_SEPARATOR); + if (idx > -1 && groupName.length() > idx + 1) { // groupName = "CodingOrganization*CodingTeam" + String orgName = groupName.substring(0, idx); + String teamName = groupName.substring(idx + 1); + LOGGER.config(String.format("Lookup for team %s in organization %s", teamName, orgName)); + CodingTeam ghTeam = authToken.loadTeam(orgName, teamName); + if (ghTeam == null) { + throw new UsernameNotFoundException("Unknown Coding team: " + teamName + " in organization " + + orgName); + } + return new CodingOAuthGroupDetails(ghTeam); + } else { // groupName = "CodingOrganization" + CodingOrganization ghOrg = authToken.loadOrganization(groupName); + if (ghOrg == null) { + throw new UsernameNotFoundException("Unknown Coding organization: " + groupName); + } + return new CodingOAuthGroupDetails(ghOrg); + } + } catch (Error e) { + throw new DataRetrievalFailureException("loadGroupByGroupname (groupname=" + groupName + ")", e); + } + } + + static Jenkins getJenkins() { + Jenkins jenkins = Jenkins.getInstance(); + if (jenkins == null) { + throw new IllegalStateException("Jenkins not started"); + } + return jenkins; + } + + /** + * Logger for debugging purposes. + */ + private static final Logger LOGGER = Logger.getLogger(CodingSecurityRealm.class.getName()); + + private static final String REFERER_ATTRIBUTE = CodingSecurityRealm.class.getName()+".referer"; + + /** + * Asks for the password. + */ + private static class InteractivelyAskForPassword extends MasterToSlaveCallable { + public String call() throws IOException { + Console console = System.console(); + if(console == null) { + return null; // no terminal + } + char[] w = console.readPassword("Coding Personal Access Token: "); + if(w==null) { + return null; + } + return new String(w); + } + private static final long serialVersionUID = 1L; + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java new file mode 100644 index 0000000..4b0ac4f --- /dev/null +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java @@ -0,0 +1,32 @@ +/** + * Jenkins plugin for Coding https://coding.net + * + * Copyright (c) 2016-2018 Shuanglei Tao + * Copyright (c) 2016-present, Coding, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.coding.jenkins.plugin.oauth; + +public class CodingUtil { + public static String fixEndwithSlash(String uri) { + if (uri == null || uri.length() == 0) { + return ""; + } + if (uri.endsWith("/")) { + return uri.substring(0, uri.length() - 1); + } + return uri; + } +} diff --git a/src/main/java/net/coding/jenkins/plugin/webhook/CodingWebHook.java b/src/main/java/net/coding/jenkins/plugin/webhook/CodingWebHook.java index ab52d33..3586769 100644 --- a/src/main/java/net/coding/jenkins/plugin/webhook/CodingWebHook.java +++ b/src/main/java/net/coding/jenkins/plugin/webhook/CodingWebHook.java @@ -139,16 +139,7 @@ public void getDynamic(final String projectName, final StaplerRequest request, S LOGGER.log(Level.WARNING, "Fail to parse request: {0}", task.getRequestBody()); } - ACL.impersonate(ACL.SYSTEM, () -> { - LOGGER.log(Level.FINEST, "Finding CodingPushTrigger"); - CodingPushTrigger trigger = CodingPushTrigger.getFromJob(project); - if (trigger == null) { - LOGGER.log(Level.WARNING, "CodingPushTrigger not found"); - return; - } - LOGGER.log(Level.FINEST, "CodingPushTrigger going to posting"); - trigger.onPost(task); - }); + ACL.impersonate(ACL.SYSTEM, new PostTaskRunnable(project, task)); throw hudson.util.HttpResponses.ok(); case "GET": throw hudson.util.HttpResponses.errorWithoutStack(400, "This url is not intend" + @@ -159,6 +150,29 @@ public void getDynamic(final String projectName, final StaplerRequest request, S } } + public static class PostTaskRunnable implements Runnable { + + private final Job project; + private final WebHookTask task; + + public PostTaskRunnable(Job project, WebHookTask task) { + this.project = project; + this.task = task; + } + + @Override + public void run() { + LOGGER.log(Level.FINEST, "Finding CodingPushTrigger"); + CodingPushTrigger trigger = CodingPushTrigger.getFromJob(project); + if (trigger == null) { + LOGGER.log(Level.WARNING, "CodingPushTrigger not found"); + return; + } + LOGGER.log(Level.FINEST, "CodingPushTrigger going to posting"); + trigger.onPost(task); + } + } + private Job resolveProject(final String projectName, final Iterator restOfPathParts) { return ACL.impersonate(ACL.SYSTEM, new Callable, RuntimeException>() { @Override diff --git a/src/main/java/net/coding/jenkins/plugin/webhook/WebHookHelperV1.java b/src/main/java/net/coding/jenkins/plugin/webhook/WebHookHelperV1.java index bfbd6e2..b52d6c0 100644 --- a/src/main/java/net/coding/jenkins/plugin/webhook/WebHookHelperV1.java +++ b/src/main/java/net/coding/jenkins/plugin/webhook/WebHookHelperV1.java @@ -35,13 +35,11 @@ import org.apache.commons.lang.StringUtils; import javax.servlet.http.HttpServletRequest; -import java.net.MalformedURLException; import java.net.URI; -import java.net.URL; +import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; public class WebHookHelperV1 implements IWebHookHelper { public static final String version = "v1"; @@ -203,7 +201,11 @@ private List to(List commits) { if (commits == null) { return null; } - return commits.stream().map(this::to).collect(Collectors.toList()); + List result = new ArrayList<>(commits.size()); + for (Commit commit: commits) { + result.add(to(commit)); + } + return result; } private net.coding.jenkins.plugin.model.Commit to(net.coding.jenkins.plugin.v1.model.Commit commit) { diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly index a17c36f..6f7f4da 100644 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -1,6 +1,6 @@

This plugin integrates - Coding + Coding with Jenkins.
diff --git a/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help.properties b/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help.properties index 2c7302c..c5607c0 100644 --- a/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help.properties +++ b/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help.properties @@ -22,8 +22,8 @@ coding.trigger.help=\
\

\ Configure your Jenkins instance to handle \ - WebHook \ - request sent by Coding and triggers \ + WebHook \ + request sent by Coding and triggers \ builds for pushes and merge/pull requests.\

\ To getting started, you need to create an WebHook on Coding using the WebHook URL \ diff --git a/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help_zh_CN.properties b/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help_zh_CN.properties index 6194505..a1fc205 100644 --- a/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help_zh_CN.properties +++ b/src/main/resources/net/coding/jenkins/plugin/CodingPushTrigger/help_zh_CN.properties @@ -21,8 +21,8 @@ coding.trigger.help=\
\

\ - \u4E3A Jenkins \u5B9E\u4F8B\u6DFB\u52A0\u5904\u7406 Coding \ - \u53D1\u9001\u8FC7\u6765\u7684 WebHook \ + \u4E3A Jenkins \u5B9E\u4F8B\u6DFB\u52A0\u5904\u7406 Coding \ + \u53D1\u9001\u8FC7\u6765\u7684 WebHook \ \u8BF7\u6C42\u652F\u6301, \u5E76\u5728\u6536\u5230\u4EE3\u7801\u63A8\u9001\u548C Merge/Pull request \u65F6\u89E6\u53D1\u6784\u5EFA\u3002\

\ \u8981\u4F7F\u7528\u6B64\u529F\u80FD, \u5FC5\u987B\u4F7F\u7528\u6B64\u9009\u9879\u7ED3\u5C3E\u663E\u793A\u7684 WebHook \u5730\u5740 \u5148\u5728 Coding \u4E0A\u521B\u5EFA\u4E00\u4E2A WebHook, \ diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.jelly b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.jelly new file mode 100644 index 0000000..c3a05dc --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.jelly @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.properties new file mode 100644 index 0000000..e7b4755 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config.properties @@ -0,0 +1,30 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.authorization.codingAuthorizationSettings=Coding Authorization Settings +coding.oauth.authorization.adminUserNames=Admin User Names +coding.oauth.authorization.organizationNames=Participant in Organization +coding.oauth.authorization.useRepositoryPermissions=Use Coding repository permissions +coding.oauth.authorization.authenticatedUserReadPermission=Grant READ permissions to all Authenticated Users +coding.oauth.authorization.authenticatedUserCreateJobPermission=Grant CREATE Job permissions to all Authenticated Users +coding.oauth.authorization.allowCodingWebHookPermission=Grant READ permissions for /coding-webhook +coding.oauth.authorization.allowCcTrayPermission=Grant READ permissions for .*/cc.xml +coding.oauth.authorization.allowAnonymousReadPermission=Grant READ permissions for Anonymous Users +coding.oauth.authorization.allowAnonymousJobStatusPermission=Grant ViewStatus permissions for Anonymous Users diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config_zh_CN.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config_zh_CN.properties new file mode 100644 index 0000000..b3e8ae1 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy/config_zh_CN.properties @@ -0,0 +1,30 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.authorization.codingAuthorizationSettings=Coding \u6388\u6743\u8BBE\u7F6E +coding.oauth.authorization.adminUserNames=\u7BA1\u7406\u5458\u7528\u6237\u540D\u5217\u8868 +coding.oauth.authorization.organizationNames=\u53C2\u4E0E\u7EC4\u7EC7 +coding.oauth.authorization.useRepositoryPermissions=\u4F7F\u7528 Coding \u4ED3\u5E93\u6743\u9650 +coding.oauth.authorization.authenticatedUserReadPermission=\u5BF9\u6240\u6709\u767B\u5F55\u7528\u6237\u6388\u4E88\u53EA\u8BFB\u6743\u9650 +coding.oauth.authorization.authenticatedUserCreateJobPermission=\u5BF9\u6240\u6709\u767B\u5F55\u7528\u6237\u6388\u4E88\u521B\u5EFA\u9879\u76EE\u6743\u9650 +coding.oauth.authorization.allowCodingWebHookPermission=\u5BF9 /coding-webhook \u6388\u6743 +coding.oauth.authorization.allowCcTrayPermission=\u5BF9 .*/cc.xml \u6388\u6743 +coding.oauth.authorization.allowAnonymousReadPermission=\u5BF9\u533F\u540D\u7528\u6237\u6388\u4E88\u53EA\u8BFB\u6743\u9650 +coding.oauth.authorization.allowAnonymousJobStatusPermission=\u5BF9\u533F\u540D\u7528\u6237\u6388\u4E88 ViewStatus \u6743\u9650 \ No newline at end of file diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.jelly b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.jelly new file mode 100644 index 0000000..29479d7 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.jelly @@ -0,0 +1,42 @@ + + + + + + + +

${%coding.oauth.logoutSucceed}${it.codingText}.

+

${%coding.oauth.niceDay}

+
+ +

${%coding.oauth.whoaThere}

+

${%coding.oauth.notLogoutYet}

+

${%coding.oauth.pressLogoutAgain}

+
+
+
+
+
diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.properties new file mode 100644 index 0000000..5754455 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index.properties @@ -0,0 +1,25 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.logoutSucceed=You are now logged out of Jenkins. However, you have not been logged out of +coding.oauth.niceDay=Have a nice day! +coding.oauth.whoaThere=Whoa there... +coding.oauth.notLogoutYet=You are not logged out - don't run away! +coding.oauth.pressLogoutAgain=Whilst you should have been logged out, you are not actually logged out. Press the logout button to try logging out again. diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index_zh_CN.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index_zh_CN.properties new file mode 100644 index 0000000..6234f50 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingLogoutAction/index_zh_CN.properties @@ -0,0 +1,25 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.logoutSucceed=\u4F60\u73B0\u5728\u5DF2\u7ECF\u9000\u51FA Jenkins \u4E86\u3002\u4F46\u662F\uFF0C\u60A8\u5C1A\u672A\u767B\u51FA +coding.oauth.niceDay=\u795D\u60A8\u6709\u4E2A\u7F8E\u597D\u7684\u4E00\u5929\uFF01 +coding.oauth.whoaThere=\u54C7\u54E6\u2026 +coding.oauth.notLogoutYet=\u522B\u6025\u7740\u8D70\uFF01\u4F60\u5C1A\u672A\u767B\u51FA\u3002 +coding.oauth.pressLogoutAgain=\u5C1D\u8BD5\u767B\u51FA\u8D26\u53F7\uFF0C\u4F46\u5E76\u672A\u6210\u529F\u3002\u8BF7\u4F60\u6309\u4E0B\u767B\u51FA\u6309\u94AE\u518D\u6B21\u5C1D\u8BD5\u3002 diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.jelly b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.jelly new file mode 100644 index 0000000..1703921 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.jelly @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.properties new file mode 100644 index 0000000..ce3ead7 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config.properties @@ -0,0 +1,26 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.globalOauthSetting=Global Coding OAuth Settings +coding.oauth.codingWebUri=Coding Web URI +coding.oauth.codingApiUri=Coding API URI +coding.oauth.clientID=Client ID +coding.oauth.clientSecret=Client Secret +coding.oauth.oauthScopes=OAuth Scope(s) \ No newline at end of file diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config_zh_CN.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config_zh_CN.properties new file mode 100644 index 0000000..4c3180e --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/CodingSecurityRealm/config_zh_CN.properties @@ -0,0 +1,26 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.globalOauthSetting=\u5168\u5C40 Coding \u5B89\u5168\u8BBE\u7F6E +coding.oauth.codingWebUri=Coding Web URI +coding.oauth.codingApiUri=Coding API URI +coding.oauth.clientID=Client ID +coding.oauth.clientSecret=Client Secret +coding.oauth.oauthScopes=OAuth \u6388\u6743\u8303\u56F4 \ No newline at end of file diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/Messages.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/Messages.properties new file mode 100644 index 0000000..a95c66b --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/Messages.properties @@ -0,0 +1,22 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.codingAuthenticationPlugin=Coding Authentication Plugin +coding.oauth.codingAuthorizationStrategy=Coding Authorization Strategy diff --git a/src/main/resources/net/coding/jenkins/plugin/oauth/Messages_zh_CN.properties b/src/main/resources/net/coding/jenkins/plugin/oauth/Messages_zh_CN.properties new file mode 100644 index 0000000..1e7dd92 --- /dev/null +++ b/src/main/resources/net/coding/jenkins/plugin/oauth/Messages_zh_CN.properties @@ -0,0 +1,22 @@ +# +# Jenkins plugin for Coding https://coding.net +# +# Copyright (c) 2016-2018 Shuanglei Tao +# Copyright (c) 2016-present, Coding, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +coding.oauth.codingAuthenticationPlugin=Coding \u5B89\u5168\u63D2\u4EF6 +coding.oauth.codingAuthorizationStrategy=Coding \u6388\u6743\u7B56\u7565 diff --git a/src/main/webapp/help/help-webhook-api-personal-token.html b/src/main/webapp/help/help-webhook-api-personal-token.html index fbec256..38d170e 100644 --- a/src/main/webapp/help/help-webhook-api-personal-token.html +++ b/src/main/webapp/help/help-webhook-api-personal-token.html @@ -1,5 +1,5 @@
Personal token is required for publishing comment and project tweet, you can enable and get it from the - Personal Token + Personal Token setting page.
diff --git a/src/main/webapp/help/help-webhook-api-personal-token_zh_CN.html b/src/main/webapp/help/help-webhook-api-personal-token_zh_CN.html index 732d11c..1640f4d 100644 --- a/src/main/webapp/help/help-webhook-api-personal-token_zh_CN.html +++ b/src/main/webapp/help/help-webhook-api-personal-token_zh_CN.html @@ -1,5 +1,5 @@
访问令牌用于发布评论和项目内冒泡的认证,你可以在 - 访问令牌 + 访问令牌 设置页面开启和获取到它。
diff --git a/src/main/webapp/help/help-webhook-apitoken.html b/src/main/webapp/help/help-webhook-apitoken.html index 71c4036..ab92b16 100644 --- a/src/main/webapp/help/help-webhook-apitoken.html +++ b/src/main/webapp/help/help-webhook-apitoken.html @@ -1,5 +1,5 @@
(Deprecated) Private token is required for publishing comment and project tweet, you can enable and get it from the - Access Token + Access Token setting page.
diff --git a/src/main/webapp/help/help-webhook-apitoken_zh_CN.html b/src/main/webapp/help/help-webhook-apitoken_zh_CN.html index b584622..8a8e830 100644 --- a/src/main/webapp/help/help-webhook-apitoken_zh_CN.html +++ b/src/main/webapp/help/help-webhook-apitoken_zh_CN.html @@ -1,5 +1,5 @@
(废弃)访问令牌用于发布评论和项目内冒泡的认证,你可以在 - 访问令牌 + 访问令牌 设置页面开启和获取到它。
diff --git a/src/main/webapp/help/oauth/aaa.sh b/src/main/webapp/help/oauth/aaa.sh new file mode 100644 index 0000000..436c3f7 --- /dev/null +++ b/src/main/webapp/help/oauth/aaa.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +for i in `find . -name '*.zh_CN.html'` +do + ii=`echo $i | cut -f2 -d '.'` + mv .$ii.zh_CN.html .${ii}_zh_CN.html +done \ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/admin-user-names-help.html b/src/main/webapp/help/oauth/auth/admin-user-names-help.html new file mode 100644 index 0000000..e5a2646 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/admin-user-names-help.html @@ -0,0 +1,3 @@ +
+Comma Separated list of user names that when authenticated should be given administrator rights. +
\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/admin-user-names-help_zh_CN.html b/src/main/webapp/help/oauth/auth/admin-user-names-help_zh_CN.html new file mode 100644 index 0000000..8aec21d --- /dev/null +++ b/src/main/webapp/help/oauth/auth/admin-user-names-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 用英文逗号分隔的管理员用户名列表。 +
\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help.html b/src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help.html new file mode 100644 index 0000000..6136113 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help.html @@ -0,0 +1,3 @@ +
+If checked will grant the create job permission to all authenticated coding users even those that aren't members of the declared organizations. +
diff --git a/src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help_zh_CN.html b/src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help_zh_CN.html new file mode 100644 index 0000000..76a35bc --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-create-job-to-authenticated-help_zh_CN.html @@ -0,0 +1,3 @@ +
+若勾选,将授予所有登录用户创建项目的权利,即使该用户不属于设定的企业中。 +
diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help.html b/src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help.html new file mode 100644 index 0000000..5314684 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help.html @@ -0,0 +1,3 @@ +
+If checked will grant the READ permission to everyone that connects to the Jenkins instance. Anyone will be able to see all the jobs and related state but only authenticated users will be able to BUILD the jobs. +
diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help_zh_CN.html b/src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help_zh_CN.html new file mode 100644 index 0000000..71f132c --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-anonymous-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 若勾选,将授予所有用户只读权限。任何人都将能看到所有任务及其状态,不过只有登录用户能够构建项目。 +
diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help.html b/src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help.html new file mode 100644 index 0000000..8fb94c5 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help.html @@ -0,0 +1,3 @@ +
+If checked will grant the read permission to all authenticated coding users even those that aren't members of the declared organizations. +
diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help_zh_CN.html b/src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help_zh_CN.html new file mode 100644 index 0000000..2507693 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-authenticated-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 若勾选,将授予所有 Coding OAuth 登录用户只读权限,即使该用户不属于设定的企业中。 +
diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-cctray-help.html b/src/main/webapp/help/oauth/auth/grant-read-to-cctray-help.html new file mode 100644 index 0000000..220792e --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-cctray-help.html @@ -0,0 +1,7 @@ +
+Open a hole in security to allow unauthenticated access to URLs ending with /cc.xml. +This URI provides monitoring capability +to a range of desktop clients. + +Enabling this option reveals limited information about your build to the whole world. Use with care. +
\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-cctray-help_zh_CN.html b/src/main/webapp/help/oauth/auth/grant-read-to-cctray-help_zh_CN.html new file mode 100644 index 0000000..c7f95d6 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-cctray-help_zh_CN.html @@ -0,0 +1,5 @@ +
+ 在安全防护上开一个洞,对 /cc.xml 结尾的未鉴权请求予以访问权限。 + 这个链接为众多桌面程序提供了 监控能力。 + 开启这个选项,将有限度地暴露你的构建信息给全世界。请小心使用。 +
diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help.html b/src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help.html new file mode 100644 index 0000000..287c7e0 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help.html @@ -0,0 +1,6 @@ +
+The coding-webhook has a web hook trigger that can be used to notify Jenkins when a push has occurred and that a build should also happen.
By enabling this permission you grant anonymous external READ access to the /coding/* URL so that the request can be received. +

+The coding-webhook checks that a change has actually occurred so this should be safe to enable. + +

\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help_zh_CN.html b/src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help_zh_CN.html new file mode 100644 index 0000000..abfce65 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-read-to-coding-webhook-help_zh_CN.html @@ -0,0 +1,6 @@ +
+ The coding-webhook has a web hook trigger that can be used to notify Jenkins when a push has occurred and that a build should also happen.
By enabling this permission you grant anonymous external READ access to the /coding/* URL so that the request can be received. +

+ The coding-webhook checks that a change has actually occurred so this should be safe to enable. + +

\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help.html b/src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help.html new file mode 100644 index 0000000..60decf9 --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help.html @@ -0,0 +1,4 @@ +
+ If checked will grant the ViewStatus permission to everyone that connects to the Jenkins instance. Anyone will be able to see the status of a job, but nothing else. + This is useful especially for plugins like Embeddable Build Status Plugin. +
\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help_zh_CN.html b/src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help_zh_CN.html new file mode 100644 index 0000000..28858df --- /dev/null +++ b/src/main/webapp/help/oauth/auth/grant-viewstatus-to-anonymous-help_zh_CN.html @@ -0,0 +1,4 @@ +
+ 若勾选,将对所有人授予 ViewStatus 权限。任何人讲可以看到一个任务的状态,不过也就只能看到这么多。 + 这对于一些插件很有用,特别如 Embeddable Build Status Plugin。 +
\ No newline at end of file diff --git a/src/main/webapp/help/oauth/auth/organization-names-help.html b/src/main/webapp/help/oauth/auth/organization-names-help.html new file mode 100644 index 0000000..59cce8d --- /dev/null +++ b/src/main/webapp/help/oauth/auth/organization-names-help.html @@ -0,0 +1,3 @@ +
+Comma Separated list of organization names that if a user is registered with will have job view and build rights. +
diff --git a/src/main/webapp/help/oauth/auth/organization-names-help_zh_CN.html b/src/main/webapp/help/oauth/auth/organization-names-help_zh_CN.html new file mode 100644 index 0000000..01d07eb --- /dev/null +++ b/src/main/webapp/help/oauth/auth/organization-names-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 用英文逗号分隔的组织名列表。在这些组织中的用户,将有查看项目和构建的权限。 +
diff --git a/src/main/webapp/help/oauth/auth/use-repository-permissions-help.html b/src/main/webapp/help/oauth/auth/use-repository-permissions-help.html new file mode 100644 index 0000000..b454c4e --- /dev/null +++ b/src/main/webapp/help/oauth/auth/use-repository-permissions-help.html @@ -0,0 +1,7 @@ +
+If checked will use coding repository permissions to determine jenkins permissions for each project. +
    +
  • Public projects - all authenticated users can READ. Only collaborators can BUILD, EDIT, CONFIGURE, CANCEL or DELETE. +
  • Private projects, only collaborators can READ, BUILD, EDIT, CONFIGURE, CANCEL or DELETE +
+
diff --git a/src/main/webapp/help/oauth/auth/use-repository-permissions-help_zh_CN.html b/src/main/webapp/help/oauth/auth/use-repository-permissions-help_zh_CN.html new file mode 100644 index 0000000..b454c4e --- /dev/null +++ b/src/main/webapp/help/oauth/auth/use-repository-permissions-help_zh_CN.html @@ -0,0 +1,7 @@ +
+If checked will use coding repository permissions to determine jenkins permissions for each project. +
    +
  • Public projects - all authenticated users can READ. Only collaborators can BUILD, EDIT, CONFIGURE, CANCEL or DELETE. +
  • Private projects, only collaborators can READ, BUILD, EDIT, CONFIGURE, CANCEL or DELETE +
+
diff --git a/src/main/webapp/help/oauth/help-authorization-strategy.html b/src/main/webapp/help/oauth/help-authorization-strategy.html new file mode 100644 index 0000000..ee884b9 --- /dev/null +++ b/src/main/webapp/help/oauth/help-authorization-strategy.html @@ -0,0 +1,13 @@ +
+ + Requires the Coding Webhook Plugin to be used as the authentication source. +

+ We use the OAuth token for each authenticated coding user to interact with the Coding API to determine the level of access each user should have. + +

+ + We grant READ and BUILD job permissions to an authenticated user if they are a member in at least one named organization.

+ + We also support defining a set of Jenkins Admin users and whether or not any authenticated user can have READ access to the jobs. + +

diff --git a/src/main/webapp/help/oauth/help-authorization-strategy_zh_CN.html b/src/main/webapp/help/oauth/help-authorization-strategy_zh_CN.html new file mode 100644 index 0000000..802b9d7 --- /dev/null +++ b/src/main/webapp/help/oauth/help-authorization-strategy_zh_CN.html @@ -0,0 +1,14 @@ +
+ + 使用 Coding Webhook Plugin 作为鉴权手段。 +

+ 我们使用 Coding 用户的 OAuth token 从 Coding API 获取数据,以提供合适的用户权限。 + +

+ + 如果用户属于配置许可的组织,则对次用户授予读取和构建作业权限。

+ + + 我们也支持设置一系列 Jenkins 管理员 账户,以及设置允许或不允许任何登录用户拥有只读权限。 + +

diff --git a/src/main/webapp/help/oauth/help-security-realm.html b/src/main/webapp/help/oauth/help-security-realm.html new file mode 100644 index 0000000..de960f8 --- /dev/null +++ b/src/main/webapp/help/oauth/help-security-realm.html @@ -0,0 +1,23 @@ +
+ + Authentication requires a valid OAuth application to be registered with Coding.net. +
+ Using your Coding account you can create a new application registration using this link: + https://coding.net/user/account/setting/applications/add +
+ +You can use any name you want but bear in mind this is what coding will show to the users when they authenticate and authorize this plugin to act on their behalf. +
+ +The entry should look like this: + + + + +
Main URLhttp://127.0.0.1:8080
Callback URLhttp://127.0.0.1:8080/securityRealm/finishLogin
+ +With 127.0.0.1:8080 replaced with the public hostname and port of your jenkins instance. + +

+ +

diff --git a/src/main/webapp/help/oauth/help-security-realm_zh_CN.html b/src/main/webapp/help/oauth/help-security-realm_zh_CN.html new file mode 100644 index 0000000..7d7549b --- /dev/null +++ b/src/main/webapp/help/oauth/help-security-realm_zh_CN.html @@ -0,0 +1,23 @@ +
+ + 需要在 Coding.net 注册一个有效 OAuth 应用,以提供身份验证功能 +
+ 你可以使用你的 Coding 账号,点击这个链接创建一个新的 OAuth 应用: + https://coding.net/user/account/setting/applications/add +
+ +你可以使用任何你想要的名称。但请注意,Coding 将把这个名称显示给用户,并请他们确认和授权这个插件获取他们的信息。 +
+ +创建时,你将需要输入如下信息: + + + + +
应用主页http://127.0.0.1:8080
回调地址http://127.0.0.1:8080/securityRealm/finishLogin
+ +请把 127.0.0.1:8080 替换为 Jenkins 的域名和端口。 + +

+ +

diff --git a/src/main/webapp/help/oauth/realm/client-id-help.html b/src/main/webapp/help/oauth/realm/client-id-help.html new file mode 100644 index 0000000..ee323cc --- /dev/null +++ b/src/main/webapp/help/oauth/realm/client-id-help.html @@ -0,0 +1,3 @@ +
+The Client ID hash from the Coding application entry being configured. See https://coding.net/user/account/setting/applications. +
diff --git a/src/main/webapp/help/oauth/realm/client-id-help_zh_CN.html b/src/main/webapp/help/oauth/realm/client-id-help_zh_CN.html new file mode 100644 index 0000000..a366005 --- /dev/null +++ b/src/main/webapp/help/oauth/realm/client-id-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 配置 Coding OAuth 应用里的 Client ID。 查看 https://coding.net/user/account/setting/applications. +
diff --git a/src/main/webapp/help/oauth/realm/client-secret-help.html b/src/main/webapp/help/oauth/realm/client-secret-help.html new file mode 100644 index 0000000..c081378 --- /dev/null +++ b/src/main/webapp/help/oauth/realm/client-secret-help.html @@ -0,0 +1,3 @@ +
+ The Client Secret hash from the Coding application entry being configured. See https://coding.net/user/account/setting/applications. +
diff --git a/src/main/webapp/help/oauth/realm/client-secret-help_zh_CN.html b/src/main/webapp/help/oauth/realm/client-secret-help_zh_CN.html new file mode 100644 index 0000000..38efe67 --- /dev/null +++ b/src/main/webapp/help/oauth/realm/client-secret-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 配置 Coding OAuth 应用里的 Client Secret。 查看 https://coding.net/user/account/setting/applications. +
diff --git a/src/main/webapp/help/oauth/realm/coding-api-uri-help.html b/src/main/webapp/help/oauth/realm/coding-api-uri-help.html new file mode 100644 index 0000000..81a7550 --- /dev/null +++ b/src/main/webapp/help/oauth/realm/coding-api-uri-help.html @@ -0,0 +1,15 @@ +
+

+ Normally this value stays as-is. If you are using Coding Enterprise + then you should enter the URI to the API root of your Coding installation + (e.g. https://democorp.coding.net). +

+ + Notes: + +

    +
  1. The https:// / http:// part needs to be specified.
  2. +
  3. There should not be any trailing slash (/)
  4. +
  5. For Coding Enterprise, the API URI is usually the same as the Web URI.
  6. +
+
diff --git a/src/main/webapp/help/oauth/realm/coding-api-uri-help_zh_CN.html b/src/main/webapp/help/oauth/realm/coding-api-uri-help_zh_CN.html new file mode 100644 index 0000000..53765fd --- /dev/null +++ b/src/main/webapp/help/oauth/realm/coding-api-uri-help_zh_CN.html @@ -0,0 +1,15 @@ +
+

+ 通常这个值保持不变就行了。 如果你使用的是 Coding 企业版 + 那么你需要输入你 Coding 企业版的 API 地址。 + (例如: https://democorp.coding.net). +

+ + 注意: + +

    +
  1. 需要填写 https:// / http:// 部分
  2. +
  3. 地址 应该有斜线 (/) 结尾
  4. +
  5. 对于 Coding 企业版而已, API 地址 通常 跟 Web 地址一致。
  6. +
+
diff --git a/src/main/webapp/help/oauth/realm/coding-web-uri-help.html b/src/main/webapp/help/oauth/realm/coding-web-uri-help.html new file mode 100644 index 0000000..30653be --- /dev/null +++ b/src/main/webapp/help/oauth/realm/coding-web-uri-help.html @@ -0,0 +1,14 @@ +
+

+ Normally this value stays as-is. If you are using Coding Enterprise + then you should enter the URI to the Web root of your Coding installation + (e.g. https://democorp.coding.net). +

+ + Notes: + +

    +
  1. The https:// / http:// part needs to be specified.
  2. +
  3. There should not be any trailing slash (/)
  4. +
+
\ No newline at end of file diff --git a/src/main/webapp/help/oauth/realm/coding-web-uri-help_zh_CN.html b/src/main/webapp/help/oauth/realm/coding-web-uri-help_zh_CN.html new file mode 100644 index 0000000..f66f245 --- /dev/null +++ b/src/main/webapp/help/oauth/realm/coding-web-uri-help_zh_CN.html @@ -0,0 +1,14 @@ +
+

+ 通常这个值保持不变就行了。 如果你使用的是 Coding 企业版 + 那么你需要输入你 Coding 企业版的 Web 地址。 + (例如: https://democorp.coding.net). +

+ + 注意: + +

    +
  1. 需要填写 https:// / http:// 部分
  2. +
  3. 地址 应该有斜线 (/) 结尾
  4. +
+
diff --git a/src/main/webapp/help/oauth/realm/oauth-scopes-help.html b/src/main/webapp/help/oauth/realm/oauth-scopes-help.html new file mode 100644 index 0000000..fcb70c1 --- /dev/null +++ b/src/main/webapp/help/oauth/realm/oauth-scopes-help.html @@ -0,0 +1,3 @@ +
+A comma separated list of OAuth Scopes to request access to. See https://open.coding.net/references/personal-access-token/. +
diff --git a/src/main/webapp/help/oauth/realm/oauth-scopes-help_zh_CN.html b/src/main/webapp/help/oauth/realm/oauth-scopes-help_zh_CN.html new file mode 100644 index 0000000..e398f8a --- /dev/null +++ b/src/main/webapp/help/oauth/realm/oauth-scopes-help_zh_CN.html @@ -0,0 +1,3 @@ +
+ 用英文逗号分隔的 OAuth 权限列表。 查看 https://open.coding.net/references/personal-access-token/。 +
From 72f751a3db85c82680a3d58fe22b68fd4ae8b9a3 Mon Sep 17 00:00:00 2001 From: wusisu Date: Fri, 18 May 2018 17:08:44 +0800 Subject: [PATCH 2/8] add exclude --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0243bca..7eb1f6d 100644 --- a/build.gradle +++ b/build.gradle @@ -73,7 +73,7 @@ task wrapper(type: Wrapper) { license { header project.file('LICENSE_HEADER') - excludes (["**/webhook/filter/*.java", "**/Messages.java"]) + excludes (["**/webhook/filter/*.java", "**/Messages.java", "**/net/coding/jenkins/plugin/oauth/**", "**/net/coding/api/**"]) } jenkinsPlugin { From a11dca1772aa7aafbc4b467af9a7e7a316bdf4c2 Mon Sep 17 00:00:00 2001 From: wusisu Date: Fri, 18 May 2018 17:18:18 +0800 Subject: [PATCH 3/8] cahnge api --- src/main/java/net/coding/api/Coding.java | 34 +++++++++++-------- .../java/net/coding/api/CodingBuilder.java | 34 +++++++++++-------- src/main/java/net/coding/api/CodingEmail.java | 34 +++++++++++-------- .../java/net/coding/api/CodingMyself.java | 34 +++++++++++-------- .../java/net/coding/api/CodingObject.java | 34 +++++++++++-------- .../net/coding/api/CodingOrganization.java | 34 +++++++++++-------- .../java/net/coding/api/CodingPerson.java | 34 +++++++++++-------- .../java/net/coding/api/CodingPersonSet.java | 34 +++++++++++-------- .../java/net/coding/api/CodingRepository.java | 34 +++++++++++-------- src/main/java/net/coding/api/CodingTeam.java | 34 +++++++++++-------- src/main/java/net/coding/api/CodingUser.java | 34 +++++++++++-------- .../java/net/coding/api/HttpConnector.java | 34 +++++++++++-------- .../java/net/coding/api/HttpException.java | 34 +++++++++++-------- .../java/net/coding/api/PagedIterable.java | 34 +++++++++++-------- .../java/net/coding/api/PagedIterator.java | 34 +++++++++++-------- src/main/java/net/coding/api/Requester.java | 34 +++++++++++-------- .../java/net/coding/api/SkipFromToString.java | 34 +++++++++++-------- .../api/extras/ImpatientHttpConnector.java | 34 +++++++++++-------- .../coding/api/extras/OkHttpConnector.java | 34 +++++++++++-------- 19 files changed, 380 insertions(+), 266 deletions(-) diff --git a/src/main/java/net/coding/api/Coding.java b/src/main/java/net/coding/api/Coding.java index f6071a1..bbca65a 100644 --- a/src/main/java/net/coding/api/Coding.java +++ b/src/main/java/net/coding/api/Coding.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingBuilder.java b/src/main/java/net/coding/api/CodingBuilder.java index aee8623..a6d5ff4 100644 --- a/src/main/java/net/coding/api/CodingBuilder.java +++ b/src/main/java/net/coding/api/CodingBuilder.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingEmail.java b/src/main/java/net/coding/api/CodingEmail.java index a9e59f8..ad49835 100644 --- a/src/main/java/net/coding/api/CodingEmail.java +++ b/src/main/java/net/coding/api/CodingEmail.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingMyself.java b/src/main/java/net/coding/api/CodingMyself.java index be50e5d..97c6b68 100644 --- a/src/main/java/net/coding/api/CodingMyself.java +++ b/src/main/java/net/coding/api/CodingMyself.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingObject.java b/src/main/java/net/coding/api/CodingObject.java index 578221d..ce3b6c5 100644 --- a/src/main/java/net/coding/api/CodingObject.java +++ b/src/main/java/net/coding/api/CodingObject.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingOrganization.java b/src/main/java/net/coding/api/CodingOrganization.java index 63403cb..5644599 100644 --- a/src/main/java/net/coding/api/CodingOrganization.java +++ b/src/main/java/net/coding/api/CodingOrganization.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingPerson.java b/src/main/java/net/coding/api/CodingPerson.java index 23cbb69..3e67f82 100644 --- a/src/main/java/net/coding/api/CodingPerson.java +++ b/src/main/java/net/coding/api/CodingPerson.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingPersonSet.java b/src/main/java/net/coding/api/CodingPersonSet.java index d602ee0..aad7c68 100644 --- a/src/main/java/net/coding/api/CodingPersonSet.java +++ b/src/main/java/net/coding/api/CodingPersonSet.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingRepository.java b/src/main/java/net/coding/api/CodingRepository.java index 04c15c3..acd1081 100644 --- a/src/main/java/net/coding/api/CodingRepository.java +++ b/src/main/java/net/coding/api/CodingRepository.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingTeam.java b/src/main/java/net/coding/api/CodingTeam.java index 3a553a9..b8248b7 100644 --- a/src/main/java/net/coding/api/CodingTeam.java +++ b/src/main/java/net/coding/api/CodingTeam.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/CodingUser.java b/src/main/java/net/coding/api/CodingUser.java index aa7b90b..5eeeeb5 100644 --- a/src/main/java/net/coding/api/CodingUser.java +++ b/src/main/java/net/coding/api/CodingUser.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/HttpConnector.java b/src/main/java/net/coding/api/HttpConnector.java index 24ccd88..13bf48f 100644 --- a/src/main/java/net/coding/api/HttpConnector.java +++ b/src/main/java/net/coding/api/HttpConnector.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/HttpException.java b/src/main/java/net/coding/api/HttpException.java index c6ae00b..c8ac329 100644 --- a/src/main/java/net/coding/api/HttpException.java +++ b/src/main/java/net/coding/api/HttpException.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/PagedIterable.java b/src/main/java/net/coding/api/PagedIterable.java index f7bcbfa..9780117 100644 --- a/src/main/java/net/coding/api/PagedIterable.java +++ b/src/main/java/net/coding/api/PagedIterable.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/PagedIterator.java b/src/main/java/net/coding/api/PagedIterator.java index acdf118..aefdb10 100644 --- a/src/main/java/net/coding/api/PagedIterator.java +++ b/src/main/java/net/coding/api/PagedIterator.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/Requester.java b/src/main/java/net/coding/api/Requester.java index 9810481..db52819 100644 --- a/src/main/java/net/coding/api/Requester.java +++ b/src/main/java/net/coding/api/Requester.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/SkipFromToString.java b/src/main/java/net/coding/api/SkipFromToString.java index d71fd8d..5275994 100644 --- a/src/main/java/net/coding/api/SkipFromToString.java +++ b/src/main/java/net/coding/api/SkipFromToString.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api; diff --git a/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java b/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java index 74a229f..5b3b899 100644 --- a/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java +++ b/src/main/java/net/coding/api/extras/ImpatientHttpConnector.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api.extras; diff --git a/src/main/java/net/coding/api/extras/OkHttpConnector.java b/src/main/java/net/coding/api/extras/OkHttpConnector.java index 43c69c1..a88e56f 100644 --- a/src/main/java/net/coding/api/extras/OkHttpConnector.java +++ b/src/main/java/net/coding/api/extras/OkHttpConnector.java @@ -1,21 +1,27 @@ /** - * Jenkins plugin for Coding https://coding.net + * Copyright (c) 2011- Kohsuke Kawaguchi and other contributors + * Copyright (c) 2016-present, Coding, Inc. * - * Copyright (c) 2016-2018 Shuanglei Tao - * Copyright (c) 2016-present, Coding, 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: * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.api.extras; From 29613268c9b9677a8b79506e5860b6cb23e404aa Mon Sep 17 00:00:00 2001 From: wusisu Date: Fri, 18 May 2018 17:18:58 +0800 Subject: [PATCH 4/8] change readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0586e68..25ea415 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,12 @@ You may want to disable debug options to get faster page load time: ## Acknowledgements This project is started and based on the [gitlab-plugin][3], thanks for the great project. -The coding-api module follows [github-api-plugin][6], and coding-auth module follows [github-oauth-plugin][7], thanks for them. +The coding-api module follows [github-api][6], and coding-auth module follows [github-oauth-plugin][7], thanks for them. [1]: https://coding.net [2]: https://open.coding.net/webhooks [3]: https://github.com/jenkinsci/gitlab-plugin [4]: https://plugins.jenkins.io [5]: https://jenkins.io/doc/book/managing/plugins - [6]: https://github.com/jenkinsci/github-api-plugin + [6]: https://github.com/kohsuke/github-api [7]: https://github.com/jenkinsci/github-oauth-plugin From 727fcdecb0bd07a585a366bc410630bbf93dd3ef Mon Sep 17 00:00:00 2001 From: wusisu Date: Fri, 18 May 2018 17:25:16 +0800 Subject: [PATCH 5/8] change oauth --- .../oauth/CodingAccessTokenProperty.java | 35 ++++++++++--------- .../oauth/CodingAuthenticationToken.java | 35 ++++++++++--------- .../oauth/CodingAuthorizationStrategy.java | 35 ++++++++++--------- .../plugin/oauth/CodingLogoutAction.java | 35 ++++++++++--------- .../plugin/oauth/CodingOAuthGroupDetails.java | 35 ++++++++++--------- .../plugin/oauth/CodingOAuthScope.java | 35 ++++++++++--------- .../plugin/oauth/CodingOAuthUserDetails.java | 35 ++++++++++--------- .../plugin/oauth/CodingRepositoryName.java | 35 ++++++++++--------- ...odingRequireOrganizationMembershipACL.java | 35 ++++++++++--------- .../plugin/oauth/CodingSecretStorage.java | 35 ++++++++++--------- .../plugin/oauth/CodingSecurityRealm.java | 35 ++++++++++--------- .../jenkins/plugin/oauth/CodingUtil.java | 35 ++++++++++--------- 12 files changed, 228 insertions(+), 192 deletions(-) diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java index 69b55cc..446eab7 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.jenkins.plugin.oauth; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java index b9839d3..c31d6eb 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** The MIT License diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java index eb0dabe..27ea112 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** The MIT License diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java index de4a88f..f1d9b74 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.jenkins.plugin.oauth; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java index b4dca36..d99fef2 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** * diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java index 932d5cf..0bc4df2 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.jenkins.plugin.oauth; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java index 490b96b..46a8f8a 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** * diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java index c87848d..191d979 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** The MIT License diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java index fcd4646..fb0bfb4 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** The MIT License diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java index 2ab727b..b7f4cc4 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.jenkins.plugin.oauth; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java index eae3dcc..dcc6fee 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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. + * */ */ /** The MIT License diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java index 4b0ac4f..dfe8db4 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java @@ -1,21 +1,24 @@ /** - * Jenkins plugin for Coding https://coding.net - * - * Copyright (c) 2016-2018 Shuanglei Tao + * /** + * The MIT License + * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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 net.coding.jenkins.plugin.oauth; From 31c183b2e8fc3c601b94f87bc4175e1de7a078d6 Mon Sep 17 00:00:00 2001 From: wusisu Date: Fri, 18 May 2018 18:02:27 +0800 Subject: [PATCH 6/8] fix oauth --- .../oauth/CodingAccessTokenProperty.java | 5 ++-- .../oauth/CodingAuthenticationToken.java | 29 ++----------------- .../oauth/CodingAuthorizationStrategy.java | 29 ++----------------- .../plugin/oauth/CodingLogoutAction.java | 5 ++-- .../plugin/oauth/CodingOAuthGroupDetails.java | 8 ++--- .../plugin/oauth/CodingOAuthScope.java | 6 ++-- .../plugin/oauth/CodingOAuthUserDetails.java | 8 ++--- .../plugin/oauth/CodingRepositoryName.java | 27 ++--------------- ...odingRequireOrganizationMembershipACL.java | 29 ++----------------- .../plugin/oauth/CodingSecretStorage.java | 5 ++-- .../plugin/oauth/CodingSecurityRealm.java | 29 ++----------------- .../jenkins/plugin/oauth/CodingUtil.java | 5 ++-- 12 files changed, 32 insertions(+), 153 deletions(-) diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java index 446eab7..3f42ec5 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAccessTokenProperty.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,8 +19,8 @@ * 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 net.coding.jenkins.plugin.oauth; import hudson.Extension; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java index c31d6eb..d799383 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthenticationToken.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,34 +19,8 @@ * 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. - * */ */ -/** - The MIT License - -Copyright (c) 2011 Michael O'Cleirigh - -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 net.coding.jenkins.plugin.oauth; import com.google.common.cache.Cache; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java index 27ea112..2ed6053 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingAuthorizationStrategy.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,34 +19,8 @@ * 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. - * */ */ -/** - The MIT License - -Copyright (c) 2011 Michael O'Cleirigh - -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 net.coding.jenkins.plugin.oauth; import com.google.common.collect.ImmutableList; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java index f1d9b74..acb1ee2 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingLogoutAction.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,8 +19,8 @@ * 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 net.coding.jenkins.plugin.oauth; import hudson.Extension; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java index d99fef2..b66d4b4 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthGroupDetails.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,11 +19,8 @@ * 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 net.coding.jenkins.plugin.oauth; import hudson.security.GroupDetails; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java index 0bc4df2..81f6990 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthScope.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,8 +19,9 @@ * 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 net.coding.jenkins.plugin.oauth; import hudson.ExtensionPoint; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java index 46a8f8a..b09840d 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingOAuthUserDetails.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,11 +19,8 @@ * 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 net.coding.jenkins.plugin.oauth; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java index 191d979..5b64913 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRepositoryName.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,32 +19,8 @@ * 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. - * */ */ -/** - The MIT License - -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 net.coding.jenkins.plugin.oauth; import java.util.logging.Level; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java index fb0bfb4..bacdb4f 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingRequireOrganizationMembershipACL.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,34 +19,8 @@ * 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. - * */ */ -/** - The MIT License - -Copyright (c) 2011 Michael O'Cleirigh - -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 net.coding.jenkins.plugin.oauth; import hudson.model.AbstractItem; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java index b7f4cc4..86e3010 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecretStorage.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,8 +19,8 @@ * 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 net.coding.jenkins.plugin.oauth; import hudson.model.User; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java index dcc6fee..d3ac7a9 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,34 +19,8 @@ * 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. - * */ */ -/** - The MIT License - -Copyright (c) 2011-2016 Michael O'Cleirigh, James Nord, CloudBees, 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 net.coding.jenkins.plugin.oauth; import com.google.gson.Gson; diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java index dfe8db4..97c21df 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingUtil.java @@ -1,8 +1,9 @@ /** - * /** * The MIT License + * * Copyright (c) 2011 Michael O'Cleirigh * Copyright (c) 2016-present, Coding, 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 @@ -18,8 +19,8 @@ * 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 net.coding.jenkins.plugin.oauth; public class CodingUtil { From d654ba3b371f5863e9f27bbe9bc999a7a5a95797 Mon Sep 17 00:00:00 2001 From: wusisu Date: Thu, 24 May 2018 17:35:16 +0800 Subject: [PATCH 7/8] compatible with private deploy --- .../plugin/oauth/CodingSecurityRealm.java | 124 ++++++++++-------- 1 file changed, 72 insertions(+), 52 deletions(-) diff --git a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java index d3ac7a9..ff478f2 100644 --- a/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java +++ b/src/main/java/net/coding/jenkins/plugin/oauth/CodingSecurityRealm.java @@ -61,6 +61,7 @@ import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.apache.commons.httpclient.URIException; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; @@ -89,6 +90,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Proxy; +import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -137,12 +139,13 @@ public CodingSecurityRealm(String codingWebUri, this.codingWebUri = CodingUtil.fixEndwithSlash(Util.fixEmptyAndTrim(codingWebUri)); this.codingApiUri = CodingUtil.fixEndwithSlash(Util.fixEmptyAndTrim(codingApiUri)); - this.clientID = Util.fixEmptyAndTrim(clientID); + this.clientID = Util.fixEmptyAndTrim(clientID); setClientSecret(Util.fixEmptyAndTrim(clientSecret)); - this.oauthScopes = Util.fixEmptyAndTrim(oauthScopes); + this.oauthScopes = Util.fixEmptyAndTrim(oauthScopes); } - private CodingSecurityRealm() { } + private CodingSecurityRealm() { + } /** * Tries to automatically determine the Coding API URI based on @@ -152,7 +155,7 @@ private CodingSecurityRealm() { } * @return The expected API URI for the given Web UI */ private String determineApiUri(String codingWebUri) { - if(codingWebUri.equals(DEFAULT_WEB_URI)) { + if (codingWebUri.equals(DEFAULT_WEB_URI)) { return DEFAULT_API_URI; } else { return codingWebUri + DEFAULT_ENTERPRISE_API_SUFFIX; @@ -195,7 +198,7 @@ private void setOauthScopes(String oauthScopes) { * @return true if security realm has the scope or false if it does not. */ public boolean hasScope(String scope) { - if(this.myScopes == null) { + if (this.myScopes == null) { this.myScopes = this.oauthScopes.split(","); Arrays.sort(this.myScopes); } @@ -225,7 +228,7 @@ public boolean canConvert(Class type) { } public void marshal(Object source, HierarchicalStreamWriter writer, - MarshallingContext context) { + MarshallingContext context) { CodingSecurityRealm realm = (CodingSecurityRealm) source; writer.startNode("codingWebUri"); @@ -251,7 +254,7 @@ public void marshal(Object source, HierarchicalStreamWriter writer, } public Object unmarshal(HierarchicalStreamReader reader, - UnmarshallingContext context) { + UnmarshallingContext context) { CodingSecurityRealm realm = new CodingSecurityRealm(); @@ -330,20 +333,20 @@ public String getOauthScopes() { public HttpResponse doCommenceLogin(StaplerRequest request, @Header("Referer") final String referer) throws IOException { - request.getSession().setAttribute(REFERER_ATTRIBUTE,referer); + request.getSession().setAttribute(REFERER_ATTRIBUTE, referer); Set scopes = new HashSet<>(); for (CodingOAuthScope s : getJenkins().getExtensionList(CodingOAuthScope.class)) { scopes.addAll(s.getScopesToRequest()); } - String suffix="&response_type=code"; + String suffix = "&response_type=code"; // TODO: can be removed when fix https://codingcorp.coding.net/p/coding-dev/task/85488 String redirectUri = getJenkins().getRootUrl() + "securityRealm/finishLogin"; suffix += "&redirect_uri=" + redirectUri; if (!scopes.isEmpty()) { - suffix += "&scope="+ Util.join(scopes,","); + suffix += "&scope=" + Util.join(scopes, ","); } else { // We need repo scope in order to access private repos // see https://open.coding.net/references/personal-access-token/#%E8%AE%BF%E9%97%AE%E4%BB%A4%E7%89%8C%E7%9A%84%E6%9D%83%E9%99%90 @@ -390,14 +393,14 @@ public HttpResponse doFinishLogin(StaplerRequest request) u.setFullName(self.getName()); // Set email from coding only if empty if (!u.getProperty(Mailer.UserProperty.class).hasExplicitlyConfiguredAddress()) { - if(hasScope("user") || hasScope("user:email")) { + if (hasScope("user") || hasScope("user:email")) { String primary_email = null; - for(CodingEmail e : self.getEmails2()) { - if(e.isPrimary()) { + for (CodingEmail e : self.getEmails2()) { + if (e.isPrimary()) { primary_email = e.getEmail(); } } - if(primary_email != null) { + if (primary_email != null) { u.addProperty(new Mailer.UserProperty(primary_email)); } } else { @@ -416,8 +419,8 @@ public HttpResponse doFinishLogin(StaplerRequest request) LOGGER.info("Coding did not return an access token."); } - String referer = (String)request.getSession().getAttribute(REFERER_ATTRIBUTE); - if (referer!=null) return HttpResponses.redirectTo(referer); + String referer = (String) request.getSession().getAttribute(REFERER_ATTRIBUTE); + if (referer != null) return HttpResponses.redirectTo(referer); return HttpResponses.redirectToContextRoot(); // referer should be always there, but be defensive } @@ -431,6 +434,22 @@ private String getAccessToken(@Nonnull String code) throws IOException { entityList.add(new BasicNameValuePair("client_id", clientID)); entityList.add(new BasicNameValuePair("client_secret", clientSecret.getPlainText())); entityList.add(new BasicNameValuePair("code", code)); + + String team = "private"; + try { + URI uri = new URI(codingWebUri); + String host = uri.getHost(); + // real enterprise + if (StringUtils.endsWithIgnoreCase(host, ".coding.net") || + StringUtils.equalsIgnoreCase(host, "coding.net")) { + team = null; + } + } catch (Exception e) { + LOGGER.fine("error to parse team from webUrl " + e); + } + if (team != null) { + entityList.add(new BasicNameValuePair("team", team)); + } httpost.setEntity(new UrlEncodedFormEntity(entityList)); HttpHost proxy = getProxy(httpost); if (proxy != null) { @@ -456,18 +475,18 @@ private String getAccessToken(@Nonnull String code) throws IOException { */ private HttpHost getProxy(HttpUriRequest method) throws URIException { ProxyConfiguration proxy = getJenkins().proxy; - if (proxy==null) return null; // defensive check + if (proxy == null) return null; // defensive check Proxy p = proxy.createProxy(method.getURI().getHost()); switch (p.type()) { - case DIRECT: - return null; // no proxy - case HTTP: - InetSocketAddress sa = (InetSocketAddress) p.address(); - return new HttpHost(sa.getHostName(),sa.getPort()); - case SOCKS: - default: - return null; // not supported yet + case DIRECT: + return null; // no proxy + case HTTP: + InetSocketAddress sa = (InetSocketAddress) p.address(); + return new HttpHost(sa.getHostName(), sa.getPort()); + case SOCKS: + default: + return null; // not supported yet } } @@ -496,7 +515,7 @@ public Authentication authenticate(Authentication authentication) SecurityContextHolder.getContext().setAuthentication(coding); User user = User.getById(token.getName(), false); - if(user != null){ + if (user != null) { CodingSecretStorage.put(user, token.getCredentials().toString()); } @@ -504,7 +523,7 @@ public Authentication authenticate(Authentication authentication) return coding; } catch (IOException e) { - throw new RuntimeException(e); + throw new RuntimeException(e); } throw new BadCredentialsException( "Unexpected authentication type: " + authentication); @@ -521,7 +540,7 @@ public UserDetails loadUserByUsername(String username) protected CodingOAuthUserDetails authenticate(String username, String password) throws AuthenticationException { try { CodingAuthenticationToken coding = new CodingAuthenticationToken(password, getCodingApiUri()); - if(username.equals(coding.getPrincipal())) { + if (username.equals(coding.getPrincipal())) { SecurityContextHolder.getContext().setAuthentication(coding); return coding.getUserDetails(username); } @@ -534,32 +553,32 @@ protected CodingOAuthUserDetails authenticate(String username, String password) @Override public CliAuthenticator createCliAuthenticator(final CLICommand command) { return new CliAuthenticator() { - @Option(name="--username",usage="Coding username to authenticate yourself to Jenkins.") + @Option(name = "--username", usage = "Coding username to authenticate yourself to Jenkins.") public String userName; - @Option(name="--password",usage="Coding personal access token. Note that passing a password in arguments is insecure.") + @Option(name = "--password", usage = "Coding personal access token. Note that passing a password in arguments is insecure.") public String password; - @Option(name="--password-file",usage="File that contains the personal access token.") + @Option(name = "--password-file", usage = "File that contains the personal access token.") public String passwordFile; public Authentication authenticate() throws AuthenticationException, IOException, InterruptedException { - if(userName == null) { + if (userName == null) { // no authentication parameter. fallback to the transport return command.getTransportAuthentication(); } - if(passwordFile != null) { + if (passwordFile != null) { try { password = new FilePath(command.channel, passwordFile).readToString().trim(); } catch (IOException e) { throw new BadCredentialsException("Failed to read " + passwordFile, e); } } - if(password == null) { + if (password == null) { password = command.channel.call(new InteractivelyAskForPassword()); } - if(password == null) { + if (password == null) { throw new BadCredentialsException("No Coding personal access token specified."); } CodingSecurityRealm.this.authenticate(userName, password); @@ -582,7 +601,7 @@ protected String getPostLogOutUrl(StaplerRequest req, Authentication auth) { if (j.hasPermission(Jenkins.READ)) { return super.getPostLogOutUrl(req, auth); } - return req.getContextPath()+ "/" + CodingLogoutAction.POST_LOGOUT_URL; + return req.getContextPath() + "/" + CodingLogoutAction.POST_LOGOUT_URL; } @Extension @@ -642,7 +661,7 @@ public DescriptorImpl getDescriptor() { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { //username is in org*team format - if(username.contains(CodingOAuthGroupDetails.ORG_TEAM_SEPARATOR)) { + if (username.contains(CodingOAuthGroupDetails.ORG_TEAM_SEPARATOR)) { throw new UsernameNotFoundException("Using org*team format instead of username: " + username); } @@ -651,7 +670,7 @@ public UserDetails loadUserByUsername(String username) Authentication token = SecurityContextHolder.getContext().getAuthentication(); if (token == null) { - if(localUser != null && CodingSecretStorage.contains(localUser)){ + if (localUser != null && CodingSecretStorage.contains(localUser)) { String accessToken = CodingSecretStorage.retrieve(localUser); try { token = new CodingAuthenticationToken(accessToken, getCodingApiUri()); @@ -659,7 +678,7 @@ public UserDetails loadUserByUsername(String username) throw new UserMayOrMayNotExistException("Could not connect to Coding API server, target URL = " + getCodingApiUri(), e); } SecurityContextHolder.getContext().setAuthentication(token); - }else{ + } else { throw new UserMayOrMayNotExistException("Could not get auth token."); } } @@ -693,7 +712,7 @@ public UserDetails loadUserByUsername(String username) return userDetails; } catch (IOException | Error e) { - throw new DataRetrievalFailureException("loadUserByUsername (username=" + username +")", e); + throw new DataRetrievalFailureException("loadUserByUsername (username=" + username + ")", e); } } @@ -703,14 +722,14 @@ public UserDetails loadUserByUsername(String username) * @return true if the objects are the same instance and configuration. */ @Override - public boolean equals(Object object){ - if(object instanceof CodingSecurityRealm) { + public boolean equals(Object object) { + if (object instanceof CodingSecurityRealm) { CodingSecurityRealm obj = (CodingSecurityRealm) object; return this.getCodingWebUri().equals(obj.getCodingWebUri()) && - this.getCodingApiUri().equals(obj.getCodingApiUri()) && - this.getClientID().equals(obj.getClientID()) && - this.getClientSecret().equals(obj.getClientSecret()) && - this.getOauthScopes().equals(obj.getOauthScopes()); + this.getCodingApiUri().equals(obj.getCodingApiUri()) && + this.getClientID().equals(obj.getClientID()) && + this.getClientSecret().equals(obj.getClientSecret()) && + this.getOauthScopes().equals(obj.getOauthScopes()); } else { return false; } @@ -737,9 +756,9 @@ public int hashCode() { @Override public GroupDetails loadGroupByGroupname(String groupName) throws UsernameNotFoundException, DataAccessException { - CodingAuthenticationToken authToken = (CodingAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + CodingAuthenticationToken authToken = (CodingAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); - if(authToken == null) + if (authToken == null) throw new UsernameNotFoundException("No known group: " + groupName); try { @@ -779,23 +798,24 @@ static Jenkins getJenkins() { */ private static final Logger LOGGER = Logger.getLogger(CodingSecurityRealm.class.getName()); - private static final String REFERER_ATTRIBUTE = CodingSecurityRealm.class.getName()+".referer"; + private static final String REFERER_ATTRIBUTE = CodingSecurityRealm.class.getName() + ".referer"; /** * Asks for the password. */ - private static class InteractivelyAskForPassword extends MasterToSlaveCallable { + private static class InteractivelyAskForPassword extends MasterToSlaveCallable { public String call() throws IOException { Console console = System.console(); - if(console == null) { + if (console == null) { return null; // no terminal } char[] w = console.readPassword("Coding Personal Access Token: "); - if(w==null) { + if (w == null) { return null; } return new String(w); } + private static final long serialVersionUID = 1L; } } From f1eb14798c1da53a1e11ae6da7a56f00806f3cd8 Mon Sep 17 00:00:00 2001 From: wusisu Date: Wed, 30 May 2018 13:59:23 +0800 Subject: [PATCH 8/8] adjust jenkins version of 2.7.3 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7eb1f6d..5d8ff72 100644 --- a/build.gradle +++ b/build.gradle @@ -77,7 +77,7 @@ license { } jenkinsPlugin { - coreVersion = '2.7.1' + coreVersion = '2.7.3' shortName = 'coding-webhook' displayName = 'Coding Webhook Plugin' url = 'https://wiki.jenkins.io/display/JENKINS/Coding+Webhook+Plugin'