Skip to content

Commit 5d17bda

Browse files
authored
Merge pull request #2750 from simonredfern/develop
Chat Room endpoints with optional gRPC services for GET
2 parents 04db571 + 30f6068 commit 5d17bda

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+8275
-83
lines changed

flushall_build_and_run.sh

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,23 @@ JAVA_OPTS="--add-opens java.base/java.lang=ALL-UNNAMED \
149149
--add-opens java.base/java.util.jar=ALL-UNNAMED \
150150
--add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED"
151151

152+
RUNTIME_LOG=/tmp/obp-api.log
153+
152154
if [ "$RUN_BACKGROUND" = true ]; then
153-
# Run in background with output to log file
154-
nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > http4s-server.log 2>&1 &
155+
# Run in background with output to log file (tee'd to /tmp as well)
156+
nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > >(tee "$RUNTIME_LOG") 2>&1 &
155157
SERVER_PID=$!
156158
echo "✓ HTTP4S server started in background"
157159
echo " PID: $SERVER_PID"
158-
echo " Log: http4s-server.log"
160+
echo " Log: http4s-server.log (also $RUNTIME_LOG)"
159161
echo ""
160162
echo "To stop the server: kill $SERVER_PID"
161163
echo "To view logs: tail -f http4s-server.log"
162164
else
163-
# Run in foreground (Ctrl+C to stop)
165+
# Run in foreground (Ctrl+C to stop). Also tee output to /tmp so it can be
166+
# tailed from another terminal without taking over this one.
164167
echo "Press Ctrl+C to stop the server"
168+
echo "Runtime log also written to: $RUNTIME_LOG"
165169
echo ""
166-
java $JAVA_OPTS -jar obp-api/target/obp-api.jar
170+
java $JAVA_OPTS -jar obp-api/target/obp-api.jar 2>&1 | tee "$RUNTIME_LOG"
167171
fi

obp-api/pom.xml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,25 @@
323323
<artifactId>scalapb-runtime-grpc_${scala.version}</artifactId>
324324
<version>0.8.4</version>
325325
</dependency>
326-
<!-- https://mvnrepository.com/artifact/io.grpc/grpc-all -->
327326
<dependency>
328327
<groupId>io.grpc</groupId>
329-
<artifactId>grpc-all</artifactId>
328+
<artifactId>grpc-netty-shaded</artifactId>
330329
<version>1.48.1</version>
331330
</dependency>
332331
<dependency>
333-
<groupId>io.netty</groupId>
334-
<artifactId>netty-tcnative-boringssl-static</artifactId>
335-
<version>2.0.27.Final</version>
332+
<groupId>io.grpc</groupId>
333+
<artifactId>grpc-protobuf</artifactId>
334+
<version>1.48.1</version>
335+
</dependency>
336+
<dependency>
337+
<groupId>io.grpc</groupId>
338+
<artifactId>grpc-stub</artifactId>
339+
<version>1.48.1</version>
340+
</dependency>
341+
<dependency>
342+
<groupId>io.grpc</groupId>
343+
<artifactId>grpc-services</artifactId>
344+
<version>1.48.1</version>
336345
</dependency>
337346
<dependency>
338347
<groupId>org.asynchttpclient</groupId>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
syntax = "proto3";
2+
package code.obp.grpc.chat.g1;
3+
4+
import "google/protobuf/timestamp.proto";
5+
6+
message StreamMessagesRequest {
7+
string chat_room_id = 1;
8+
}
9+
10+
// Fields match ChatMessageJsonV600 exactly, plus event_type for stream events
11+
message ChatMessageEvent {
12+
string event_type = 1;
13+
string chat_message_id = 2;
14+
string chat_room_id = 3;
15+
string sender_user_id = 4;
16+
string sender_consumer_id = 5;
17+
string sender_username = 6;
18+
string sender_provider = 7;
19+
string sender_consumer_name = 8;
20+
string content = 9;
21+
string message_type = 10;
22+
repeated string mentioned_user_ids = 11;
23+
string reply_to_message_id = 12;
24+
string thread_id = 13;
25+
bool is_deleted = 14;
26+
google.protobuf.Timestamp created_at = 15;
27+
google.protobuf.Timestamp updated_at = 16;
28+
}
29+
30+
message TypingEvent {
31+
string chat_room_id = 1;
32+
bool is_typing = 2;
33+
}
34+
35+
// Fields match TypingUserJsonV600
36+
message TypingIndicator {
37+
string chat_room_id = 1;
38+
string user_id = 2;
39+
string username = 3;
40+
string provider = 4;
41+
bool is_typing = 5;
42+
}
43+
44+
message StreamPresenceRequest {
45+
string chat_room_id = 1;
46+
}
47+
48+
message PresenceEvent {
49+
string user_id = 1;
50+
string username = 2;
51+
string provider = 3;
52+
bool is_online = 4;
53+
}
54+
55+
message StreamUnreadCountsRequest {
56+
}
57+
58+
message UnreadCountEvent {
59+
string chat_room_id = 1;
60+
int64 unread_count = 2;
61+
}
62+
63+
service ChatStreamService {
64+
rpc StreamMessages(StreamMessagesRequest) returns (stream ChatMessageEvent);
65+
rpc StreamTyping(stream TypingEvent) returns (stream TypingIndicator);
66+
rpc StreamPresence(StreamPresenceRequest) returns (stream PresenceEvent);
67+
rpc StreamUnreadCounts(StreamUnreadCountsRequest) returns (stream UnreadCountEvent);
68+
}

