Package ru.org.linux.topic

Source Code of ru.org.linux.topic.TopicPermissionService

/*
* Copyright 1998-2014 Linux.org.ru
*    Licensed 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 ru.org.linux.topic;

import com.google.common.base.Preconditions;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.Errors;
import ru.org.linux.auth.AccessViolationException;
import ru.org.linux.comment.Comment;
import ru.org.linux.comment.CommentService;
import ru.org.linux.group.Group;
import ru.org.linux.group.GroupDao;
import ru.org.linux.section.Section;
import ru.org.linux.site.MessageNotFoundException;
import ru.org.linux.spring.SiteConfig;
import ru.org.linux.user.User;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

@Service
public class TopicPermissionService {
  public static final int POSTSCORE_MOD_AUTHOR = 9999;
  public static final int POSTSCORE_UNRESTRICTED = -9999;
  public static final int POSTSCORE_MODERATORS_ONLY = 10000;
  public static final int POSTSCORE_REGISTERED_ONLY = -50;
  public static final int LINK_FOLLOW_MIN_SCORE = 100;
  public static final int VIEW_DELETED_SCORE = 100;
  public static final Duration DELETE_PERIOD = Duration.standardHours(3);

  @Autowired
  private CommentService commentService;

  @Autowired
  private SiteConfig siteConfig;

  @Autowired
  private GroupDao groupDao;

  public static String getPostScoreInfo(int postscore) {
    switch (postscore) {
      case POSTSCORE_UNRESTRICTED:
        return "";
      case 50:
        return "Закрыто добавление комментариев для недавно зарегистрированных пользователей.";
      case 100:
        return "<b>Ограничение на отправку комментариев</b>: " + User.getStars(100, 100);
      case 200:
        return "<b>Ограничение на отправку комментариев</b>: " + User.getStars(200, 200);
      case 300:
        return "<b>Ограничение на отправку комментариев</b>: " + User.getStars(300, 300);
      case 400:
        return "<b>Ограничение на отправку комментариев</b>: " + User.getStars(400, 400);
      case 500:
        return "<b>Ограничение на отправку комментариев</b>: " + User.getStars(500, 500);
      case POSTSCORE_MOD_AUTHOR:
        return "<b>Ограничение на отправку комментариев</b>: только для модераторов и автора";
      case POSTSCORE_MODERATORS_ONLY:
        return "<b>Ограничение на отправку комментариев</b>: только для модераторов";
      case POSTSCORE_REGISTERED_ONLY:
        return "<b>Ограничение на отправку комментариев</b>: только для зарегистрированных пользователей";
      default:
        return "<b>Ограничение на отправку комментариев</b>: только для зарегистрированных пользователей, score>=" + postscore;
    }
  }

  public void checkView(
          @Nonnull Group group,
          @Nonnull Topic message,
          @Nullable User currentUser,
          boolean showDeleted
  ) throws MessageNotFoundException, AccessViolationException {
    Preconditions.checkArgument(message.getGroupId()==group.getId());

    if (currentUser!=null && currentUser.isModerator()) {
      return;
    }

    if (message.isExpired() && showDeleted) {
      throw new MessageNotFoundException(message.getId(), "нельзя посмотреть удаленные комментарии в устаревших темах");
    }

    boolean unauthorized = currentUser == null || currentUser.isAnonymous();
    boolean topicAuthor = currentUser!=null && currentUser.getId() == message.getUid();

    if (message.isDeleted()) {
      if (message.isExpired()) {
        throw new MessageNotFoundException(message.getId(), "нельзя посмотреть устаревшие удаленные сообщения");
      }

      if (unauthorized) {
        throw new MessageNotFoundException(message.getId(), "Сообщение удалено");
      }

      if (topicAuthor) {
        return;
      }

      if (currentUser.getScore() < VIEW_DELETED_SCORE) {
        throw new MessageNotFoundException(message.getId(), "Сообщение удалено");
      }
    }

    if (message.isDraft()) {
      if (message.isExpired()) {
        throw new MessageNotFoundException(message.getId(), "Черновик устарел");
      }

      if (!topicAuthor) {
        throw new MessageNotFoundException(message.getId(), "Нельзя посмотреть чужой черновик");
      }
    }

    if (group.getCommentsRestriction() == -1 && unauthorized) {
      throw new AccessViolationException("Это сообщение нельзя посмотреть");
    }
  }

  public void checkCommentsAllowed(Topic topic, User user, Errors errors) {
    if (topic.isDeleted()) {
      errors.reject(null, "Нельзя добавлять комментарии к удаленному сообщению");
      return;
    }

    if (topic.isDraft()) {
      errors.reject(null, "Нельзя добавлять комментарии к черновику");
      return;
    }

    if (topic.isExpired()) {
      errors.reject(null, "Сообщение уже устарело");
      return;
    }

    Group group = groupDao.getGroup(topic.getGroupId());

    if (!isCommentsAllowed(group, topic, user)) {
      errors.reject(null, "Вы не можете добавлять комментарии в эту тему");
    }
  }

  private static int getCommentCountRestriction(Topic topic) {
    int commentCountPS = POSTSCORE_UNRESTRICTED;

    if (!topic.isSticky()) {
      int commentCount = topic.getCommentCount();

      if (commentCount > 3000) {
        commentCountPS = 200;
      } else if (commentCount > 2000) {
        commentCountPS = 100;
      } else if (commentCount > 1000) {
        commentCountPS = 50;
      }
    }

    return commentCountPS;
  }

  public int getPostscore(Group group, Topic topic) {
    int effective = Math.max(topic.getPostscore(), group.getCommentsRestriction());

    effective = Math.max(effective, Section.getCommentPostscore(topic.getSectionId()));

    effective = Math.max(effective, getCommentCountRestriction(topic));

    return effective;
  }

  public int getPostscore(Topic topic) {
    Group group = groupDao.getGroup(topic.getGroupId());

    return getPostscore(group, topic);
  }

  public boolean isCommentsAllowed(Group group, Topic topic, User user) {
    if (user != null && user.isBlocked()) {
      return false;
    }

    if (topic.isDeleted() || topic.isExpired() || topic.isDraft()) {
      return false;
    }

    int score = getPostscore(group, topic);

    if (score == POSTSCORE_UNRESTRICTED) {
      return true;
    }

    if (user == null || user.isAnonymous()) {
      return false;
    }

    if (user.isModerator()) {
      return true;
    }

    if (score == POSTSCORE_REGISTERED_ONLY) {
      return true;
    }

    if (score == POSTSCORE_MODERATORS_ONLY) {
      return false;
    }

    boolean isAuthor = user.getId() == topic.getUid();

    if (score == POSTSCORE_MOD_AUTHOR) {
      return isAuthor;
    }

    if (isAuthor) {
      return true;
    } else {
      return user.getScore() >= score;
    }
  }

  /**
   * Проверка на права редактирования комментария.
   *
   * @return true если комментарий доступен для редактирования текущему пользователю, иначе false
   */
  public boolean isCommentsEditingAllowed(
          @Nonnull Comment comment,
          @Nonnull Topic topic,
          @Nullable User currentUser
  ) {
    Preconditions.checkNotNull(comment);
    Preconditions.checkNotNull(topic);

    final boolean haveAnswers = commentService.isHaveAnswers(comment);
    return isCommentEditableNow(
        comment,
        currentUser,
        haveAnswers,
        topic
    );
  }

  /**
   * Проверяем можно ли редактировать комментарий на текущий момент
   *
   * @param haveAnswers есть у комменатрия ответы
   * @return результат
   */
  public boolean isCommentEditableNow(@Nonnull Comment comment, @Nullable User currentUser,
                                      boolean haveAnswers, @Nonnull Topic topic) {
    if (comment.isDeleted() || topic.isDeleted()) {
      return false;
    }

    if (currentUser==null || currentUser.isAnonymous()) {
      return false;
    }

    boolean moderatorMode = currentUser.isModerator();
    boolean authored = currentUser.getId() == comment.getUserid();

    /* Проверка на то, что пользователь модератор */
    boolean editable = moderatorMode && siteConfig.isModeratorAllowedToEditComments();

    if (!editable && authored) {
      /* проверка на то, что время редактирования не вышло */
      boolean isbyMinutesEnable;
      if (siteConfig.getCommentExpireMinutesForEdit() != 0) {
        long nowTimestamp = System.currentTimeMillis();
        long deltaTimestamp = siteConfig.getCommentExpireMinutesForEdit() * 60 * 1000;

        isbyMinutesEnable = comment.getPostdate().getTime() + deltaTimestamp > nowTimestamp;
      } else {
        isbyMinutesEnable = true;
      }

      /* Проверка на то, что у комментария нет ответов */
      boolean isbyAnswersEnable = siteConfig.isCommentEditingAllowedIfAnswersExists() || !haveAnswers;

      /* Проверка на то, что у пользователя достаточно скора для редактирования комментария */
      boolean isByScoreEnable = currentUser.getScore() >= siteConfig.getCommentScoreValueForEditing();

      editable = isbyMinutesEnable && isbyAnswersEnable && isByScoreEnable;
    }

    return editable;
  }

  /**
   * Проверяем можно ли удалять комментарий на текущий момент
   *
   * @param haveAnswers у комментрия есть ответы?
   * @return резултат
   */
  public boolean isCommentDeletableNow(
          Comment comment,
          @Nullable User currentUser,
          Topic topic,
          boolean haveAnswers
  ) {
    if (comment.isDeleted() || topic.isDeleted()) {
      return false;
    }

    if (currentUser==null || currentUser.isAnonymous()) {
      return false;
    }

    boolean moderatorMode = currentUser.isModerator();
    boolean authored = currentUser.getId() == comment.getUserid();

    DateTime deleteDeadline = new DateTime(comment.getPostdate()).plus(DELETE_PERIOD);

    return moderatorMode ||
        (!topic.isExpired() &&
         authored &&
         !haveAnswers &&
          deleteDeadline.isAfterNow());
  }

  /**
   * Follow для ссылок автора
   *
   * @param author автор сообщения содержащего ссылку
   * @return true обычная ссылка, false - добавить rel=nofollow
   */
  public boolean followAuthorLinks(User author) {
    if (author.isBlocked() || author.isAnonymous()) {
      return false;
    }

    return author.getScore()>= LINK_FOLLOW_MIN_SCORE;
  }

  /**
   * follow топиков которые подтверждены и у которых автор не заблокирован и
   * score > LINK_FOLLOW_MIN_SCORE
   * @param topic
   * @param author
   * @return
   */
  public boolean followInTopic(Topic topic, User author) {
    return topic.isCommited() || followAuthorLinks(author);
  }

  public boolean isUserCastAllowed(User author) {
    return !author.isAnonymousScore();
  }
}
TOP

Related Classes of ru.org.linux.topic.TopicPermissionService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.