blob: 8274de455f4ae041aedced2ad5e91bbed67b2130 [file] [log] [blame]
/*
* 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()
)
}
}