This is an automated email from the ASF dual-hosted git repository. sergeykamov pushed a commit to branch NLPCRAFT-257 in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
commit 5ec9a27b5c9e4e47e5d405181b7f7a3cff517eb8 Author: Sergey Kamov <[email protected]> AuthorDate: Wed Mar 17 16:04:17 2021 +0300 WIP. --- nlpcraft/src/main/resources/sql/create_schema.sql | 19 ++++-- nlpcraft/src/main/resources/sql/drop_schema.sql | 3 +- .../nlpcraft/server/company/NCCompanyManager.scala | 52 ++++++++++++--- .../nlpcraft/server/rest/NCBasicRestApi.scala | 32 ++++++--- .../apache/nlpcraft/server/sql/NCSqlManager.scala | 78 +++++++++++++++++++--- .../nlpcraft/server/user/NCUserManager.scala | 3 +- .../nlpcraft/server/rest/NCRestCompanySpec.scala | 67 ++++++++++++++----- openapi/nlpcraft_swagger.yml | 15 +++++ sql/mysql/drop_schema.sql | 13 ++-- sql/mysql/schema.sql | 14 ++++ sql/oracle/drop_schema.sql | 8 +++ sql/oracle/schema.sql | 19 +++++- sql/postgres/drop_schema.sql | 13 ++-- sql/postgres/schema.sql | 15 +++++ 14 files changed, 286 insertions(+), 65 deletions(-) diff --git a/nlpcraft/src/main/resources/sql/create_schema.sql b/nlpcraft/src/main/resources/sql/create_schema.sql index d10cc4e..570e215 100644 --- a/nlpcraft/src/main/resources/sql/create_schema.sql +++ b/nlpcraft/src/main/resources/sql/create_schema.sql @@ -34,9 +34,21 @@ CREATE TABLE nc_company ( last_modified_on TIMESTAMP NOT NULL ) WITH "template=replicated, atomicity=transactional"; -CREATE INDEX company_idx_1 ON nc_company(name); -CREATE INDEX company_idx_2 ON nc_company(auth_token); -CREATE INDEX company_idx_3 ON nc_company(auth_token_hash); +CREATE INDEX nc_company_idx_1 ON nc_company(name); +CREATE INDEX nc_company_idx_2 ON nc_company(auth_token); +CREATE INDEX nc_company_idx_3 ON nc_company(auth_token_hash); + +DROP TABLE IF EXISTS nc_company_property; +CREATE TABLE nc_company_property ( + id LONG PRIMARY KEY, + company_id LONG NOT NULL, -- Foreign key nc_company.id. + property VARCHAR NOT NULL, + value VARCHAR NULL, + created_on TIMESTAMP NOT NULL, + last_modified_on TIMESTAMP NOT NULL +) WITH "template=replicated, atomicity=transactional"; + +CREATE INDEX nc_company_property_idx_1 ON nc_company_property(company_id); DROP TABLE IF EXISTS nc_user; CREATE TABLE nc_user ( @@ -57,7 +69,6 @@ CREATE INDEX nc_user_idx_1 ON nc_user(email); CREATE INDEX nc_user_idx_2 ON nc_user(company_id, ext_id); CREATE INDEX nc_user_idx_3 ON nc_user(company_id); - DROP TABLE IF EXISTS nc_user_property; CREATE TABLE nc_user_property ( id LONG PRIMARY KEY, diff --git a/nlpcraft/src/main/resources/sql/drop_schema.sql b/nlpcraft/src/main/resources/sql/drop_schema.sql index 8756fd4..b1ce0b9 100644 --- a/nlpcraft/src/main/resources/sql/drop_schema.sql +++ b/nlpcraft/src/main/resources/sql/drop_schema.sql @@ -18,6 +18,7 @@ DROP TABLE IF EXISTS proc_log; DROP TABLE IF EXISTS nc_user_property; DROP TABLE IF EXISTS nc_user; +DROP TABLE IF EXISTS nc_company_property; DROP TABLE IF EXISTS nc_company; DROP TABLE IF EXISTS passwd_pool; -DROP TABLE IF EXISTS feedback CASCADE; \ No newline at end of file +DROP TABLE IF EXISTS feedback; \ No newline at end of file diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/company/NCCompanyManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/company/NCCompanyManager.scala index 8274de4..41a6444 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/company/NCCompanyManager.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/company/NCCompanyManager.scala @@ -21,7 +21,7 @@ import io.opencensus.trace.Span import org.apache.ignite.{IgniteAtomicSequence, IgniteSemaphore} import org.apache.nlpcraft.common.{NCService, _} import org.apache.nlpcraft.server.ignite.NCIgniteInstance -import org.apache.nlpcraft.server.mdo.NCCompanyMdo +import org.apache.nlpcraft.server.mdo.{NCCompanyMdo, NCCompanyPropertyMdo} import org.apache.nlpcraft.server.sql.{NCSql, NCSqlManager} import org.apache.nlpcraft.server.user.NCUserManager @@ -98,8 +98,9 @@ object NCCompanyManager extends NCService with NCIgniteInstance { adminFirstName = "Hermann", adminLastName = "Minkowski", adminAvatarUrl = None, - () ⇒ U.DFLT_PROBE_TOKEN, - span + props = None, + mkToken = () ⇒ U.DFLT_PROBE_TOKEN, + parent = span ) logger.info(s"Default admin user ($adminEmail/$adminPwd) created for default company: $compName") @@ -149,12 +150,13 @@ object NCCompanyManager extends NCService with NCIgniteInstance { * @param id * @param name * @param website - * @param address - * @param city + * @param country * @param region + * @param city + * @param address * @param postalCode - * @param country - * parent Optional parent span. + * @param props + * @param parent */ @throws[NCE] def updateCompany( @@ -166,6 +168,7 @@ object NCCompanyManager extends NCService with NCIgniteInstance { city: Option[String], address: Option[String], postalCode: Option[String], + props: Option[Map[String, String]], parent: Span = null ): Unit = startScopedSpan("updateCompany", parent, "id" → id) { span ⇒ @@ -191,6 +194,7 @@ object NCCompanyManager extends NCService with NCIgniteInstance { city = city, address = address, postalCode = postalCode, + propsOpt = props, parent = span ) @@ -250,12 +254,19 @@ object NCCompanyManager extends NCService with NCIgniteInstance { * * @param name * @param website - * @param address - * @param city + * @param country * @param region + * @param city + * @param address * @param postalCode - * @param country - * @param parent Optional parent span. + * @param adminEmail + * @param adminPwd + * @param adminFirstName + * @param adminLastName + * @param adminAvatarUrl + * @param props + * @param mkToken + * @param parent */ @throws[NCE] private def addCompany0( @@ -271,6 +282,7 @@ object NCCompanyManager extends NCService with NCIgniteInstance { adminFirstName: String, adminLastName: String, adminAvatarUrl: Option[String], + props: Option[Map[String, String]], mkToken: () ⇒ String, parent: Span = null ): NCCompanyCreationData = { @@ -299,6 +311,7 @@ object NCCompanyManager extends NCService with NCIgniteInstance { city, address, postalCode, + props, span ) @@ -340,6 +353,7 @@ object NCCompanyManager extends NCService with NCIgniteInstance { * @param adminPwd * @param adminFirstName * @param adminLastName + * @param props * @param adminAvatarUrl * @param parent Optional parent span. */ @@ -357,6 +371,7 @@ object NCCompanyManager extends NCService with NCIgniteInstance { adminFirstName: String, adminLastName: String, adminAvatarUrl: Option[String], + props: Option[Map[String, String]], parent: Span = null ): NCCompanyCreationData = startScopedSpan("addCompany", parent, "name" → name) { _ ⇒ addCompany0( @@ -372,7 +387,22 @@ object NCCompanyManager extends NCService with NCIgniteInstance { adminFirstName, adminLastName, adminAvatarUrl, + props, () ⇒ mkToken() ) } + + /** + * Gets company properties for given company ID. + * + * @param id User ID. + * @param parent Optional parent span. + */ + @throws[NCE] + def getCompanyProperties(id: Long, parent: Span = null): Seq[NCCompanyPropertyMdo] = + startScopedSpan("getCompanyProperties", parent, "companyId" → id) { span ⇒ + NCSql.sql { + NCSqlManager.getCompanyProperties(id, span) + } + } } diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/rest/NCBasicRestApi.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/rest/NCBasicRestApi.scala index 48204a0..bfd8d2a 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/rest/NCBasicRestApi.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/rest/NCBasicRestApi.scala @@ -232,7 +232,7 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w * @param propsOpt Optional properties. */ @throws[TooLargeField] - private def checkUserProperties(propsOpt: Option[Map[String, String]]): Unit = + private def checkProperties(propsOpt: Option[Map[String, String]]): Unit = propsOpt match { case Some(props) ⇒ props.foreach { case (k, v) ⇒ @@ -880,7 +880,8 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w adminPasswd: String, adminFirstName: String, adminLastName: String, - adminAvatarUrl: Option[String] + adminAvatarUrl: Option[String], + properties: Option[Map[String, String]] ) case class Res$Company$Add( status: String, @@ -888,7 +889,7 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w adminId: Long ) - implicit val reqFmt: RootJsonFormat[Req$Company$Add] = jsonFormat13(Req$Company$Add) + implicit val reqFmt: RootJsonFormat[Req$Company$Add] = jsonFormat14(Req$Company$Add) implicit val resFmt: RootJsonFormat[Res$Company$Add] = jsonFormat3(Res$Company$Add) //noinspection DuplicatedCod @@ -910,6 +911,8 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w "adminAvatarUrl" → req.adminAvatarUrl ) + checkProperties(req.properties) + // Via REST only administrators of already created companies can create new companies. authenticateAsAdmin(req.acsTok) @@ -926,6 +929,7 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w req.adminFirstName, req.adminLastName, req.adminAvatarUrl, + req.properties, span ) @@ -953,11 +957,12 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w region: Option[String], city: Option[String], address: Option[String], - postalCode: Option[String] + postalCode: Option[String], + properties: Option[Map[String, String]] ) implicit val reqFmt: RootJsonFormat[Req$Company$Get] = jsonFormat1(Req$Company$Get) - implicit val resFmt: RootJsonFormat[Res$Company$Get] = jsonFormat9(Res$Company$Get) + implicit val resFmt: RootJsonFormat[Res$Company$Get] = jsonFormat10(Res$Company$Get) entity(as[Req$Company$Get]) { req ⇒ startScopedSpan("company$get", "acsTok" → req.acsTok) { span ⇒ @@ -969,6 +974,8 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w getCompany(acsUsr.companyId, span). getOrElse(throw new NCE(s"Company not found: ${acsUsr.companyId}")) + val props = NCCompanyManager.getCompanyProperties(acsUsr.companyId, span) + complete { Res$Company$Get(API_OK, company.id, @@ -978,7 +985,8 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w company.region, company.city, company.address, - company.postalCode + company.postalCode, + if (props.isEmpty) None else Some(props.map(p ⇒ p.property → p.value).toMap) ) } } @@ -1001,13 +1009,14 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w region: Option[String], city: Option[String], address: Option[String], - postalCode: Option[String] + postalCode: Option[String], + properties: Option[Map[String, String]] ) case class Res$Company$Update( status: String ) - implicit val reqFmt: RootJsonFormat[Req$Company$Update] = jsonFormat8(Req$Company$Update) + implicit val reqFmt: RootJsonFormat[Req$Company$Update] = jsonFormat9(Req$Company$Update) implicit val resFmt: RootJsonFormat[Res$Company$Update] = jsonFormat1(Res$Company$Update) entity(as[Req$Company$Update]) { req ⇒ @@ -1022,6 +1031,8 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w "postalCode" → req.postalCode ) + checkProperties(req.properties) + val admUsr = authenticateAsAdmin(req.acsTok) NCCompanyManager.updateCompany( @@ -1033,6 +1044,7 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w req.city, req.address, req.postalCode, + req.properties, span ) @@ -1325,7 +1337,7 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w "usrExtId" → req.usrExtId ) - checkUserProperties(req.properties) + checkProperties(req.properties) val admUsr = authenticateAsAdmin(req.acsTok) @@ -1381,7 +1393,7 @@ class NCBasicRestApi extends NCRestApi with LazyLogging with NCOpenCensusTrace w "avatarUrl" → req.avatarUrl ) - checkUserProperties(req.properties) + checkProperties(req.properties) val acsUsr = authenticate(req.acsTok) diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/sql/NCSqlManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/sql/NCSqlManager.scala index 93d8788..00fe81b 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/sql/NCSqlManager.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/sql/NCSqlManager.scala @@ -17,8 +17,6 @@ package org.apache.nlpcraft.server.sql -import java.sql.Timestamp - import io.opencensus.trace.Span import org.apache.ignite.IgniteAtomicSequence import org.apache.nlpcraft.common.config.NCConfigurable @@ -28,6 +26,7 @@ import org.apache.nlpcraft.server.ignite.NCIgniteInstance import org.apache.nlpcraft.server.mdo._ import org.apache.nlpcraft.server.sql.NCSql.Implicits._ +import java.sql.Timestamp import scala.util.control.Exception.catching /** @@ -35,7 +34,9 @@ import scala.util.control.Exception.catching * Note that all functions in this class expect outside `NCSql.sql()` block. */ object NCSqlManager extends NCService with NCIgniteInstance { - private final val DB_TABLES = Seq("nc_company", "nc_user", "nc_user_property", "passwd_pool", "proc_log", "feedback") + private final val DB_TABLES = Seq( + "nc_company", "nc_company_property", "nc_user", "nc_user_property", "passwd_pool", "proc_log", "feedback" + ) private final val CACHE_2_CLEAR = Seq( "user-token-signin-cache", "user-id-signin-cache", @@ -50,6 +51,7 @@ object NCSqlManager extends NCService with NCIgniteInstance { } @volatile private var usersPropsSeq: IgniteAtomicSequence = _ + @volatile private var compPropsSeq: IgniteAtomicSequence = _ /** * @@ -68,6 +70,7 @@ object NCSqlManager extends NCService with NCIgniteInstance { catching(wrapIE) { usersPropsSeq = NCSql.mkSeq(ignite, "usersPropsSeq", "nc_user_property", "id") + compPropsSeq = NCSql.mkSeq(ignite, "companiesPropsSeq", "nc_company_property", "id") } ackStarted() @@ -276,7 +279,6 @@ object NCSqlManager extends NCService with NCIgniteInstance { n } - /** * * @param id @@ -308,6 +310,36 @@ object NCSqlManager extends NCService with NCIgniteInstance { } /** + * + * @param id + * @param propsOpt + * @param parent Optional parent span. + */ + private def addCompanyProperties(id: Long, propsOpt: Option[Map[String, String]], parent: Span): Unit = + startScopedSpan("addCompanyProperties", parent, "companyId" → id) { _ ⇒ + propsOpt match { + case Some(props) ⇒ + val now = U.nowUtcTs() + + props.foreach { case (k, v) ⇒ + NCSql.insert( + s""" + |INSERT INTO nc_company_property (id, company_id, property, value, created_on, last_modified_on) + |VALUES(?, ?, ?, ?, ?, ?) + """.stripMargin, + compPropsSeq.getAndIncrement(), + id, + k, + v, + now, + now + ) + } + case None ⇒ // No-op. + } + } + + /** * Updates user. * * @param id ID of the user to update. @@ -342,6 +374,7 @@ object NCSqlManager extends NCService with NCIgniteInstance { * @param city Company's city. Optional. * @param address Company's address. Optional. * @param postalCode Company's postal code. Optional. + * @param propsOpt Company's property. Optional. * @param parent Optional parent span. */ @throws[NCE] @@ -354,9 +387,11 @@ object NCSqlManager extends NCService with NCIgniteInstance { city: Option[String], address: Option[String], postalCode: Option[String], - parent: Span): Int = + propsOpt: Option[Map[String, String]], + parent: Span + ): Int = startScopedSpan("updateCompany", parent, "compId" → id) { _ ⇒ - NCSql.update( + val res = NCSql.update( s""" |UPDATE nc_company |SET @@ -380,6 +415,12 @@ object NCSqlManager extends NCService with NCIgniteInstance { U.nowUtcTs(), id ) + + NCSql.delete("DELETE FROM nc_company_property WHERE company_id = ?", id) + + addCompanyProperties(id, propsOpt, parent) + + res } /** @@ -503,6 +544,20 @@ object NCSqlManager extends NCService with NCIgniteInstance { } /** + * Gets company properties for given ID. + * + * @param id User ID. + * @param parent Optional parent span. + * @return Company properties. + * + */ + @throws[NCE] + def getCompanyProperties(id: Long, parent: Span): Seq[NCCompanyPropertyMdo] = + startScopedSpan("getCompanyProperties", parent, "usrId" → id) { _ ⇒ + NCSql.select[NCCompanyPropertyMdo]("SELECT * FROM nc_company_property WHERE company_id = ?", id) + } + + /** * Gets user properties for given external ID. * * @param companyId Company ID. @@ -574,6 +629,7 @@ object NCSqlManager extends NCService with NCIgniteInstance { * @param city Company's city. Optional. * @param address Company's address. Optional. * @param postalCode Company's postal code. Optional. + * @param propsOpt Company's properties. Optional. * @param parent Optional parent span. */ @throws[NCE] @@ -587,7 +643,9 @@ object NCSqlManager extends NCService with NCIgniteInstance { city: Option[String], address: Option[String], postalCode: Option[String], - parent: Span): Unit = + propsOpt: Option[Map[String, String]], + parent: Span + ): Unit = startScopedSpan("addCompany", parent, "compId" → id, "name" → name, "tkn" → tkn) { _ ⇒ val now = U.nowUtcTs() @@ -623,6 +681,8 @@ object NCSqlManager extends NCService with NCIgniteInstance { now, now ) + + addCompanyProperties(id, propsOpt, parent) } /** @@ -637,7 +697,7 @@ object NCSqlManager extends NCService with NCIgniteInstance { * @param avatarUrl User's avatar URL. Optional. * @param passwdSalt Salt for password Blowfish hashing. Optional. * @param isAdmin Whether or not the user is admin. - * @param propsOpt User properties. Optional. + * @param propsOpt User properties. Optional. * @param parent Optional parent span. */ @throws[NCE] @@ -1020,7 +1080,7 @@ object NCSqlManager extends NCService with NCIgniteInstance { */ @throws[NCE] private def executeScript(sqlPath: String): Unit = startScopedSpan("executeScript", "sqlPath" → sqlPath) { _ ⇒ - U.readResource(sqlPath, "UTF-8"). + U.readResource(sqlPath). map(_.strip). filter(p ⇒ !p.startsWith("--")). mkString("\n"). diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/user/NCUserManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/user/NCUserManager.scala index c7e95e5..4471b31 100644 --- a/nlpcraft/src/main/scala/org/apache/nlpcraft/server/user/NCUserManager.scala +++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/server/user/NCUserManager.scala @@ -392,7 +392,8 @@ object NCUserManager extends NCService with NCIgniteInstance { lastName: String, avatarUrl: Option[String], props: Option[Map[String, String]], - parent: Span = null): Unit = + parent: Span = null + ): Unit = startScopedSpan("updateUser", parent, "usrId" → id) { span ⇒ NCSql.sql { if (NCSqlManager.updateUser(id, firstName, lastName, avatarUrl, props, span) != 1) diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/server/rest/NCRestCompanySpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/server/rest/NCRestCompanySpec.scala index fa31849..6206fa8 100644 --- a/nlpcraft/src/test/scala/org/apache/nlpcraft/server/rest/NCRestCompanySpec.scala +++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/server/rest/NCRestCompanySpec.scala @@ -20,7 +20,11 @@ package org.apache.nlpcraft.server.rest import org.junit.jupiter.api.Assertions._ import org.junit.jupiter.api.Test +import scala.collection.JavaConverters._ + class NCRestCompanySpec extends NCRestSpec { + private final val PROPS = Map("k1" → "v1", "k2" → "v2").asJava + @Test def testCurrentCompany(): Unit = { var compName: String = null @@ -93,7 +97,8 @@ class NCRestCompanySpec extends NCRestSpec { "region" → "region2", "city" → "city2", "address" → "address2", - "postalCode" → "postalCode2" + "postalCode" → "postalCode2", + "properties" → PROPS )() // Checks company fields. @@ -104,7 +109,8 @@ class NCRestCompanySpec extends NCRestSpec { ("$.region", (region: String) ⇒ assertEquals("region2", region)), ("$.city", (city: String) ⇒ assertEquals("city2", city)), ("$.address", (address: String) ⇒ assertEquals("address2", address)), - ("$.postalCode", (postalCode: String) ⇒ assertEquals("postalCode2", postalCode)) + ("$.postalCode", (postalCode: String) ⇒ assertEquals("postalCode2", postalCode)), + ("$.properties", (properties: java.util.Map[String, String]) ⇒ assertEquals(PROPS, properties)) ) // Updates company. @@ -118,7 +124,8 @@ class NCRestCompanySpec extends NCRestSpec { ("$.region", (region: String) ⇒ assertEquals(null, region)), ("$.city", (city: String) ⇒ assertEquals(null, city)), ("$.address", (address: String) ⇒ assertEquals(null, address)), - ("$.postalCode", (postalCode: String) ⇒ assertEquals(null, postalCode)) + ("$.postalCode", (postalCode: String) ⇒ assertEquals(null, postalCode)), + ("$.properties", (properties: java.util.Map[String, String]) ⇒ assertEquals(null, properties)), ) // Resets token. @@ -130,31 +137,31 @@ class NCRestCompanySpec extends NCRestSpec { @Test def testParameters(): Unit = { - testCompany() - testCompany(website = Some("website")) - testCompany( + testParameters0() + testParameters0(website = Some("website")) + testParameters0( website = Some("website"), country = Some("country") ) - testCompany( + testParameters0( website = Some("website"), country = Some("country"), region = Some("region") ) - testCompany( + testParameters0( website = Some("website"), country = Some("country"), region = Some("region"), city = Some("city") ) - testCompany( + testParameters0( website = Some("website"), country = Some("country"), region = Some("region"), city = Some("city"), address = Some("address") ) - testCompany( + testParameters0( website = Some("website"), country = Some("country"), region = Some("region"), @@ -162,7 +169,7 @@ class NCRestCompanySpec extends NCRestSpec { address = Some("address"), postalCode = Some("postalCode") ) - testCompany( + testParameters0( website = Some("website"), country = Some("country"), region = Some("region"), @@ -171,6 +178,16 @@ class NCRestCompanySpec extends NCRestSpec { postalCode = Some("postalCode"), adminAvatarUrl = Some("adminAvatarUrl") ) + testParameters0( + website = Some("website"), + country = Some("country"), + region = Some("region"), + city = Some("city"), + address = Some("address"), + postalCode = Some("postalCode"), + adminAvatarUrl = Some("adminAvatarUrl"), + properties = Some(PROPS) + ) } /** @@ -183,14 +200,15 @@ class NCRestCompanySpec extends NCRestSpec { * @param postalCode * @param adminAvatarUrl */ - private def testCompany( + private def testParameters0( website: Option[String] = None, country: Option[String] = None, region: Option[String] = None, city: Option[String] = None, address: Option[String] = None, postalCode: Option[String] = None, - adminAvatarUrl: Option[String] = None + adminAvatarUrl: Option[String] = None, + properties: Option[java.util.Map[String, String]] = None ): Unit = { val compName = rnd() @@ -210,11 +228,30 @@ class NCRestCompanySpec extends NCRestSpec { "adminPasswd" → adminPswd, "adminFirstName" → "firstName", "adminLastName" → "lastName", - "adminAvatarUrl" → adminAvatarUrl.orNull + "adminAvatarUrl" → adminAvatarUrl.orNull, + "properties" → properties.orNull )( ("$.adminId", (id: Number) ⇒ assertNotNull(id)) ) - post("company/delete", signin(adminEmail, adminPswd))() + def check(paramOpt: Option[Any], exp: Any, js: Any): Unit = + paramOpt match { + case Some(_) ⇒ assertEquals(exp, js) + case None ⇒ assertEquals(null, js) + } + + val adminTkn = signin(adminEmail, adminPswd) + + post("company/get", adminTkn)( + ("$.website", (websiteJs: String) ⇒ check(website, "website", websiteJs)), + ("$.country", (countryJs: String) ⇒ check(country, "country", countryJs)), + ("$.region", (regionJs: String) ⇒ check(region, "region", regionJs)), + ("$.city", (cityJs: String) ⇒ check(city, "city", cityJs)), + ("$.address", (addressJs: String) ⇒ check(address, "address", addressJs)), + ("$.postalCode", (postalCodeJs: String) ⇒ check(postalCode, "postalCode", postalCodeJs)), + ("$.properties", (propertiesJs: java.util.Map[String, String]) ⇒ check(properties, PROPS, propertiesJs)) + ) + + post("company/delete", adminTkn)() } } diff --git a/openapi/nlpcraft_swagger.yml b/openapi/nlpcraft_swagger.yml index 872ff19..ac72473 100644 --- a/openapi/nlpcraft_swagger.yml +++ b/openapi/nlpcraft_swagger.yml @@ -1154,6 +1154,11 @@ paths: postalCode: description: Company postal code. type: string + properties: + type: object + description: Additional company properties. + additionalProperties: + type: string '400': description: Failed operation. schema: @@ -1233,6 +1238,11 @@ paths: type: string description: <em>Optional.</em> Admin user avatar URL. maxLength: 512000 + properties: + type: object + description: <em>Optional.</em> Additional company properties. + additionalProperties: + type: string responses: '200': description: Successful operation. @@ -1311,6 +1321,11 @@ paths: type: string description: <em>Optional.</em> Company postal code. maxLength: 512 + properties: + type: object + description: <em>Optional.</em> Additional company properties. + additionalProperties: + type: string responses: '200': description: Successful operation. diff --git a/sql/mysql/drop_schema.sql b/sql/mysql/drop_schema.sql index d461dda..fba01aa 100644 --- a/sql/mysql/drop_schema.sql +++ b/sql/mysql/drop_schema.sql @@ -17,9 +17,10 @@ USE nlpcraft; -DROP TABLE IF EXISTS proc_log CASCADE; -DROP TABLE IF EXISTS nc_user_property CASCADE; -DROP TABLE IF EXISTS nc_user CASCADE; -DROP TABLE IF EXISTS nc_company CASCADE; -DROP TABLE IF EXISTS passwd_pool CASCADE; -DROP TABLE IF EXISTS feedback CASCADE; +DROP TABLE IF EXISTS proc_log; +DROP TABLE IF EXISTS nc_user_property; +DROP TABLE IF EXISTS nc_user; +DROP TABLE IF EXISTS nc_company_property; +DROP TABLE IF EXISTS nc_company; +DROP TABLE IF EXISTS passwd_pool; +DROP TABLE IF EXISTS feedback; diff --git a/sql/mysql/schema.sql b/sql/mysql/schema.sql index 0e1bc7d..cac0bf8 100644 --- a/sql/mysql/schema.sql +++ b/sql/mysql/schema.sql @@ -46,6 +46,20 @@ CREATE TABLE nc_company ( CREATE UNIQUE INDEX nc_company_idx_1 ON nc_company(name); CREATE UNIQUE INDEX nc_company_idx_2 ON nc_company(auth_token); CREATE UNIQUE INDEX nc_company_idx_3 ON nc_company(auth_token_hash); + +-- +-- Company properties table. +-- +CREATE TABLE nc_company_property ( + id SERIAL PRIMARY KEY, + company_id BIGINT UNSIGNED NOT NULL, + property VARCHAR(64) NOT NULL, + value VARCHAR(512) NULL, + created_on TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(3), + last_modified_on TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(3), + FOREIGN KEY (company_id) REFERENCES nc_company(id) +); + -- -- User table. -- diff --git a/sql/oracle/drop_schema.sql b/sql/oracle/drop_schema.sql index a20720f..652bdb8 100644 --- a/sql/oracle/drop_schema.sql +++ b/sql/oracle/drop_schema.sql @@ -40,6 +40,14 @@ EXCEPTION WHEN OTHERS THEN END; BEGIN + EXECUTE IMMEDIATE 'DROP TABLE nc_company_property'; +EXCEPTION WHEN OTHERS THEN + IF SQLCODE != -942 THEN + RAISE; +END IF; +END; + +BEGIN EXECUTE IMMEDIATE 'DROP TABLE nc_company'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN diff --git a/sql/oracle/schema.sql b/sql/oracle/schema.sql index 09a61ef..1ad495c 100644 --- a/sql/oracle/schema.sql +++ b/sql/oracle/schema.sql @@ -46,6 +46,21 @@ CREATE UNIQUE INDEX nc_company_idx_2 ON nc_company(auth_token); CREATE UNIQUE INDEX nc_company_idx_3 ON nc_company(auth_token_hash); -- +-- Company properties table. +-- +CREATE TABLE nc_company_property ( + id NUMBER PRIMARY KEY, + company_id NUMBER NOT NULL, + property VARCHAR2(64) NOT NULL, + value VARCHAR2(512) NULL, + created_on DATE DEFAULT sysdate NOT NULL, + last_modified_on DATE DEFAULT sysdate NOT NULL, + CONSTRAINT fk_company_id_company_property FOREIGN KEY (company_id) REFERENCES nc_company(id) +); + +CREATE INDEX nc_company_property_idx1 ON nc_company_property(company_id); + +-- -- User table. -- CREATE TABLE nc_user ( @@ -60,7 +75,7 @@ CREATE TABLE nc_user ( passwd_salt VARCHAR2(64) NULL, created_on DATE DEFAULT sysdate NOT NULL, last_modified_on DATE DEFAULT sysdate NOT NULL, - CONSTRAINT fk_company_id FOREIGN KEY (company_id)REFERENCES nc_company(id) + CONSTRAINT fk_company_id_user FOREIGN KEY (company_id) REFERENCES nc_company(id) ); CREATE UNIQUE INDEX nc_user_idx_1 ON nc_user(email); @@ -77,7 +92,7 @@ CREATE TABLE nc_user_property ( value VARCHAR2(512) NULL, created_on DATE DEFAULT sysdate NOT NULL, last_modified_on DATE DEFAULT sysdate NOT NULL, - CONSTRAINT fk_user_id FOREIGN KEY (user_id)REFERENCES nc_user(id) + CONSTRAINT fk_user_id_user_property FOREIGN KEY (user_id) REFERENCES nc_user(id) ); CREATE INDEX nc_user_property_idx1 ON nc_user_property(user_id); diff --git a/sql/postgres/drop_schema.sql b/sql/postgres/drop_schema.sql index 4cd8646..b1ce0b9 100644 --- a/sql/postgres/drop_schema.sql +++ b/sql/postgres/drop_schema.sql @@ -15,9 +15,10 @@ -- limitations under the License. -- -DROP TABLE IF EXISTS proc_log CASCADE; -DROP TABLE IF EXISTS nc_user_property CASCADE; -DROP TABLE IF EXISTS nc_user CASCADE; -DROP TABLE IF EXISTS nc_company CASCADE; -DROP TABLE IF EXISTS passwd_pool CASCADE; -DROP TABLE IF EXISTS feedback CASCADE; \ No newline at end of file +DROP TABLE IF EXISTS proc_log; +DROP TABLE IF EXISTS nc_user_property; +DROP TABLE IF EXISTS nc_user; +DROP TABLE IF EXISTS nc_company_property; +DROP TABLE IF EXISTS nc_company; +DROP TABLE IF EXISTS passwd_pool; +DROP TABLE IF EXISTS feedback; \ No newline at end of file diff --git a/sql/postgres/schema.sql b/sql/postgres/schema.sql index 79c3af4..561418e 100644 --- a/sql/postgres/schema.sql +++ b/sql/postgres/schema.sql @@ -46,6 +46,21 @@ CREATE UNIQUE INDEX nc_company_idx_2 ON nc_company(auth_token); CREATE UNIQUE INDEX nc_company_idx_3 ON nc_company(auth_token_hash); -- +-- Company properties table. +-- +CREATE TABLE nc_company_property ( + id SERIAL PRIMARY KEY, + company_id BIGINT NOT NULL, + property VARCHAR(64) NOT NULL, + value VARCHAR(512) NULL, + created_on TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(3), + last_modified_on TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(3), + FOREIGN KEY (company_id) REFERENCES nc_company(id) +); + +CREATE INDEX nc_company_property_idx1 ON nc_company_property(company_id); + +-- -- -- User table. --
