-
Notifications
You must be signed in to change notification settings - Fork 166
WIP: Add email domain filter #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,6 +91,7 @@ of this software and associated documentation files (the "Software"), to deal | |
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.logging.Logger; | ||
import java.util.logging.Level; | ||
import javax.annotation.Nonnull; | ||
import javax.annotation.Nullable; | ||
|
||
|
@@ -107,12 +108,15 @@ public class GithubSecurityRealm extends AbstractPasswordBasedSecurityRealm impl | |
private static final String DEFAULT_API_URI = "https://api.github.com"; | ||
private static final String DEFAULT_ENTERPRISE_API_SUFFIX = "/api/v3"; | ||
private static final String DEFAULT_OAUTH_SCOPES = "read:org,user:email,repo"; | ||
private static final Boolean DEFAULT_FORCE_GITHUB_EMAIL = false; | ||
|
||
private String githubWebUri; | ||
private String githubApiUri; | ||
private String clientID; | ||
private Secret clientSecret; | ||
private String oauthScopes; | ||
private String emailDomains; | ||
private Boolean forceGithubEmail; | ||
private String[] myScopes; | ||
|
||
/** | ||
|
@@ -123,20 +127,39 @@ public class GithubSecurityRealm extends AbstractPasswordBasedSecurityRealm impl | |
* @param clientID The client ID for the created OAuth Application. | ||
* @param clientSecret The client secret for the created GitHub OAuth Application. | ||
* @param oauthScopes A comma separated list of OAuth Scopes to request access to. | ||
* @param emailDomains An optional comma separated list of domain(s) to select for email | ||
* @param forceGithubEmail Force the email from github to override the one in the profile | ||
*/ | ||
@DataBoundConstructor | ||
public GithubSecurityRealm(String githubWebUri, | ||
String githubApiUri, | ||
String clientID, | ||
String clientSecret, | ||
String oauthScopes) { | ||
String oauthScopes, | ||
String emailDomains, | ||
Boolean forceGithubEmail) { | ||
super(); | ||
|
||
this.githubWebUri = Util.fixEmptyAndTrim(githubWebUri); | ||
this.githubApiUri = Util.fixEmptyAndTrim(githubApiUri); | ||
this.clientID = Util.fixEmptyAndTrim(clientID); | ||
setClientSecret(Util.fixEmptyAndTrim(clientSecret)); | ||
this.oauthScopes = Util.fixEmptyAndTrim(oauthScopes); | ||
this.emailDomains = emailDomains.trim(); | ||
this.forceGithubEmail = forceGithubEmail; | ||
} | ||
|
||
/** | ||
This method is deprecated. | ||
@deprecated use GithubSecurityRealm(githubWebUri, githubApiUri, clientID, clientSecret, oauthScopes, emailDomains, forceGithubEmail) | ||
*/ | ||
@Deprecated | ||
public GithubSecurityRealm(String githubWebUri, | ||
String githubApiUri, | ||
String clientID, | ||
String clientSecret, | ||
String oauthScopes) { | ||
this(githubWebUri, githubApiUri, clientID, clientSecret, oauthScopes, "", false); | ||
} | ||
|
||
private GithubSecurityRealm() { } | ||
|
@@ -186,6 +209,20 @@ private void setOauthScopes(String oauthScopes) { | |
this.oauthScopes = oauthScopes; | ||
} | ||
|
||
/** | ||
* @param emailDomains the emailDomains to set | ||
*/ | ||
private void setEmailDomains(String emailDomains) { | ||
this.emailDomains = emailDomains; | ||
} | ||
|
||
/** | ||
* @param forceGithubEmail the forceGithubEmail to set | ||
*/ | ||
private void setForceGithubEmail(Boolean forceGithubEmail) { | ||
this.forceGithubEmail = forceGithubEmail; | ||
} | ||
|
||
/** | ||
* Checks the security realm for a GitHub OAuth scope. | ||
* @param scope A scope to check for in the security realm. | ||
|
@@ -244,6 +281,20 @@ public void marshal(Object source, HierarchicalStreamWriter writer, | |
writer.setValue(realm.getOauthScopes()); | ||
writer.endNode(); | ||
|
||
writer.startNode("emailDomains"); | ||
writer.setValue(realm.getEmailDomains()); | ||
writer.endNode(); | ||
|
||
writer.startNode("forceGithubEmail"); | ||
//TODO: Is there a better way to do this? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a better/preferred way to store a boolean value in the config file? If not and what I have is ok I'll remove the TODO comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check how other plugins save and load booleans. I'll check as well. |
||
if (realm.getForceGithubEmail()) { | ||
writer.setValue("true"); | ||
} | ||
else { | ||
writer.setValue("false"); | ||
} | ||
writer.endNode(); | ||
|
||
} | ||
|
||
public Object unmarshal(HierarchicalStreamReader reader, | ||
|
@@ -270,6 +321,10 @@ public Object unmarshal(HierarchicalStreamReader reader, | |
realm.setGithubApiUri(DEFAULT_API_URI); | ||
} | ||
|
||
if (realm.getForceGithubEmail() == null) { | ||
realm.setForceGithubEmail(DEFAULT_FORCE_GITHUB_EMAIL); | ||
} | ||
|
||
return realm; | ||
} | ||
|
||
|
@@ -289,6 +344,15 @@ private void setValue(GithubSecurityRealm realm, String node, | |
realm.setGithubApiUri(value); | ||
} else if (node.toLowerCase().equals("oauthscopes")) { | ||
realm.setOauthScopes(value); | ||
} else if (node.toLowerCase().equals("emaildomains")) { | ||
realm.setEmailDomains(value); | ||
} else if (node.toLowerCase().equals("forcegithubemail")) { | ||
if (value.toLowerCase().equals("true")){ | ||
realm.setForceGithubEmail(true); | ||
} | ||
else { | ||
realm.setForceGithubEmail(false); | ||
} | ||
} else { | ||
throw new ConversionException("Invalid node value = " + node); | ||
} | ||
|
@@ -333,6 +397,20 @@ public String getOauthScopes() { | |
return oauthScopes; | ||
} | ||
|
||
/** | ||
* @return the emailDomains | ||
*/ | ||
public String getEmailDomains() { | ||
return emailDomains; | ||
} | ||
|
||
/** | ||
* @return the forceGithubEmail | ||
*/ | ||
public Boolean getForceGithubEmail() { | ||
return forceGithubEmail; | ||
} | ||
|
||
public HttpResponse doCommenceLogin(StaplerRequest request, @Header("Referer") final String referer) | ||
throws IOException { | ||
request.getSession().setAttribute(REFERER_ATTRIBUTE,referer); | ||
|
@@ -383,17 +461,40 @@ public HttpResponse doFinishLogin(StaplerRequest request) | |
GithubSecretStorage.put(u, accessToken); | ||
|
||
u.setFullName(self.getName()); | ||
// Set email from github only if empty | ||
if (!u.getProperty(Mailer.UserProperty.class).hasExplicitlyConfiguredAddress()) { | ||
// Set email from github only if empty or forceGithubEmail flag is set | ||
if (forceGithubEmail || !u.getProperty(Mailer.UserProperty.class).hasExplicitlyConfiguredAddress()) { | ||
if(hasScope("user") || hasScope("user:email")) { | ||
String primary_email = null; | ||
for(GHEmail e : self.getEmails2()) { | ||
if(e.isPrimary()) { | ||
primary_email = e.getEmail(); | ||
String domain_email = null; | ||
if (emailDomains != null) { | ||
LOGGER.log(Level.FINE, "Searching for email of github user \"" + u.getId() + "\" that match domain(s) \"" + emailDomains + "\""); | ||
for (String emailDomain : emailDomains.split(",")) { | ||
for(GHEmail e : self.getEmails2()) { | ||
LOGGER.log(Level.FINE, "Checking if email \"" + e.getEmail() + "\" matches domain \"" + emailDomain + "\" for github user \"" + u.getId() + "\""); | ||
if(e.getEmail().endsWith("@" + emailDomain)) { | ||
domain_email = e.getEmail(); | ||
LOGGER.log(Level.FINE, "Email \"" + e.getEmail() + "\" matches domain \"" + emailDomain + "\" for github user \"" + u.getId() + "\""); | ||
break; | ||
} | ||
} | ||
if (domain_email != null) { | ||
LOGGER.log(Level.FINE, "Setting email for github user \"" + u.getId() + "\" to \"" + domain_email + "\" due to matching domain in domain list"); | ||
u.addProperty(new Mailer.UserProperty(domain_email)); | ||
break; | ||
} | ||
} | ||
} | ||
if(primary_email != null) { | ||
u.addProperty(new Mailer.UserProperty(primary_email)); | ||
if (domain_email == null) { | ||
LOGGER.log(Level.FINE, "Getting primary email for github user \"" + u.getId() + "\""); | ||
for(GHEmail e : self.getEmails2()) { | ||
LOGGER.log(Level.FINE, "Checking if email \"" + e.getEmail() + "\" is primary email for github user \"" + u.getId() + "\""); | ||
if (e.isPrimary()) { | ||
primary_email = e.getEmail(); | ||
LOGGER.log(Level.FINE, "Setting email for github user \"" + u.getId() + "\" to primary address \"" + primary_email + "\""); | ||
u.addProperty(new Mailer.UserProperty(primary_email)); | ||
break; | ||
} | ||
} | ||
} | ||
} else { | ||
u.addProperty(new Mailer.UserProperty(auth.getGitHub().getMyself().getEmail())); | ||
|
@@ -600,6 +701,10 @@ public String getDefaultOauthScopes() { | |
return DEFAULT_OAUTH_SCOPES; | ||
} | ||
|
||
public Boolean getDefaultForceGithubEmail() { | ||
return DEFAULT_FORCE_GITHUB_EMAIL; | ||
} | ||
|
||
public DescriptorImpl() { | ||
super(); | ||
// TODO Auto-generated constructor stub | ||
|
@@ -700,7 +805,9 @@ public boolean equals(Object object){ | |
this.getGithubApiUri().equals(obj.getGithubApiUri()) && | ||
this.getClientID().equals(obj.getClientID()) && | ||
this.getClientSecret().equals(obj.getClientSecret()) && | ||
this.getOauthScopes().equals(obj.getOauthScopes()); | ||
this.getOauthScopes().equals(obj.getOauthScopes()) && | ||
this.getEmailDomains().equals(obj.getEmailDomains()) && | ||
this.getForceGithubEmail().equals(obj.getForceGithubEmail()); | ||
} else { | ||
return false; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<div> | ||
Specify the domain(s) to prefer emails from in a comma seperated list in the prefered order. Useful if users in your users have personal and organization emails on Github and you want to ensure that their email in Jenkins is the one with your Org's domain. Examples: "example.com", "example.com,example.net" (If user has both example.com and example.net, example.com will be chosen) | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<div> | ||
If selected the email found in Github will overwrite the email stored in Jenkins, every time the user logs in via Github Oauth. | ||
</div> |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not cleanly migrate configuration. Please overload this method with another deprecated method so that configurations cleanly migrate.