Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
IA2
GMS
Commits
c67052b0
Commit
c67052b0
authored
Aug 21, 2020
by
Sonia Zorba
Browse files
Added endpoint for retrieving member email addresses; CLI improvements
parent
909daf60
Changes
16
Hide whitespace changes
Inline
Side-by-side
gms-client/gms-cli/pom.xml
View file @
c67052b0
...
...
@@ -22,6 +22,7 @@
</dependency>
</dependencies>
<build>
<finalName>
gms-cli
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
...
...
gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java
View file @
c67052b0
package
it.inaf.ia2.gms.cli
;
import
it.inaf.ia2.gms.client.GmsClient
;
import
it.inaf.ia2.gms.client.GmsClientBuilder
;
import
it.inaf.ia2.gms.client.model.Permission
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.UncheckedIOException
;
import
java.util.List
;
import
java.util.Properties
;
public
class
CLI
{
private
final
GmsClient
client
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
CLI
().
run
(
args
);
new
CLI
(
args
).
run
();
}
private
final
String
args
[];
private
int
argIndex
;
private
String
gmsBaseUrl
;
private
String
rapBaseUrl
;
private
String
clientId
;
private
String
clientSecret
;
private
String
token
;
private
GmsClient
client
;
private
CLI
(
String
...
args
)
{
this
.
args
=
args
;
}
private
void
run
()
throws
Exception
{
if
(
args
.
length
<
2
)
{
displayUsage
();
}
boolean
commandParsed
=
false
;
while
(
argIndex
<
args
.
length
&&
!
commandParsed
)
{
switch
(
args
[
argIndex
])
{
case
"--config-file"
:
loadConfigFromFile
(
new
File
(
getNextArg
()));
break
;
case
"--token-file"
:
loadTokenFromFile
(
new
File
(
getNextArg
()));
break
;
case
"--gms-url"
:
gmsBaseUrl
=
getNextArg
();
break
;
case
"--rap-url"
:
rapBaseUrl
=
getNextArg
();
break
;
case
"--client-id"
:
clientId
=
getNextArg
();
break
;
case
"--client-secret"
:
clientSecret
=
getNextArg
();
break
;
default
:
verifyConfigLoaded
();
createClient
();
parseCommand
();
commandParsed
=
true
;
break
;
}
argIndex
++;
}
}
private
String
getNextArg
()
{
if
(
argIndex
+
1
==
args
.
length
)
{
System
.
err
.
println
(
"Missing value for option "
+
args
[
argIndex
]);
System
.
exit
(
1
);
}
return
args
[++
argIndex
];
}
private
CLI
()
throws
IOException
{
private
void
verifyConfigLoaded
()
{
if
(
gmsBaseUrl
==
null
)
{
// Attempt reading gms.properties in current directory
loadConfigFromFile
(
new
File
(
"gms.properties"
));
}
if
(
clientId
==
null
&&
token
==
null
)
{
// Attempt loading token.txt in current directory
loadTokenFromFile
(
new
File
(
"token.txt"
));
}
if
(
token
!=
null
&&
(
clientSecret
==
null
||
rapBaseUrl
==
null
))
{
System
.
err
.
println
(
"Client secret and RAP base URL not configured"
);
System
.
exit
(
1
);
}
}
private
void
createClient
()
{
GmsClientBuilder
clientBuilder
=
new
GmsClientBuilder
()
.
setGmsBaseUrl
(
gmsBaseUrl
);
if
(
token
!=
null
)
{
client
=
clientBuilder
.
build
();
client
.
setAccessToken
(
token
);
}
else
{
client
=
clientBuilder
.
setClientId
(
clientId
)
.
setClientSecret
(
clientSecret
)
.
setRapBaseUrl
(
rapBaseUrl
)
.
build
();
}
}
private
void
loadConfigFromFile
(
File
config
)
{
File
config
=
new
File
(
"gms.properties"
);
if
(!
config
.
exists
())
{
System
.
err
.
println
(
"
Unable to find the file gms.properties
"
);
System
.
err
.
println
(
"
Config file "
+
config
.
getAbsolutePath
()
+
" doesn't exist
"
);
System
.
exit
(
1
);
}
Properties
properties
=
new
Properties
();
try
(
InputStream
in
=
new
FileInputStream
(
config
))
{
properties
.
load
(
in
);
}
catch
(
IOException
ex
)
{
throw
new
UncheckedIOException
(
ex
);
}
String
b
aseUrl
=
(
String
)
properties
.
get
(
"base
_url"
);
if
(
b
aseUrl
==
null
)
{
System
.
err
.
println
(
"Missing
base
_url in gms.properties"
);
gmsB
aseUrl
=
properties
.
get
Property
(
"gms
_url"
);
if
(
gmsB
aseUrl
==
null
)
{
System
.
err
.
println
(
"Missing
gms
_url in gms.properties"
);
System
.
exit
(
1
);
}
rapBaseUrl
=
properties
.
getProperty
(
"rap_url"
);
clientId
=
properties
.
getProperty
(
"client_id"
);
clientSecret
=
properties
.
getProperty
(
"client_secret"
);
}
private
void
loadTokenFromFile
(
File
tokenFile
)
{
String
token
=
(
String
)
properties
.
get
(
"token"
);
if
(
token
==
null
)
{
System
.
err
.
println
(
"Missing token in gms.properties"
);
if
(!
tokenFile
.
exists
())
{
System
.
err
.
println
(
"Token file "
+
tokenFile
.
getAbsolutePath
()
+
" doesn't exist"
);
System
.
exit
(
1
);
}
client
=
new
GmsClient
(
baseUrl
).
setAccessToken
(
token
);
try
(
InputStream
in
=
new
FileInputStream
(
tokenFile
))
{
java
.
util
.
Scanner
s
=
new
java
.
util
.
Scanner
(
in
).
useDelimiter
(
"\\A"
);
token
=
s
.
next
().
trim
();
}
catch
(
IOException
ex
)
{
throw
new
UncheckedIOException
(
ex
);
}
}
public
void
run
(
String
...
args
)
throws
Exception
{
if
(
args
.
length
<
2
)
{
displayUsage
();
}
private
void
parseCommand
()
{
switch
(
args
[
0
])
{
switch
(
args
[
argIndex
])
{
case
"create-group"
:
boolean
leaf
=
false
;
if
(
args
.
length
>
1
)
{
leaf
=
Boolean
.
parseBoolean
(
args
[
2
]);
if
(
argIndex
+
2
<
args
.
length
)
{
leaf
=
Boolean
.
parseBoolean
(
args
[
argIndex
+
2
]);
}
client
.
createGroup
(
args
[
1
],
leaf
);
client
.
createGroup
(
args
[
argIndex
+
1
],
leaf
);
System
.
out
.
println
(
"Group created"
);
break
;
case
"delete-group"
:
client
.
deleteGroup
(
args
[
1
]);
client
.
deleteGroup
(
args
[
argIndex
+
1
]);
System
.
out
.
println
(
"Group deleted"
);
break
;
case
"add-member"
:
if
(
args
.
length
<
3
)
{
if
(
argIndex
+
2
>=
args
.
length
)
{
displayUsage
();
}
client
.
addMember
(
args
[
1
],
args
[
2
]);
client
.
addMember
(
args
[
argIndex
+
1
],
args
[
argIndex
+
2
]);
System
.
out
.
println
(
"Member added"
);
break
;
case
"remove-member"
:
if
(
args
.
length
<
3
)
{
if
(
argIndex
+
2
>=
args
.
length
)
{
displayUsage
();
}
client
.
removeMember
(
args
[
1
],
args
[
2
]);
client
.
removeMember
(
args
[
argIndex
+
1
],
args
[
argIndex
+
2
]);
System
.
out
.
println
(
"Member removed"
);
break
;
case
"add-permission"
:
if
(
args
.
length
<
4
)
{
if
(
argIndex
+
3
>=
args
.
length
)
{
displayUsage
();
}
client
.
addPermission
(
args
[
1
],
args
[
2
],
Permission
.
valueOf
(
args
[
3
]));
client
.
addPermission
(
args
[
argIndex
+
1
],
args
[
argIndex
+
2
],
Permission
.
valueOf
(
args
[
argIndex
+
3
]));
System
.
out
.
println
(
"Permission added"
);
break
;
case
"delete-permission"
:
if
(
args
.
length
<
4
)
{
if
(
argIndex
+
2
>=
args
.
length
)
{
displayUsage
();
}
client
.
removePermission
(
args
[
1
],
args
[
2
]);
client
.
removePermission
(
args
[
argIndex
+
1
],
args
[
argIndex
+
2
]);
System
.
out
.
println
(
"Permission removed"
);
break
;
case
"get-member-email-addresses"
:
Permission
permission
=
null
;
if
(
argIndex
+
2
<
args
.
length
)
{
permission
=
Permission
.
valueOf
(
args
[
argIndex
+
2
]);
}
List
<
String
>
addresses
=
client
.
getMemberEmailAddresses
(
args
[
argIndex
+
1
],
permission
);
for
(
String
address
:
addresses
)
{
System
.
out
.
println
(
address
);
}
break
;
default
:
displayUsage
();
break
;
...
...
@@ -97,13 +209,20 @@ public class CLI {
}
private
void
displayUsage
()
{
System
.
out
.
println
(
"java -jar gms-client.jar\n"
+
" create-group <name1.name2.name3> <leaf>\n"
System
.
out
.
println
(
"gms-client\n"
+
" [--config-file <file>]\n"
+
" [--token-file <file>]\n"
+
" [--gms-url <url>]\n"
+
" [--rap-url <url>]\n"
+
" [--client-id <id>]\n"
+
" [--client-secret <secret>]\n"
+
" create-group <name1.name2.name3> [<leaf>]\n"
+
" delete-group <name1.name2.name3>\n"
+
" add-member <name1.name2.name3> <user_id>\n"
+
" remove-member <name1.name2.name3> <user_id>\n"
+
" add-permission <name1.name2.name3> <user_id> <permission>\n"
+
" delete-permission <name1.name2.name3> <user_id>"
);
+
" delete-permission <name1.name2.name3> <user_id>\n"
+
" get-member-email-addresses <name1.name2.name3> [<permission>]"
);
System
.
exit
(
0
);
}
}
gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java
View file @
c67052b0
...
...
@@ -7,6 +7,7 @@ import it.inaf.ia2.gms.client.call.AddPermissionCall;
import
it.inaf.ia2.gms.client.call.CreateGroupCall
;
import
it.inaf.ia2.gms.client.call.DeleteGroupCall
;
import
it.inaf.ia2.gms.client.call.GetGroupPermissionsCall
;
import
it.inaf.ia2.gms.client.call.GetMemberEmailAddresses
;
import
it.inaf.ia2.gms.client.call.GetUserGroupsCall
;
import
it.inaf.ia2.gms.client.call.GetUserPermissionsCall
;
import
it.inaf.ia2.gms.client.call.ListGroupsCall
;
...
...
@@ -20,15 +21,10 @@ import java.util.Map;
public
class
GmsClient
{
HttpClientWrapper
httpClientWrapper
;
private
final
HttpClientWrapper
httpClientWrapper
;
public
GmsClient
(
String
baseUrl
)
{
if
(!
baseUrl
.
endsWith
(
"/"
))
{
baseUrl
+=
"/"
;
}
httpClientWrapper
=
new
HttpClientWrapper
(
baseUrl
);
GmsClient
(
HttpClientWrapper
httpClientWrapper
)
{
this
.
httpClientWrapper
=
httpClientWrapper
;
}
public
GmsClient
setAccessToken
(
String
accessToken
)
{
...
...
@@ -83,4 +79,8 @@ public class GmsClient {
public
void
addInvitedRegistration
(
String
token
,
String
email
,
Map
<
String
,
Permission
>
groupsPermissions
)
{
new
AddInvitedRegistrationCall
(
httpClientWrapper
).
addInvitedRegistration
(
token
,
email
,
groupsPermissions
);
}
public
List
<
String
>
getMemberEmailAddresses
(
String
groupId
,
Permission
permission
)
{
return
new
GetMemberEmailAddresses
(
httpClientWrapper
).
getMemberEmailAddresses
(
groupId
,
permission
);
}
}
gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClientBuilder.java
0 → 100644
View file @
c67052b0
package
it.inaf.ia2.gms.client
;
import
it.inaf.ia2.gms.client.call.HttpClientWrapper
;
public
class
GmsClientBuilder
{
private
String
gmsBaseUrl
;
private
String
rapBaseUrl
;
private
String
clientId
;
private
String
clientSecret
;
public
GmsClientBuilder
setGmsBaseUrl
(
String
gmsBaseUrl
)
{
this
.
gmsBaseUrl
=
gmsBaseUrl
;
return
this
;
}
public
GmsClientBuilder
setRapBaseUrl
(
String
rapBaseUrl
)
{
this
.
rapBaseUrl
=
rapBaseUrl
;
return
this
;
}
public
GmsClientBuilder
setClientId
(
String
clientId
)
{
this
.
clientId
=
clientId
;
return
this
;
}
public
GmsClientBuilder
setClientSecret
(
String
clientSecret
)
{
this
.
clientSecret
=
clientSecret
;
return
this
;
}
public
GmsClient
build
()
{
HttpClientWrapper
clientWrapper
=
new
HttpClientWrapper
(
gmsBaseUrl
);
if
(
rapBaseUrl
!=
null
&&
clientId
!=
null
&&
clientSecret
!=
null
)
{
clientWrapper
.
setRapBaseUrl
(
rapBaseUrl
)
.
setClientId
(
clientId
).
setClientSecret
(
clientSecret
);
}
return
new
GmsClient
(
clientWrapper
);
}
}
gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/BaseGmsCall.java
View file @
c67052b0
...
...
@@ -27,13 +27,13 @@ public abstract class BaseGmsCall {
return
clientWrapper
.
newHttpRequest
(
endpoint
);
}
protected
void
logServerError
(
HttpRequest
request
,
HttpResponse
<
String
>
response
)
{
protected
static
void
logServerError
(
HttpRequest
request
,
HttpResponse
<
String
>
response
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
()
->
"Error while reading "
+
request
.
uri
()
+
"\nServer response status code is "
+
response
.
statusCode
()
+
"\n
A
Server response text is "
+
response
.
body
());
+
"\nServer response text is "
+
response
.
body
());
}
protected
void
logServerErrorInputStream
(
HttpRequest
request
,
HttpResponse
<
InputStream
>
response
)
{
protected
static
void
logServerErrorInputStream
(
HttpRequest
request
,
HttpResponse
<
InputStream
>
response
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
()
->
{
Scanner
s
=
new
Scanner
(
response
.
body
()).
useDelimiter
(
"\\A"
);
String
responseBody
=
s
.
hasNext
()
?
s
.
next
()
:
""
;
...
...
gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/GetMemberEmailAddresses.java
0 → 100644
View file @
c67052b0
package
it.inaf.ia2.gms.client.call
;
import
it.inaf.ia2.gms.client.model.Permission
;
import
java.net.http.HttpRequest
;
import
java.net.http.HttpResponse
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Scanner
;
public
class
GetMemberEmailAddresses
extends
BaseGmsCall
{
public
GetMemberEmailAddresses
(
HttpClientWrapper
clientWrapper
)
{
super
(
clientWrapper
);
}
public
List
<
String
>
getMemberEmailAddresses
(
String
group
,
Permission
permission
)
{
List
<
String
>
emailAddresses
=
new
ArrayList
<>();
String
endpoint
=
"email/"
+
group
;
if
(
permission
!=
null
)
{
endpoint
+=
"?permission="
+
permission
;
}
HttpRequest
request
=
newHttpRequest
(
endpoint
)
.
header
(
"Accept"
,
"text/plain"
)
.
GET
()
.
build
();
return
getClient
().
sendAsync
(
request
,
HttpResponse
.
BodyHandlers
.
ofInputStream
())
.
thenApply
(
response
->
{
if
(
response
.
statusCode
()
==
200
)
{
return
response
.
body
();
}
logServerErrorInputStream
(
request
,
response
);
throw
new
IllegalStateException
(
"Unable to retrieve groups"
);
})
.
thenApply
(
inputStream
->
{
try
(
Scanner
scan
=
new
Scanner
(
inputStream
))
{
while
(
scan
.
hasNextLine
())
{
String
line
=
scan
.
nextLine
();
if
(!
line
.
isEmpty
())
{
emailAddresses
.
add
(
line
);
}
}
}
return
emailAddresses
;
}).
join
();
}
}
gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/HttpClientWrapper.java
View file @
c67052b0
...
...
@@ -4,12 +4,20 @@ import java.net.URI;
import
java.net.http.HttpClient
;
import
java.net.http.HttpRequest
;
import
java.net.http.HttpRequest.Builder
;
import
java.net.http.HttpResponse
;
import
java.util.Base64
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
public
class
HttpClientWrapper
{
private
final
String
baseGmsUri
;
private
final
HttpClient
client
;
private
String
rapBaseUrl
;
private
String
clientId
;
private
String
clientSecret
;
private
String
accessToken
;
public
HttpClientWrapper
(
String
baseGmsUri
)
{
...
...
@@ -29,12 +37,68 @@ public class HttpClientWrapper {
return
this
;
}
public
HttpClientWrapper
setRapBaseUrl
(
String
rapBaseUrl
)
{
if
(!
rapBaseUrl
.
endsWith
(
"/"
))
{
rapBaseUrl
+=
"/"
;
}
this
.
rapBaseUrl
=
rapBaseUrl
;
return
this
;
}
public
HttpClientWrapper
setClientId
(
String
clientId
)
{
this
.
clientId
=
clientId
;
return
this
;
}
public
HttpClientWrapper
setClientSecret
(
String
clientSecret
)
{
this
.
clientSecret
=
clientSecret
;
return
this
;
}
Builder
newHttpRequest
(
String
endpoint
)
{
if
(
accessToken
==
null
)
{
accessToken
=
getAccessTokenFromClientCredentials
();
}
return
HttpRequest
.
newBuilder
()
.
uri
(
URI
.
create
(
baseGmsUri
+
endpoint
))
.
header
(
"Authorization"
,
"Bearer "
+
accessToken
);
}
private
String
getAccessTokenFromClientCredentials
()
{
if
(
rapBaseUrl
==
null
||
clientId
==
null
||
clientSecret
==
null
)
{
throw
new
IllegalStateException
(
"Access token is null and client credentials are not configured"
);
}
String
basicAuthHeader
=
clientId
+
":"
+
clientSecret
;
HttpRequest
tokenRequest
=
HttpRequest
.
newBuilder
()
.
uri
(
URI
.
create
(
rapBaseUrl
+
"auth/oauth2/token"
))
.
header
(
"Authorization"
,
"Basic "
+
Base64
.
getEncoder
().
encodeToString
(
basicAuthHeader
.
getBytes
()))
.
header
(
"Accept"
,
"application/json"
)
.
header
(
"Content-Type"
,
"application/x-www-form-urlencoded"
)
.
POST
(
HttpRequest
.
BodyPublishers
.
ofString
(
"grant_type=client_credentials"
))
.
build
();
return
client
.
sendAsync
(
tokenRequest
,
HttpResponse
.
BodyHandlers
.
ofString
())
.
thenApply
(
response
->
{
if
(
response
.
statusCode
()
==
200
)
{
return
getAccessTokenFromResponse
(
response
.
body
());
}
BaseGmsCall
.
logServerError
(
tokenRequest
,
response
);
throw
new
IllegalStateException
(
"Unable to retrieve access token"
);
}).
join
();
}
protected
String
getAccessTokenFromResponse
(
String
body
)
{
Pattern
codePattern
=
Pattern
.
compile
(
".*\"access_token\":\\s*\"([^\"]+).*"
);
Matcher
matcher
=
codePattern
.
matcher
(
body
);
if
(
matcher
.
find
())
{
return
matcher
.
group
(
1
);
}
throw
new
IllegalStateException
(
"Unable to extract access token from body"
);
}
HttpClient
getClient
()
{
return
client
;
}
...
...
gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/GmsClientTest.java
View file @
c67052b0
...
...
@@ -7,7 +7,6 @@ import java.io.ByteArrayInputStream;
import
java.io.InputStream
;
import
java.net.http.HttpClient
;
import
java.net.http.HttpRequest
;
import
java.net.http.HttpRequest.BodyPublisher
;
import
java.net.http.HttpResponse
;
import
java.net.http.HttpResponse.BodySubscriber
;
import
java.net.http.HttpResponse.BodySubscribers
;
...
...
@@ -18,7 +17,6 @@ import java.util.List;
import
java.util.Map
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.Flow
;
import
java.util.concurrent.Flow.Subscriber
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -47,9 +45,9 @@ public class GmsClientTest {
httpClient
=
mock
(
HttpClient
.
class
);
HttpClientWrapper
clientWrapper
=
new
MockedHttpClientWrapper
(
BASE_URL
,
httpClient
);
clientWrapper
.
setAccessToken
(
"foo"
);
client
=
new
GmsClient
(
BASE_URL
);
client
.
httpClientWrapper
=
clientWrapper
;
client
=
new
GmsClient
(
clientWrapper
);
}
@Test
...
...
gms-client/gms-client-lib/src/test/java/it/inaf/ia2/gms/client/call/HttpClientWrapperTest.java
0 → 100644
View file @
c67052b0
package
it.inaf.ia2.gms.client.call
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
org.junit.Test
;
public
class
HttpClientWrapperTest
{
@Test
public
void
testExtractAccessToken
()
{
String
response
=
"{\"access_token\":\"TEST_TOKEN\",\"token_type\":\"Bearer\",\"expires_in\":3600}"
;
HttpClientWrapper
clientWrapper
=
new
HttpClientWrapper
(
"http://localhost"
);
assertEquals
(
"TEST_TOKEN"
,
clientWrapper
.
getAccessTokenFromResponse
(
response
));
}
}
gms/pom.xml
View file @
c67052b0
...
...
@@ -62,6 +62,7 @@
</dependencies>
<build>
<finalName>
gms
</finalName>
<plugins>
<plugin>
<groupId>
com.github.eirslett
</groupId>
...
...
gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
View file @
c67052b0
...
...
@@ -7,6 +7,7 @@ import it.inaf.ia2.gms.manager.InvitedRegistrationManager;
import
it.inaf.ia2.gms.manager.MembershipManager
;
import
it.inaf.ia2.gms.manager.PermissionsManager
;
import
it.inaf.ia2.gms.model.Permission
;
import
it.inaf.ia2.gms.model.RapUser
;
import
it.inaf.ia2.gms.model.response.UserPermission
;