예제 #1
0
def group_view(request, group_abbr):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    permission_flags = 0 if request.user.is_anonymous else permissions.get_user_group_permissions(request.user, group)

    context = build_base_context(request)
    context['membership_perms'] = {
        'is_admin': permission_flags & permissions.IS_ADMIN,
        'can_announce': permission_flags & permissions.CAN_ANNOUNCE,
        'can_modify_roles': permission_flags & permissions.CAN_MODIFY_ROLES,
        'can_change_schedule': permission_flags & permissions.CAN_CHANGE_SCHEDULE}
    context['title'] = group.name
    context['group'] = group
    context['pcode'], nav_type = resolve_group_type(group)
    context['activities'] = m.Activity.objects.filter(group=group).order_by('datetime').reverse()
    context['is_member'] = is_member = not request.user.is_anonymous and group in request.user.groups_custom.all()

    if is_member:
        context['actions'] = [
            {'name': 'Sair do grupo', 'url': '#TODO'}]  # TODO
    else:
        if group.outsiders_openness == m.Group.REQUEST:
            context['actions'] = [
                {'name': 'Solicitar admissão', 'url': reverse('groups:membership_req', args=[group_abbr])}]
        elif group.outsiders_openness == m.Group.OPEN:
            context['actions'] = [
                {'name': 'Entrar no grupo', 'url': reverse('groups:membership_req', args=[group_abbr])}]

    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])}]
    return render(request, 'groups/group.html', context)
예제 #2
0
def settings_view(request, group_abbr):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    context = build_base_context(request)
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_settings'
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Definições', 'url': reverse('groups:settings', args=[group_abbr])}]

    permission_flags = permissions.get_user_group_permissions(request.user, group)
    if not (permission_flags & permissions.IS_ADMIN):
        context['title'] = context['msg_title'] = 'Insuficiência de permissões'
        context['msg_content'] = 'O seu utilizador não tem permissões suficientes para mudar as definições do grupo.'
        return render(request, 'supernova/message.html', context)

    context['title'] = f'Definições de {group.name}'
    context['group'] = group

    if request.method == 'POST':
        group_form = f.GroupSettingsForm(request.POST, request.FILES, instance=group)
        if group_form.is_valid():
            group_form.save()
            return redirect('groups:group', group_abbr=group_abbr)
    else:
        group_form = f.GroupSettingsForm(instance=group)

    context['group_form'] = group_form
    return render(request, 'groups/settings.html', context)
예제 #3
0
def calendar_management_view(request, group_abbr):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)

    if 'del' in request.GET:
        try:
            del_id = int(request.GET['del'])
            m.ScheduleEntry.objects.get(id=del_id, group=group).delete()
            return redirect('users:calendar_manage', abbreviation=group_abbr)
        except (ValueError, m.ScheduleOnce.DoesNotExist):
            return HttpResponse(status=400)

    context = build_base_context(request)
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_cal_man'

    permission_flags = permissions.get_user_group_permissions(request.user, group)
    if not permission_flags & permissions.CAN_CHANGE_SCHEDULE:
        context['title'] = context['msg_title'] = 'Insuficiência de permissões'
        context['msg_content'] = 'O seu utilizador não tem permissões suficientes para alterar a agenda do grupo.'
        return render(request, 'supernova/message.html', context)

    context['group'] = group
    once_schedule_entries = m.ScheduleOnce.objects.filter(group=group)
    periodic_schedule_entries = m.SchedulePeriodic.objects.filter(group=group)
    context['once_entries'] = once_schedule_entries
    context['periodic_entries'] = periodic_schedule_entries

    # Show empty forms by default
    once_form = f.ScheduleOnceForm()
    periodic_form = f.SchedulePeriodicForm()
    if 'type' in request.GET:
        rtype = request.GET['type']
        if rtype == "periodic" and request.method == 'POST':
            filled_form = f.SchedulePeriodicForm(request.POST)
            if filled_form.is_valid():
                entry = filled_form.save(commit=False)
                entry.group = group
                entry.save()
                m.ScheduleCreation.objects.create(group=group, author=request.user, entry=entry)
            else:
                periodic_form = filled_form  # Replace empty form with filled form with form filled with errors
        elif rtype == "once" and request.method == 'POST':
            filled_form = f.ScheduleOnceForm(request.POST)
            if filled_form.is_valid():
                entry = filled_form.save(commit=False)
                entry.group = group
                entry.save()
                m.ScheduleCreation.objects.create(group=group, author=request.user, entry=entry)
            else:
                once_form = filled_form  # Replace empty form with form filled with errors

    context['once_form'] = once_form
    context['periodic_form'] = periodic_form
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Agenda', 'url': reverse('groups:calendar_manage', args=[group_abbr])}]

    return render(request, 'groups/calendar_manage.html', context)
예제 #4
0
def conversations_view(request, group_abbr):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    permission_flags = 0 if request.user.is_anonymous else permissions.get_user_group_permissions(request.user, group)
    read_acc = permission_flags & permissions.CAN_READ_CONVERSATIONS
    context = build_base_context(request)
    context['title'] = f'Contactos com {group.name}'
    context['group'] = group
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_cnt'
    if read_acc:
        context['conversations'] = chat.GroupExternalConversation.objects \
            .filter(group=group) \
            .order_by('-creation') \
            .select_related('last_activity_user')
    else:
        context['conversations'] = chat.GroupExternalConversation.objects \
            .filter(group=group, creator=request.user) \
            .exclude(creator=request.user) \
            .order_by('-creation') \
            .select_related('last_activity_user')
    context['actions'] = [
        {'name': 'Criar nova', 'url': reverse('groups:conversation_create', args=[group_abbr])}]
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Conversas', 'url': reverse('groups:conversations', args=[group_abbr])}]
    return render(request, 'groups/conversations.html', context)
예제 #5
0
def group_candidates_view(request, group_abbr):
    group = get_object_or_404(m.Group.objects.select_related('default_role'), abbreviation=group_abbr)

    # Check for permissions
    permission_flags = 0 if request.user.is_anonymous else permissions.get_user_group_permissions(request.user, group)
    roles_acc = permission_flags & permissions.CAN_ASSIGN_ROLES
    if not roles_acc:
        raise PermissionDenied("No permission to manage roles.")

    accepted = request.GET.get('accept')
    denied = request.GET.get('deny')
    try:
        if accepted:
            m.MembershipRequest.objects.get(id=int(accepted)).accept()
        elif denied:
            m.MembershipRequest.objects.get(id=int(accepted)).deny()
    except ValueError:
        pass

    pcode, nav_type = resolve_group_type(group)
    context = build_base_context(request)
    context['title'] = f'Candidaturas a {group.name}'
    context['default_role'] = group.default_role
    context['candidates'] = m.MembershipRequest.objects.filter(group=group, granted=None).select_related('user').all()
    context['group'] = group
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Candidatos', 'url': reverse('groups:candidates', args=[group_abbr])}]
    return render(request, 'groups/membership_requests.html', context)
예제 #6
0
def announce_view(request, group_abbr):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    context = build_base_context(request)
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_announce'
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Anunciar', 'url': reverse('groups:announce', args=[group_abbr])}]

    permission_flags = permissions.get_user_group_permissions(request.user, group)
    if not (permission_flags & permissions.CAN_ANNOUNCE):
        context['title'] = context['msg_title'] = 'Insuficiência de permissões'
        context['msg_content'] = 'O seu utilizador não tem permissões suficientes para anúnciar pelo grupo.'
        return render(request, 'supernova/message.html', context)

    context['title'] = f'Anúnciar por {group.name}'
    context['group'] = group

    if request.method == 'POST':
        form = f.AnnounceForm(request.POST)
        if form.is_valid():
            announcement = form.save(commit=False)
            announcement.group = group
            announcement.author = request.user
            announcement.save()
            group.notify_subscribers(announcement)
            return redirect('groups:announcement', group_abbr=group_abbr, announcement_id=announcement.id)
    else:
        form = f.AnnounceForm()

    context['form'] = form
    return render(request, 'groups/announce.html', context)
예제 #7
0
def conversation_view(request, group_abbr, conversation_id):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    conversation = get_object_or_404(chat.GroupExternalConversation, id=conversation_id, group=group)

    permission_flags = 0 if request.user.is_anonymous else permissions.get_user_group_permissions(request.user, group)
    is_author = conversation.creator == request.user  # TODO: Change creator to is member of (use the conversation m2m)
    read_acc = permission_flags & permissions.CAN_READ_CONVERSATIONS
    write_acc = permission_flags & permissions.CAN_WRITE_CONVERSATIONS
    if not is_author and not read_acc:
        # FIXME this allows finding that this conversation exists (as it does not 404)
        # maybe change conversation identifiers to URL slugs to make it inviable to brute force URLs.
        raise PermissionDenied("No authorization to view this conversation.")

    if request.method == 'POST':
        if not (is_author or write_acc):
            raise PermissionDenied("No authorization to post in this conversation.")

        message_form = chat_f.MessageForm(request.POST)
        if message_form.is_valid():
            message = message_form.save(commit=False)
            message.author = request.user
            message.conversation = conversation
            message.save()
            message_form = chat_f.MessageForm()
    else:
        message_form = chat_f.MessageForm()

    messages = chat.Message.objects \
        .filter(conversation=conversation) \
        .order_by('creation') \
        .select_related('author') \
        .all()
    context = build_base_context(request)
    context['title'] = f'Contactar {group.name}'
    context['group'] = group
    context['conversation'] = conversation
    context['messages'] = messages
    if write_acc:
        context['message_form'] = message_form
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_cnt'
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Conversas', 'url': reverse('groups:conversations', args=[group_abbr])},
        {'name': conversation.title, 'url': reverse('groups:conversation', args=[group_abbr, conversation_id])}]
    return render(request, 'groups/conversation.html', context)