obp-api/src/main/resources/props/sample.props.template

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,10 +1196,13 @@ database_messages_scheduler_interval=3600
11961196
# GRPC
11971197
# the default GRPC is disabled
11981198
# grpc.server.enabled = false
1199-
# If do not set this props, the grpc port will be set randomly when OBP starts.
1200-
# And you can call `Get API Configuration` endpoint to see the `grpc_port` there.
1201-
# When you set this props, need to make sure this port is available.
1199+
# The default gRPC port is 50051. Override if needed.
12021200
# grpc.server.port = 50051
1201+
# When gRPC is enabled, chat streaming services (StreamMessages, StreamTyping,
1202+
# StreamPresence, StreamUnreadCounts) are available on the same port.
1203+
# Clients authenticate via the "authorization" metadata key using the same
1204+
# DirectLogin or OAuth tokens as the REST API.
1205+
# See src/main/protobuf/chat.proto for the service contract.
12031206

12041207
# Create System Views At Boot -----------------------------------------------
12051208
# In case is not defined default value is true

obp-api/src/main/scala/bootstrap/liftweb/Boot.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ import code.migration.MigrationScriptLog
105105
import code.model._
106106
import code.model.dataAccess._
107107
import code.model.dataAccess.internalMapping.AccountIdMapping
108-
import code.obp.grpc.HelloWorldServer
108+
import code.obp.grpc.ObpGrpcServer
109109
import code.productAttributeattribute.MappedProductAttribute
110110
import code.productcollection.MappedProductCollection
111111
import code.productcollectionitem.MappedProductCollectionItem
@@ -131,6 +131,7 @@ import code.transaction_types.MappedTransactionType
131131
import code.transactionattribute.MappedTransactionAttribute
132132
import code.transactionrequests.{MappedTransactionRequest, MappedTransactionRequestTypeCharge, TransactionRequestReasons}
133133
import code.usercustomerlinks.MappedUserCustomerLink
134+
import code.customerlinks.CustomerLink
134135
import code.userlocks.UserLocks
135136
import code.users._
136137
import code.util.Helper.{MdcLoggable, ObpS, SILENCE_IS_GOLDEN}
@@ -761,6 +762,8 @@ class Boot extends MdcLoggable {
761762

762763
def schemifyAll() = {
763764
Schemifier.schemify(true, Schemifier.infoF _, ToSchemify.models: _*)
765+
// Create default system-level "general" chat room (all_users_are_participants = true)
766+
code.chat.ChatRoomTrait.chatRoomProvider.vend.getOrCreateDefaultRoom()
764767
}
765768

766769
private def showExceptionAtJson(error: Throwable): String = {
@@ -1161,6 +1164,7 @@ object ToSchemify {
11611164
MappedNarrative,
11621165
MappedCustomer,
11631166
MappedUserCustomerLink,
1167+
CustomerLink,
11641168
Consumer,
11651169
Token,
11661170
OpenIDConnectToken,
@@ -1203,12 +1207,16 @@ object ToSchemify {
12031207
CounterpartyAttributeMapper,
12041208
BankAccountBalance,
12051209
Group,
1206-
AccountAccessRequest
1210+
AccountAccessRequest,
1211+
code.chat.ChatRoom,
1212+
code.chat.Participant,
1213+
code.chat.ChatMessage,
1214+
code.chat.Reaction
12071215
)
12081216

12091217
// start grpc server
12101218
if (APIUtil.getPropsAsBoolValue("grpc.server.enabled", false)) {
1211-
val server = new HelloWorldServer(ExecutionContext.global)
1219+
val server = new ObpGrpcServer(ExecutionContext.global)
12121220
server.start()
12131221
LiftRules.unloadHooks.append(server.stop)
12141222
}

obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6103,6 +6103,75 @@ object SwaggerDefinitionsJSON {
61036103
List(counterpartyAttributeResponseJsonV600)
61046104
)
61056105

6106+
lazy val postCustomerLinkJsonV600 = PostCustomerLinkJsonV600(
6107+
customer_id = customerIdExample.value,
6108+
other_bank_id = bankIdExample.value,
6109+
other_customer_id = customerIdExample.value,
6110+
relationship_to = "spouse"
6111+
)
6112+
6113+
lazy val putCustomerLinkJsonV600 = PutCustomerLinkJsonV600(
6114+
relationship_to = "close_associate"
6115+
)
6116+
6117+
lazy val customerLinkJsonV600 = CustomerLinkJsonV600(
6118+
customer_link_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f",
6119+
bank_id = bankIdExample.value,
6120+
customer_id = customerIdExample.value,
6121+
other_bank_id = bankIdExample.value,
6122+
other_customer_id = customerIdExample.value,
6123+
relationship_to = "spouse",
6124+
date_inserted = DateWithDayExampleObject,
6125+
date_updated = DateWithDayExampleObject
6126+
)
6127+
6128+
lazy val customerLinksJsonV600 = CustomerLinksJsonV600(
6129+
List(customerLinkJsonV600)
6130+
)
6131+
6132+
lazy val investigationTransactionJsonV600 = InvestigationTransactionJsonV600(
6133+
transaction_id = transactionIdExample.value,
6134+
account_id = accountIdExample.value,
6135+
amount = "1250",
6136+
currency = currencyExample.value,
6137+
transaction_type = "DEBIT",
6138+
description = "Payment for consulting services",
6139+
start_date = DateWithDayExampleObject,
6140+
finish_date = DateWithDayExampleObject,
6141+
counterparty_name = "ACME Corp",
6142+
counterparty_account = "DE89370400440532013000",
6143+
counterparty_bank_name = "Deutsche Bank"
6144+
)
6145+
6146+
lazy val investigationAccountJsonV600 = InvestigationAccountJsonV600(
6147+
account_id = accountIdExample.value,
6148+
bank_id = bankIdExample.value,
6149+
currency = currencyExample.value,
6150+
balance = "150000",
6151+
account_name = "Current Account",
6152+
account_type = "CURRENT",
6153+
transactions = List(investigationTransactionJsonV600)
6154+
)
6155+
6156+
lazy val investigationCustomerLinkJsonV600 = InvestigationCustomerLinkJsonV600(
6157+
customer_link_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f",
6158+
other_customer_id = customerIdExample.value,
6159+
other_bank_id = bankIdExample.value,
6160+
relationship = "spouse",
6161+
other_legal_name = "Jane Doe"
6162+
)
6163+
6164+
lazy val investigationReportJsonV600 = InvestigationReportJsonV600(
6165+
customer_id = customerIdExample.value,
6166+
legal_name = "John Doe",
6167+
bank_id = bankIdExample.value,
6168+
accounts = List(investigationAccountJsonV600),
6169+
related_customers = List(investigationCustomerLinkJsonV600),
6170+
from_date = DateWithDayExampleObject,
6171+
to_date = DateWithDayExampleObject,
6172+
data_source = "mapped_database"
6173+
)
6174+
61066175
lazy val bankAccountBalanceRequestJsonV510 = BankAccountBalanceRequestJsonV510(
61076176
balance_type = balanceTypeExample.value,
61086177
balance_amount = balanceAmountExample.value

obp-api/src/main/scala/code/api/util/ApiRole.scala

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,25 @@ object ApiRole extends MdcLoggable{
317317

318318
case class CanGetCustomerAccountLinks(requiresBankId: Boolean = true) extends ApiRole
319319
lazy val canGetCustomerAccountLinks = CanGetCustomerAccountLinks()
320-
320+
321+
case class CanCreateCustomerLink(requiresBankId: Boolean = true) extends ApiRole
322+
lazy val canCreateCustomerLink = CanCreateCustomerLink()
323+
324+
case class CanUpdateCustomerLink(requiresBankId: Boolean = true) extends ApiRole
325+
lazy val canUpdateCustomerLink = CanUpdateCustomerLink()
326+
327+
case class CanDeleteCustomerLink(requiresBankId: Boolean = true) extends ApiRole
328+
lazy val canDeleteCustomerLink = CanDeleteCustomerLink()
329+
330+
case class CanGetCustomerLink(requiresBankId: Boolean = true) extends ApiRole
331+
lazy val canGetCustomerLink = CanGetCustomerLink()
332+
333+
case class CanGetCustomerLinks(requiresBankId: Boolean = true) extends ApiRole
334+
lazy val canGetCustomerLinks = CanGetCustomerLinks()
335+
336+
case class CanGetInvestigationReport(requiresBankId: Boolean = true) extends ApiRole
337+
lazy val canGetInvestigationReport = CanGetInvestigationReport()
338+
321339
case class CanCreateBranch(requiresBankId: Boolean = true) extends ApiRole
322340
lazy val canCreateBranch = CanCreateBranch()
323341

@@ -1352,6 +1370,20 @@ object ApiRole extends MdcLoggable{
13521370
case class CanGetAccountDirectoryAtOneBank(requiresBankId: Boolean = true) extends ApiRole
13531371
lazy val canGetAccountDirectoryAtOneBank = CanGetAccountDirectoryAtOneBank()
13541372

1373+
// Chat Room roles
1374+
case class CanDeleteBankChatRoom(requiresBankId: Boolean = true) extends ApiRole
1375+
lazy val canDeleteBankChatRoom = CanDeleteBankChatRoom()
1376+
case class CanDeleteSystemChatRoom(requiresBankId: Boolean = false) extends ApiRole
1377+
lazy val canDeleteSystemChatRoom = CanDeleteSystemChatRoom()
1378+
case class CanArchiveBankChatRoom(requiresBankId: Boolean = true) extends ApiRole
1379+
lazy val canArchiveBankChatRoom = CanArchiveBankChatRoom()
1380+
case class CanArchiveSystemChatRoom(requiresBankId: Boolean = false) extends ApiRole
1381+
lazy val canArchiveSystemChatRoom = CanArchiveSystemChatRoom()
1382+
case class CanSetBankChatRoomAUAP(requiresBankId: Boolean = true) extends ApiRole
1383+
lazy val canSetBankChatRoomAUAP = CanSetBankChatRoomAUAP()
1384+
case class CanSetSystemChatRoomAUAP(requiresBankId: Boolean = false) extends ApiRole
1385+
lazy val canSetSystemChatRoomAUAP = CanSetSystemChatRoomAUAP()
1386+
13551387
private val dynamicApiRoles = new ConcurrentHashMap[String, ApiRole]
13561388

13571389
private case class DynamicApiRole(role: String, requiresBankId: Boolean = false) extends ApiRole{

obp-api/src/main/scala/code/api/util/ApiTag.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ object ApiTag {
8989
val apiTagAggregateMetrics = ResourceDocTag("Aggregate-Metrics")
9090
val apiTagSystemIntegrity = ResourceDocTag("System-Integrity")
9191
val apiTagBalance = ResourceDocTag("Balance")
92+
val apiTagChat = ResourceDocTag("Chat")
9293
val apiTagGroup = ResourceDocTag("Group")
9394
val apiTagWebhook = ResourceDocTag("Webhook")
9495
val apiTagMockedData = ResourceDocTag("Mocked-Data")
@@ -164,6 +165,7 @@ object ApiTag {
164165
val apiTagSignal = ResourceDocTag("Signal")
165166
val apiTagSignalling = ResourceDocTag("Signalling")
166167
val apiTagChannel = ResourceDocTag("Channel")
168+
val apiTagFinancialCrime = ResourceDocTag("Financial-Crime")
167169

168170
private[this] val tagNameSymbolMapTag: MutableMap[String, ResourceDocTag] = MutableMap()
169171

0 commit comments

Comments
 (0)