| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.nlpcraft.server.company |
| |
| 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.sql.{NCSql, NCSqlManager} |
| import org.apache.nlpcraft.server.user.NCUserManager |
| |
| import scala.util.control.Exception._ |
| |
| /** |
| * |
| * @param companyId Company ID. |
| * @param token |
| * @param adminId |
| */ |
| case class NCCompanyCreationData(companyId: Long, token: String, adminId: Long) |
| |
| /** |
| * Company CRUD manager. |
| */ |
| object NCCompanyManager extends NCService with NCIgniteInstance { |
| @volatile private var compSeq: IgniteAtomicSequence = _ |
| @volatile private var compLock: IgniteSemaphore = _ |
| |
| /** |
| * |
| */ |
| @throws[NCE] |
| private def mkToken(): String = { |
| val tok = U.genGuid() |
| |
| if (NCSqlManager.getCompanyByHashToken(U.mkSha256Hash(tok), null).isDefined) |
| throw new NCE(s"Invalid attempt. Try again.") |
| |
| tok |
| } |
| |
| /** |
| * |
| * @param parent Optional parent span. |
| */ |
| override def stop(parent: Span): Unit = startScopedSpan("start", parent) { _ ⇒ |
| ackStopping() |
| ackStopped() |
| } |
| |
| /** |
| * |
| * @param parent Optional parent span. |
| * @return |
| */ |
| override def start(parent: Span = null): NCService = startScopedSpan("start", parent) { span ⇒ |
| ackStarting() |
| |
| catching(wrapIE) { |
| compSeq = NCSql.mkSeq(ignite, "compSeq", "nc_company", "id") |
| } |
| |
| compLock = ignite.semaphore("compSemaphore", 1, true, true) |
| |
| NCSql.sql { |
| if (!NCSql.exists("nc_company")) |
| try { |
| val compName = "ETH Zurich" |
| val adminEmail = "admin@admin.com" |
| val adminPwd = "admin" |
| |
| addCompany0( |
| name = compName, |
| website = None, |
| country = None, |
| region = None, |
| city = None, |
| address = None, |
| postalCode = None, |
| adminEmail = adminEmail, |
| adminPwd = adminPwd, |
| adminFirstName = "Hermann", |
| adminLastName = "Minkowski", |
| adminAvatarUrl = None, |
| () ⇒ U.DFLT_PROBE_TOKEN, |
| span |
| ) |
| |
| logger.info(s"Default admin user ($adminEmail/$adminPwd) created for default company: $compName") |
| } |
| catch { |
| case e: NCE ⇒ U.prettyError( |
| logger, |
| s"Failed to add default admin user: ${e.getLocalizedMessage}", |
| e |
| ) |
| } |
| } |
| |
| ackStarted() |
| } |
| |
| /** |
| * Gets user for given user ID. |
| * |
| * @param id User ID. |
| * parent Optional parent span. |
| */ |
| @throws[NCE] |
| def getCompany(id: Long, parent: Span = null): Option[NCCompanyMdo] = |
| startScopedSpan("getCompany", parent, "id" → id) { span ⇒ |
| NCSql.sql { |
| NCSqlManager.getCompany(id, span) |
| } |
| } |
| |
| /** |
| * Gets user for given token hash. |
| * |
| * @param hash Token hash. |
| * parent Optional parent span. |
| */ |
| @throws[NCE] |
| def getCompanyByHashToken(hash: String, parent: Span = null): Option[NCCompanyMdo] = |
| startScopedSpan("getCompanyByHashToken", parent, "hash" → hash) { span ⇒ |
| NCSql.sql { |
| NCSqlManager.getCompanyByHashToken(hash, span) |
| } |
| } |
| |
| /** |
| * |
| * @param id |
| * @param name |
| * @param website |
| * @param address |
| * @param city |
| * @param region |
| * @param postalCode |
| * @param country |
| * parent Optional parent span. |
| */ |
| @throws[NCE] |
| def updateCompany( |
| id: Long, |
| name: String, |
| website: Option[String], |
| country: Option[String], |
| region: Option[String], |
| city: Option[String], |
| address: Option[String], |
| postalCode: Option[String], |
| parent: Span = null |
| ): Unit = |
| startScopedSpan("updateCompany", parent, "id" → id) { span ⇒ |
| try { |
| compLock.acquire() |
| |
| NCSql.sql { |
| NCSqlManager.getCompanyByName(name, span) match { |
| case Some(c) ⇒ |
| if (c.id != id) |
| throw new NCE(s"Company with this name already exists: $name") |
| |
| case None ⇒ // No-op. |
| } |
| |
| val n = |
| NCSqlManager.updateCompany( |
| id = id, |
| name = name, |
| website = website, |
| country = country, |
| region = region, |
| city = city, |
| address = address, |
| postalCode = postalCode, |
| parent = span |
| ) |
| |
| if (n == 0) |
| throw new NCE(s"Unknown company ID: $id") |
| |
| logger.info(s"Company updated: $id") |
| } |
| } |
| finally |
| compLock.release() |
| } |
| |
| /** |
| * |
| * @param id |
| * @param parent Optional parent span. |
| */ |
| @throws[NCE] |
| def resetToken(id: Long, parent: Span): String = startScopedSpan("resetToken", parent, "id" → id) { span ⇒ |
| try { |
| compLock.acquire() |
| |
| NCSql.sql { |
| val tnk = mkToken() |
| |
| val n = NCSqlManager.updateCompanyToken(id, tnk, span) |
| |
| if (n == 0) |
| throw new NCE(s"Unknown company ID: $id") |
| |
| tnk |
| } |
| } |
| finally |
| compLock.release() |
| } |
| |
| /** |
| * |
| * @param id |
| * @param parent Optional parent span. |
| * @return |
| */ |
| @throws[NCE] |
| def deleteCompany(id: Long, parent: Span = null): Unit = |
| startScopedSpan("deleteCompany", parent, "id" → id) { span ⇒ |
| NCSql.sql { |
| if (NCSqlManager.deleteCompany(id, span) != 1) |
| throw new NCE(s"Unknown company ID: $id") |
| } |
| |
| logger.info(s"Company deleted: $id") |
| } |
| |
| /** |
| * |
| * @param name |
| * @param website |
| * @param address |
| * @param city |
| * @param region |
| * @param postalCode |
| * @param country |
| * @param parent Optional parent span. |
| */ |
| @throws[NCE] |
| private def addCompany0( |
| name: String, |
| website: Option[String], |
| country: Option[String], |
| region: Option[String], |
| city: Option[String], |
| address: Option[String], |
| postalCode: Option[String], |
| adminEmail: String, |
| adminPwd: String, |
| adminFirstName: String, |
| adminLastName: String, |
| adminAvatarUrl: Option[String], |
| mkToken: () ⇒ String, |
| parent: Span = null |
| ): NCCompanyCreationData = { |
| val compId = compSeq.incrementAndGet() |
| |
| startScopedSpan("addCompany0", parent, "id" → compId, "name" → name) { span ⇒ |
| NCSql.sql { |
| val tkn = |
| // Some database implementations (including Ignite database) may not support unique constraints. |
| // Because we have to support user email unique values, adding user operation is synchronized. |
| try { |
| compLock.acquire() |
| |
| if (NCSqlManager.getCompanyByName(name, span).isDefined) |
| throw new NCE(s"Company with this name already exists: $name") |
| |
| val tkn = mkToken() |
| |
| NCSqlManager.addCompany( |
| compId, |
| name, |
| tkn, |
| website, |
| country, |
| region, |
| city, |
| address, |
| postalCode, |
| span |
| ) |
| |
| tkn |
| } |
| finally |
| compLock.release() |
| |
| val adminId = NCUserManager.addUser( |
| compId, |
| adminEmail, |
| adminPwd, |
| adminFirstName, |
| adminLastName, |
| adminAvatarUrl, |
| isAdmin = true, |
| props = None, |
| usrExtIdOpt = None, |
| parent = span |
| ) |
| |
| logger.info(s"Company '$name' created.") |
| |
| NCCompanyCreationData(compId, tkn, adminId) |
| } |
| } |
| } |
| |
| /** |
| * |
| * @param name |
| * @param website |
| * @param country |
| * @param region |
| * @param city |
| * @param address |
| * @param postalCode |
| * @param adminEmail |
| * @param adminPwd |
| * @param adminFirstName |
| * @param adminLastName |
| * @param adminAvatarUrl |
| * @param parent Optional parent span. |
| */ |
| @throws[NCE] |
| def addCompany( |
| name: String, |
| website: Option[String], |
| country: Option[String], |
| region: Option[String], |
| city: Option[String], |
| address: Option[String], |
| postalCode: Option[String], |
| adminEmail: String, |
| adminPwd: String, |
| adminFirstName: String, |
| adminLastName: String, |
| adminAvatarUrl: Option[String], |
| parent: Span = null |
| ): NCCompanyCreationData = startScopedSpan("addCompany", parent, "name" → name) { _ ⇒ |
| addCompany0( |
| name, |
| website, |
| country, |
| region, |
| city, |
| address, |
| postalCode, |
| adminEmail, |
| adminPwd, |
| adminFirstName, |
| adminLastName, |
| adminAvatarUrl, |
| () ⇒ mkToken() |
| ) |
| } |
| } |