All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tairanchina.csp.dew.auth.service.UserService.scala Maven / Gradle / Ivy

package com.tairanchina.csp.dew.auth.service

import com.ecfront.dew.common.{$, Resp}
import com.tairanchina.csp.dew.Dew
import com.tairanchina.csp.dew.auth.AuthConfig
import com.tairanchina.csp.dew.auth.domain.{Account, Ident}
import com.tairanchina.csp.dew.auth.dto.user._
import com.tairanchina.csp.dew.auth.repository._
import com.tairanchina.csp.dew.auth.sdk.TokenInfo
import com.typesafe.scalalogging.LazyLogging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.mail.javamail.{JavaMailSender, MimeMessageHelper}
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

import scala.collection.JavaConverters._


@Service
class UserService @Autowired()(
                                val identRepository: IdentRepository,
                                val accountRepository: AccountRepository,
                                val authConfig: AuthConfig,
                                var mailSender: JavaMailSender
                              ) extends LazyLogging {


  @Transactional(readOnly = true)
  def sendRegisterVC(req: SendVCReq): Resp[Void] = {
    if (identRepository.getByCategoryAndKeyAndTenantId(req.identCategory, req.identKey,
      Dew.auth.getOptInfo.get().asInstanceOf[TokenInfo].getTenantId) != null) {
      Resp.conflict(req.identKey + " 已存在")
    } else if (req.identCategory == Ident.IDENT_CATEGORY_EMAIL) {
      val mimeMessage = mailSender.createMimeMessage
      val message = new MimeMessageHelper(mimeMessage, true)
      message.setFrom(authConfig.emailAccount)
      message.setTo(req.identKey)
      message.setSubject(Dew.dewConfig.getBasic.getName + " 注册验证")
      message.setText("请输入验证码 " + generateVC(AuthConfig.CACHE_REG_VC_EMAIL + req.identKey) + " , 10分钟内有效")
      mailSender.send(mimeMessage)
      Resp.success(null)
    } else {
      Resp.badRequest("请求凭证类型错误")
    }
  }

  @Transactional(readOnly = true)
  def sendLoginVC(req: SendVCReq): Resp[Void] = {
    if (req.identCategory == Ident.IDENT_CATEGORY_EMAIL) {
      val mimeMessage = mailSender.createMimeMessage
      val message = new MimeMessageHelper(mimeMessage, true)
      message.setFrom(authConfig.emailAccount)
      message.setTo(req.identKey)
      message.setSubject(Dew.dewConfig.getBasic.getName + " 登录验证")
      message.setText("请输入验证码 " + generateVC(AuthConfig.CACHE_LOGIN_VC + req.identKey) + " , 10分钟内有效")
      mailSender.send(mimeMessage)
      Resp.success(null)
    } else {
      Resp.badRequest("请求凭证类型错误")
    }
  }

  @Transactional
  def register(req: RegisterReq): Resp[TokenInfo] = {
    val tenantId = Dew.auth.getOptInfo.get().asInstanceOf[TokenInfo].getTenantId
    if (req.identCategory == Ident.IDENT_CATEGORY_EMAIL) {
      if (Dew.cluster.cache.get(AuthConfig.CACHE_REG_VC_EMAIL + req.identKey) == req.identSecret) {
        doRegister(req.name, null, Ident.IDENT_CATEGORY_EMAIL, req.identKey, tenantId)
      } else {
        Resp.unAuthorized("验证码错误")
      }
    } else if (req.identCategory == Ident.IDENT_CATEGORY_USERNAME) {
      doRegister(req.name, req.identSecret, Ident.IDENT_CATEGORY_USERNAME, req.identKey, tenantId)
    } else {
      Resp.badRequest("注册类型[" + req.identCategory + "]不支持")
    }
  }

  @Transactional
  def login(req: LoginReq): Resp[TokenInfo] = {
    val tenantId = Dew.auth.getOptInfo.get().asInstanceOf[TokenInfo].getTenantId
    val loginKey = (req.identCategory + req.identKey + tenantId).hashCode + ""
    val errorTimes = Dew.cluster.cache.get(AuthConfig.CACHE_LOGIN_ERROR + loginKey)
    if (errorTimes != null && errorTimes.toInt > authConfig.maxLoginErrorTimes) {
      return Resp.locked("多次登录错误,请稍后重试")
    }
    val ident = identRepository.getByCategoryAndKeyAndTenantId(req.identCategory, req.identKey, tenantId)
    if (ident == null || !ident.enabled) {
      logger.warn(tenantId + " - " + req.identKey + " NOT exist OR disabled")
      loginError(loginKey)
    } else {
      val account = accountRepository.findOne(ident.accountId)
      if (account == null || !account.enabled) {
        logger.warn(tenantId + " - " + req.identKey + " related account NOT exist OR disabled")
        loginError(loginKey)
      } else {
        if (req.byVC) {
          if (req.identSecret != Dew.cluster.cache.get(AuthConfig.CACHE_LOGIN_VC + req.identKey)) {
            logger.warn(tenantId + " - " + req.identKey + " vc error")
            loginError(loginKey)
          } else {
            cacheLogin(loginKey, account)
          }
        } else {
          if (account.password != Account.generatePassword(req.identSecret, authConfig.passwordSalt)) {
            logger.warn(tenantId + " - " + req.identKey + " password error")
            loginError(loginKey)
          } else {
            cacheLogin(loginKey, account)
          }
        }
      }
    }
  }

  @Transactional
  def logout(): Resp[Void] = {
    Dew.cluster.cache.del(AuthConfig.CACHE_TOKEN + Dew.auth.getOptInfo.get().asInstanceOf[TokenInfo].getToken)
    Resp.success(null)
  }

  @Transactional(readOnly = true)
  def getCurrentUser: Resp[UserResp] = {
    val accountId = Dew.auth.getOptInfo.get().asInstanceOf[TokenInfo].getAccountCode.asInstanceOf[String]
    Resp.success(accountRepository.findOne(accountId))
  }

  @Transactional
  def modifyCurrentUser(req: UserModifyReq): Resp[Void] = {
    val accountId = Dew.auth.getOptInfo.get().asInstanceOf[TokenInfo].getAccountCode.asInstanceOf[String]
    val account = accountRepository.findOne(accountId)
    account.name = req.name
    if (req.password != null && req.password.nonEmpty) {
      account.password = Account.generatePassword(req.password, authConfig.passwordSalt)
    }
    accountRepository.save(account)
    logout()
    Resp.success(null)
  }

  private def doRegister(name: String, password: String, identCategory: String, identKey: String, tenantId: String): Resp[TokenInfo] = {
    if (identRepository.getByCategoryAndKeyAndTenantId(identCategory, identKey, tenantId) != null) {
      Resp.conflict(identKey + " 已存在")
    } else {
      var account = new Account
      account.id = $.field.createShortUUID()
      account.name = if (name != null) name else ""
      account.password = Account.generatePassword(
        if (password != null) password else $.field.createShortUUID(), authConfig.passwordSalt)
      account.tenantId = tenantId
      account.enabled = true
      account = accountRepository.save(account)
      val ident = new Ident
      ident.category = Ident.IDENT_CATEGORY_USERNAME
      ident.key = identKey
      ident.secret = ""
      ident.accountId = account.id
      ident.tenantId = tenantId
      ident.enabled = true
      identRepository.save(ident)
      cacheLogin(identKey, account)
    }
  }

  private def loginError(loginKey: String): Resp[TokenInfo] = {
    Dew.cluster.cache.incrBy(AuthConfig.CACHE_LOGIN_ERROR + loginKey, 1)
    Dew.cluster.cache.expire(AuthConfig.CACHE_LOGIN_ERROR + loginKey, authConfig.cleanErrorTimeMin * 60)
    Resp.unAuthorized("认证错误")
  }

  private def cacheLogin(loginKey: String, account: Account): Resp[TokenInfo] = {
    val tokenInfo = new TokenInfo
    tokenInfo.setAccountCode(account.id)
    tokenInfo.setName(account.name)
    tokenInfo.setTenantId(account.tenantId)
    tokenInfo.setRoles(account.roles.asScala.map(role => role.id -> role.name).toMap.asJava)
    tokenInfo.setToken($.field.createUUID())
    Dew.cluster.cache.del(AuthConfig.CACHE_LOGIN_ERROR + loginKey)
    Dew.cluster.cache.setex(AuthConfig.CACHE_TOKEN + tokenInfo.getToken, $.json.toJsonString(tokenInfo), authConfig.tokenExpireSec)
    Resp.success(tokenInfo)
  }

  private def generateVC(cacheKey: String): String = {
    val vc = ((Math.random() * 9 + 1) * 1000).toInt + ""
    Dew.cluster.cache.setex(cacheKey, vc, 600)
    vc
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy