loomio/loomio

View on GitHub
vue/src/shared/services/ability_service.js

Summary

Maintainability
F
4 days
Test Coverage
import AppConfig     from '@/shared/services/app_config';
import Records       from '@/shared/services/records';
import Session       from '@/shared/services/session';
import LmoUrlService from '@/shared/services/lmo_url_service';
import {intersection} from 'lodash-es';

let user = () => Session.user();

export default new class AbilityService {
  isNotEmailVerified() {
    return Session.isSignedIn() && !Session.user().emailVerified;
  }

  isEmailVerified() {
    return Session.isSignedIn() && Session.user().emailVerified;
  }

  isUser() {
    return (AppConfig.currentUserId != null);
  }

  canContactUser(user) {
    return Session.isSignedIn() &&
    (Session.user().id !== user.id) &&
    intersection(Session.user().groupIds(), user.groupIds()).length;
  }

  canAddComment(thread) {
    return !thread.closedAt &&
    thread.membersInclude(Session.user());
  }

  canRespondToComment(comment) {
    return !comment.discussion().closedAt &&
    !comment.discardedAt &&
    comment.discussion().membersInclude(Session.user());
  }

  canEdit(model) {
    return (model.isA('discussion') && this.canEditThread(model)) ||
    (model.isA('comment') && this.canEditComment(model)) ||
    (model.isA('poll') && this.canEditPoll(model)) ||
    (model.isA('stance') && this.canEditStance(model));
  }

  canEditStance(stance) {
    return Session.user() === stance.author();
  }

  canEditThread(thread) {
    return thread.adminsInclude(Session.user()) ||
    (!thread.closedAt && thread.membersInclude(Session.user()) &&
     (thread.group().membersCanEditDiscussions || (thread.author() === Session.user())));
  }

  canCloseThread(thread) {
    return !thread.closedAt && (
      thread.adminsInclude(Session.user()) ||
      (thread.membersInclude(Session.user()) && (thread.group().membersCanEditDiscussions || (thread.author() === Session.user())))
    );
  }

  canReopenThread(thread) {
    return thread.closedAt && (
      thread.adminsInclude(Session.user()) ||
      (thread.membersInclude(Session.user()) && (thread.group().membersCanEditDiscussions || (thread.author() === Session.user())))
    );
  }

  canPinThread(thread) {
    return !thread.closedAt && !thread.pinnedAt && this.canEditThread(thread);
  }

  canUnpinThread(thread) {
    return !thread.closedAt && thread.pinnedAt && this.canEditThread(thread);
  }

  canExportThread(thread) {
    return !thread.discardedAt && thread.membersInclude(Session.user());
  }

  canPinEvent(event) {
    return (event.depth === 1) &&
    !event.model().discardedAt &&
    !event.pinned &&
    !event.discussion().closedAt &&
    this.canEditThread(event.discussion());
  }

  canUnpinEvent(event) {
    return !event.discussion().closedAt &&
    event.pinned && this.canEditThread(event.discussion());
  }

  canMoveThread(thread) { 
    return thread.adminsInclude(Session.user()) || (
      thread.membersInclude(Session.user()) &&
      (thread.group().membersCanEditDiscussions || (thread.author() === Session.user()))
    )
  }

  canDeleteThread(thread) {
    return thread.adminsInclude(Session.user()) || (thread.author() === Session.user());
  }

  canChangeGroupVolume(group) {
    return group.membersInclude(Session.user());
  }

  canAdminister(model) {
    switch (model.constructor.singular) {
      case 'group':                     return model.adminsInclude(Session.user());
      case 'discussion': case 'comment':     return model.discussion().adminsInclude(Session.user());
      case 'outcome': case 'stance': case 'poll': return model.poll().adminsInclude(Session.user());
    }
  }

  canChangeVolume(discussion) { return discussion.membersInclude(Session.user()); }

  canStartThread(group) {
    return group.adminsInclude(Session.user()) ||
    (group.membersInclude(Session.user()) && group.membersCanStartDiscussions);
  }

  canAnnounceDiscussion(discussion) {
    if (discussion.discardedAt || discussion.closedAt) { return false; }
    if (discussion.groupId) {
      return discussion.group().adminsInclude(Session.user()) ||
      (discussion.group().membersCanAnnounce && discussion.group().membersInclude(Session.user()));
    } else {
      return !discussion.id || discussion.adminsInclude(Session.user());
    }
  }

  canNotifyGroup(model) {
    return model.adminsInclude(Session.user()) ||
    (model.membersCanAnnounce && model.membersInclude(Session.user()));
  }

  canAnnounce(model) {
    if ((typeof model.isA === 'function' ? model.isA('poll') : undefined)) {
      return this.canAnnouncePoll(model);
    } else {
      return this.canAnnounceDiscussion(model);
    }
  }

  canAddGuests(model) {
    if ((typeof model.isA === 'function' ? model.isA('poll') : undefined)) {
      return this.canAddGuestsPoll(model);
    } else {
      return this.canAddGuestsDiscussion(model);
    }
  }

  canAddGuestsDiscussion(discussion) {
    if (discussion.groupId) {
      return discussion.group().adminsInclude(Session.user()) ||
      (discussion.group().membersCanAddGuests && discussion.group().membersInclude(Session.user()));
    } else {
      return !discussion.id || discussion.adminsInclude(Session.user());
    }
  }

  canAnnouncePoll(poll) {
    user = Session.user();
    if (poll.discardedAt) { return false; }
    if (poll.groupId) {
      return poll.group().adminsInclude(user) ||
      (poll.group().membersCanAnnounce && poll.adminsInclude(user))
    } else {
      return poll.adminsInclude(user) ||
      (!poll.specifiedVotersOnly && poll.membersInclude(user));
    }
  }

  canAddMembersPoll(poll) {
    return poll.adminsInclude(Session.user());
  }

  canAddGuestsPoll(poll) {
    if (poll.groupId) {
      return poll.group().adminsInclude(Session.user()) ||
      (poll.group().membersCanAddGuests && poll.adminsInclude(Session.user()));
    } else {
      return poll.adminsInclude(Session.user());
    }
  }

  canAddMembersToGroup(group) {
    return group.adminsInclude(Session.user()) ||
    (group.membersInclude(Session.user()) && group.membersCanAddMembers);
  }

  canCreateSubgroups(group) {
    return group.isParent() &&
    (group.adminsInclude(Session.user()) ||
    (group.membersInclude(Session.user()) && group.membersCanCreateSubgroups));
  }

  canEditGroup(group) {
    return group.adminsInclude(Session.user());
  }

  canLeaveGroup(group) {
    return (Session.user().membershipFor(group) != null);
  }

  canArchiveGroup(group) {
    return group.adminsInclude(Session.user());
  }

  canEditOwnComment(comment) {
    return comment.authorIs(Session.user()) && this.canEditComment(comment);
  }

  canEditComment(comment) {
    return !comment.discussion().closedAt && (
      (comment.discussion().adminsInclude(Session.user()) && comment.group().adminsCanEditUserContent) ||
      (comment.authorIs(Session.user()) && comment.group().membersCanEditComments && comment.discussion().membersInclude(Session.user()))
    );
  }

  canDeleteComment(comment) {
    return (Records.comments.find({parentId: comment.id, parentType: 'Comment'}).length === 0) &&
    comment.discardedAt &&
    (
      comment.discussion().adminsInclude(Session.user()) ||
      (comment.group().membersCanDeleteComments && comment.authorIs(Session.user()))
    );
  }

  canDiscardComment(comment) {
    return !comment.discussion().closedAt &&
    !comment.discardedAt &&
    (
      comment.authorIs(Session.user()) ||
      comment.discussion().adminsInclude(Session.user())
    );
  }

  canUndiscardComment(comment) {
    return !comment.discussion().closedAt &&
    comment.discardedAt && (
      comment.authorIs(Session.user()) ||
      comment.discussion().adminsInclude(Session.user())
    );
  }

  canRemoveMembership(membership) {
    return membership &&
    ((membership.user() === Session.user()) || this.canAdminister(membership.group()));
  }

  canSetMembershipTitle(membership) {
    return (Session.user() === membership.user()) || this.canAdminister(membership.group());
  }

  canResendMembership(membership) {
    return membership && !membership.acceptedAt && this.canAdminister(membership.group());
  }

  canManageMembershipRequests(group) {
    return (group.membersCanAddMembers && group.membersInclude(Session.user())) || group.adminsInclude(Session.user());
  }

  canViewPublicGroups() {
    return AppConfig.features.app.public_groups;
  }

  canStartGroups() {
    return this.isEmailVerified() && (AppConfig.features.app.create_group || Session.user().isAdmin);
  }

  canViewGroup(group) {
    return !group.privacyIsSecret() || group.membersInclude(Session.user());
  }

  canViewPrivateContent(group) {
    return group.membersInclude(Session.user());
  }

  canJoinGroup(group) {
    if (group.subscription.plan === 'demo') { return false; }
    if (!this.canViewGroup(group) || group.membersInclude(Session.user())) { return false; }
    return (group.membershipGrantedUpon === 'request') || group.parentOrSelf().adminsInclude(Session.user());
  }

  canRequestMembership(group) {
    return (group.membershipGrantedUpon === 'approval') &&
    this.canViewGroup(group) &&
    !group.membersInclude(Session.user()) &&
    !this.canJoinGroup(group);
  }

  canTranslate(model) {
    if (model.discardedAt) { return false; }
    return (AppConfig.inlineTranslation.isAvailable &&
    (Object.keys(model.translation).length === 0) &&
    !model.isBlank() &&
    (model.contentLocale && (model.contentLocale !== Session.user().locale))) ||
    (!model.contentLocale && (model.author().locale !== Session.user().locale));
  }

  canStartPoll(model) {
    return model.adminsInclude(Session.user()) ||
    (model.membersInclude(Session.user()) && model.group().membersCanRaiseMotions);
  }

  canParticipateInPoll(poll) {
    if (!poll) { return false; }
    if (poll.closedAt) { return false; }
    return poll.myStance() || (!poll.specifiedVotersOnly && poll.membersInclude(Session.user()));
  }

  canMovePoll(poll) {
    return (!poll.discussionId || !poll.discussion().closedAt) &&
    !poll.discussionId && poll.adminsInclude(Session.user());
  }

  canEditPoll(poll) {
    return (!poll.discussionId || !poll.discussion().closedAt) &&
    poll.adminsInclude(Session.user()) && !poll.closedAt;
  }

  canDeletePoll(poll) {
    return (!poll.discussionId || !poll.discussion().closedAt) &&
    !poll.discardedAt && poll.adminsInclude(Session.user());
  }

  canExportPoll(poll) {
    return !poll.discardedAt && poll.membersInclude(Session.user()) && (poll.closedAt || (poll.hideResults !== "until_closed"));
  }

  canAddPollToThread(poll) {
    return !poll.discardedAt && !poll.discussionId && poll.adminsInclude(Session.user());
  }

  canSetPollOutcome(poll) {
    return (!poll.discussionId || !poll.discussion().closedAt) &&
    !poll.discardedAt &&
    poll.closedAt &&
    poll.adminsInclude(Session.user());
  }

  canClosePoll(poll) {
    return !!poll.closingAt && !poll.discardedAt && !poll.closedAt && this.canEditPoll(poll);
  }

  canReopenPoll(poll) {
    return !poll.discardedAt && poll.closedAt && !poll.anonymous && poll.adminsInclude(Session.user());
  }
}