diff --git a/anonticket/templates/anonticket/note_pending.html b/anonticket/templates/anonticket/note_pending.html new file mode 100644 index 0000000000000000000000000000000000000000..6531a14a1c71f41f00eaad67e75680e69206f0ce --- /dev/null +++ b/anonticket/templates/anonticket/note_pending.html @@ -0,0 +1,49 @@ +{% extends 'shared/layout.html' %} +{% load static %} + +{% load custom_filters %} + +{% load markdownify %} + +{% block extra_links %} + {% include 'shared/extend_sidebar.html' %} +{% endblock %} + +{% block h3 %} + +
+

{{note.linked_project}}

+

Created by {{note.linked_user.user_identifier}}

+
+
+
+

Milestone: NA, Note Pending Mod Approval.

+
+

+ Labels: NA, Note Pending Mod Approval

+
+
+
+
+

Pending Noteon Issue: "{{note.gitlab_issue_title|capfirst|truncatewords:20}}"

+
+
+
+
+{% endblock %} +{% block subheader %} +

"{{note.body|capfirst|markdownify}}"

+

(***This note is pending moderator approval.)

+{% endblock %} + +{% block content %} +
+
+ + {% url 'user-landing' note.linked_user.user_identifier as go_back_url %} +

+ Go Back To Landing Page +

+
+
+{% endblock %} \ No newline at end of file diff --git a/anonticket/templates/anonticket/user_landing.html b/anonticket/templates/anonticket/user_landing.html index b15e8d93cee494abb6aea8ed73265d92d813dc41..92dd4f38590a3c27af170cc60b13ed29f868e2f5 100644 --- a/anonticket/templates/anonticket/user_landing.html +++ b/anonticket/templates/anonticket/user_landing.html @@ -46,11 +46,15 @@

@@ -83,4 +87,40 @@ {% endif %} + + +
+
+

You have created the following notes:

+ + {% url 'issue-search' results.user_identifier as search_url %} + {% url 'project-list' results.user_identifier as project_list_url%} +

(To create a new note, + search for the issue you want to comment on, or look at the + project's detail view to find an issue. + Notes marked with *** have not been approved by moderators + and therefore have not been posted to GitLab.)

+ {% if results.linked_notes %} + +

+ {% else %} + +

You have not created any Notes.

+ {% endif %} +
+
{% endblock %} \ No newline at end of file diff --git a/anonticket/tests.py b/anonticket/tests.py index b9595ef7c27bd9a535a950c24a0cc768d84844dd..cdf0875c86681d03c7cd362b325ec7db061cf23f 100644 --- a/anonticket/tests.py +++ b/anonticket/tests.py @@ -11,6 +11,8 @@ from anonticket.forms import ( Anonymous_Ticket_Base_Search_Form, Anonymous_Ticket_Project_Search_Form, CreateIssueForm) +import pprint +pp = pprint.PrettyPrinter(indent=4) # Create your tests here. @@ -655,8 +657,11 @@ class TestModeratorViews(TestCase): # will allow test group permissions to exactly match those from file. from anonticket.management.commands.create_groups import GROUPS from anonticket.management.commands.create_groups import Command as create_groups + # Add a bad permission call so that you can test this part of the code. + GROUPS["Account Approvers"]["user identifier"].append("smash") create_groups.handle(create_groups) self.Moderators = Group.objects.get(name="Moderators") + self.AccountApprovers = Group.objects.get(name="Account Approvers") # Set up users to test the staff decorator and is_mod decorator. UserStaffNoGroup = User.objects.create( @@ -682,6 +687,14 @@ class TestModeratorViews(TestCase): self.UserGroupAndStaff = UserGroupAndStaff self.Moderators.user_set.add(UserGroupAndStaff) + UserAccountApprover = User.objects.create( + username='UserAccountApprover', + password='IAmATestPassword', + is_staff=True, + ) + self.UserAccountApprover = UserAccountApprover + self.AccountApprovers.user_set.add(UserAccountApprover) + # set the login redirect url for views testing from anonticket.views import login_redirect_url as login_redirect_url self.login_redirect_url = login_redirect_url @@ -711,7 +724,15 @@ class TestModeratorViews(TestCase): self.assertEqual(self.UserGroupAndStaff.username, "UserGroupAndStaff") self.assertTrue(self.UserGroupAndStaff.is_staff) self.assertTrue(self.UserGroupAndStaff.groups.filter(name="Moderators").exists()) - + + def test_user_account_approver_created_successfully(self): + """Tese that the username exists, that the user is staff, and that + the user is part of the Account Approvers group.""" + self.assertEqual(self.UserAccountApprover.username, "UserAccountApprover") + self.assertTrue(self.UserAccountApprover.is_staff) + self.assertTrue( + self.UserAccountApprover.groups.filter(name="Account Approvers").exists()) + def test_moderator_view_GET_not_logged_in(self): """Test that the moderator view redirects to a login form if there is no logged in user.""" @@ -741,7 +762,22 @@ class TestModeratorViews(TestCase): url = reverse('moderator') response = self.client.get(url) self.assertTemplateNotUsed(response, 'anonticket/moderator.html') - # print(response) + + def test_moderator_view_GET_account_approver(self): + """Test that the moderator view loads if a user is an account + approver.""" + current_user = self.UserAccountApprover + self.client.force_login(current_user) + url = reverse('moderator') + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + # Assert that the correct template loaded + self.assertTemplateUsed(response, 'anonticket/moderator.html') + # But that users in Account Approvers Group and not in Moderators + # Group do not have access to pending issues. + self.assertInHTML( + "You do not have permission to view pending issues at this time.", + '

You do not have permission to view pending issues at this time.

') def test_moderator_view_GET_valid_moderator(self): """Test that the moderator view displays correctly if diff --git a/anonticket/urls.py b/anonticket/urls.py index b6b6b1fe07d7ef1d96d97a6d69d1b7b7dffdbe6b..415395813938384788d826903c6f769dfe439286 100644 --- a/anonticket/urls.py +++ b/anonticket/urls.py @@ -22,6 +22,7 @@ urlpatterns = [ path('user/login/', views.login_view, name='login'), path('user//login_error/', views.UserLoginErrorView.as_view(), name='user-login-error'), path('user//projects//issues//notes/create/', views.NoteCreateView.as_view(), name='create-note'), + path('user//projects//issues//notes//', views.PendingNoteDetailView.as_view(), name='pending-note'), path('user//projects//issues//details/', views.issue_detail_view, name='issue-detail-view'), path('user//projects//issues/pending//', views.PendingIssueDetailView.as_view(), name='pending-issue-detail-view'), path('user//projects/all/issues/search/', views.issue_search_view, name="issue-search"), diff --git a/anonticket/views.py b/anonticket/views.py index ca801cbb3f100d230a3989d312739c38a89b16a9..3879a7e354392390cf9affaaa719ec0180f0ed47 100644 --- a/anonticket/views.py +++ b/anonticket/views.py @@ -58,6 +58,11 @@ def get_linked_issues(UserIdentifier): linked_issues = Issue.objects.filter(linked_user=UserIdentifier) return linked_issues +def get_linked_notes(UserIdentifier): + """Gets a list of the notes assigned to a User Identifier.""" + linked_notes = Note.objects.filter(linked_user=UserIdentifier) + return linked_notes + # --------------------DECORATORS AND MIXINS----------------------------- # Django decorators wrap functions (such as views) in other functions. # Mixins perform a similar function for class based views. @@ -209,8 +214,10 @@ def user_landing_view(request, user_identifier): # results dictionary. working_user = get_user_as_object(user_identifier) linked_issues = get_linked_issues(working_user) - results['linked_issues'] = linked_issues - # if found or not found, pass 'user_identifier' to context dictionary + linked_notes = get_linked_notes(working_user) + results['linked_issues'] = linked_issues + results['linked_notes'] = linked_notes + # whether user found or not found, pass 'user_identifier' to context dictionary results['user_identifier'] = user_identifier return render(request, 'anonticket/user_landing.html', {'results': results}) @@ -374,6 +381,11 @@ class NoteCreateView(PassUserIdentifierMixin, CreateView): working_url = reverse('issue-created', args=[user_identifier_to_pass]) return working_url +class PendingNoteDetailView(PassUserIdentifierMixin, DetailView): + """View For Pending Notes that have not been mod approved.""" + model = Note + template_name = 'anonticket/note_pending.html' + # ----------------------MODERATOR_VIEWS--------------------------------- # Views related to moderators. Should all have decorator # @staff_member_required, which forces staff status and allows access diff --git a/db.sqlite3 b/db.sqlite3 index 3a4bcceeb353f87fe2eeea03a857b4f39f27b50b..75bfc937216c2e59b40d744481ec30d8498ab6a7 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