Skip to content

Commit

Permalink
Merge pull request #12 from jenkinsci/placeholder-attributes
Browse files Browse the repository at this point in the history
Support placeholders in email/fullname attributes
  • Loading branch information
fcrespel authored Feb 16, 2021
2 parents 684160a + dee9184 commit 53bbf02
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Added option to customize validation URL parameters in advanced protocol configuration.
- Fixed handling of empty attributes.
- Allow using `{{attribute}}` placeholders in Full Name and Email Attribute configuration (e.g. `{{firstName}} {{lastName}}`).

## [1.5.0] - 2020-11-22

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -30,6 +32,7 @@ public class CasEventListener implements ApplicationListener<AuthenticationSucce

private String fullNameAttribute = DEFAULT_FULL_NAME_ATTRIBUTE;
private String emailAttribute = DEFAULT_EMAIL_ATTRIBUTE;
private Pattern placeholderPattern = Pattern.compile("\\{\\{[a-zA-Z0-9._-]+\\}\\}");

/**
* Handle an application event.
Expand Down Expand Up @@ -80,14 +83,14 @@ protected void syncUserAttributes(CasAuthenticationToken casToken) throws IOExce
hudson.model.User user = hudson.model.User.getOrCreateByIdOrFullName(casToken.getName());

// Sync the full name
String fullName = getAttributeValue(casToken, getFullNameAttribute());
String fullName = parseAttributeTemplate(casToken, getFullNameAttribute());
if (StringUtils.hasText(fullName)) {
LOG.debug("Setting user '{}' full name to '{}'", casToken.getName(), fullName);
user.setFullName(fullName);
}

// Sync the email address
String email = getAttributeValue(casToken, getEmailAttribute());
String email = parseAttributeTemplate(casToken, getEmailAttribute());
if (StringUtils.hasText(email)) {
LOG.debug("Setting user '{}' email address to '{}'", casToken.getName(), email);
user.addProperty(new Mailer.UserProperty(email));
Expand All @@ -97,24 +100,44 @@ protected void syncUserAttributes(CasAuthenticationToken casToken) throws IOExce
user.save();
}

/**
* Replace placeholders in an attribute template string.
* @param authToken CAS authentication token
* @param attributeTemplate attribute template containing '{{placeholder}}' or plain attribute name
* @return attribute value or null if not found
*/
protected String parseAttributeTemplate(CasAuthenticationToken authToken, String attributeTemplate) {
if (StringUtils.hasText(attributeTemplate)) {
if (attributeTemplate.contains("{{")) {
StringBuffer sb = new StringBuffer();
Matcher m = placeholderPattern.matcher(attributeTemplate);
while (m.find()) {
String attrName = m.group();
String attrValue = getAttributeValue(authToken, attrName.substring(2, attrName.length() - 2));
m.appendReplacement(sb, StringUtils.hasText(attrValue) ? attrValue : "");
}
m.appendTail(sb);
return sb.toString();
} else {
return getAttributeValue(authToken, attributeTemplate);
}
}
return null;
}

/**
* Retrieve an attribute's value from a CAS authentication token.
* @param authToken CAS authentication token
* @param attributeName attribute name
* @return attribute value or null if not found
*/
@SuppressWarnings("rawtypes")
protected String getAttributeValue(CasAuthenticationToken authToken, String attributeName) {
if (authToken != null && authToken.getAssertion() != null &&
authToken.getAssertion().getPrincipal() != null &&
authToken.getAssertion().getPrincipal().getAttributes() != null &&
attributeName != null) {

Map attributes = authToken.getAssertion().getPrincipal().getAttributes();
if (StringUtils.hasText(attributeName)) {
Map<String, Object> attributes = authToken.getAssertion().getPrincipal().getAttributes();
Object attribute = attributes.get(attributeName);
if (attribute != null) {
if (attribute instanceof Collection) {
return ((Collection) attribute).iterator().next().toString();
return ((Collection<?>) attribute).iterator().next().toString();
} else {
return attribute.toString();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div>
Attribute holding the user's email address.
Attribute holding the user's email address. Can also be a template string containing
placeholders such as {{attributeName}} (e.g. '{{uid}}@example.com').
</div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div>
Attribute holding the user's full name.
Attribute holding the user's full name. Can also be a template string containing
placeholders such as {{attributeName}} (e.g. '{{givenName}} {{sn}}').
</div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div>
Attribute holding the user's email address.
Attribute holding the user's email address. Can also be a template string containing
placeholders such as {{attributeName}} (e.g. '{{uid}}@example.com').
</div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div>
Attribute holding the user's full name.
Attribute holding the user's full name. Can also be a template string containing
placeholders such as {{attributeName}} (e.g. '{{givenName}} {{sn}}').
</div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div>
Attribute holding the user's email address.
Attribute holding the user's email address. Can also be a template string containing
placeholders such as {{attributeName}} (e.g. '{{uid}}@example.com').
</div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div>
Attribute holding the user's full name.
Attribute holding the user's full name. Can also be a template string containing
placeholders such as {{attributeName}} (e.g. '{{givenName}} {{sn}}').
</div>

0 comments on commit 53bbf02

Please sign in to comment.