return super.authenticate(username, password);\r
}\r
\r
- String urlText = this.settings.getString(Keys.realm.redmine.url, "");\r
- if (!urlText.endsWith("/")) {\r
- urlText.concat("/");\r
+ String jsonString = null;\r
+ try {\r
+ // first attempt by username/password\r
+ jsonString = getCurrentUserAsJson(username, password);\r
+ } catch (Exception e1) {\r
+ logger.warn("Failed to authenticate via username/password against Redmine");\r
+ try {\r
+ // second attempt is by apikey\r
+ jsonString = getCurrentUserAsJson(null, password);\r
+ username = null;\r
+ } catch (Exception e2) {\r
+ logger.error("Failed to authenticate via apikey against Redmine", e2);\r
+ return null;\r
+ }\r
}\r
- String apiKey = String.valueOf(password);\r
-\r
+ \r
+ RedmineCurrent current = null;\r
try {\r
- String jsonString = getCurrentUserAsJson(urlText, apiKey);\r
-\r
- RedmineCurrent current = new Gson().fromJson(jsonString, RedmineCurrent.class);\r
- String login = current.user.login;\r
-\r
- boolean canAdmin = true;\r
- if (StringUtils.isEmpty(login)) {\r
- login = current.user.mail;\r
- \r
- // non admin user can not get login name\r
- // TODO review this assumption, if it is true, it is undocumented\r
- canAdmin = false;\r
- }\r
- \r
- UserModel user = getUserModel(login);\r
- if (user == null) // create user object for new authenticated user\r
- user = new UserModel(login);\r
- \r
- // create a user cookie\r
- if (StringUtils.isEmpty(user.cookie) && !ArrayUtils.isEmpty(password)) {\r
- user.cookie = StringUtils.getSHA1(user.username + new String(password));\r
- }\r
- \r
- // update user attributes from Redmine\r
- user.accountType = getAccountType();\r
- user.canAdmin = canAdmin;\r
- user.displayName = current.user.firstname + " " + current.user.lastname;\r
- user.emailAddress = current.user.mail;\r
- user.password = ExternalAccount;\r
- \r
- // TODO Redmine group mapping for administration & teams\r
- // http://www.redmine.org/projects/redmine/wiki/Rest_Users\r
- \r
- // push the changes to the backing user service\r
- super.updateUserModel(user);\r
- \r
- return user;\r
- } catch (IOException e) {\r
- logger.error("authenticate", e);\r
+ current = new Gson().fromJson(jsonString, RedmineCurrent.class);\r
+ } catch (Exception e) {\r
+ logger.error("Failed to deserialize Redmine json response: " + jsonString, e);\r
+ return null;\r
+ }\r
+\r
+ if (StringUtils.isEmpty(username)) {\r
+ // if the username has been reset because of apikey authentication\r
+ // then use the email address of the user. this is the original\r
+ // behavior as contributed by github/mallowlabs\r
+ username = current.user.mail;\r
+ }\r
+\r
+ UserModel user = getUserModel(username);\r
+ if (user == null) // create user object for new authenticated user\r
+ user = new UserModel(username.toLowerCase());\r
+\r
+ // create a user cookie\r
+ if (StringUtils.isEmpty(user.cookie) && !ArrayUtils.isEmpty(password)) {\r
+ user.cookie = StringUtils.getSHA1(user.username + new String(password));\r
+ }\r
+\r
+ // update user attributes from Redmine\r
+ user.accountType = getAccountType();\r
+ user.displayName = current.user.firstname + " " + current.user.lastname;\r
+ user.emailAddress = current.user.mail;\r
+ user.password = ExternalAccount;\r
+ if (!StringUtils.isEmpty(current.user.login)) {\r
+ // only admin users can get login name\r
+ // evidently this is an undocumented behavior of Redmine\r
+ user.canAdmin = true;\r
}\r
- return null;\r
+\r
+ // TODO consider Redmine group mapping for team membership\r
+ // http://www.redmine.org/projects/redmine/wiki/Rest_Users\r
+\r
+ // push the changes to the backing user service\r
+ super.updateUserModel(user);\r
+\r
+ return user;\r
}\r
\r
- private String getCurrentUserAsJson(String url, String apiKey) throws IOException {\r
+ private String getCurrentUserAsJson(String username, char [] password) throws IOException {\r
if (testingJson != null) { // for testing\r
return testingJson;\r
}\r
\r
- String apiUrl = url + "users/current.json?key=" + apiKey;\r
- HttpURLConnection http = (HttpURLConnection) ConnectionUtils.openConnection(apiUrl, null, null);\r
+ String url = this.settings.getString(Keys.realm.redmine.url, "");\r
+ if (!url.endsWith("/")) {\r
+ url.concat("/");\r
+ }\r
+ HttpURLConnection http;\r
+ if (username == null) {\r
+ // apikey authentication\r
+ String apiKey = String.valueOf(password);\r
+ String apiUrl = url + "users/current.json?key=" + apiKey;\r
+ http = (HttpURLConnection) ConnectionUtils.openConnection(apiUrl, null, null);\r
+ } else {\r
+ // username/password BASIC authentication\r
+ String apiUrl = url + "users/current.json";\r
+ http = (HttpURLConnection) ConnectionUtils.openConnection(apiUrl, username, password);\r
+ }\r
http.setRequestMethod("GET");\r
http.connect();\r
InputStreamReader reader = new InputStreamReader(http.getInputStream());\r
return IOUtils.toString(reader);\r
}\r
-\r
+ \r
/**\r
* set json response. do NOT invoke from production code.\r
* @param json json\r
RedmineUserService redmineUserService = new RedmineUserService();\r
redmineUserService.setup(new MemorySettings(new HashMap<String, Object>()));\r
redmineUserService.setTestingCurrentUserAsJson(JSON);\r
- UserModel userModel = redmineUserService.authenticate("RedmineUserId", "RedmineAPIKey".toCharArray());\r
- assertThat(userModel.getName(), is("redmineuserid"));\r
+ UserModel userModel = redmineUserService.authenticate("RedmineAdminId", "RedmineAPIKey".toCharArray());\r
+ assertThat(userModel.getName(), is("redmineadminid"));\r
assertThat(userModel.getDisplayName(), is("baz foo"));\r
assertThat(userModel.emailAddress, is("baz@example.com"));\r
assertNotNull(userModel.cookie);\r
redmineUserService.setup(new MemorySettings(new HashMap<String, Object>()));\r
redmineUserService.setTestingCurrentUserAsJson(NOT_ADMIN_JSON);\r
UserModel userModel = redmineUserService.authenticate("RedmineUserId", "RedmineAPIKey".toCharArray());\r
- assertThat(userModel.getName(), is("baz@example.com"));\r
+ assertThat(userModel.getName(), is("redmineuserid"));\r
assertThat(userModel.getDisplayName(), is("baz foo"));\r
assertThat(userModel.emailAddress, is("baz@example.com"));\r
assertNotNull(userModel.cookie);\r