예제 #8
0
def role_view(request, group_abbr, role_id):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    context = build_base_context(request)
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_role'
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Cargos', 'url': reverse('groups:roles', args=[group_abbr])}]

    permission_flags = permissions.get_user_group_permissions(request.user, group)
    if not permission_flags & permissions.CAN_MODIFY_ROLES:
        context['title'] = context['msg_title'] = 'Insuficiência de permissões'
        context['msg_content'] = 'O seu utilizador não tem permissões suficientes para mudar os cargos do grupo.'
        return render(request, 'supernova/message.html', context)

    context['group'] = group
    context['role_id'] = role_id

    if role_id == 0:
        context['title'] = f'Criar cargo'
        if request.method == 'POST':
            form = f.RoleForm(request.POST)
            if form.is_valid():
                form.save()
                return redirect('groups:roles', group_abbr=group_abbr)
        else:
            form = f.RoleForm()
            context['sub_nav'].append({'name': "Criar cargo", 'url': reverse('groups:role', args=[group_abbr, 0])})
    else:
        role = get_object_or_404(m.Role, id=role_id, group__abbreviation=group_abbr)
        if request.method == 'POST':
            form = f.RoleForm(request.POST, instance=role)
            if form.is_valid():
                form.save()
                return redirect('groups:roles', group_abbr=group_abbr)
        else:
            form = f.RoleForm(instance=role)

        context['role'] = role
        context['title'] = f'Edição do cargo {role.name}'
        context['sub_nav'].append({'name': role.name, 'url': reverse('groups:role', args=[group_abbr, role_id])})
    context['form'] = form
    return render(request, 'groups/role.html', context)
예제 #9
0
    def clean(self):
        super().clean()
        current_permissions = permissions.get_user_group_permissions(self.current_user, self.instance)
        for form in self.forms:
            if not form.has_changed():
                continue
            if form.instance:
                old_role_permissions = permissions.roles_combined((form.instance.role,))
                if not permissions.can_handle_permissions(current_permissions, old_role_permissions):
                    raise djf.ValidationError("O cargo anterior tinha mais permissões do que o utilizador atual.")

                new_role = form.cleaned_data.get('role')
                new_role_permissions = permissions.roles_combined((new_role,))
                if not permissions.can_handle_permissions(current_permissions, new_role_permissions):
                    raise djf.ValidationError("O cargo definido tem mais permissões que o utilizador atual.")

        for form in self.deleted_forms:
            old_role_permissions = permissions.roles_combined((form.instance.role,))
            if not permissions.can_handle_permissions(current_permissions, old_role_permissions):
                raise djf.ValidationError("Não pode remover membros com mais do que as suas permissões.")
예제 #10
0
def roles_view(request, group_abbr):
    group = get_object_or_404(m.Group, abbreviation=group_abbr)
    context = build_base_context(request)
    pcode, nav_type = resolve_group_type(group)
    context['pcode'] = pcode + '_roles'
    context['sub_nav'] = [
        {'name': 'Grupos', 'url': reverse('groups:index')},
        nav_type,
        {'name': group.abbreviation, 'url': reverse('groups:group', args=[group_abbr])},
        {'name': 'Cargos', 'url': reverse('groups:roles', args=[group_abbr])}]

    permission_flags = permissions.get_user_group_permissions(request.user, group)
    if not (permission_flags & permissions.CAN_MODIFY_ROLES or permission_flags & permissions.CAN_ASSIGN_ROLES):
        context['title'] = context['msg_title'] = 'Insuficiência de permissões'
        context['msg_content'] = 'O seu utilizador não tem permissões suficientes para mudar os cargos do grupo.'
        return render(request, 'supernova/message.html', context)

    context['title'] = f'Gerir cargos de {group.name}'
    context['group'] = group
    context['can_edit'] = permission_flags & permissions.CAN_MODIFY_ROLES
    if request.method == 'POST':
        membership_formset = f.GroupMembershipFormSet(
            request.user,
            request.POST,
            instance=group,
            queryset=group.memberships)
        if membership_formset.is_valid():
            membership_formset.save()
            # Reset formset data to remove deleted
            membership_formset = f.GroupMembershipFormSet(
                request.user,
                instance=group,
                queryset=group.memberships)
    else:
        membership_formset = f.GroupMembershipFormSet(
            request.user,
            instance=group,
            queryset=group.memberships)

    context['membership_formset'] = membership_formset
    return render(request, 'groups/roles.html', context)