Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eclipse Foundation
IT
APIs
git-eca-rest-api
Commits
f02f2295
Commit
f02f2295
authored
Jun 02, 2021
by
Martin Lowe
🇨🇦
Committed by
Martin Lowe
Jun 03, 2021
Browse files
Add checks for no-reply email address ratification
parent
4e064e48
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/eclipsefoundation/git/eca/api/AccountsAPI.java
View file @
f02f2295
...
@@ -14,6 +14,7 @@ import java.util.List;
...
@@ -14,6 +14,7 @@ import java.util.List;
import
javax.ws.rs.GET
;
import
javax.ws.rs.GET
;
import
javax.ws.rs.HeaderParam
;
import
javax.ws.rs.HeaderParam
;
import
javax.ws.rs.Path
;
import
javax.ws.rs.Path
;
import
javax.ws.rs.PathParam
;
import
javax.ws.rs.Produces
;
import
javax.ws.rs.Produces
;
import
javax.ws.rs.QueryParam
;
import
javax.ws.rs.QueryParam
;
...
@@ -29,7 +30,6 @@ import org.eclipsefoundation.git.eca.model.EclipseUser;
...
@@ -29,7 +30,6 @@ import org.eclipsefoundation.git.eca.model.EclipseUser;
* @author Martin Lowe
* @author Martin Lowe
*
*
*/
*/
@Path
(
"/account"
)
@RegisterRestClient
@RegisterRestClient
public
interface
AccountsAPI
{
public
interface
AccountsAPI
{
...
@@ -42,8 +42,22 @@ public interface AccountsAPI {
...
@@ -42,8 +42,22 @@ public interface AccountsAPI {
* @return all matching eclipse accounts
* @return all matching eclipse accounts
*/
*/
@GET
@GET
@Path
(
"/profile"
)
@Path
(
"/
account/
profile"
)
@Produces
(
"application/json"
)
@Produces
(
"application/json"
)
List
<
EclipseUser
>
getUsers
(
@HeaderParam
(
"Authorization"
)
String
authBearer
,
@QueryParam
(
"uid"
)
String
id
,
List
<
EclipseUser
>
getUsers
(
@HeaderParam
(
"Authorization"
)
String
authBearer
,
@QueryParam
(
"uid"
)
String
id
,
@QueryParam
(
"name"
)
String
name
,
@QueryParam
(
"mail"
)
String
mail
);
@QueryParam
(
"name"
)
String
name
,
@QueryParam
(
"mail"
)
String
mail
);
/**
* Retrieves user objects that matches the given Github username.
*
* @param authBearer authorization header value for validating call
* @param uname username of the Github account to retrieve Eclipse Account
* for
* @return the matching Eclipse account or null
*/
@GET
@Path
(
"/github/profile/{uname}"
)
@Produces
(
"application/json"
)
EclipseUser
getUserByGithubUname
(
@HeaderParam
(
"Authorization"
)
String
authBearer
,
@PathParam
(
"uname"
)
String
uname
);
}
}
src/main/java/org/eclipsefoundation/git/eca/resource/ValidationResource.java
View file @
f02f2295
...
@@ -12,8 +12,10 @@ import java.net.MalformedURLException;
...
@@ -12,8 +12,10 @@ import java.net.MalformedURLException;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.Optional
;
import
java.util.regex.Pattern
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
javax.annotation.PostConstruct
;
import
javax.inject.Inject
;
import
javax.inject.Inject
;
import
javax.ws.rs.Consumes
;
import
javax.ws.rs.Consumes
;
import
javax.ws.rs.POST
;
import
javax.ws.rs.POST
;
...
@@ -60,6 +62,9 @@ public class ValidationResource {
...
@@ -60,6 +62,9 @@ public class ValidationResource {
@Inject
@Inject
@ConfigProperty
(
name
=
"eclipse.mail.allowlist"
)
@ConfigProperty
(
name
=
"eclipse.mail.allowlist"
)
List
<
String
>
allowListUsers
;
List
<
String
>
allowListUsers
;
@Inject
@ConfigProperty
(
name
=
"eclipse.noreply.email-patterns"
)
List
<
String
>
emailPatterns
;
// eclipse API rest client interfaces
// eclipse API rest client interfaces
@Inject
@RestClient
AccountsAPI
accounts
;
@Inject
@RestClient
AccountsAPI
accounts
;
...
@@ -70,6 +75,15 @@ public class ValidationResource {
...
@@ -70,6 +75,15 @@ public class ValidationResource {
@Inject
CachingService
cache
;
@Inject
CachingService
cache
;
@Inject
ProjectsService
projects
;
@Inject
ProjectsService
projects
;
// rendered list of regex values
List
<
Pattern
>
patterns
;
@PostConstruct
void
init
()
{
// compile the patterns once per object to save processing time
this
.
patterns
=
emailPatterns
.
stream
().
map
(
Pattern:
:
compile
).
collect
(
Collectors
.
toList
());
}
/**
/**
* Consuming a JSON request, this method will validate all passed commits, using the repo URL and
* Consuming a JSON request, this method will validate all passed commits, using the repo URL and
* the repository provider. These commits will be validated to ensure that all users are covered
* the repository provider. These commits will be validated to ensure that all users are covered
...
@@ -392,17 +406,13 @@ public class ValidationResource {
...
@@ -392,17 +406,13 @@ public class ValidationResource {
// get the Eclipse account for the user
// get the Eclipse account for the user
try
{
try
{
// use cache to avoid asking for the same user repeatedly on repeated requests
// use cache to avoid asking for the same user repeatedly on repeated requests
@SuppressWarnings
(
"unchecked"
)
Optional
<
EclipseUser
>
foundUser
=
Optional
<
List
<
EclipseUser
>>
users
=
cache
.
get
(
"user|"
+
user
.
getMail
(),
()
->
retrieveUser
(
user
),
EclipseUser
.
class
);
cache
.
get
(
if
(!
foundUser
.
isPresent
())
{
"user|"
+
user
.
getMail
(),
LOGGER
.
warn
(
"No users found for mail '{}'"
,
user
.
getMail
());
()
->
accounts
.
getUsers
(
"Bearer "
+
oauth
.
getToken
(),
null
,
null
,
user
.
getMail
()),
(
Class
<
List
<
EclipseUser
>>)
(
Object
)
List
.
class
);
if
(!
users
.
isPresent
()
||
users
.
get
().
isEmpty
())
{
LOGGER
.
error
(
"No users found for mail '{}'"
,
user
.
getMail
());
return
null
;
return
null
;
}
}
return
u
ser
s
.
get
()
.
get
(
0
)
;
return
foundU
ser
.
get
();
}
catch
(
WebApplicationException
e
)
{
}
catch
(
WebApplicationException
e
)
{
Response
r
=
e
.
getResponse
();
Response
r
=
e
.
getResponse
();
if
(
r
!=
null
&&
r
.
getStatus
()
==
404
)
{
if
(
r
!=
null
&&
r
.
getStatus
()
==
404
)
{
...
@@ -414,6 +424,60 @@ public class ValidationResource {
...
@@ -414,6 +424,60 @@ public class ValidationResource {
return
null
;
return
null
;
}
}
/**
* Checks for standard and noreply email address matches for a Git user and converts to a
* Eclipse Foundation account object.
*
* @param user the user to attempt account retrieval for.
* @return the user account if found by mail, or null if none found.
*/
private
EclipseUser
retrieveUser
(
GitUser
user
)
{
// standard user check (returns best match)
LOGGER
.
debug
(
"Checking user with mail {}"
,
user
.
getMail
());
try
{
List
<
EclipseUser
>
users
=
accounts
.
getUsers
(
"Bearer "
+
oauth
.
getToken
(),
null
,
null
,
user
.
getMail
());
if
(
users
!=
null
)
{
return
users
.
get
(
0
);
}
}
catch
(
WebApplicationException
e
)
{
LOGGER
.
warn
(
"Could not find user account with mail '{}'"
,
user
.
getMail
());
}
// return results for no-reply
return
checkForNoReplyUser
(
user
);
}
/**
* Checks git user for no-reply address, and attempts to ratify user through reverse lookup in API service.
* Currently, this service only recognizes Github no-reply addresses as they have a route to be mapped.
*
* @param user the Git user account to check for no-reply mail address
* @return the Eclipse user if email address is detected no reply and one can be mapped, otherwise null
*/
private
EclipseUser
checkForNoReplyUser
(
GitUser
user
)
{
LOGGER
.
debug
(
"Checking user with mail {} for no-reply"
,
user
.
getMail
());
boolean
isNoReply
=
patterns
.
stream
().
anyMatch
(
pattern
->
pattern
.
matcher
(
user
.
getMail
().
trim
()).
find
());
if
(
isNoReply
)
{
String
[]
nameParts
=
user
.
getMail
().
split
(
"[\\+@]"
);
// check if the userName part is not null/empty in the email address
if
(
nameParts
[
0
]
!=
null
&&
nameParts
[
0
].
trim
().
length
()
>
0
)
{
// grab the portion before the first + symbol, which tends to indicate a user account
String
uname
=
nameParts
[
0
].
trim
();
LOGGER
.
debug
(
"User with mail {} detected as noreply account, checking services for username match on '{}'"
,
user
.
getMail
(),
uname
);
// check github for no-reply (only allowed noreply currently)
if
(
user
.
getMail
().
contains
(
"noreply.github.com"
))
{
try
{
// check for Github no reply + return as its the last shot
return
accounts
.
getUserByGithubUname
(
"Bearer "
+
oauth
.
getToken
(),
uname
);
}
catch
(
WebApplicationException
e
)
{
LOGGER
.
warn
(
"No match for '{}' in Github"
,
uname
);
}
}
}
}
return
null
;
}
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
private
List
<
BotUser
>
getBots
()
{
private
List
<
BotUser
>
getBots
()
{
Optional
<
List
<
BotUser
>>
allBots
=
Optional
<
List
<
BotUser
>>
allBots
=
...
...
src/main/resources/application.properties
View file @
f02f2295
...
@@ -2,6 +2,8 @@ org.eclipsefoundation.git.eca.api.AccountsAPI/mp-rest/url=https://api.eclipse.or
...
@@ -2,6 +2,8 @@ org.eclipsefoundation.git.eca.api.AccountsAPI/mp-rest/url=https://api.eclipse.or
org.eclipsefoundation.git.eca.api.ProjectsAPI/mp-rest/
url
=
https://projects.eclipse.org
org.eclipsefoundation.git.eca.api.ProjectsAPI/mp-rest/
url
=
https://projects.eclipse.org
org.eclipsefoundation.git.eca.api.BotsAPI/mp-rest/
url
=
https://api.eclipse.org
org.eclipsefoundation.git.eca.api.BotsAPI/mp-rest/
url
=
https://api.eclipse.org
eclipse.noreply.email-patterns
=
@users.noreply.github.com
\$
## Expect to be mounted to '/git' to match current URL spec
## Expect to be mounted to '/git' to match current URL spec
quarkus.http.root-path
=
/git
quarkus.http.root-path
=
/git
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment