Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
6 changes: 6 additions & 0 deletions libs/teams/teams-chat-workflow-spring-boot-starter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
<artifactId>azure-storage-blob</artifactId>
<version>${azure-storage-blob.version}</version>
</dependency>

<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>${azure-identity.version}</version>
</dependency>

<dependency>
<groupId>com.azure</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import com.microsoft.bot.builder.teams.TeamsInfo;
import com.microsoft.bot.connector.ConnectorClient;
import com.microsoft.bot.connector.Conversations;
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
import com.microsoft.bot.schema.Activity;
import com.microsoft.bot.schema.ChannelAccount;
import com.microsoft.bot.schema.ConversationAccount;
Expand All @@ -40,11 +39,11 @@
*/
public abstract class AbstractTeamsConversations implements TeamsConversations {

private MicrosoftAppCredentials mac;
private SpringBotMicrosoftAppCredentials mac;
private BotFrameworkAdapter bfa;
private ChannelAccount botAccount;

public AbstractTeamsConversations(BotFrameworkAdapter bfa, MicrosoftAppCredentials mac, ChannelAccount botAccount) {
public AbstractTeamsConversations(BotFrameworkAdapter bfa, SpringBotMicrosoftAppCredentials mac, ChannelAccount botAccount) {
super();
this.mac = mac;
this.bfa = bfa;
Expand Down Expand Up @@ -145,7 +144,7 @@ protected String getOneToOneConversationId(TeamsUser tu) {
try {
ConversationParameters cp = new ConversationParameters();
cp.setIsGroup(false);
cp.setTenantId(mac.getChannelAuthTenant());
cp.setTenantId(mac.getTenantId());
cp.setMembers(Collections.singletonList(new ChannelAccount(tu.getKey())));

return getConversations().createConversation(cp).get().getId();
Expand All @@ -159,17 +158,17 @@ public ConversationAccount getConversationAccount(TeamsAddressable address) {
if (address instanceof TeamsUser) {
String chatForUser = getOneToOneConversationId((TeamsUser) address);
ConversationAccount ca = new ConversationAccount(chatForUser);
ca.setTenantId(mac.getChannelAuthTenant());
ca.setTenantId(mac.getTenantId());
ca.setConversationType("personal");
return ca;
} else if (address instanceof TeamsChannel) {
ConversationAccount ca = new ConversationAccount(address.getKey());
ca.setTenantId(mac.getChannelAuthTenant());
ca.setTenantId(mac.getTenantId());
ca.setConversationType("channel");
return ca;
} else if (address instanceof TeamsMultiwayChat) {
ConversationAccount ca = new ConversationAccount(address.getKey());
ca.setTenantId(mac.getChannelAuthTenant());
ca.setTenantId(mac.getTenantId());
ca.setConversationType("groupChat");
return ca;
} else {
Expand Down Expand Up @@ -226,7 +225,7 @@ private TurnContext getWorkingTurnContext(TeamsAddressable ta) {

TurnContext[] holder = new TurnContext[1];

bfa.continueConversation(mac.getAppId(), createConversationReference(ta), tc -> {
bfa.continueConversation(mac.getClientId(), createConversationReference(ta), tc -> {
holder[0] = tc;
return CompletableFuture.completedFuture(null);
}).get();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.finos.springbot.teams.conversations;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientCertificateCredential;
import com.azure.identity.ClientCertificateCredentialBuilder;

public class SpringBotMicrosoftAppCredentials {

private String tenantId;
private String clientId;
private ClientCertificateCredential credential;

public SpringBotMicrosoftAppCredentials(String tenantId, String clientId, String certificate,
String certificatePassword) {
this.tenantId = tenantId;
this.clientId = clientId;
String pemContent = certificate;
// Check for file extension and illegal path characters
boolean isFilePath = (certificate != null && (certificate.endsWith(".p12")));
try {
if (!isFilePath) {
byte[] decode = Base64.getDecoder().decode(pemContent);

java.nio.file.Path tempFile = Files.createTempFile("cert", ".p12");
Files.write(tempFile, decode);
certificate = tempFile.toAbsolutePath().toString();
}

this.credential = new ClientCertificateCredentialBuilder().tenantId(tenantId).clientId(clientId)
.pemCertificate(Files.newInputStream(Paths.get(certificate)))
.clientCertificatePassword(certificatePassword).build();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Failed to create certificate", e);
}
}

public String getTenantId() {
return tenantId;
}

public String getClientId() {
return clientId;
}

public ClientCertificateCredential getCredential() {
return credential;
}

public String getToken() {
// SOMETHING LIKE THIS
return credential.getTokenSync(new TokenRequestContext().addScopes("https://graph.microsoft.com/.default"))
.getToken();
}

public static InputStream stringToInputStream(String content) {
return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.finos.springbot.workflow.content.Chat;

import com.microsoft.bot.builder.BotFrameworkAdapter;
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
import com.microsoft.bot.schema.ChannelAccount;

public class StateStorageBasedTeamsConversations extends AbstractTeamsConversations {
Expand All @@ -34,7 +33,7 @@ public class StateStorageBasedTeamsConversations extends AbstractTeamsConversati

protected final TeamsStateStorage tss;

public StateStorageBasedTeamsConversations(BotFrameworkAdapter bfa, MicrosoftAppCredentials mac,
public StateStorageBasedTeamsConversations(BotFrameworkAdapter bfa, SpringBotMicrosoftAppCredentials mac,
ChannelAccount botAccount, TeamsStateStorage tss) {
super(bfa, mac, botAccount);
this.tss = tss;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import com.azure.identity.ClientCertificateCredential;
import com.microsoft.bot.builder.BotFrameworkAdapter;
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
import com.microsoft.bot.integration.AdapterWithErrorHandler;
Expand All @@ -19,24 +20,32 @@
public class TeamsConversationsConfig extends BotDependencyConfiguration {

@Bean
public MicrosoftAppCredentials microsoftCredentials(@Value("${teams.app.tennantId}") String tennantId) {
public SpringBotMicrosoftAppCredentials microsoftCredentials(@Value("${teams.app.tennantId}") String tennantId) {
com.microsoft.bot.integration.Configuration conf = getConfiguration();
MicrosoftAppCredentials mac = new MicrosoftAppCredentials(
conf.getProperty(MicrosoftAppCredentials.MICROSOFTAPPID),
conf.getProperty(MicrosoftAppCredentials.MICROSOFTAPPPASSWORD),
tennantId);
return mac;

String clientId = conf.getProperty(MicrosoftAppCredentials.MICROSOFTAPPID);

SpringBotMicrosoftAppCredentials out = new SpringBotMicrosoftAppCredentials(tennantId,
clientId, conf.getProperty("MicrosoftAppIdPemCertificate"), conf.getProperty("MicrosoftAppIdPemCertificatePassword"));

// MicrosoftAppCredentials mac = new MicrosoftAppCredentials(
// conf.getProperty(MicrosoftAppCredentials.MICROSOFTAPPID),
// conf.getProperty(MicrosoftAppCredentials.MICROSOFTAPPPASSWORD),
// tennantId);

return out;
}


@Bean
@ConditionalOnMissingBean
public TeamsConversations teamsConversations(
BotFrameworkAdapter bfa,
MicrosoftAppCredentials mac,
SpringBotMicrosoftAppCredentials appCredentials,
@Value("${teams.bot.id:}") String id,
TeamsStateStorage teamsState) {
ChannelAccount botAccount = new ChannelAccount(id);
return new StateStorageBasedTeamsConversations(bfa, mac, botAccount, teamsState);
return new StateStorageBasedTeamsConversations(bfa, appCredentials, botAccount, teamsState);
}


Expand Down
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
<jsoup.version>1.17.2</jsoup.version>
<graalvm.version>23.0.3</graalvm.version>
<symphony-bdk.version>3.0.0</symphony-bdk.version>
<azure-core-http-netty.version>1.16.1</azure-core-http-netty.version>
<azure-core-http-netty.version>1.16.1</azure-core-http-netty.version>
<azure-identity.version>1.18.0</azure-identity.version>
<corenlp.version>4.5.7</corenlp.version>
<azure-msal4j.version>1.21.0</azure-msal4j.version>
<protonpack.version>1.16</protonpack.version>
Expand Down
Loading