Added bot-connector UserToken and BotSignIn (used by bot-builder).

This commit is contained in:
Tracy Boehrer 2019-09-16 08:49:22 -05:00
Родитель 0c21fa47d2
Коммит d5f742fc0e
14 изменённых файлов: 1250 добавлений и 63 удалений

Просмотреть файл

@ -0,0 +1,37 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.bot.connector;
import java.util.concurrent.CompletableFuture;
/**
* An instance of this class provides access to all the operations defined
* in BotSignIns.
*/
public interface BotSignIn {
/**
*
* @param state the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the String object
*/
CompletableFuture<String> getSignInUrl(String state);
/**
*
* @param state the String value
* @param codeChallenge the String value
* @param emulatorUrl the String value
* @param finalRedirect the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the String object
*/
CompletableFuture<String> getSignInUrl(String state,
String codeChallenge,
String emulatorUrl,
String finalRedirect);
}

Просмотреть файл

@ -94,4 +94,16 @@ public interface ConnectorClient {
* @return the Conversations object.
*/
Conversations getConversations();
/**
* Gets the BotSignIns object to access its operations.
* @return the BotSignIns object.
*/
BotSignIn botSignIn();
/**
* Gets the UserTokens object to access its operations.
* @return the UserTokens object.
*/
UserToken userToken();
}

Просмотреть файл

@ -12,6 +12,7 @@ package com.microsoft.bot.connector;
import com.microsoft.bot.schema.*;
import com.microsoft.rest.ServiceResponse;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@ -127,6 +128,10 @@ public interface Conversations {
*/
CompletableFuture<ResourceResponse> updateActivity(String conversationId, String activityId, Activity activity);
default CompletableFuture<ResourceResponse> updateActivity(Activity activity) {
return updateActivity(activity.getConversation().getId(), activity.getId(), activity);
}
/**
* ReplyToActivity.
* This method allows you to reply to an activity.
@ -146,6 +151,14 @@ public interface Conversations {
*/
CompletableFuture<ResourceResponse> replyToActivity(String conversationId, String activityId, Activity activity);
default CompletableFuture<ResourceResponse> replyToActivity(Activity activity) {
if (StringUtils.isEmpty(activity.getReplyToId())) {
throw new IllegalArgumentException("ReplyToId cannot be emoty");
}
return replyToActivity(activity.getConversation().getId(), activity.getReplyToId(), activity);
}
/**
* DeleteActivity.
* Delete an existing activity.

Просмотреть файл

@ -1,12 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.microsoft.bot.connector.authentication;
package com.microsoft.bot.connector;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.bot.connector.ExecutorFactory;
import com.microsoft.bot.connector.UserAgent;
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentialsInterceptor;
import com.microsoft.bot.connector.rest.RestConnectorClient;
import com.microsoft.bot.schema.Activity;
import com.microsoft.bot.schema.TokenExchangeState;
@ -31,6 +33,7 @@ import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import static com.microsoft.bot.connector.authentication.MicrosoftAppCredentials.JSON;
@ -38,7 +41,6 @@ import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.util.stream.Collectors.joining;
/**
* Service client to handle requests to the botframework api service.
* <p>
@ -75,11 +77,11 @@ public class OAuthClient extends ServiceClient {
* @param magicCode
* @return CompletableFuture<TokenResponse> on success; otherwise null.
*/
public CompletableFuture<TokenResponse> GetUserToken(String userId, String connectionName, String magicCode) throws IOException, URISyntaxException, ExecutionException, InterruptedException {
return GetUserToken(userId, connectionName, magicCode, null);
public CompletableFuture<TokenResponse> getUserToken(String userId, String connectionName, String magicCode) {
return getUserToken(userId, connectionName, magicCode, null);
}
protected URI MakeUri(String uri, HashMap<String, String> queryStrings) throws URISyntaxException {
protected URI makeUri(String uri, HashMap<String, String> queryStrings) throws URISyntaxException {
String newUri = queryStrings.keySet().stream()
.map(key -> {
try {
@ -90,8 +92,6 @@ public class OAuthClient extends ServiceClient {
})
.collect(joining("&", uri.endsWith("?") ? uri : uri + "?", ""));
return new URI(newUri);
}
/**
@ -103,7 +103,10 @@ public class OAuthClient extends ServiceClient {
* @param customHeaders
* @return CompletableFuture<TokenResponse> on success; null otherwise.
*/
public CompletableFuture<TokenResponse> GetUserToken(String userId, String connectionName, String magicCode, Map<String, ArrayList<String>> customHeaders) throws IllegalArgumentException {
public CompletableFuture<TokenResponse> getUserToken(String userId,
String connectionName,
String magicCode,
Map<String, ArrayList<String>> customHeaders) {
if (StringUtils.isEmpty(userId)) {
throw new IllegalArgumentException("userId");
}
@ -122,7 +125,7 @@ public class OAuthClient extends ServiceClient {
String strUri = String.format("%sapi/usertoken/GetToken", this.uri);
URI tokenUrl = null;
try {
tokenUrl = MakeUri(strUri, qstrings);
tokenUrl = makeUri(strUri, qstrings);
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
@ -172,7 +175,7 @@ public class OAuthClient extends ServiceClient {
* @param connectionName
* @return True on successful sign-out; False otherwise.
*/
public CompletableFuture<Boolean> SignOutUser(String userId, String connectionName) throws URISyntaxException, IOException {
public CompletableFuture<Boolean> signOutUser(String userId, String connectionName) {
if (StringUtils.isEmpty(userId)) {
throw new IllegalArgumentException("userId");
}
@ -188,7 +191,7 @@ public class OAuthClient extends ServiceClient {
String strUri = String.format("%sapi/usertoken/SignOut", this.uri);
URI tokenUrl = null;
try {
tokenUrl = MakeUri(strUri, qstrings);
tokenUrl = makeUri(strUri, qstrings);
} catch (URISyntaxException e) {
e.printStackTrace();
return false;
@ -221,7 +224,6 @@ public class OAuthClient extends ServiceClient {
e.printStackTrace();
}
return false;
}, ExecutorFactory.getExecutor());
}
@ -233,43 +235,53 @@ public class OAuthClient extends ServiceClient {
* @param connectionName
* @return Sign in link on success; null otherwise.
*/
public CompletableFuture<String> GetSignInLink(Activity activity, String connectionName) throws IllegalArgumentException, URISyntaxException, JsonProcessingException {
public CompletableFuture<String> getSignInLink(Activity activity, String connectionName) {
if (StringUtils.isEmpty(connectionName)) {
throw new IllegalArgumentException("connectionName");
}
if (activity == null) {
throw new IllegalArgumentException("activity");
}
final MicrosoftAppCredentials creds = (MicrosoftAppCredentials) this.client.restClient().credentials();
TokenExchangeState tokenExchangeState = new TokenExchangeState() {{
setConnectionName(connectionName);
setConversation(new ConversationReference() {{
setActivityId(activity.getId());
setBot(activity.getRecipient());
setChannelId(activity.getChannelId());
setConversation(activity.getConversation());
setServiceUrl(activity.getServiceUrl());
setUser(activity.getFrom());
}});
setMsAppId((creds == null) ? null : creds.appId());
}};
String serializedState = this.mapper.writeValueAsString(tokenExchangeState);
// Construct URL
String encoded = Base64.getEncoder().encodeToString(serializedState.getBytes(StandardCharsets.UTF_8));
HashMap<String, String> qstrings = new HashMap<>();
qstrings.put("state", encoded);
String strUri = String.format("%sapi/botsignin/getsigninurl", this.uri);
final URI tokenUrl = MakeUri(strUri, qstrings);
return CompletableFuture.supplyAsync(() -> {
final MicrosoftAppCredentials creds = (MicrosoftAppCredentials) this.client.restClient().credentials();
TokenExchangeState tokenExchangeState = new TokenExchangeState() {{
setConnectionName(connectionName);
setConversation(new ConversationReference() {{
setActivityId(activity.getId());
setBot(activity.getRecipient());
setChannelId(activity.getChannelId());
setConversation(activity.getConversation());
setServiceUrl(activity.getServiceUrl());
setUser(activity.getFrom());
}});
setMsAppId((creds == null) ? null : creds.appId());
}};
String serializedState;
try {
serializedState = mapper.writeValueAsString(tokenExchangeState);
} catch(Throwable t) {
throw new CompletionException(t);
}
// Construct URL
String encoded = Base64.getEncoder().encodeToString(serializedState.getBytes(StandardCharsets.UTF_8));
HashMap<String, String> qstrings = new HashMap<>();
qstrings.put("state", encoded);
String strUri = String.format("%sapi/botsignin/getsigninurl", this.uri);
final URI tokenUrl;
try {
tokenUrl = makeUri(strUri, qstrings);
} catch(Throwable t) {
throw new CompletionException(t);
}
// add botframework api service url to the list of trusted service url's for these app credentials.
MicrosoftAppCredentials.trustServiceUrl(tokenUrl);
// Later: Use client in clientimpl?
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new MicrosoftAppCredentialsInterceptor(creds))
@ -299,18 +311,23 @@ public class OAuthClient extends ServiceClient {
* @param emulateOAuthCards
* @return CompletableFuture with no result code
*/
public CompletableFuture SendEmulateOAuthCards(Boolean emulateOAuthCards) throws URISyntaxException, IOException {
public CompletableFuture<Void> sendEmulateOAuthCards(Boolean emulateOAuthCards) {
// Construct URL
HashMap<String, String> qstrings = new HashMap<>();
qstrings.put("emulate", emulateOAuthCards.toString());
String strUri = String.format("%sapi/usertoken/emulateOAuthCards", this.uri);
URI tokenUrl = MakeUri(strUri, qstrings);
// add botframework api service url to the list of trusted service url's for these app credentials.
MicrosoftAppCredentials.trustServiceUrl(tokenUrl);
return CompletableFuture.runAsync(() -> {
URI tokenUrl;
try {
tokenUrl = makeUri(strUri, qstrings);
} catch(Throwable t) {
throw new CompletionException(t);
}
// add botframework api service url to the list of trusted service url's for these app credentials.
MicrosoftAppCredentials.trustServiceUrl(tokenUrl);
// Construct dummy body
RequestBody body = RequestBody.create(JSON, "{}");

Просмотреть файл

@ -0,0 +1,19 @@
package com.microsoft.bot.connector;
import com.microsoft.bot.connector.authentication.AuthenticationConstants;
import org.apache.commons.lang3.NotImplementedException;
import java.util.concurrent.CompletableFuture;
public final class OAuthClientConfig {
private OAuthClientConfig() {
}
public static String OAUTHENDPOINT = AuthenticationConstants.OAUTH_URL;
public static boolean EMULATEOAUTHCARDS = false;
public static CompletableFuture<Void> sendEmulateOAuthCards(OAuthClient client, boolean emulateOAuthCards) {
throw new NotImplementedException("sendEmulateOAuthCards");
}
}

Просмотреть файл

@ -0,0 +1,102 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.bot.connector;
import com.microsoft.bot.schema.AadResourceUrls;
import com.microsoft.bot.schema.TokenResponse;
import com.microsoft.bot.schema.TokenStatus;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
* An instance of this class provides access to all the operations defined
* in UserTokens.
*/
public interface UserToken {
/**
*
* @param userId the String value
* @param connectionName the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the TokenResponse object
*/
CompletableFuture<TokenResponse> getToken(String userId, String connectionName);
/**
*
* @param userId the String value
* @param connectionName the String value
* @param channelId the String value
* @param code the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the TokenResponse object
*/
CompletableFuture<TokenResponse> getToken(String userId, String connectionName, String channelId, String code);
/**
*
* @param userId the String value
* @param connectionName the String value
* @param aadResourceUrls the AadResourceUrls value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Map&lt;String, TokenResponse&gt; object
*/
CompletableFuture<Map<String, TokenResponse>> getAadTokens(String userId,
String connectionName,
AadResourceUrls aadResourceUrls);
/**
*
* @param userId the String value
* @param connectionName the String value
* @param aadResourceUrls the AadResourceUrls value
* @param channelId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Map&lt;String, TokenResponse&gt; object
*/
CompletableFuture<Map<String, TokenResponse>> getAadTokens(String userId,
String connectionName,
AadResourceUrls aadResourceUrls,
String channelId);
/**
*
* @param userId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Object object
*/
CompletableFuture<Object> signOut(String userId);
/**
*
* @param userId the String value
* @param connectionName the String value
* @param channelId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Object object
*/
CompletableFuture<Object> signOut(String userId, String connectionName, String channelId);
/**
*
* @param userId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the List&lt;TokenStatus&gt; object
*/
CompletableFuture<List<TokenStatus>> getTokenStatus(String userId);
/**
*
* @param userId the String value
* @param channelId the String value
* @param include the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the List&lt;TokenStatus&gt; object
*/
CompletableFuture<List<TokenStatus>> getTokenStatus(String userId, String channelId, String include);
}

Просмотреть файл

@ -12,7 +12,7 @@ import java.io.IOException;
/**
* Token credentials filter for placing a token credential into request headers.
*/
class MicrosoftAppCredentialsInterceptor implements Interceptor {
public class MicrosoftAppCredentialsInterceptor implements Interceptor {
/**
* The credentials instance to apply to the HTTP client pipeline.
*/
@ -24,7 +24,7 @@ class MicrosoftAppCredentialsInterceptor implements Interceptor {
*
* @param credentials a TokenCredentials instance
*/
MicrosoftAppCredentialsInterceptor(MicrosoftAppCredentials credentials) {
public MicrosoftAppCredentialsInterceptor(MicrosoftAppCredentials credentials) {
this.credentials = credentials;
}

Просмотреть файл

@ -0,0 +1,121 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.bot.connector.rest;
import retrofit2.Retrofit;
import com.microsoft.bot.connector.BotSignIn;
import com.google.common.reflect.TypeToken;
import com.microsoft.azure.CloudException;
import com.microsoft.rest.ServiceResponse;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import okhttp3.ResponseBody;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Query;
import retrofit2.Response;
/**
* An instance of this class provides access to all the operations defined
* in BotSignIns.
*/
public class RestBotSignIn implements BotSignIn {
/** The Retrofit service to perform REST calls. */
private BotSignInsService service;
/** The service client containing this operation class. */
private RestConnectorClient client;
/**
* Initializes an instance of BotSignInsImpl.
*
* @param retrofit the Retrofit instance built from a Retrofit Builder.
* @param client the instance of the service client containing this operation class.
*/
public RestBotSignIn(Retrofit retrofit, RestConnectorClient client) {
this.service = retrofit.create(BotSignInsService.class);
this.client = client;
}
/**
* The interface defining all the services for BotSignIns to be
* used by Retrofit to perform actually REST calls.
*/
@SuppressWarnings("checkstyle:linelength")
interface BotSignInsService {
@Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.BotSignIns getSignInUrl" })
@GET("api/botsignin/GetSignInUrl")
CompletableFuture<Response<ResponseBody>> getSignInUrl(@Query("state") String state, @Query("code_challenge") String codeChallenge, @Query("emulatorUrl") String emulatorUrl, @Query("finalRedirect") String finalRedirect, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent);
}
/**
*
* @param state the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the String object
*/
public CompletableFuture<String> getSignInUrl(String state) {
if (state == null) {
throw new IllegalArgumentException("Parameter state is required and cannot be null.");
}
final String codeChallenge = null;
final String emulatorUrl = null;
final String finalRedirect = null;
return service.getSignInUrl(state, codeChallenge, emulatorUrl, finalRedirect,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getSignInUrlDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getSignInUrl", responseBodyResponse);
}
});
}
/**
*
* @param state the String value
* @param codeChallenge the String value
* @param emulatorUrl the String value
* @param finalRedirect the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the String object
*/
public CompletableFuture<String> getSignInUrl(String state,
String codeChallenge,
String emulatorUrl,
String finalRedirect) {
if (state == null) {
throw new IllegalArgumentException("Parameter state is required and cannot be null.");
}
return service.getSignInUrl(state, codeChallenge, emulatorUrl, finalRedirect,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getSignInUrlDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getSignInUrl", responseBodyResponse);
}
});
}
private ServiceResponse<String> getSignInUrlDelegate(Response<ResponseBody> response)
throws CloudException, IOException, IllegalArgumentException {
return this.client.restClient().responseBuilderFactory().<String, CloudException>newInstance(this.client.serializerAdapter())
.register(200, new TypeToken<String>() { }.getType())
.registerError(CloudException.class)
.build(response);
}
}

Просмотреть файл

@ -9,10 +9,7 @@ package com.microsoft.bot.connector.rest;
import com.microsoft.azure.AzureClient;
import com.microsoft.azure.AzureResponseBuilder;
import com.microsoft.azure.AzureServiceClient;
import com.microsoft.bot.connector.Attachments;
import com.microsoft.bot.connector.ConnectorClient;
import com.microsoft.bot.connector.Conversations;
import com.microsoft.bot.connector.UserAgent;
import com.microsoft.bot.connector.*;
import com.microsoft.rest.credentials.ServiceClientCredentials;
import com.microsoft.rest.RestClient;
import com.microsoft.rest.retry.RetryStrategy;
@ -162,6 +159,35 @@ public class RestConnectorClient extends AzureServiceClient implements Connector
return this.conversations;
}
/**
* The BotSignIns object to access its operations.
*/
private BotSignIn botSignIn;
/**
* Gets the BotSignIns object to access its operations.
* @return the BotSignIns object.
*/
@Override
public BotSignIn botSignIn() {
return this.botSignIn;
}
/**
* The UserTokens object to access its operations.
*/
private UserToken userToken;
/**
* Gets the UserTokens object to access its operations.
* @return the UserTokens object.
*/
@Override
public UserToken userToken() {
return this.userToken;
}
/**
* Initializes an instance of ConnectorClient client.
*
@ -198,6 +224,8 @@ public class RestConnectorClient extends AzureServiceClient implements Connector
this.generateClientRequestId = true;
this.attachments = new RestAttachments(restClient().retrofit(), this);
this.conversations = new RestConversations(restClient().retrofit(), this);
this.botSignIn = new RestBotSignIn(restClient().retrofit(), this);
this.userToken = new RestUserToken(restClient().retrofit(), this);
this.azureClient = new AzureClient(this);
this.user_agent_string = UserAgent.value();
}

Просмотреть файл

@ -226,7 +226,9 @@ public class RestConversations implements Conversations {
}
Validator.validate(activity);
return service.sendToConversation(conversationId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.sendToConversation(conversationId, activity,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return sendToConversationDelegate(responseBodyResponse).body();
@ -255,7 +257,9 @@ public class RestConversations implements Conversations {
* @see Conversations#updateActivity
*/
@Override
public CompletableFuture<ResourceResponse> updateActivity(String conversationId, String activityId, Activity activity) {
public CompletableFuture<ResourceResponse> updateActivity(String conversationId,
String activityId,
Activity activity) {
if (conversationId == null) {
throw new IllegalArgumentException("Parameter conversationId is required and cannot be null.");
}
@ -267,7 +271,9 @@ public class RestConversations implements Conversations {
}
Validator.validate(activity);
return service.updateActivity(conversationId, activityId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.updateActivity(conversationId, activityId, activity,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return updateActivityDelegate(responseBodyResponse).body();
@ -310,7 +316,9 @@ public class RestConversations implements Conversations {
}
Validator.validate(activity);
return service.replyToActivity(conversationId, activityId, activity, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.replyToActivity(conversationId, activityId, activity,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return replyToActivityDelegate(responseBodyResponse).body();
@ -347,7 +355,9 @@ public class RestConversations implements Conversations {
throw new IllegalArgumentException("Parameter activityId is required and cannot be null.");
}
return service.deleteActivity(conversationId, activityId, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.deleteActivity(conversationId, activityId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return deleteActivityDelegate(responseBodyResponse).body();
@ -379,7 +389,9 @@ public class RestConversations implements Conversations {
if (conversationId == null) {
throw new IllegalArgumentException("Parameter conversationId is required and cannot be null.");
}
return service.getConversationMembers(conversationId, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.getConversationMembers(conversationId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getConversationMembersDelegate(responseBodyResponse).body();
@ -414,7 +426,9 @@ public class RestConversations implements Conversations {
throw new IllegalArgumentException("Parameter memberId is required and cannot be null.");
}
return service.deleteConversationMember(conversationId, memberId, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.deleteConversationMember(conversationId, memberId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return deleteConversationMemberDelegate(responseBodyResponse).body();
@ -451,7 +465,9 @@ public class RestConversations implements Conversations {
throw new IllegalArgumentException("Parameter activityId is required and cannot be null.");
}
return service.getActivityMembers(conversationId, activityId, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.getActivityMembers(conversationId, activityId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getActivityMembersDelegate(responseBodyResponse).body();
@ -478,7 +494,8 @@ public class RestConversations implements Conversations {
* @see Conversations#uploadAttachment
*/
@Override
public CompletableFuture<ResourceResponse> uploadAttachment(String conversationId, AttachmentData attachmentUpload) {
public CompletableFuture<ResourceResponse> uploadAttachment(String conversationId,
AttachmentData attachmentUpload) {
if (conversationId == null) {
throw new IllegalArgumentException("Parameter conversationId is required and cannot be null.");
}
@ -487,7 +504,9 @@ public class RestConversations implements Conversations {
}
Validator.validate(attachmentUpload);
return service.uploadAttachment(conversationId, attachmentUpload, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.uploadAttachment(conversationId, attachmentUpload,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return uploadAttachmentDelegate(responseBodyResponse).body();
@ -526,7 +545,9 @@ public class RestConversations implements Conversations {
}
Validator.validate(history);
return service.sendConversationHistory(conversationId, history, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.sendConversationHistory(conversationId, history,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return sendConversationHistoryDelegate(responseBodyResponse).body();
@ -556,12 +577,14 @@ public class RestConversations implements Conversations {
* @see Conversations#getConversationPagedMembers
*/
@Override
public CompletableFuture<PagedMembersResult> getConversationPagedMembers(String conversationId){
public CompletableFuture<PagedMembersResult> getConversationPagedMembers(String conversationId) {
if (conversationId == null) {
throw new IllegalArgumentException("Parameter conversationId is required and cannot be null.");
}
return service.getConversationPagedMembers(conversationId, this.client.getAcceptLanguage(), this.client.getUserAgent())
return service.getConversationPagedMembers(conversationId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getConversationPagedMembersDelegate(responseBodyResponse).body();

Просмотреть файл

@ -0,0 +1,375 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.bot.connector.rest;
import retrofit2.Retrofit;
import com.microsoft.bot.connector.UserToken;
import com.google.common.reflect.TypeToken;
import com.microsoft.bot.schema.AadResourceUrls;
import com.microsoft.bot.connector.rest.ErrorResponseException;
import com.microsoft.bot.schema.TokenResponse;
import com.microsoft.bot.schema.TokenStatus;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceFuture;
import com.microsoft.rest.ServiceResponse;
import com.microsoft.rest.Validator;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import okhttp3.ResponseBody;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.HTTP;
import retrofit2.http.POST;
import retrofit2.http.Query;
import retrofit2.Response;
import rx.functions.Func1;
import rx.Observable;
/**
* An instance of this class provides access to all the operations defined
* in UserTokens.
*/
public class RestUserToken implements UserToken {
/** The Retrofit service to perform REST calls. */
private UserTokensService service;
/** The service client containing this operation class. */
private RestConnectorClient client;
/**
* Initializes an instance of UserTokensImpl.
*
* @param retrofit the Retrofit instance built from a Retrofit Builder.
* @param client the instance of the service client containing this operation class.
*/
public RestUserToken(Retrofit retrofit, RestConnectorClient client) {
this.service = retrofit.create(UserTokensService.class);
this.client = client;
}
/**
* The interface defining all the services for UserTokens to be
* used by Retrofit to perform actually REST calls.
*/
@SuppressWarnings("checkstyle:linelength")
interface UserTokensService {
@Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.UserTokens getToken" })
@GET("api/usertoken/GetToken")
CompletableFuture<Response<ResponseBody>> getToken(@Query("userId") String userId, @Query("connectionName") String connectionName, @Query("channelId") String channelId, @Query("code") String code, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent);
@Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.UserTokens getAadTokens" })
@POST("api/usertoken/GetAadTokens")
CompletableFuture<Response<ResponseBody>> getAadTokens(@Query("userId") String userId, @Query("connectionName") String connectionName, @Body AadResourceUrls aadResourceUrls, @Query("channelId") String channelId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent);
@Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.UserTokens signOut" })
@HTTP(path = "api/usertoken/SignOut", method = "DELETE", hasBody = true)
CompletableFuture<Response<ResponseBody>> signOut(@Query("userId") String userId, @Query("connectionName") String connectionName, @Query("channelId") String channelId, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent);
@Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.bot.schema.UserTokens getTokenStatus" })
@GET("api/usertoken/GetTokenStatus")
CompletableFuture<Response<ResponseBody>> getTokenStatus(@Query("userId") String userId, @Query("channelId") String channelId, @Query("include") String include, @Header("accept-language") String acceptLanguage, @Header("User-Agent") String userAgent);
}
/**
*
* @param userId the String value
* @param connectionName the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the TokenResponse object
*/
@Override
public CompletableFuture<TokenResponse> getToken(String userId, String connectionName) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
if (connectionName == null) {
throw new IllegalArgumentException("Parameter connectionName is required and cannot be null.");
}
final String channelId = null;
final String code = null;
return service.getToken(userId, connectionName, channelId, code,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getTokenDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getToken", responseBodyResponse);
}
});
}
/**
*
* @param userId the String value
* @param connectionName the String value
* @param channelId the String value
* @param code the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the TokenResponse object
*/
@Override
public CompletableFuture<TokenResponse> getToken(String userId,
String connectionName,
String channelId,
String code) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
if (connectionName == null) {
throw new IllegalArgumentException("Parameter connectionName is required and cannot be null.");
}
return service.getToken(userId, connectionName, channelId, code,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getTokenDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getToken", responseBodyResponse);
}
});
}
private ServiceResponse<TokenResponse> getTokenDelegate(Response<ResponseBody> response)
throws ErrorResponseException, IOException, IllegalArgumentException {
return this.client.restClient().responseBuilderFactory()
.<TokenResponse, ErrorResponseException>newInstance(this.client.serializerAdapter())
.register(200, new TypeToken<TokenResponse>() { }.getType())
.register(404, new TypeToken<TokenResponse>() { }.getType())
.registerError(ErrorResponseException.class)
.build(response);
}
/**
*
* @param userId the String value
* @param connectionName the String value
* @param aadResourceUrls the AadResourceUrls value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Map&lt;String, TokenResponse&gt; object
*/
@Override
public CompletableFuture<Map<String, TokenResponse>> getAadTokens(String userId,
String connectionName,
AadResourceUrls aadResourceUrls) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
if (connectionName == null) {
throw new IllegalArgumentException("Parameter connectionName is required and cannot be null.");
}
if (aadResourceUrls == null) {
throw new IllegalArgumentException("Parameter aadResourceUrls is required and cannot be null.");
}
Validator.validate(aadResourceUrls);
final String channelId = null;
return service.getAadTokens(userId, connectionName, aadResourceUrls, channelId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getAadTokensDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getAadTokens", responseBodyResponse);
}
});
}
/**
*
* @param userId the String value
* @param connectionName the String value
* @param aadResourceUrls the AadResourceUrls value
* @param channelId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Map&lt;String, TokenResponse&gt; object
*/
@Override
public CompletableFuture<Map<String, TokenResponse>> getAadTokens(String userId,
String connectionName,
AadResourceUrls aadResourceUrls,
String channelId) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
if (connectionName == null) {
throw new IllegalArgumentException("Parameter connectionName is required and cannot be null.");
}
if (aadResourceUrls == null) {
throw new IllegalArgumentException("Parameter aadResourceUrls is required and cannot be null.");
}
Validator.validate(aadResourceUrls);
return service.getAadTokens(userId, connectionName, aadResourceUrls, channelId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getAadTokensDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getAadTokens", responseBodyResponse);
}
});
}
private ServiceResponse<Map<String, TokenResponse>> getAadTokensDelegate(Response<ResponseBody> response)
throws ErrorResponseException, IOException, IllegalArgumentException {
return this.client.restClient().responseBuilderFactory()
.<Map<String, TokenResponse>, ErrorResponseException>newInstance(this.client.serializerAdapter())
.register(200, new TypeToken<Map<String, TokenResponse>>() { }.getType())
.registerError(ErrorResponseException.class)
.build(response);
}
/**
*
* @param userId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Object object
*/
@Override
public CompletableFuture<Object> signOut(String userId) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
final String connectionName = null;
final String channelId = null;
return service.signOut(userId, connectionName, channelId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return signOutDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("signOut", responseBodyResponse);
}
});
}
/**
*
* @param userId the String value
* @param connectionName the String value
* @param channelId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the Object object
*/
@Override
public CompletableFuture<Object> signOut(String userId, String connectionName, String channelId) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
return service.signOut(userId, connectionName, channelId,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return signOutDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("signOut", responseBodyResponse);
}
});
}
private ServiceResponse<Object> signOutDelegate(Response<ResponseBody> response)
throws ErrorResponseException, IOException, IllegalArgumentException {
return this.client.restClient().responseBuilderFactory()
.<Object, ErrorResponseException>newInstance(this.client.serializerAdapter())
.register(200, new TypeToken<Object>() { }.getType())
.register(204, new TypeToken<Void>() { }.getType())
.registerError(ErrorResponseException.class)
.build(response);
}
/**
*
* @param userId the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the List&lt;TokenStatus&gt; object
*/
@Override
public CompletableFuture<List<TokenStatus>> getTokenStatus(String userId) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
final String channelId = null;
final String include = null;
return service.getTokenStatus(userId, channelId, include,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getTokenStatusDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getTokenStatus", responseBodyResponse);
}
});
}
/**
*
* @param userId the String value
* @param channelId the String value
* @param include the String value
* @throws IllegalArgumentException thrown if parameters fail the validation
* @return the observable to the List&lt;TokenStatus&gt; object
*/
@Override
public CompletableFuture<List<TokenStatus>> getTokenStatus(String userId, String channelId, String include) {
if (userId == null) {
throw new IllegalArgumentException("Parameter userId is required and cannot be null.");
}
return service.getTokenStatus(userId, channelId, include,
this.client.getAcceptLanguage(), this.client.getUserAgent())
.thenApply(responseBodyResponse -> {
try {
return getTokenStatusDelegate(responseBodyResponse).body();
} catch (ErrorResponseException e) {
throw e;
} catch (Throwable t) {
throw new ErrorResponseException("getTokenStatus", responseBodyResponse);
}
});
}
private ServiceResponse<List<TokenStatus>> getTokenStatusDelegate(Response<ResponseBody> response)
throws ErrorResponseException, IOException, IllegalArgumentException {
return this.client.restClient().responseBuilderFactory()
.<List<TokenStatus>, ErrorResponseException>newInstance(this.client.serializerAdapter())
.register(200, new TypeToken<List<TokenStatus>>() { }.getType())
.registerError(ErrorResponseException.class)
.build(response);
}
}

Просмотреть файл

@ -1,7 +1,6 @@
package com.microsoft.bot.connector;
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
import com.microsoft.bot.connector.authentication.OAuthClient;
import com.microsoft.bot.connector.rest.RestConnectorClient;
import org.junit.Assert;
import org.junit.Test;
@ -24,6 +23,7 @@ public class OAuthConnectorTest extends OAuthTestBase {
this.credentials = new MicrosoftAppCredentials(clientId, clientSecret);
}
/*
@Test(expected = IllegalArgumentException.class)
public void OAuthClient_ShouldThrowOnInvalidUrl() throws MalformedURLException, URISyntaxException {
@ -43,6 +43,8 @@ public class OAuthConnectorTest extends OAuthTestBase {
OAuthClient client = new OAuthClient(this.connector, "https://localhost");
client.GetUserToken("userid", "", "");
}
*/
/*
TODO: Need to set up a bot and login with AADv2 to perform new recording (or convert the C# recordings)
@Test

Просмотреть файл

@ -0,0 +1,42 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.bot.schema;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* The AadResourceUrls model.
*/
public class AadResourceUrls {
/**
* The resourceUrls property.
*/
@JsonProperty(value = "resourceUrls")
private List<String> resourceUrls;
/**
* Get the resourceUrls value.
*
* @return the resourceUrls value
*/
public List<String> resourceUrls() {
return this.resourceUrls;
}
/**
* Set the resourceUrls value.
*
* @param resourceUrls the resourceUrls value to set
* @return the AadResourceUrls object itself.
*/
public AadResourceUrls withResourceUrls(List<String> resourceUrls) {
this.resourceUrls = resourceUrls;
return this;
}
}

Просмотреть файл

@ -0,0 +1,396 @@
{
"swagger": "2.0",
"info": {
"version": "token",
"title": "Microsoft Bot Token API - V3.1",
"termsOfService": "https://www.microsoft.com/en-us/legal/intellectualproperty/copyright/default.aspx",
"contact": {
"name": "Bot Framework",
"url": "https://botframework.com",
"email": "botframework@microsoft.com"
},
"license": {
"name": "The MIT License (MIT)",
"url": "https://opensource.org/licenses/MIT"
}
},
"host": "token.botframework.com",
"schemes": [
"https"
],
"paths": {
"/api/botsignin/GetSignInUrl": {
"get": {
"tags": [
"BotSignIn"
],
"operationId": "BotSignIn_GetSignInUrl",
"consumes": [],
"produces": [
"application/json",
"text/json",
"application/xml",
"text/xml"
],
"parameters": [
{
"name": "state",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "code_challenge",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "emulatorUrl",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "finalRedirect",
"in": "query",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "",
"schema": {
"type": "string"
}
}
}
}
},
"/api/usertoken/GetToken": {
"get": {
"tags": [
"UserToken"
],
"operationId": "UserToken_GetToken",
"consumes": [],
"produces": [
"application/json",
"text/json",
"application/xml",
"text/xml"
],
"parameters": [
{
"name": "userId",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "connectionName",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "channelId",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "code",
"in": "query",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "A Token Response object will be returned\r\n",
"schema": {
"$ref": "#/definitions/TokenResponse"
}
},
"404": {
"description": "Resource was not found\r\n",
"schema": {
"$ref": "#/definitions/TokenResponse"
}
},
"default": {
"description": "The operation failed and the response is an error object describing the status code and failure.",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/api/usertoken/GetAadTokens": {
"post": {
"tags": [
"UserToken"
],
"operationId": "UserToken_GetAadTokens",
"consumes": [
"application/json",
"text/json",
"application/xml",
"text/xml",
"application/x-www-form-urlencoded"
],
"produces": [
"application/json",
"text/json",
"application/xml",
"text/xml"
],
"parameters": [
{
"name": "userId",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "connectionName",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "aadResourceUrls",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/AadResourceUrls"
}
},
{
"name": "channelId",
"in": "query",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "An array of key value pairs",
"schema": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/TokenResponse"
}
}
},
"default": {
"description": "The operation failed and the response is an error object describing the status code and failure.",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/api/usertoken/SignOut": {
"delete": {
"tags": [
"UserToken"
],
"operationId": "UserToken_SignOut",
"consumes": [],
"produces": [],
"parameters": [
{
"name": "userId",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "connectionName",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "channelId",
"in": "query",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "The operation succeeded, there is no response.",
"schema": {
"$ref": "#/definitions/Void"
}
},
"204": {
"description": "No Content"
},
"default": {
"description": "The operation failed and the response is an error object describing the status code and failure.",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/api/usertoken/GetTokenStatus": {
"get": {
"tags": [
"UserToken"
],
"operationId": "UserToken_GetTokenStatus",
"consumes": [],
"produces": [
"application/json",
"text/json",
"application/xml",
"text/xml"
],
"parameters": [
{
"name": "userId",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "channelId",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "include",
"in": "query",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": "An array of TokenStatus objects",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/TokenStatus"
}
}
},
"default": {
"description": "The operation failed and the response is an error object describing the status code and failure.",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
}
},
"definitions": {
"TokenResponse": {
"type": "object",
"properties": {
"channelId": {
"type": "string"
},
"connectionName": {
"type": "string"
},
"token": {
"type": "string"
},
"expiration": {
"type": "string"
}
}
},
"ErrorResponse": {
"type": "object",
"properties": {
"error": {
"$ref": "#/definitions/Error"
}
}
},
"Error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"innerHttpError": {
"$ref": "#/definitions/InnerHttpError"
}
}
},
"InnerHttpError": {
"type": "object",
"properties": {
"statusCode": {
"format": "int32",
"type": "integer"
},
"body": {
"type": "object"
}
}
},
"AadResourceUrls": {
"type": "object",
"properties": {
"resourceUrls": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"Void": {
"type": "object",
"properties": {}
},
"TokenStatus": {
"description": "The status of a particular token",
"type": "object",
"properties": {
"channelId": {
"description": "The channelId of the token status pertains to",
"type": "string"
},
"connectionName": {
"description": "The name of the connection the token status pertains to",
"type": "string"
},
"hasToken": {
"description": "True if a token is stored for this ConnectionName",
"type": "boolean"
},
"serviceProviderDisplayName": {
"description": "The display name of the service provider for which this Token belongs to",
"type": "string"
}
}
}
},
"securityDefinitions": {
"bearer_auth": {
"type": "apiKey",
"description": "Access token to authenticate calls to the Bot Connector Service.",
"name": "Authorization",
"in": "header"
}
}
}