Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APP-3104: Fluent OBO API for services #284

Merged
merged 7 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions docs/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ public class Example {
### OBO (On Behalf Of) authentication
> Read more about OBO authentication [here](https://developers.symphony.com/symphony-developer/docs/obo-overview)

The following example shows how to retrieve OBO sessions using `username` (type `String`) or `userId` (type `Long`):
The following example shows how to retrieve OBO sessions using `username` (type `String`) or `userId` (type `Long`)
and to call services which have OBO endpoints (users, streams and messages so far):
```java
public class Example {

Expand All @@ -169,7 +170,11 @@ public class Example {
final AuthSession oboSessionUserId = bdk.obo(123456789L);

// list streams OBO user "user.name"
bdk.streams().listStreams(oboSessionUsername, new StreamFilter());
bdk.obo(oboSessionUsername).streams().listStreams(new StreamFilter());

// or send a message OBO:
Message message = Message.builder().content("<messageML>Hello, World</messageML>").build();
bdk.obo(oboSessionUserId).messages().send("streamID", message);
}
}
```
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.symphony.bdk.core;

import com.symphony.bdk.core.auth.AuthSession;
import com.symphony.bdk.core.client.ApiClientFactory;
import com.symphony.bdk.core.config.model.BdkConfig;
import com.symphony.bdk.core.service.message.OboMessageService;
import com.symphony.bdk.core.service.stream.OboStreamService;
import com.symphony.bdk.core.service.user.OboUserService;

import org.apiguardian.api.API;

/**
* Entry point for OBO-enabled services.
*/
@API(status = API.Status.EXPERIMENTAL)
public class OboServices {

private final OboStreamService oboStreamService;
private final OboUserService oboUserService;
private final OboMessageService oboMessageService;

public OboServices(BdkConfig config, AuthSession oboSession) {
final ServiceFactory serviceFactory = new ServiceFactory(new ApiClientFactory(config), oboSession, config);

oboStreamService = serviceFactory.getStreamService();
oboUserService = serviceFactory.getUserService();
oboMessageService = serviceFactory.getMessageService();
}

/**
* Get the {@link OboStreamService} using the provided OBO session in constructor.
*
* @return an {@link OboStreamService} instance with the provided OBO session.
*/
public OboStreamService streams() {
return oboStreamService;
}

/**
* Get the {@link OboUserService} using the provided OBO session in constructor.
*
* @return an {@link OboUserService} instance with the provided OBO session.
*/
public OboUserService users() {
return oboUserService;
}

/**
* Get the {@link OboMessageService} using the provided OBO session in constructor.
* The returned message service instance.
*
* @return an {@link OboMessageService} instance with the provided OBO session.
*/
public OboMessageService messages() {
return oboMessageService;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import com.symphony.bdk.core.client.ApiClientFactory;
import com.symphony.bdk.core.config.model.BdkConfig;
import com.symphony.bdk.core.retry.RetryWithRecoveryBuilder;
import com.symphony.bdk.core.service.message.MessageService;
import com.symphony.bdk.core.service.SessionService;
import com.symphony.bdk.core.service.datafeed.DatafeedService;
import com.symphony.bdk.core.service.datafeed.DatafeedVersion;
import com.symphony.bdk.core.service.datafeed.impl.DatafeedServiceV1;
import com.symphony.bdk.core.service.datafeed.impl.DatafeedServiceV2;
import com.symphony.bdk.core.service.message.MessageService;
import com.symphony.bdk.core.service.stream.StreamService;
import com.symphony.bdk.core.service.user.UserService;
import com.symphony.bdk.gen.api.AttachmentsApi;
Expand All @@ -25,10 +25,10 @@
import com.symphony.bdk.gen.api.StreamsApi;
import com.symphony.bdk.gen.api.UserApi;
import com.symphony.bdk.gen.api.UsersApi;

import com.symphony.bdk.http.api.ApiClient;

import com.symphony.bdk.http.api.ApiException;

import com.symphony.bdk.template.api.TemplateEngine;

import org.apiguardian.api.API;
Expand All @@ -50,16 +50,16 @@ class ServiceFactory {
private final ApiClient podClient;
private final ApiClient agentClient;
private final AuthSession authSession;
private final BdkConfig config;
private final TemplateEngine templateEngine;
private final BdkConfig config;
private final RetryWithRecoveryBuilder<?> retryBuilder;

public ServiceFactory(ApiClientFactory apiClientFactory, AuthSession authSession, BdkConfig config) {
this.podClient = apiClientFactory.getPodClient();
this.agentClient = apiClientFactory.getAgentClient();
this.authSession = authSession;
this.config = config;
this.templateEngine = TemplateEngine.getDefaultImplementation();
this.config = config;
this.retryBuilder = new RetryWithRecoveryBuilder<>()
.retryConfig(config.getRetry())
.recoveryStrategy(ApiException::isUnauthorized, authSession::refresh);
Expand All @@ -68,7 +68,7 @@ public ServiceFactory(ApiClientFactory apiClientFactory, AuthSession authSession
/**
* Returns a fully initialized {@link UserService}.
*
* @return an new {@link UserService} instance.
* @return a new {@link UserService} instance.
*/
public UserService getUserService() {
return new UserService(new UserApi(podClient), new UsersApi(podClient), authSession, retryBuilder);
Expand All @@ -77,7 +77,7 @@ public UserService getUserService() {
/**
* Returns a fully initialized {@link StreamService}.
*
* @return an new {@link StreamService} instance.
* @return a new {@link StreamService} instance.
*/
public StreamService getStreamService() {
return new StreamService(new StreamsApi(podClient), new RoomMembershipApi(podClient), new ShareApi(agentClient),
Expand All @@ -87,7 +87,7 @@ public StreamService getStreamService() {
/**
* Returns a fully initialized {@link SessionService}.
*
* @return an new {@link SessionService} instance.
* @return a new {@link SessionService} instance.
*/
public SessionService getSessionService() {
return new SessionService(new SessionApi(podClient),
Expand All @@ -97,7 +97,7 @@ public SessionService getSessionService() {
/**
* Returns a fully initialized {@link DatafeedService}.
*
* @return an new {@link DatafeedService} instance.
* @return a new {@link DatafeedService} instance.
*/
public DatafeedService getDatafeedService() {
if (DatafeedVersion.of(config.getDatafeed().getVersion()) == DatafeedVersion.V2) {
Expand All @@ -109,7 +109,7 @@ public DatafeedService getDatafeedService() {
/**
* Returns a fully initialized {@link MessageService}.
*
* @return an new {@link MessageService} instance.
* @return a new {@link MessageService} instance.
*/
public MessageService getMessageService() {
return new MessageService(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import com.symphony.bdk.core.auth.exception.AuthUnauthorizedException;
import com.symphony.bdk.core.client.ApiClientFactory;
import com.symphony.bdk.core.config.model.BdkConfig;
import com.symphony.bdk.core.service.message.MessageService;
import com.symphony.bdk.core.service.SessionService;
import com.symphony.bdk.core.service.datafeed.DatafeedService;
import com.symphony.bdk.core.service.message.MessageService;
import com.symphony.bdk.core.service.stream.StreamService;
import com.symphony.bdk.core.service.user.UserService;
import com.symphony.bdk.core.util.ServiceLookup;
Expand All @@ -31,6 +31,7 @@
@API(status = API.Status.EXPERIMENTAL)
public class SymphonyBdk {

private final BdkConfig config;
private final AuthSession botSession;
private final UserV2 botInfo;

Expand All @@ -50,11 +51,13 @@ public SymphonyBdk(BdkConfig config) throws AuthInitializationException, AuthUna

protected SymphonyBdk(BdkConfig config, ApiClientFactory apiClientFactory)
throws AuthInitializationException, AuthUnauthorizedException {
this.config = config;

final AuthenticatorFactory authenticatorFactory = new AuthenticatorFactory(config, apiClientFactory);
this.botSession = authenticatorFactory.getBotAuthenticator().authenticateBot();
this.oboAuthenticator = config.isOboConfigured() ? authenticatorFactory.getOboAuthenticator() : null;
this.extensionAppAuthenticator = config.isOboConfigured() ? authenticatorFactory.getExtensionAppAuthenticator() : null;
this.extensionAppAuthenticator =
config.isOboConfigured() ? authenticatorFactory.getExtensionAppAuthenticator() : null;

// service init
final ServiceFactory serviceFactory = new ServiceFactory(apiClientFactory, this.botSession, config);
Expand Down Expand Up @@ -148,6 +151,16 @@ public AuthSession obo(String username) throws AuthUnauthorizedException {
return this.getOboAuthenticator().authenticateByUsername(username);
}

/**
* Get an {@link OboServices} gathering all OBO enabled services
*
* @param oboSession the OBO session to use
* @return an {@link OboServices} instance using the provided OBO session
*/
public OboServices obo(AuthSession oboSession) {
return new OboServices(config, oboSession);
}

/**
* Returns the {@link ExtensionAppAuthenticator}.
*
Expand All @@ -166,6 +179,7 @@ public ExtensionAppAuthenticator appAuthenticator() {
public AuthSession botSession() {
return this.botSession;
}

/**
* Returns the bot information.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import com.symphony.bdk.core.auth.OboAuthenticator;
import com.symphony.bdk.core.auth.exception.AuthUnauthorizedException;

import lombok.NonNull;
import org.apiguardian.api.API;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
Expand All @@ -22,13 +22,13 @@ public class AuthSessionOboCertImpl implements AuthSession {

private String sessionToken;

public AuthSessionOboCertImpl(@NonNull OboAuthenticatorCertImpl authenticator, @NonNull Long userId) {
public AuthSessionOboCertImpl(@Nonnull OboAuthenticatorCertImpl authenticator, @Nonnull Long userId) {
this.authenticator = authenticator;
this.userId = userId;
this.username = null;
}

public AuthSessionOboCertImpl(@NonNull OboAuthenticatorCertImpl authenticator, @NonNull String username) {
public AuthSessionOboCertImpl(@Nonnull OboAuthenticatorCertImpl authenticator, @Nonnull String username) {
this.authenticator = authenticator;
this.username = username;
this.userId = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.symphony.bdk.gen.api.model.OboAuthResponse;
import com.symphony.bdk.gen.api.model.Token;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apiguardian.api.API;

Expand Down Expand Up @@ -57,7 +56,7 @@ public AuthSession authenticateByUserId(@Nonnull Long userId) throws AuthUnautho
return authSession;
}

protected String retrieveOboSessionTokenByUserId(@NonNull Long userId) throws AuthUnauthorizedException {
protected String retrieveOboSessionTokenByUserId(@Nonnull Long userId) throws AuthUnauthorizedException {
final String appSessionToken = this.retrieveAppSessionToken();
try {
OboAuthResponse oboAuthResponse = this.authenticationApi.v1AppUserUidAuthenticatePost(userId, appSessionToken);
Expand All @@ -72,7 +71,7 @@ protected String retrieveOboSessionTokenByUserId(@NonNull Long userId) throws Au
}
}

protected String retrieveOboSessionTokenByUsername(@NonNull String username) throws AuthUnauthorizedException {
protected String retrieveOboSessionTokenByUsername(@Nonnull String username) throws AuthUnauthorizedException {
final String appSessionToken = this.retrieveAppSessionToken();
try {
OboAuthResponse oboAuthResponse = this.authenticationApi.v1AppUsernameUsernameAuthenticatePost(username, appSessionToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.symphony.bdk.core.service;

import com.symphony.bdk.core.auth.AuthSession;

import org.apiguardian.api.API;

/**
* Interface which returns an OBO-enabled service class from a given OBO session.
*
* @param <S> type returned by the {@link #obo(AuthSession)} function.
*/
@API(status = API.Status.STABLE)
public interface OboService<S> {

/**
* Returns a new service instance with OBO-enabled endpoints from a given OBO session.
*
* @param oboSession the OBO session
* @return the instance of the service class with OBO-enabled endpoints
*/
S obo(AuthSession oboSession);
}
Loading