<commit_before>package im.actor.server.api.rpc.service.messaging

import java.time.Instant

import akka.http.scaladsl.util.FastFuture
import im.actor.api.rpc.PeerHelpers._
import im.actor.api.rpc._
import im.actor.api.rpc.messaging.{ ApiEmptyMessage, _ }
import im.actor.api.rpc.misc.{ ResponseSeq, ResponseVoid }
import im.actor.api.rpc.peers.{ ApiGroupOutPeer, ApiOutPeer, ApiPeerType, ApiUserOutPeer }
import im.actor.api.rpc.sequence.ApiUpdateOptimization
import im.actor.server.dialog.HistoryUtils
import im.actor.server.group.GroupQueries.CanSendMessageResponse
import im.actor.server.group.{ CanSendMessageInfo, GroupUtils }
import im.actor.server.model.{ DialogObsolete, HistoryMessage, Peer, PeerType }
import im.actor.server.persist.contact.UserContactRepo
import im.actor.server.persist.dialog.DialogRepo
import im.actor.server.persist.{ GroupUserRepo, HistoryMessageRepo }
import im.actor.server.sequence.SeqState
import im.actor.server.user.UserUtils
import org.joda.time.DateTime
import slick.dbio
import slick.driver.PostgresDriver.api._

import scala.concurrent.Future
import scala.language.postfixOps

trait HistoryHandlers {
  self: MessagingServiceImpl ⇒

  import DBIOResultRpc._
  import HistoryUtils._
  import Implicits._

  private val CantDelete = Error(CommonRpcErrors.forbidden("You can't delete these messages"))

  override def doHandleMessageReceived(peer: ApiOutPeer, date: Long, clientData: im.actor.api.rpc.ClientData): Future[HandlerResult[ResponseVoid]] = {
    authorized(clientData) { client ⇒
      dialogExt.messageReceived(peer.asPeer, client.userId, date) map (_ ⇒ Ok(ResponseVoid))
    }
  }

  override def doHandleMessageRead(peer: ApiOutPeer, date: Long, clientData: ClientData): Future[HandlerResult[ResponseVoid]] = {
    authorized(clientData) { client ⇒
      dialogExt.messageRead(peer.asPeer, client.userId, client.authId, date) map (_ ⇒ Ok(ResponseVoid))
    }
  }

  // FIXME: handle clear chat for groups with shared history
  override def doHandleClearChat(peer: ApiOutPeer, clientData: ClientData): Future[HandlerResult[ResponseSeq]] =
    authorized(clientData) { implicit client ⇒
      val update = UpdateChatClear(peer.asPeer)

      val action = (for {
        _ ← fromDBIOBoolean(CommonRpcErrors.forbidden("Clearing of public chats is forbidden")) {
          if (peer.`type` == ApiPeerType.Private) {
            DBIO.successful(true)
          } else {
            DBIO.from(groupExt.isHistoryShared(peer.id)) flatMap (isHistoryShared ⇒ DBIO.successful(!isHistoryShared))
          }
        }
        _ ← fromDBIO(HistoryMessageRepo.deleteAll(client.userId, peer.asModel))
        seqState ← fromFuture(seqUpdExt.deliverClientUpdate(
          client.userId,
          client.authId,
          update,
          pushRules = seqUpdExt.pushRules(isFat = false, None)
        ))
      } yield ResponseSeq(seqState.seq, seqState.state.toByteArray)).value
      db.run(action)
    }

  override def doHandleDeleteChat(peer: ApiOutPeer, clientData: ClientData): Future[HandlerResult[ResponseSeq]] = {
    authorized(clientData) { implicit client ⇒
      for {
        SeqState(seq, state) ← dialogExt.delete(client.userId, client.authId, peer.asModel)
      } yield Ok(ResponseSeq(seq, state.toByteArray))
    }
  }

