diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 17920b96a..b285837c0 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -1901,6 +1901,7 @@ object NewStyle extends MdcLoggable{ name: String, attributeType: UserAttributeType.Value, value: String, + isPersonal: Boolean, callContext: Option[CallContext] ): OBPReturnType[UserAttribute] = { Connector.connector.vend.createOrUpdateUserAttribute( @@ -1909,6 +1910,7 @@ object NewStyle extends MdcLoggable{ name: String, attributeType: UserAttributeType.Value, value: String, + isPersonal: Boolean, callContext: Option[CallContext] ) map { i => (connectorEmptyResponse(i._1, callContext), i._2) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 39e3126f0..18a86f5b6 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -8739,13 +8739,13 @@ trait APIMethods400 { } staticResourceDocs += ResourceDoc( - getCurrentUserAttributes, + getMyPersonalUserAttributes, implementedInApiVersion, - nameOf(getCurrentUserAttributes), + nameOf(getMyPersonalUserAttributes), "GET", "/my/user/attributes", - "Get User Attributes for current user", - s"""Get User Attributes for current user. + "Get My Personal User Attributes", + s"""Get My Personal User Attributes. | |${authenticationRequiredMessage(true)} |""".stripMargin, @@ -8758,7 +8758,7 @@ trait APIMethods400 { List(apiTagUser, apiTagNewStyle) ) - lazy val getCurrentUserAttributes: OBPEndpoint = { + lazy val getMyPersonalUserAttributes: OBPEndpoint = { case "my" :: "user" :: "attributes" :: Nil JsonGet _ => { cc => for { @@ -8805,15 +8805,15 @@ trait APIMethods400 { staticResourceDocs += ResourceDoc( - createCurrentUserAttribute, + createMyPersonalUserAttribute, implementedInApiVersion, - nameOf(createCurrentUserAttribute), + nameOf(createMyPersonalUserAttribute), "POST", "/my/user/attributes", - "Create User Attribute for current user", - s""" Create User Attribute for current user + "Create My Personal User Attribute", + s""" Create My Personal User Attribute | - |The type field must be one of "STRING", "INTEGER", "DOUBLE" or DATE_WITH_DAY" + |The `type` field must be one of "STRING", "INTEGER", "DOUBLE" or DATE_WITH_DAY" | |${authenticationRequiredMessage(true)} | @@ -8828,18 +8828,17 @@ trait APIMethods400 { List(apiTagUser, apiTagNewStyle), Some(List())) - lazy val createCurrentUserAttribute : OBPEndpoint = { + lazy val createMyPersonalUserAttribute : OBPEndpoint = { case "my" :: "user" :: "attributes" :: Nil JsonPost json -> _=> { cc => - val failMsg = s"$InvalidJsonFormat The Json body should be the $TransactionAttributeJsonV400 " + val failMsg = s"$InvalidJsonFormat The Json body should be the $UserAttributeJsonV400 " for { - (attributes, callContext) <- NewStyle.function.getUserAttributes(cc.userId, cc.callContext) - postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.extract[TransactionAttributeJsonV400] + postedData <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { + json.extract[UserAttributeJsonV400] } failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + - s"${TransactionAttributeType.DOUBLE}(12.1234), ${TransactionAttributeType.STRING}(TAX_NUMBER), ${TransactionAttributeType.INTEGER} (123)and ${TransactionAttributeType.DATE_WITH_DAY}(2012-04-23)" - userAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { + s"${TransactionAttributeType.DOUBLE}(12.1234), ${UserAttributeType.STRING}(TAX_NUMBER), ${UserAttributeType.INTEGER} (123)and ${UserAttributeType.DATE_WITH_DAY}(2012-04-23)" + userAttributeType <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { UserAttributeType.withName(postedData.`type`) } (userAttribute, callContext) <- NewStyle.function.createOrUpdateUserAttribute( @@ -8848,7 +8847,8 @@ trait APIMethods400 { postedData.name, userAttributeType, postedData.value, - callContext + true, + cc.callContext ) } yield { (JSONFactory400.createUserAttributeJson(userAttribute), HttpCode.`201`(callContext)) @@ -8862,8 +8862,8 @@ trait APIMethods400 { nameOf(updateCurrentUserAttribute), "PUT", "/my/user/attributes/USER_ATTRIBUTE_ID", - "Update User Attribute for current user", - s"""Update User Attribute for current user by USER_ATTRIBUTE_ID + "Update My Personal User Attribute", + s"""Update My Personal User Attribute for current user by USER_ATTRIBUTE_ID | |The type field must be one of "STRING", "INTEGER", "DOUBLE" or DATE_WITH_DAY" | @@ -8883,7 +8883,7 @@ trait APIMethods400 { lazy val updateCurrentUserAttribute : OBPEndpoint = { case "my" :: "user" :: "attributes" :: userAttributeId :: Nil JsonPut json -> _=> { cc => - val failMsg = s"$InvalidJsonFormat The Json body should be the $TransactionAttributeJsonV400 " + val failMsg = s"$InvalidJsonFormat The Json body should be the $UserAttributeJsonV400 " for { (attributes, callContext) <- NewStyle.function.getUserAttributes(cc.userId, cc.callContext) failMsg = s"$UserAttributeNotFound" @@ -8891,10 +8891,10 @@ trait APIMethods400 { attributes.exists(_.userAttributeId == userAttributeId) } postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { - json.extract[TransactionAttributeJsonV400] + json.extract[UserAttributeJsonV400] } failMsg = s"$InvalidJsonFormat The `Type` field can only accept the following field: " + - s"${TransactionAttributeType.DOUBLE}(12.1234), ${TransactionAttributeType.STRING}(TAX_NUMBER), ${TransactionAttributeType.INTEGER} (123)and ${TransactionAttributeType.DATE_WITH_DAY}(2012-04-23)" + s"${UserAttributeType.DOUBLE}(12.1234), ${UserAttributeType.STRING}(TAX_NUMBER), ${UserAttributeType.INTEGER} (123)and ${UserAttributeType.DATE_WITH_DAY}(2012-04-23)" userAttributeType <- NewStyle.function.tryons(failMsg, 400, callContext) { UserAttributeType.withName(postedData.`type`) } @@ -8904,6 +8904,7 @@ trait APIMethods400 { postedData.name, userAttributeType, postedData.value, + true, callContext ) } yield { diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 3da4fc675..5046b11bb 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -121,8 +121,8 @@ trait APIMethods510 { nameOf(createUserAttribute), "POST", "/users/USER_ID/attributes", - "Create User Attribute for the user", - s""" Create User Attribute for the user + "Create User Attribute", + s""" Create User Attribute | |The type field must be one of "STRING", "INTEGER", "DOUBLE" or DATE_WITH_DAY" | @@ -161,9 +161,11 @@ trait APIMethods510 { postedData.name, userAttributeType, postedData.value, - callContext) + false, + callContext + ) } yield { - (JSONFactory400.createUserAttributeJson(userAttribute), HttpCode.`201`(callContext)) + (JSONFactory510.createUserAttributeJson(userAttribute), HttpCode.`201`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala b/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala index ec2529ad3..c3a3eab94 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/JSONFactory5.1.0.scala @@ -35,10 +35,12 @@ import code.api.v3_0_0.{AddressJsonV300, OpeningTimesV300} import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400} import code.atmattribute.AtmAttribute import code.atms.Atms.Atm +import code.users.UserAttribute import code.views.system.{AccountAccess, ViewDefinition} import com.openbankproject.commons.model.{Address, AtmId, AtmT, BankId, Location, Meta} import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} +import java.util.Date import scala.collection.immutable.List import scala.util.Try @@ -155,6 +157,16 @@ case class AtmAttributeResponseJsonV510( ) case class AtmAttributesResponseJsonV510(atm_attributes: List[AtmAttributeResponseJsonV510]) +case class UserAttributeResponseJsonV510( + user_attribute_id: String, + name: String, + `type`: String, + value: String, + insert_date: Date, + is_personal: Boolean +) + + object JSONFactory510 { @@ -372,6 +384,16 @@ object JSONFactory510 { def createAtmAttributesJson(atmAttributes: List[AtmAttribute]): AtmAttributesResponseJsonV510 = AtmAttributesResponseJsonV510(atmAttributes.map(createAtmAttributeJson)) + def createUserAttributeJson(userAttribute: UserAttribute): UserAttributeResponseJsonV510 = { + UserAttributeResponseJsonV510( + user_attribute_id = userAttribute.userAttributeId, + name = userAttribute.name, + `type` = userAttribute.attributeType.toString, + value = userAttribute.value, + insert_date = userAttribute.insertDate, + is_personal = userAttribute.isPersonal + ) + } } diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 2a2e8ec69..e4160e1d3 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -2269,6 +2269,7 @@ trait Connector extends MdcLoggable { name: String, attributeType: UserAttributeType.Value, value: String, + isPersonal: Boolean, callContext: Option[CallContext] ): OBPReturnType[Box[UserAttribute]] = Future{(Failure(setUnimplementedError), callContext)} diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index ba3f9edd0..1484bb208 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -4089,6 +4089,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { name: String, attributeType: UserAttributeType.Value, value: String, + isPersonal: Boolean, callContext: Option[CallContext] ): OBPReturnType[Box[UserAttribute]] = { UserAttributeProvider.userAttributeProvider.vend.createOrUpdateUserAttribute( @@ -4096,7 +4097,8 @@ object LocalMappedConnector extends Connector with MdcLoggable { userAttributeId: Option[String], name: String, attributeType: UserAttributeType.Value, - value: String + value: String, + isPersonal: Boolean ) map { (_, callContext) } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUserAttribute.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUserAttribute.scala index 5707f9688..eb78d96fb 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUserAttribute.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUserAttribute.scala @@ -29,7 +29,8 @@ object RemotedataUserAttribute extends ObpActorInit with UserAttributeProvider { userAttributeId: Option[String], name: String, attributeType: UserAttributeType.Value, - value: String): Future[Box[UserAttribute]] = - (actor ? cc.createOrUpdateUserAttribute(userId, userAttributeId, name, attributeType, value )).mapTo[Box[UserAttribute]] + value: String, + isPersonal: Boolean): Future[Box[UserAttribute]] = + (actor ? cc.createOrUpdateUserAttribute(userId, userAttributeId, name, attributeType, value, isPersonal)).mapTo[Box[UserAttribute]] } diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataUserAttributeActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataUserAttributeActor.scala index 9faacc237..312902aae 100644 --- a/obp-api/src/main/scala/code/remotedata/RemotedataUserAttributeActor.scala +++ b/obp-api/src/main/scala/code/remotedata/RemotedataUserAttributeActor.scala @@ -23,9 +23,13 @@ class RemotedataUserAttributeActor extends Actor with ObpActorHelper with MdcLog logger.debug(s"getUserAttributesByUser(${userIds})") mapper.getUserAttributesByUsers(userIds) pipeTo sender - case cc.createOrUpdateUserAttribute(userId: String, userAttributeId: Option[String], name: String, attributeType: UserAttributeType.Value, value: String) => - logger.debug(s"createOrUpdateUserAttribute(${userId}, ${userAttributeId}, ${name}, ${attributeType}, ${value})") - mapper.createOrUpdateUserAttribute(userId, userAttributeId, name, attributeType, value) pipeTo sender + case cc.createOrUpdateUserAttribute( + userId: String, userAttributeId: Option[String], name: String, + attributeType: UserAttributeType.Value, value: String, + isPersonal: Boolean + ) => + logger.debug(s"createOrUpdateUserAttribute(${userId}, ${userAttributeId}, ${name}, ${attributeType}, ${value}, ${isPersonal})") + mapper.createOrUpdateUserAttribute(userId, userAttributeId, name, attributeType, value, isPersonal) pipeTo sender case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) } diff --git a/obp-api/src/main/scala/code/users/MappedUserAttribute.scala b/obp-api/src/main/scala/code/users/MappedUserAttribute.scala index 2c336d973..002cb3132 100644 --- a/obp-api/src/main/scala/code/users/MappedUserAttribute.scala +++ b/obp-api/src/main/scala/code/users/MappedUserAttribute.scala @@ -41,7 +41,8 @@ object MappedUserAttributeProvider extends UserAttributeProvider { userAttributeId: Option[String], name: String, attributeType: UserAttributeType.Value, - value: String): Future[Box[UserAttribute]] = { + value: String, + isPersonal: Boolean): Future[Box[UserAttribute]] = { userAttributeId match { case Some(id) => Future { UserAttribute.find(By(UserAttribute.UserAttributeId, id)) match { @@ -51,6 +52,7 @@ object MappedUserAttributeProvider extends UserAttributeProvider { .Name(name) .Type(attributeType.toString) .`Value`(value) +// .IsPersonal(isPersonal) //Can not update this field in update ne .saveMe() } case _ => Empty @@ -63,6 +65,7 @@ object MappedUserAttributeProvider extends UserAttributeProvider { .Name(name) .Type(attributeType.toString()) .`Value`(value) + .IsPersonal(isPersonal) .saveMe() } } @@ -79,6 +82,9 @@ class UserAttribute extends UserAttributeTrait with LongKeyedMapper[UserAttribut object Name extends MappedString(this, 255) object Type extends MappedString(this, 50) object `Value` extends MappedString(this, 255) + object IsPersonal extends MappedBoolean(this) { + override def defaultValue = true + } override def userAttributeId: String = UserAttributeId.get override def userId: String = UserId.get @@ -86,6 +92,7 @@ class UserAttribute extends UserAttributeTrait with LongKeyedMapper[UserAttribut override def attributeType: UserAttributeType.Value = UserAttributeType.withName(Type.get) override def value: String = `Value`.get override def insertDate: Date = createdAt.get + override def isPersonal: Boolean = IsPersonal.get } object UserAttribute extends UserAttribute with LongKeyedMetaMapper[UserAttribute] { diff --git a/obp-api/src/main/scala/code/users/UserAttributeProvider.scala b/obp-api/src/main/scala/code/users/UserAttributeProvider.scala index 1040a071b..c386b7514 100644 --- a/obp-api/src/main/scala/code/users/UserAttributeProvider.scala +++ b/obp-api/src/main/scala/code/users/UserAttributeProvider.scala @@ -44,7 +44,8 @@ trait UserAttributeProvider { userAttributeId: Option[String], name: String, attributeType: UserAttributeType.Value, - value: String): Future[Box[UserAttribute]] + value: String, + isPersonal: Boolean): Future[Box[UserAttribute]] // End of Trait } @@ -56,7 +57,8 @@ class RemotedataUserAttributeCaseClasses { userAttributeId: Option[String], name: String, attributeType: UserAttributeType.Value, - value: String) + value: String, + isPersonal: Boolean) } object RemotedataUserAttributeCaseClasses extends RemotedataUserAttributeCaseClasses diff --git a/obp-api/src/test/scala/code/api/v4_0_0/UserAttributesTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/UserAttributesTest.scala index 46f1067f2..27e7eb172 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/UserAttributesTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/UserAttributesTest.scala @@ -23,8 +23,8 @@ class UserAttributesTest extends V400ServerSetup { * This is made possible by the scalatest maven plugin */ object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString) - object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createCurrentUserAttribute)) - object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getCurrentUserAttributes)) + object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createMyPersonalUserAttribute)) + object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.getMyPersonalUserAttributes)) object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.updateCurrentUserAttribute)) diff --git a/obp-api/src/test/scala/code/api/v5_1_0/UserAttributesTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/UserAttributesTest.scala index ad87e894f..dd7095989 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/UserAttributesTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/UserAttributesTest.scala @@ -3,9 +3,8 @@ package code.api.v5_1_0 import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole -import code.api.util.ApiRole.CanCreateUserAttribute import code.api.util.ErrorMessages._ -import code.api.v4_0_0.{UserAttributeResponseJsonV400, UsersJsonV400} +import code.api.v4_0_0.UsersJsonV400 import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 import code.entitlement.Entitlement import com.github.dwickern.macros.NameOf.nameOf @@ -72,7 +71,9 @@ class UserAttributesTest extends V510ServerSetup { val response510 = makePostRequest(request510, write(postUserAttributeJsonV510)) Then("We should get a 201") response510.code should equal(201) - val jsonResponse = response510.body.extract[UserAttributeResponseJsonV400] + val jsonResponse = response510.body.extract[UserAttributeResponseJsonV510] + jsonResponse.is_personal shouldBe(false) + jsonResponse.name shouldBe(batteryLevel) val userAttributeId = jsonResponse.user_attribute_id diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala index 63da94958..b95706620 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModelTrait.scala @@ -103,6 +103,7 @@ trait UserAttributeTrait { def attributeType: UserAttributeType.Value def value: String def insertDate: Date + def isPersonal: Boolean } trait AccountAttribute {