Skip to content

Commit cd43086

Browse files
authored
Merge pull request #2721 from constantine2nd/develop
Firstname, lastname
2 parents daa97ea + e2424ea commit cd43086

9 files changed

Lines changed: 140 additions & 17 deletions

File tree

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ connector=star
3737
#hikari.connectionTimeout=
3838
#hikari.maximumPoolSize=
3939
#hikari.idleTimeout=
40-
#hikari.keepaliveTime=
40+
# keepaliveTime must be set below the database/firewall idle TCP timeout to prevent stale-connection
41+
# failures on the first call after a period of inactivity. HikariCP will ping each idle connection
42+
# at this interval (in ms), keeping it alive. Recommended: 30000 (30s) when DB/firewall timeout is ~60s.
43+
#hikari.keepaliveTime=30000
4144
#hikari.maxLifetime=
4245

4346
## if connector = star, then need to set which connectors will be used. For now, obp support rest, akka.

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class CustomDBVendor(driverName: String,
3030
val connectionTimeout = APIUtil.getPropsAsLongValue("hikari.connectionTimeout")
3131
val maximumPoolSize = APIUtil.getPropsAsIntValue("hikari.maximumPoolSize")
3232
val idleTimeout = APIUtil.getPropsAsLongValue("hikari.idleTimeout")
33-
val keepaliveTime = APIUtil.getPropsAsLongValue("hikari.keepaliveTime")
33+
val keepaliveTime = APIUtil.getPropsAsLongValue("hikari.keepaliveTime", 30000L)
3434
val maxLifetime = APIUtil.getPropsAsLongValue("hikari.maxLifetime")
3535

3636
if(connectionTimeout.isDefined){
@@ -42,9 +42,7 @@ class CustomDBVendor(driverName: String,
4242
if(idleTimeout.isDefined){
4343
config.setIdleTimeout(idleTimeout.head)
4444
}
45-
if(keepaliveTime.isDefined){
46-
config.setKeepaliveTime(keepaliveTime.head)
47-
}
45+
config.setKeepaliveTime(keepaliveTime)
4846
if(maxLifetime.isDefined){
4947
config.setMaxLifetime(maxLifetime.head)
5048
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,6 +2635,8 @@ object SwaggerDefinitionsJSON {
26352635
provider_id = providerIdValueExample.value,
26362636
provider = providerValueExample.value,
26372637
username = usernameExample.value,
2638+
first_name = ExampleValue.firstNameExample.value,
2639+
last_name = ExampleValue.lastNameExample.value,
26382640
entitlements = entitlementJSONs,
26392641
views = Some(viewsJSON300),
26402642
agreements = Some(List(userAgreementJson)),
@@ -2649,6 +2651,22 @@ object SwaggerDefinitionsJSON {
26492651
users = List(userInfoJsonV600)
26502652
)
26512653

2654+
lazy val userWithNamesJsonV510 = UserWithNamesJsonV510(
2655+
user_id = ExampleValue.userIdExample.value,
2656+
email = ExampleValue.emailExample.value,
2657+
provider_id = providerIdValueExample.value,
2658+
provider = providerValueExample.value,
2659+
username = usernameExample.value,
2660+
first_name = ExampleValue.firstNameExample.value,
2661+
last_name = ExampleValue.lastNameExample.value,
2662+
entitlements = entitlementJSONs,
2663+
views = Some(viewsJSON300),
2664+
agreements = Some(List(userAgreementJson)),
2665+
is_deleted = false,
2666+
last_marketing_agreement_signed_date = Some(DateWithDayExampleObject),
2667+
is_locked = false
2668+
)
2669+
26522670
lazy val migrationScriptLogJsonV600 = MigrationScriptLogJsonV600(
26532671
migration_script_log_id = "550e8400-e29b-41d4-a716-446655440000",
26542672
name = "addUniqueIndexOnResourceUserUserId",

obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,7 +2670,7 @@ trait APIMethods510 {
26702670
|
26712671
""".stripMargin,
26722672
EmptyBody,
2673-
userJsonV400,
2673+
userWithNamesJsonV510,
26742674
List($AuthenticatedUserIsRequired, UserHasMissingRoles, UserNotFoundByProviderAndUsername, UnknownError),
26752675
List(apiTagUser),
26762676
Some(List(canGetAnyUser))
@@ -2685,8 +2685,14 @@ trait APIMethods510 {
26852685
}
26862686
entitlements <- NewStyle.function.getEntitlementsByUserId(user.userId, cc.callContext)
26872687
isLocked = LoginAttempt.userIsLocked(user.provider, user.name)
2688+
authUser = AuthUser.find(By(AuthUser.user, user.userPrimaryKey.value))
26882689
} yield {
2689-
(JSONFactory400.createUserInfoJSON(user, entitlements, None, isLocked), HttpCode.`200`(cc.callContext))
2690+
(JSONFactory510.createUserWithNamesJSON(
2691+
user,
2692+
authUser.map(_.firstName.get).getOrElse(""),
2693+
authUser.map(_.lastName.get).getOrElse(""),
2694+
entitlements, None, isLocked
2695+
), HttpCode.`200`(cc.callContext))
26902696
}
26912697
}
26922698
}

obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ import code.api.v2_1_0.ResourceUserJSON
4040
import code.api.v3_0_0.JSONFactory300.{createLocationJson, createMetaJson, transformToAddressFromV300}
4141
import code.api.v3_0_0.{AddressJsonV300, OpeningTimesV300}
4242
import code.api.v3_1_0.{CallLimitJson, RateLimit, RedisCallLimitJson}
43-
import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400}
43+
import code.api.v2_0_0.{EntitlementJSONs, JSONFactory200}
44+
import code.api.v3_0_0.ViewsJSON300
45+
import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400, UserAgreementJson}
4446
import code.api.v5_0_0.PostConsentRequestJsonV500
47+
import code.entitlement.Entitlement
48+
import code.model.dataAccess.AuthUser
49+
import code.users.UserAgreement
50+
import net.liftweb.mapper.By
4551
import code.atmattribute.AtmAttribute
4652
import code.atms.Atms.Atm
4753
import code.consent.MappedConsent
@@ -662,6 +668,22 @@ case class SyncExternalUserJson(user_id: String)
662668

663669
case class UserValidatedJson(is_validated: Boolean)
664670

671+
case class UserWithNamesJsonV510(
672+
user_id: String,
673+
email: String,
674+
provider_id: String,
675+
provider: String,
676+
username: String,
677+
first_name: String,
678+
last_name: String,
679+
entitlements: EntitlementJSONs,
680+
views: Option[ViewsJSON300],
681+
agreements: Option[List[UserAgreementJson]],
682+
is_deleted: Boolean,
683+
last_marketing_agreement_signed_date: Option[Date],
684+
is_locked: Boolean
685+
)
686+
665687

666688
case class BankAccountBalanceRequestJsonV510(
667689
balance_type: String,
@@ -1346,4 +1368,31 @@ object JSONFactory510 extends CustomJsonFormats with MdcLoggable {
13461368

13471369
}
13481370

1371+
def createUserWithNamesJSON(
1372+
user: User,
1373+
firstName: String,
1374+
lastName: String,
1375+
entitlements: List[Entitlement],
1376+
agreements: Option[List[UserAgreement]],
1377+
isLocked: Boolean
1378+
): UserWithNamesJsonV510 = {
1379+
UserWithNamesJsonV510(
1380+
user_id = user.userId,
1381+
email = user.emailAddress,
1382+
provider_id = user.idGivenByProvider,
1383+
provider = stringOrNull(user.provider),
1384+
username = stringOrNull(user.name),
1385+
first_name = firstName,
1386+
last_name = lastName,
1387+
entitlements = JSONFactory200.createEntitlementJSONs(entitlements),
1388+
views = None,
1389+
agreements = agreements.map(
1390+
_.map(i => UserAgreementJson(`type` = i.agreementType, text = i.agreementText))
1391+
),
1392+
is_deleted = user.isDeleted.getOrElse(false),
1393+
last_marketing_agreement_signed_date = user.lastMarketingAgreementSignedDate,
1394+
is_locked = isLocked
1395+
)
1396+
}
1397+
13491398
}

obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,9 @@ trait APIMethods600 {
18521852
if (agreementList.isEmpty) None else Some(agreementList)
18531853
}
18541854
isLocked = LoginAttempt.userIsLocked(user.provider, user.name)
1855+
authUser = code.model.dataAccess.AuthUser.find(
1856+
By(code.model.dataAccess.AuthUser.user, user.userPrimaryKey.value)
1857+
)
18551858
// Fetch metrics data for the user
18561859
userMetrics <- Future {
18571860
code.metrics.MappedMetric.findAll(
@@ -1863,7 +1866,16 @@ trait APIMethods600 {
18631866
lastActivityDate = userMetrics.headOption.map(_.getDate())
18641867
recentOperationIds = userMetrics.map(_.getImplementedByPartialFunction()).distinct.take(5)
18651868
} yield {
1866-
(JSONFactory600.createUserInfoJsonV600(user, entitlements, agreements, isLocked, lastActivityDate, recentOperationIds), HttpCode.`200`(callContext))
1869+
(JSONFactory600.createUserInfoJsonV600(
1870+
user,
1871+
authUser.map(_.firstName.get).getOrElse(""),
1872+
authUser.map(_.lastName.get).getOrElse(""),
1873+
entitlements,
1874+
agreements,
1875+
isLocked,
1876+
lastActivityDate,
1877+
recentOperationIds
1878+
), HttpCode.`200`(callContext))
18671879
}
18681880
}
18691881
}

obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ import code.apiproductattribute.ApiProductAttributeTrait
3737
import code.featuredapicollection.FeaturedApiCollectionTrait
3838
import code.loginattempts.LoginAttempt
3939
import code.model.ModeratedBankAccountCore
40-
import code.model.dataAccess.ResourceUser
40+
import code.model.dataAccess.{AuthUser, ResourceUser}
4141
import code.users.UserAgreement
42+
import net.liftweb.mapper.By
4243
import code.util.Helper.MdcLoggable
4344
import com.openbankproject.commons.model.{
4445
AmountOfMoneyJsonV121,
@@ -249,6 +250,8 @@ case class UserInfoJsonV600(
249250
provider_id: String,
250251
provider: String,
251252
username: String,
253+
first_name: String,
254+
last_name: String,
252255
entitlements: EntitlementJSONs,
253256
views: Option[ViewsJSON300],
254257
agreements: Option[List[UserAgreementJson]],
@@ -1077,6 +1080,8 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable {
10771080

10781081
def createUserInfoJsonV600(
10791082
user: User,
1083+
firstName: String,
1084+
lastName: String,
10801085
entitlements: List[Entitlement],
10811086
agreements: Option[List[UserAgreement]],
10821087
isLocked: Boolean,
@@ -1089,6 +1094,8 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable {
10891094
username = stringOrNull(user.name),
10901095
provider_id = user.idGivenByProvider,
10911096
provider = stringOrNull(user.provider),
1097+
first_name = firstName,
1098+
last_name = lastName,
10921099
entitlements = JSONFactory200.createEntitlementJSONs(entitlements),
10931100
views = None,
10941101
agreements = agreements.map(
@@ -1111,16 +1118,19 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable {
11111118
]
11121119
): UsersInfoJsonV600 = {
11131120
UsersInfoJsonV600(
1114-
users.map(t =>
1121+
users.map { t =>
1122+
val authUser = AuthUser.find(By(AuthUser.user, t._1.id.get))
11151123
createUserInfoJsonV600(
11161124
t._1,
1125+
authUser.map(_.firstName.get).getOrElse(""),
1126+
authUser.map(_.lastName.get).getOrElse(""),
11171127
t._2.getOrElse(Nil),
11181128
t._3,
11191129
LoginAttempt.userIsLocked(t._1.provider, t._1.name),
11201130
None,
11211131
List.empty
11221132
)
1123-
)
1133+
}
11241134
)
11251135
}
11261136

obp-api/src/test/scala/code/api/v5_1_0/UserTest.scala

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import code.api.util.APIUtil.OAuth._
44
import code.api.util.ApiRole.{CanGetAnyUser, CanGetEntitlementsForAnyUserAtAnyBank, CanValidateUser}
55
import code.api.util.ErrorMessages.{UserHasMissingRoles, AuthenticatedUserIsRequired, attemptedToOpenAnEmptyBox}
66
import code.api.v3_0_0.UserJsonV300
7-
import code.api.v4_0_0.UserJsonV400
87
import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0
98
import code.entitlement.Entitlement
109
import code.model.UserX
10+
import code.model.dataAccess.AuthUser
1111
import code.users.Users
1212
import com.github.dwickern.macros.NameOf.nameOf
1313
import com.openbankproject.commons.model.ErrorMessage
1414
import com.openbankproject.commons.util.ApiVersion
1515
import net.liftweb.json.Serialization.write
16+
import net.liftweb.util.Helpers.randomString
1617
import org.scalatest.Tag
1718

1819
import java.util.UUID
@@ -59,14 +60,37 @@ class UserTest extends V510ServerSetup {
5960
When("We make a request v5.1.0")
6061
val request400 = (v5_1_0_Request / "users" / "provider"/user.provider / "username" / user.name ).GET <@(user1)
6162
val response400 = makeGetRequest(request400)
62-
Then("We get successful response")
63+
Then("We get successful response with first_name and last_name fields")
6364
response400.code should equal(200)
64-
response400.body.extract[UserJsonV400]
65+
val json = response400.body.extract[UserWithNamesJsonV510]
66+
json.first_name should equal("")
67+
json.last_name should equal("")
6568
Users.users.vend.deleteResourceUser(user.id.get)
6669
}
6770
}
6871

69-
72+
feature(s"test $ApiEndpoint1 version $VersionOfApi - first_name and last_name populated from AuthUser") {
73+
scenario("We will call the endpoint with an AuthUser that has first and last name set", ApiEndpoint1, VersionOfApi) {
74+
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString)
75+
val username = "user.withnames." + UUID.randomUUID.toString.take(8)
76+
val email = s"$username@example.com"
77+
val user = UserX.createResourceUser(defaultProvider, Some(username), None, Some(username), None, Some(UUID.randomUUID.toString), None).openOrThrowException(attemptedToOpenAnEmptyBox)
78+
val authUser = AuthUser.create
79+
.email(email).username(username).password(randomString(12))
80+
.validated(true).firstName("Alice").lastName("Smith")
81+
.provider(defaultProvider).user(user.userPrimaryKey.value).saveMe()
82+
When("We make a request v5.1.0")
83+
val request = (v5_1_0_Request / "users" / "provider" / user.provider / "username" / user.name).GET <@(user1)
84+
val response = makeGetRequest(request)
85+
Then("We get first_name and last_name from AuthUser")
86+
response.code should equal(200)
87+
val json = response.body.extract[UserWithNamesJsonV510]
88+
json.first_name should equal("Alice")
89+
json.last_name should equal("Smith")
90+
authUser.delete_!
91+
Users.users.vend.deleteResourceUser(user.id.get)
92+
}
93+
}
7094

7195
feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access with URL-encoded provider") {
7296
scenario("We will call the endpoint with a provider containing special URL characters (colon, slash)", ApiEndpoint1, VersionOfApi) {
@@ -81,7 +105,7 @@ class UserTest extends V510ServerSetup {
81105
val response = makeGetRequest(request)
82106
Then("We get successful response - endpoint correctly URL-decodes the provider")
83107
response.code should equal(200)
84-
response.body.extract[UserJsonV400]
108+
response.body.extract[UserWithNamesJsonV510]
85109
Users.users.vend.deleteResourceUser(user.id.get)
86110
}
87111
}

obp-api/src/test/scala/code/api/v6_0_0/GetUserByUserIdTest.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class GetUserByUserIdTest extends V600ServerSetup with DefaultUsers {
5757

5858
And("The response should contain user details")
5959
(response.body \ "user_id").extract[String] should equal(resourceUser1.userId)
60+
And("The response should include first_name and last_name fields")
61+
response.body \ "first_name" should not equal net.liftweb.json.JNothing
62+
response.body \ "last_name" should not equal net.liftweb.json.JNothing
6063
}
6164

6265
}

0 commit comments

Comments
 (0)