  override def doHandleLoadArchived(
    offset:        Option[Array[Byte]],<commit_msg>fix(server:groups): forbid to clear chats with shared history<commit_after>package im.actor.server.api.rpc.service.messaging

import java.time.Instant

import akka.http.scaladsl.util.FastFuture
import im.actor.api.rpc.PeerHelpers._
import im.actor.api.rpc._
import im.actor.api.rpc.messaging.{ ApiEmptyMessage, _ }
import im.actor.api.rpc.misc.{ ResponseSeq, ResponseVoid }
import im.actor.api.rpc.peers.{ ApiGroupOutPeer, ApiOutPeer, ApiPeerType, ApiUserOutPeer }
import im.actor.api.rpc.sequence.ApiUpdateOptimization
import im.actor.server.dialog.HistoryUtils
import im.actor.server.group.GroupQueries.CanSendMessageResponse
import im.actor.server.group.{ CanSendMessageInfo, GroupUtils }
import im.actor.server.model.{ DialogObsolete, HistoryMessage, Peer, PeerType }
import im.actor.server.persist.contact.UserContactRepo
import im.actor.server.persist.dialog.DialogRepo
import im.actor.server.persist.{ GroupUserRepo, HistoryMessageRepo }
import im.actor.server.sequence.SeqState
import im.actor.server.user.UserUtils
import org.joda.time.DateTime
import slick.dbio
import slick.driver.PostgresDriver.api._

import scala.concurrent.Future
import scala.language.postfixOps

trait HistoryHandlers {
  self: MessagingServiceImpl ⇒

  import DBIOResultRpc._
  import HistoryUtils._
  import Implicits._

  private val CantDelete = Error(CommonRpcErrors.forbidden("You can't delete these messages"))

  override def doHandleMessageReceived(peer: ApiOutPeer, date: Long, clientData: im.actor.api.rpc.ClientData): Future[HandlerResult[ResponseVoid]] = {
    authorized(clientData) { client ⇒
      dialogExt.messageReceived(peer.asPeer, client.userId, date) map (_ ⇒ Ok(ResponseVoid))
    }
  }

  override def doHandleMessageRead(peer: ApiOutPeer, date: Long, clientData: ClientData): Future[HandlerResult[ResponseVoid]] = {
    authorized(clientData) { client ⇒
      dialogExt.messageRead(peer.asPeer, client.userId, client.authId, date) map (_ ⇒ Ok(ResponseVoid))
    }
  }

  override def doHandleClearChat(peer: ApiOutPeer, clientData: ClientData): Future[HandlerResult[ResponseSeq]] =
    authorized(clientData) { client ⇒
      val canClearChat = peer.`type` match {
        case ApiPeerType.Private | ApiPeerType.EncryptedPrivate ⇒
          FastFuture.successful(true)
        case ApiPeerType.Group ⇒
          groupExt.isHistoryShared(peer.id) map (!_)
      }

      for {
        canDelete ← canClearChat
        SeqState(seq, state) ← if (canDelete) {
          for {
            _ ← db.run(HistoryMessageRepo.deleteAll(client.userId, peer.asModel))
            seqState ← seqUpdExt.deliverClientUpdate(
              client.userId,
              client.authId,
              update = UpdateChatClear(peer.asPeer)
            )
          } yield seqState
        } else {
          FastFuture.successful(Error(CommonRpcErrors.forbidden("Can't clear chat with shared history")))
        }
      } yield Ok(ResponseSeq(seq, state.toByteArray))
    }

  override def doHandleDeleteChat(peer: ApiOutPeer, clientData: ClientData): Future[HandlerResult[ResponseSeq]] = {
    authorized(clientData) { implicit client ⇒
      for {
        SeqState(seq, state) ← dialogExt.delete(client.userId, client.authId, peer.asModel)
      } yield Ok(ResponseSeq(seq, state.toByteArray))
    }
  }

  override def doHandleLoadArchived(
    offset:        Option[Array[Byte]],
{'fraction_non_alphanumeric': 0.10289532293986638, 'fraction_numerical': 0.0, 'mean_word_length': 3.9748892171344163, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5634042', 'n_tokens_mistral': 2046, 'n_tokens_neox': 2088, 'n_words': 408}