Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
course-discovery
Commits
626ea12f
Commit
626ea12f
authored
Dec 20, 2016
by
Awais
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new Permissions for courses.
Update mixins to get courses, and course runs. Addes tests cases. ECOM-6628
parent
8d4cadfb
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
314 additions
and
193 deletions
+314
-193
course_discovery/apps/publisher/api/permissions.py
+2
-2
course_discovery/apps/publisher/api/tests/test_views.py
+6
-15
course_discovery/apps/publisher/emails.py
+2
-2
course_discovery/apps/publisher/forms.py
+2
-2
course_discovery/apps/publisher/migrations/0022_auto_20161222_2135.py
+19
-0
course_discovery/apps/publisher/mixins.py
+28
-4
course_discovery/apps/publisher/models.py
+7
-12
course_discovery/apps/publisher/tests/test_emails.py
+18
-8
course_discovery/apps/publisher/tests/test_model.py
+31
-29
course_discovery/apps/publisher/tests/test_utils.py
+59
-1
course_discovery/apps/publisher/tests/test_views.py
+110
-98
course_discovery/apps/publisher/views.py
+20
-10
course_discovery/apps/publisher_comments/emails.py
+1
-1
course_discovery/apps/publisher_comments/tests/test_emails.py
+9
-8
course_discovery/apps/publisher_comments/tests/test_views.py
+0
-1
No files found.
course_discovery/apps/publisher/api/permissions.py
View file @
626ea12f
from
rest_framework.permissions
import
BasePermission
from
course_discovery.apps.publisher.mixins
import
check_
view_permission
from
course_discovery.apps.publisher.mixins
import
check_
user_course_access
from
course_discovery.apps.publisher.utils
import
is_internal_user
...
...
@@ -8,7 +8,7 @@ class CanViewAssociatedCourse(BasePermission):
""" Permission class to check user can view a publisher course. """
def
has_object_permission
(
self
,
request
,
view
,
obj
):
return
check_
view_permission
(
request
.
user
,
obj
.
course
)
return
check_
user_course_access
(
request
.
user
,
obj
.
course
)
class
InternalUserPermission
(
BasePermission
):
...
...
course_discovery/apps/publisher/api/tests/test_views.py
View file @
626ea12f
...
...
@@ -5,13 +5,10 @@ import ddt
from
django.contrib.auth.models
import
Group
from
django.core.urlresolvers
import
reverse
from
django.test
import
TestCase
from
guardian.shortcuts
import
assign_perm
from
course_discovery.apps.core.tests.factories
import
UserFactory
,
USER_PASSWORD
from
course_discovery.apps.course_metadata.tests.factories
import
OrganizationFactory
from
course_discovery.apps.publisher.choices
import
PublisherUserRole
from
course_discovery.apps.publisher.constants
import
INTERNAL_USER_GROUP_NAME
from
course_discovery.apps.publisher.models
import
Course
from
course_discovery.apps.publisher.tests
import
factories
,
JSON_CONTENT_TYPE
...
...
@@ -33,10 +30,8 @@ class CourseRoleAssignmentViewTests(TestCase):
self
.
other_internal_users
.
append
(
user
)
internal_user_group
.
user_set
.
add
(
user
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
internal_user_group
,
self
.
course
)
organization
=
OrganizationFactory
()
self
.
course
.
organizations
.
add
(
organization
)
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course
.
organizations
.
add
(
organization_extension
.
organization
)
# Create three internal user course roles for internal users against a course
# so we can test change role assignment on these roles.
...
...
@@ -54,7 +49,6 @@ class CourseRoleAssignmentViewTests(TestCase):
""" Verify non-internal users cannot change role assignments. """
non_internal_user
=
UserFactory
()
assign_perm
(
Course
.
VIEW_PERMISSION
,
non_internal_user
,
self
.
course
)
self
.
client
.
logout
()
self
.
client
.
login
(
username
=
non_internal_user
.
username
,
password
=
USER_PASSWORD
)
...
...
@@ -103,15 +97,12 @@ class OrganizationGroupUserViewTests(TestCase):
user
=
UserFactory
.
create
(
username
=
"test_user"
,
password
=
USER_PASSWORD
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
USER_PASSWORD
)
# create group and add test users in the group
group
=
factories
.
GroupFactory
()
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
org_user1
=
UserFactory
.
create
(
full_name
=
"org user1"
)
self
.
org_user2
=
UserFactory
.
create
(
full_name
=
"org user2"
)
group
.
user_set
.
add
(
self
.
org_user1
)
group
.
user_set
.
add
(
self
.
org_user2
)
self
.
organization
=
OrganizationFactory
()
factories
.
OrganizationExtensionFactory
.
create
(
organization
=
self
.
organization
,
group
=
group
)
organization_extension
.
group
.
user_set
.
add
(
self
.
org_user1
)
organization_extension
.
group
.
user_set
.
add
(
self
.
org_user2
)
self
.
organization
=
organization_extension
.
organization
def
test_get_organization_user_group
(
self
):
""" Verify that view returns list of users associated with the group
...
...
course_discovery/apps/publisher/emails.py
View file @
626ea12f
...
...
@@ -22,7 +22,7 @@ def send_email_for_change_state(course_run):
txt_template
=
'publisher/email/change_state.txt'
html_template
=
'publisher/email/change_state.html'
to_addresses
=
course_run
.
course
.
get_
group
_users_emails
()
to_addresses
=
course_run
.
course
.
get_
course
_users_emails
()
from_address
=
settings
.
PUBLISHER_FROM_EMAIL
page_path
=
reverse
(
'publisher:publisher_course_run_detail'
,
kwargs
=
{
'pk'
:
course_run
.
id
})
context
=
{
...
...
@@ -61,7 +61,7 @@ def send_email_for_studio_instance_created(course_run):
object_path
=
reverse
(
'publisher:publisher_course_run_detail'
,
kwargs
=
{
'pk'
:
course_run
.
id
})
subject
=
_
(
'Studio instance created'
)
to_addresses
=
course_run
.
course
.
get_
group
_users_emails
()
to_addresses
=
course_run
.
course
.
get_
course
_users_emails
()
from_address
=
settings
.
PUBLISHER_FROM_EMAIL
context
=
{
...
...
course_discovery/apps/publisher/forms.py
View file @
626ea12f
...
...
@@ -53,7 +53,7 @@ class CustomCourseForm(CourseForm):
)
title
=
forms
.
CharField
(
label
=
_
(
'Course Title'
),
required
=
True
)
number
=
forms
.
CharField
(
label
=
_
(
'Course Number'
),
required
=
True
)
team_admin
=
forms
.
ModelChoiceField
(
queryset
=
User
.
objects
.
filter
(
is_staff
=
True
),
required
=
True
)
team_admin
=
forms
.
ModelChoiceField
(
queryset
=
User
.
objects
.
all
(
),
required
=
True
)
class
Meta
(
CourseForm
.
Meta
):
model
=
Course
...
...
@@ -69,7 +69,7 @@ class UpdateCourseForm(BaseCourseForm):
""" Course form to update specific fields for already created course. """
number
=
forms
.
CharField
(
label
=
_
(
'Course Number'
),
required
=
True
)
team_admin
=
forms
.
ModelChoiceField
(
queryset
=
User
.
objects
.
filter
(
is_staff
=
True
),
required
=
True
)
team_admin
=
forms
.
ModelChoiceField
(
queryset
=
User
.
objects
.
all
(
),
required
=
True
)
class
Meta
:
model
=
Course
...
...
course_discovery/apps/publisher/migrations/0022_auto_20161222_2135.py
0 → 100644
View file @
626ea12f
# -*- coding: utf-8 -*-
# Generated by Django 1.9.11 on 2016-12-22 21:35
from
__future__
import
unicode_literals
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'publisher'
,
'0021_auto_20161214_1356'
),
]
operations
=
[
migrations
.
AlterModelOptions
(
name
=
'organizationextension'
,
options
=
{
'get_latest_by'
:
'modified'
,
'ordering'
:
(
'-modified'
,
'-created'
),
'permissions'
:
((
'edit_course_run'
,
'Can edit course run'
),
(
'publisher_view_course'
,
'Can view course'
),
(
'publisher_view_course_run'
,
'Can view the course run'
))},
),
]
course_discovery/apps/publisher/mixins.py
View file @
626ea12f
...
...
@@ -2,7 +2,8 @@ from django.contrib.auth.decorators import login_required
from
django.http
import
HttpResponseForbidden
,
HttpResponseRedirect
from
django.utils.decorators
import
method_decorator
from
course_discovery.apps.publisher.models
import
Course
,
Seat
from
course_discovery.apps.publisher.models
import
Course
,
Seat
,
OrganizationExtension
from
course_discovery.apps.publisher.utils
import
is_publisher_admin
,
is_internal_user
class
ViewPermissionMixin
(
object
):
...
...
@@ -20,7 +21,7 @@ class ViewPermissionMixin(object):
def
check_user
(
self
,
user
):
course
=
self
.
get_course
()
return
check_
view_permission
(
user
,
course
)
return
check_
user_course_access
(
user
,
course
)
def
permission_failed
(
self
):
return
HttpResponseForbidden
()
...
...
@@ -56,5 +57,28 @@ class FormValidMixin(object):
return
HttpResponseRedirect
(
self
.
get_success_url
())
def
check_view_permission
(
user
,
course
):
return
user
.
is_staff
or
user
.
has_perm
(
Course
.
VIEW_PERMISSION
,
course
)
def
check_roles_access
(
user
):
""" Return True if user is part of a role that gives implicit access. """
if
is_publisher_admin
(
user
)
or
is_internal_user
(
user
):
return
True
return
False
def
check_course_organization_permission
(
user
,
course
):
""" Return True if user has view permission on organization. """
if
not
hasattr
(
course
,
'organizations'
):
return
False
return
any
(
[
user
.
has_perm
(
OrganizationExtension
.
VIEW_COURSE
,
org
.
organization_extension
)
for
org
in
course
.
organizations
.
all
()
]
)
def
check_user_course_access
(
user
,
course
):
""" Return True if user is admin/internal user or has access permission. """
return
check_roles_access
(
user
)
or
check_course_organization_permission
(
user
,
course
)
course_discovery/apps/publisher/models.py
View file @
626ea12f
...
...
@@ -8,7 +8,6 @@ from django.dispatch import receiver
from
django.utils.translation
import
ugettext_lazy
as
_
from
django_extensions.db.models
import
TimeStampedModel
from
django_fsm
import
FSMField
,
transition
from
guardian.shortcuts
import
assign_perm
,
get_users_with_perms
from
simple_history.models
import
HistoricalRecords
from
sortedm2m.fields
import
SortedManyToManyField
from
stdimage.models
import
StdImageField
...
...
@@ -85,7 +84,6 @@ class State(TimeStampedModel, ChangedByMixin):
class
Course
(
TimeStampedModel
,
ChangedByMixin
):
""" Publisher Course model. It contains fields related to the course intake form."""
VIEW_PERMISSION
=
'view_course'
title
=
models
.
CharField
(
max_length
=
255
,
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Course title'
))
number
=
models
.
CharField
(
max_length
=
50
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Course number'
))
...
...
@@ -152,21 +150,14 @@ class Course(TimeStampedModel, ChangedByMixin):
(
'view_course'
,
'Can view course'
),
)
def
assign_permission_by_group
(
self
,
group
):
""" Assigns permission on the course against the group. """
assign_perm
(
self
.
VIEW_PERMISSION
,
group
,
self
)
def
get_group_users_emails
(
self
):
def
get_course_users_emails
(
self
):
""" Returns the list of users emails with enable email notifications
against a course
group
. By default if attribute value does not exists
against a course. By default if attribute value does not exists
then user will be eligible for emails.
Also get users from course-user-role table.
"""
users_list_perms
=
get_users_with_perms
(
self
)
users_list_roles
=
[
obj
.
user
for
obj
in
self
.
course_user_roles
.
all
()]
users_list
=
set
(
list
(
users_list_perms
)
+
list
(
users_list_roles
))
emails
=
[
user
.
email
for
user
in
users_list
if
is_email_notification_enabled
(
user
)]
emails
=
[
user
.
email
for
user
in
users_list_roles
if
is_email_notification_enabled
(
user
)]
return
emails
...
...
@@ -416,6 +407,8 @@ class CourseUserRole(TimeStampedModel, ChangedByMixin):
class
OrganizationExtension
(
TimeStampedModel
):
""" Organization-Extension relation model. """
EDIT_COURSE_RUN
=
'edit_course_run'
VIEW_COURSE
=
'publisher_view_course'
VIEW_COURSE_RUN
=
'publisher_view_course_run'
organization
=
models
.
OneToOneField
(
Organization
,
related_name
=
'organization_extension'
)
group
=
models
.
OneToOneField
(
Group
,
related_name
=
'organization_extension'
)
...
...
@@ -425,6 +418,8 @@ class OrganizationExtension(TimeStampedModel):
class
Meta
(
TimeStampedModel
.
Meta
):
permissions
=
(
(
'edit_course_run'
,
'Can edit course run'
),
(
'publisher_view_course'
,
'Can view course'
),
(
'publisher_view_course_run'
,
'Can view the course run'
),
)
def
__str__
(
self
):
...
...
course_discovery/apps/publisher/tests/test_emails.py
View file @
626ea12f
...
...
@@ -6,7 +6,6 @@ from django.contrib.sites.models import Site
from
django.core.urlresolvers
import
reverse
from
django.test
import
TestCase
from
django.core
import
mail
from
guardian.shortcuts
import
assign_perm
import
pytz
import
mock
from
testfixtures
import
LogCapture
...
...
@@ -14,7 +13,8 @@ from testfixtures import LogCapture
from
course_discovery.apps.core.tests.factories
import
UserFactory
from
course_discovery.apps.course_metadata.tests
import
toggle_switch
from
course_discovery.apps.publisher
import
emails
from
course_discovery.apps.publisher.models
import
State
,
Course
from
course_discovery.apps.publisher.choices
import
PublisherUserRole
from
course_discovery.apps.publisher.models
import
State
,
CourseUserRole
from
course_discovery.apps.publisher.tests
import
factories
from
course_discovery.apps.publisher.tests.factories
import
UserAttributeFactory
...
...
@@ -42,7 +42,16 @@ class StateChangeEmailTests(TestCase):
cls
.
course_run
=
cls
.
seat
.
course_run
cls
.
course
=
cls
.
course_run
.
course
assign_perm
(
Course
.
VIEW_PERMISSION
,
cls
.
group
,
cls
.
course
)
# add user in course-user-role table
factories
.
CourseUserRoleFactory
(
course
=
cls
.
course
,
role
=
PublisherUserRole
.
PartnerCoordinator
,
user
=
cls
.
user
)
factories
.
CourseUserRoleFactory
(
course
=
cls
.
course
,
role
=
PublisherUserRole
.
MarketingReviewer
,
user
=
cls
.
user_2
)
factories
.
CourseUserRoleFactory
(
course
=
cls
.
course
,
role
=
PublisherUserRole
.
Publisher
,
user
=
cls
.
user_3
)
# NOTE: We intentionally do NOT create an attribute for user_2.
# By default this user WILL receive email notifications.
...
...
@@ -94,10 +103,8 @@ class StateChangeEmailTests(TestCase):
State
.
FINALIZED
,
State
.
PUBLISHED
,
State
.
DRAFT
)
def
test_email_without_group
(
self
,
target_state
):
""" Verify that no email send if course group has no users. """
self
.
user
.
groups
.
remove
(
self
.
group
)
self
.
user_2
.
groups
.
remove
(
self
.
group
)
self
.
user_3
.
groups
.
remove
(
self
.
group
)
""" Verify that no email send if course user role has no users. """
CourseUserRole
.
objects
.
all
()
.
delete
()
self
.
course_run
.
change_state
(
target
=
target_state
)
self
.
assertEqual
(
len
(
mail
.
outbox
),
0
)
...
...
@@ -138,7 +145,10 @@ class StudioInstanceCreatedEmailTests(TestCase):
self
.
course_run
=
factories
.
CourseRunFactory
()
assign_perm
(
Course
.
VIEW_PERMISSION
,
self
.
group
,
self
.
course_run
.
course
)
# add user in course-user-role table
factories
.
CourseUserRoleFactory
(
course
=
self
.
course_run
.
course
,
role
=
PublisherUserRole
.
PartnerCoordinator
,
user
=
self
.
user
)
UserAttributeFactory
(
user
=
self
.
user
,
enable_email_notification
=
True
)
...
...
course_discovery/apps/publisher/tests/test_model.py
View file @
626ea12f
...
...
@@ -4,12 +4,13 @@ from django.db import IntegrityError
from
django.core.urlresolvers
import
reverse
from
django.test
import
TestCase
from
django_fsm
import
TransitionNotAllowed
from
guardian.shortcuts
import
get_groups_with_perms
from
guardian.shortcuts
import
assign_perm
from
course_discovery.apps.core.tests.factories
import
UserFactory
from
course_discovery.apps.publisher.choices
import
PublisherUserRole
from
course_discovery.apps.publisher.mixins
import
check_course_organization_permission
from
course_discovery.apps.publisher.models
import
(
State
,
Course
,
Course
UserRole
,
OrganizationExtension
,
OrganizationUserRole
State
,
CourseUserRole
,
OrganizationExtension
,
OrganizationUserRole
)
from
course_discovery.apps.publisher.tests
import
factories
...
...
@@ -80,6 +81,19 @@ class CourseTests(TestCase):
self
.
course
.
organizations
.
add
(
self
.
org_extension_1
.
organization
)
self
.
course2
.
organizations
.
add
(
self
.
org_extension_2
.
organization
)
# add user in course-user-role table
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
PartnerCoordinator
,
user
=
self
.
user1
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
MarketingReviewer
,
user
=
self
.
user2
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
Publisher
,
user
=
self
.
user3
)
def
test_str
(
self
):
""" Verify casting an instance to a string returns a string containing the course title. """
self
.
assertEqual
(
str
(
self
.
course
),
self
.
course
.
title
)
...
...
@@ -90,13 +104,16 @@ class CourseTests(TestCase):
reverse
(
'publisher:publisher_courses_edit'
,
kwargs
=
{
'pk'
:
self
.
course
.
id
})
)
def
test_assign_permission_
by_group
(
self
):
""" Verify that permission can be assigned using the
group
. """
def
test_assign_permission_
organization_extension
(
self
):
""" Verify that permission can be assigned using the
organization extension
. """
self
.
assert_user_cannot_view_course
(
self
.
user1
,
self
.
course
)
self
.
assert_user_cannot_view_course
(
self
.
user2
,
self
.
course2
)
self
.
course
.
assign_permission_by_group
(
self
.
org_extension_1
.
group
)
self
.
course2
.
assign_permission_by_group
(
self
.
org_extension_2
.
group
)
self
.
course
.
organizations
.
add
(
self
.
org_extension_1
.
organization
)
self
.
course2
.
organizations
.
add
(
self
.
org_extension_2
.
organization
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
user1
,
self
.
org_extension_1
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
user2
,
self
.
org_extension_2
)
self
.
assert_user_can_view_course
(
self
.
user1
,
self
.
course
)
self
.
assert_user_can_view_course
(
self
.
user2
,
self
.
course2
)
...
...
@@ -109,39 +126,24 @@ class CourseTests(TestCase):
def
assert_user_cannot_view_course
(
self
,
user
,
course
):
""" Asserts the user can NOT view the course. """
self
.
assertFalse
(
user
.
has_perm
(
Course
.
VIEW_PERMISSION
,
course
))
self
.
assertFalse
(
check_course_organization_permission
(
user
,
course
,
))
def
assert_user_can_view_course
(
self
,
user
,
course
):
""" Asserts the user can view the course. """
self
.
assertTrue
(
user
.
has_perm
(
Course
.
VIEW_PERMISSION
,
course
))
self
.
assertTrue
(
check_course_organization_permission
(
user
,
course
))
def
test_group_by_permission
(
self
):
""" Verify the method returns groups permitted to access the course."""
self
.
assertFalse
(
get_groups_with_perms
(
self
.
course
))
self
.
course
.
assign_permission_by_group
(
self
.
org_extension_1
.
group
)
self
.
assertEqual
(
get_groups_with_perms
(
self
.
course
)[
0
],
self
.
org_extension_1
.
group
)
def
test_get_group_users_emails
(
self
):
def
test_get_course_users_emails
(
self
):
""" Verify the method returns the email addresses of users who are
permitted to access the course AND have not disabled email notifications.
"""
self
.
user3
.
groups
.
add
(
self
.
org_extension_1
.
group
)
self
.
course
.
assign_permission_by_group
(
self
.
org_extension_1
.
group
)
self
.
assertListEqual
(
self
.
course
.
get_group_users_emails
(),
[
self
.
user1
.
email
,
self
.
user3
.
email
])
# add user in course-user-role table
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
PartnerCoordinator
,
user
=
self
.
user2
)
self
.
assertListEqual
(
self
.
course
.
get_
group
_users_emails
(),
self
.
course
.
get_
course
_users_emails
(),
[
self
.
user1
.
email
,
self
.
user2
.
email
,
self
.
user3
.
email
]
)
# The email addresses of users who have disabled email notifications should NOT be returned.
factories
.
UserAttributeFactory
(
user
=
self
.
user1
,
enable_email_notification
=
False
)
self
.
assertListEqual
(
self
.
course
.
get_
group
_users_emails
(),
[
self
.
user2
.
email
,
self
.
user3
.
email
])
self
.
assertListEqual
(
self
.
course
.
get_
course
_users_emails
(),
[
self
.
user2
.
email
,
self
.
user3
.
email
])
def
test_keywords_data
(
self
):
""" Verify that the property returns the keywords as comma separated string. """
...
...
@@ -155,13 +157,13 @@ class CourseTests(TestCase):
def
test_partner_coordinator
(
self
):
""" Verify that the partner_coordinator property returns user if exist. """
self
.
assertIsNone
(
self
.
course
.
partner_coordinator
)
self
.
assertIsNone
(
self
.
course
2
.
partner_coordinator
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
self
.
user1
,
role
=
PublisherUserRole
.
PartnerCoordinator
course
=
self
.
course
2
,
user
=
self
.
user1
,
role
=
PublisherUserRole
.
PartnerCoordinator
)
self
.
assertEqual
(
self
.
user1
,
self
.
course
.
partner_coordinator
)
self
.
assertEqual
(
self
.
user1
,
self
.
course
2
.
partner_coordinator
)
class
SeatTests
(
TestCase
):
...
...
course_discovery/apps/publisher/tests/test_utils.py
View file @
626ea12f
""" Tests publisher.utils"""
from
django.contrib.auth.models
import
Group
from
django.test
import
TestCase
from
guardian.shortcuts
import
assign_perm
from
course_discovery.apps.core.tests.factories
import
UserFactory
from
course_discovery.apps.publisher.constants
import
(
ADMIN_GROUP_NAME
,
INTERNAL_USER_GROUP_NAME
,
PARTNER_COORDINATOR_GROUP_NAME
)
from
course_discovery.apps.publisher.mixins
import
(
check_roles_access
,
check_course_organization_permission
,
check_user_course_access
)
from
course_discovery.apps.publisher.models
import
OrganizationExtension
from
course_discovery.apps.publisher.tests
import
factories
from
course_discovery.apps.publisher.utils
import
(
is_email_notification_enabled
,
is_publisher_admin
,
is_internal_user
,
...
...
@@ -18,7 +23,12 @@ class PublisherUtilsTests(TestCase):
def
setUp
(
self
):
super
(
PublisherUtilsTests
,
self
)
.
setUp
()
self
.
user
=
UserFactory
(
is_staff
=
True
,
is_superuser
=
True
)
self
.
user
=
UserFactory
()
self
.
course
=
factories
.
CourseFactory
()
self
.
admin_group
=
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
)
self
.
internal_user_group
=
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
)
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
def
test_email_notification_enabled_by_default
(
self
):
""" Test email notification is enabled for the user by default."""
...
...
@@ -82,3 +92,51 @@ class PublisherUtilsTests(TestCase):
partner_coordinator_group
=
Group
.
objects
.
get
(
name
=
PARTNER_COORDINATOR_GROUP_NAME
)
self
.
user
.
groups
.
add
(
partner_coordinator_group
)
self
.
assertTrue
(
is_partner_coordinator_user
(
self
.
user
))
def
test_check_roles_access_with_admin
(
self
):
""" Verify the function returns a boolean indicating if the user
access role wise.
"""
self
.
assertFalse
(
check_roles_access
(
self
.
user
))
self
.
user
.
groups
.
add
(
self
.
admin_group
)
self
.
assertTrue
(
check_roles_access
(
self
.
user
))
def
test_check_roles_access_with_internal_user
(
self
):
""" Verify the function returns a boolean indicating if the user
access role wise.
"""
self
.
assertFalse
(
check_roles_access
(
self
.
user
))
self
.
user
.
groups
.
add
(
self
.
internal_user_group
)
self
.
assertTrue
(
check_roles_access
(
self
.
user
))
def
test_check_organization_permission_without_org
(
self
):
""" Verify the function returns a boolean indicating if the user has
organization permission on given course.
"""
self
.
assertFalse
(
check_course_organization_permission
(
self
.
user
,
self
.
course
))
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
user
,
self
.
organization_extension
)
self
.
assertTrue
(
check_course_organization_permission
(
self
.
user
,
self
.
course
))
def
test_check_user_access_with_roles
(
self
):
""" Verify the function returns a boolean indicating if the user
organization permission on given course or user is internal or admin user.
"""
self
.
assertFalse
(
check_user_course_access
(
self
.
user
,
self
.
course
))
self
.
user
.
groups
.
add
(
self
.
admin_group
)
self
.
assertTrue
(
check_user_course_access
(
self
.
user
,
self
.
course
))
self
.
user
.
groups
.
remove
(
self
.
admin_group
)
self
.
assertFalse
(
check_user_course_access
(
self
.
user
,
self
.
course
))
self
.
user
.
groups
.
add
(
self
.
internal_user_group
)
self
.
assertTrue
(
check_user_course_access
(
self
.
user
,
self
.
course
))
def
test_check_user_access_with_permission
(
self
):
""" Verify the function returns a boolean indicating if the user
has view permission on organization
"""
self
.
assertFalse
(
check_course_organization_permission
(
self
.
user
,
self
.
course
))
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
user
,
self
.
organization_extension
)
self
.
assertTrue
(
check_course_organization_permission
(
self
.
user
,
self
.
course
))
course_discovery/apps/publisher/tests/test_views.py
View file @
626ea12f
...
...
@@ -43,7 +43,7 @@ class CreateUpdateCourseViewTests(TestCase):
def
setUp
(
self
):
super
(
CreateUpdateCourseViewTests
,
self
)
.
setUp
()
self
.
user
=
UserFactory
(
is_staff
=
True
,
is_superuser
=
True
)
self
.
user
=
UserFactory
()
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
group
=
self
.
organization_extension
.
group
...
...
@@ -51,7 +51,7 @@ class CreateUpdateCourseViewTests(TestCase):
self
.
course_run
=
factories
.
CourseRunFactory
(
course
=
self
.
course
)
self
.
seat
=
factories
.
SeatFactory
(
course_run
=
self
.
course_run
,
type
=
Seat
.
VERIFIED
,
price
=
2
)
self
.
user
.
groups
.
add
(
self
.
organization_extension
.
group
)
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
site
=
Site
.
objects
.
get
(
pk
=
settings
.
SITE_ID
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
self
.
start_date_time
=
datetime
.
now
()
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
...
...
@@ -90,6 +90,7 @@ class CreateUpdateCourseViewTests(TestCase):
""" Verify that new course, course run and seat can be created
with different data sets.
"""
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
self
.
_assert_records
(
1
)
course_dict
=
self
.
_post_data
(
data
,
self
.
course
,
self
.
course_run
,
self
.
seat
)
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_courses_new'
),
course_dict
,
files
=
data
[
'image'
])
...
...
@@ -107,15 +108,16 @@ class CreateUpdateCourseViewTests(TestCase):
self
.
_assert_records
(
1
)
data
=
{
'number'
:
'course_2'
,
'image'
:
make_image_file
(
'test_banner.jpg'
)}
course_dict
=
self
.
_post_data
(
data
,
self
.
course
,
self
.
course_run
,
self
.
seat
)
with
patch
.
object
(
Course
,
"
assign_permission_by_group
"
)
as
mock_method
:
with
patch
.
object
(
Course
,
"
save
"
)
as
mock_method
:
mock_method
.
side_effect
=
IntegrityError
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_courses_new'
),
course_dict
,
files
=
data
[
'image'
])
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
_assert_records
(
1
)
def
test_update_course_with_staff
(
self
):
""" Verify that staff user can update an existing course. """
def
test_update_course_with_admin
(
self
):
""" Verify that publisher admin can update an existing course. """
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
course_dict
=
model_to_dict
(
self
.
course
)
course_dict
.
pop
(
'verification_deadline'
)
course_dict
.
pop
(
'image'
)
...
...
@@ -149,9 +151,8 @@ class CreateUpdateCourseViewTests(TestCase):
self
.
assertContains
(
response
,
'Add new comment'
)
self
.
assertContains
(
response
,
comment
.
comment
)
def
test_course_edit_page_with_non_staff
(
self
):
""" Verify that non staff user can't access course edit page without permission. """
non_staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
def
test_course_edit_page_without_admin_rights
(
self
):
""" Verify that non publisher admin user can't access course edit page without rights. """
course_dict
=
model_to_dict
(
self
.
course
)
updated_course_title
=
'Updated {}'
.
format
(
self
.
course
.
title
)
...
...
@@ -163,19 +164,15 @@ class CreateUpdateCourseViewTests(TestCase):
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course
)
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
response
=
self
.
client
.
get
(
reverse
(
'publisher:publisher_courses_edit'
,
kwargs
=
{
'pk'
:
self
.
course
.
id
})
)
self
.
assertEqual
(
response
.
status_code
,
200
)
def
test_update_course_with
_non_staff
(
self
):
def
test_update_course_with
out_admin_rights
(
self
):
""" Tests for update course with non staff user. """
non_staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
course_dict
=
model_to_dict
(
self
.
course
)
course_dict
.
pop
(
'verification_deadline'
)
course_dict
.
pop
(
'image'
)
...
...
@@ -192,10 +189,7 @@ class CreateUpdateCourseViewTests(TestCase):
# verify that non staff user can't update course without permission
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course
)
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_courses_edit'
,
kwargs
=
{
'pk'
:
self
.
course
.
id
}),
course_dict
...
...
@@ -238,6 +232,7 @@ class CreateUpdateCourseViewTests(TestCase):
@ddt.data
(
Seat
.
AUDIT
,
Seat
.
HONOR
)
def
test_create_course_without_price_with_success
(
self
,
seat_type
):
""" Verify that if seat type is honor/audit then price is not required. """
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
self
.
_assert_records
(
1
)
data
=
{
'number'
:
'course_1'
,
'image'
:
''
}
course_dict
=
self
.
_post_data
(
data
,
self
.
course
,
self
.
course_run
,
self
.
seat
)
...
...
@@ -290,7 +285,6 @@ class CreateUpdateCourseViewTests(TestCase):
)
self
.
assertEqual
(
course
.
organizations
.
first
(),
self
.
organization_extension
.
organization
)
self
.
assertEqual
(
course
.
team_admin
,
self
.
user
)
self
.
assertTrue
(
self
.
user
.
has_perm
(
Course
.
VIEW_PERMISSION
,
course
))
course_run
=
course
.
publisher_course_runs
.
all
()[
0
]
self
.
assertEqual
(
self
.
course_run
.
language
,
course_run
.
language
)
self
.
assertEqual
(
course_run
.
start
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
),
self
.
start_date_time
)
...
...
@@ -311,9 +305,11 @@ class CreateUpdateCourseRunViewTests(TestCase):
def
setUp
(
self
):
super
(
CreateUpdateCourseRunViewTests
,
self
)
.
setUp
()
self
.
user
=
UserFactory
(
is_staff
=
True
,
is_superuser
=
True
)
self
.
user
=
UserFactory
()
self
.
course
=
factories
.
CourseFactory
(
team_admin
=
self
.
user
)
self
.
course_run
=
factories
.
CourseRunFactory
()
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
course_run_dict
=
model_to_dict
(
self
.
course_run
)
self
.
course_run_dict
.
update
(
{
'number'
:
self
.
course
.
number
,
'team_admin'
:
self
.
course
.
team_admin
.
id
,
'is_self_paced'
:
True
}
...
...
@@ -398,6 +394,7 @@ class CreateUpdateCourseRunViewTests(TestCase):
def
test_create_course_run_and_seat
(
self
):
""" Verify that we can create a new course run with seat. """
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
updated_course_number
=
'{number}.2'
.
format
(
number
=
self
.
course
.
number
)
new_price
=
450
post_data
=
self
.
course_run_dict
...
...
@@ -411,7 +408,7 @@ class CreateUpdateCourseRunViewTests(TestCase):
}
)
self
.
_pop_valuse_from_dict
(
post_data
,
[
'id'
,
'course'
,
'course_run'
])
assign_perm
(
OrganizationExtension
.
VIEW_COURSE_RUN
,
self
.
user
,
self
.
organization_extension
)
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_course_runs_new'
,
kwargs
=
{
'parent_course_id'
:
self
.
course
.
id
}),
post_data
...
...
@@ -436,13 +433,14 @@ class CreateUpdateCourseRunViewTests(TestCase):
# Verify that number is updated for parent course
self
.
assertEqual
(
self
.
course
.
number
,
updated_course_number
)
def
test_update_course_run_with_
staff
(
self
):
""" Verify that
staff
user can update an existing course run. """
def
test_update_course_run_with_
internal_user
(
self
):
""" Verify that
internal
user can update an existing course run. """
updated_lms_course_id
=
'course-v1:testX+AS121+2018_q1'
self
.
course_run_dict
[
'lms_course_id'
]
=
updated_lms_course_id
self
.
assertNotEqual
(
self
.
course_run
.
lms_course_id
,
updated_lms_course_id
)
self
.
assertNotEqual
(
self
.
course_run
.
changed_by
,
self
.
user
)
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_course_runs_edit'
,
kwargs
=
{
'pk'
:
self
.
course_run
.
id
}),
self
.
course_run_dict
...
...
@@ -467,9 +465,9 @@ class CreateUpdateCourseRunViewTests(TestCase):
self
.
assertContains
(
response
,
'Add new comment'
)
self
.
assertContains
(
response
,
comment
.
comment
)
def
test_edit_course_run_page_with_non_
staff
(
self
):
""" Verify that non
staff
user can't access course run edit page without permission. """
non_
staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
def
test_edit_course_run_page_with_non_
internal
(
self
):
""" Verify that non
internal
user can't access course run edit page without permission. """
non_
internal_user
,
__
=
create_non_staff_user_and_login
(
self
)
updated_lms_course_id
=
'course-v1:testX+AS121+2018_q1'
self
.
course_run_dict
[
'lms_course_id'
]
=
updated_lms_course_id
...
...
@@ -481,9 +479,7 @@ class CreateUpdateCourseRunViewTests(TestCase):
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course_run
.
course
)
non_internal_user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
response
=
self
.
client
.
get
(
reverse
(
'publisher:publisher_course_runs_edit'
,
kwargs
=
{
'pk'
:
self
.
course_run
.
id
})
...
...
@@ -491,9 +487,9 @@ class CreateUpdateCourseRunViewTests(TestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
def
test_update_course_run_with_non_
staff
(
self
):
""" Test for course run with non
staff
user. """
non_
staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
def
test_update_course_run_with_non_
internal_user
(
self
):
""" Test for course run with non
internal
user. """
non_
internal_user
,
__
=
create_non_staff_user_and_login
(
self
)
updated_lms_course_id
=
'course-v1:testX+AS121+2018_q1'
self
.
course_run_dict
[
'lms_course_id'
]
=
updated_lms_course_id
...
...
@@ -504,12 +500,10 @@ class CreateUpdateCourseRunViewTests(TestCase):
self
.
course_run_dict
)
# verify that non
staff
user can't update course run without permission
# verify that non
internal
user can't update course run without permission
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course_run
.
course
)
non_internal_user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_course_runs_edit'
,
kwargs
=
{
'pk'
:
self
.
course_run
.
id
}),
...
...
@@ -541,9 +535,11 @@ class SeatsCreateUpdateViewTests(TestCase):
def
setUp
(
self
):
super
(
SeatsCreateUpdateViewTests
,
self
)
.
setUp
()
self
.
seat
=
factories
.
SeatFactory
(
type
=
Seat
.
PROFESSIONAL
,
credit_hours
=
0
)
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
seat
.
course_run
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
seat_dict
=
model_to_dict
(
self
.
seat
)
self
.
seat_dict
.
pop
(
'upgrade_deadline'
)
self
.
user
=
UserFactory
(
is_staff
=
True
,
is_superuser
=
True
)
self
.
user
=
UserFactory
()
self
.
site
=
Site
.
objects
.
get
(
pk
=
settings
.
SITE_ID
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
self
.
seat_edit_url
=
reverse
(
'publisher:publisher_seats_edit'
,
kwargs
=
{
'pk'
:
self
.
seat
.
id
})
...
...
@@ -573,6 +569,7 @@ class SeatsCreateUpdateViewTests(TestCase):
""" Verify that we can create a new seat. """
seat_price
=
670.00
self
.
seat_dict
[
'price'
]
=
seat_price
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
user
,
self
.
organization_extension
)
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_seats_new'
),
self
.
seat_dict
)
seat
=
Seat
.
objects
.
get
(
course_run
=
self
.
seat
.
course_run
,
price
=
seat_price
)
self
.
assertRedirects
(
...
...
@@ -584,8 +581,9 @@ class SeatsCreateUpdateViewTests(TestCase):
self
.
assertEqual
(
seat
.
price
,
seat_price
)
def
test_update_seat_with_staff
(
self
):
""" Verify that staff user can update an existing seat. """
def
test_update_seat_with_admin
(
self
):
""" Verify that publisher admin can update an existing seat. """
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
self
.
assertEqual
(
self
.
seat
.
type
,
Seat
.
PROFESSIONAL
)
updated_seat_price
=
470.00
self
.
seat_dict
[
'price'
]
=
updated_seat_price
...
...
@@ -631,22 +629,20 @@ class SeatsCreateUpdateViewTests(TestCase):
self
.
assertContains
(
response
,
comment
.
comment
)
def
test_edit_seat_page_with_non_staff
(
self
):
""" Verify that non
staff
user can't access seat edit page without permission. """
non_
staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
""" Verify that non
internal
user can't access seat edit page without permission. """
non_
internal_user
,
__
=
create_non_staff_user_and_login
(
self
)
response
=
self
.
client
.
get
(
reverse
(
'publisher:publisher_seats_edit'
,
kwargs
=
{
'pk'
:
self
.
seat
.
id
}))
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
seat
.
course_run
.
course
)
non_internal_user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
response
=
self
.
client
.
get
(
reverse
(
'publisher:publisher_seats_edit'
,
kwargs
=
{
'pk'
:
self
.
seat
.
id
}))
self
.
assertEqual
(
response
.
status_code
,
200
)
def
test_update_seat_with_
non_staff
(
self
):
""" Tests update seat for
non staff
user. """
non_
staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
def
test_update_seat_with_
internal_user
(
self
):
""" Tests update seat for
internal
user. """
non_
internal_user
,
__
=
create_non_staff_user_and_login
(
self
)
self
.
assertEqual
(
self
.
seat
.
type
,
Seat
.
PROFESSIONAL
)
updated_seat_price
=
470.00
...
...
@@ -659,12 +655,10 @@ class SeatsCreateUpdateViewTests(TestCase):
self
.
seat_dict
)
# verify that non
staff
user can't update course seat without permission
# verify that non
internal
user can't update course seat without permission
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
seat
.
course_run
.
course
)
non_internal_user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
response
=
self
.
client
.
post
(
reverse
(
'publisher:publisher_seats_edit'
,
kwargs
=
{
'pk'
:
self
.
seat
.
id
}),
...
...
@@ -707,9 +701,14 @@ class CourseRunDetailTests(TestCase):
def
setUp
(
self
):
super
(
CourseRunDetailTests
,
self
)
.
setUp
()
self
.
course
=
factories
.
CourseFactory
()
self
.
user
=
UserFactory
(
is_staff
=
True
)
self
.
user
=
UserFactory
()
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
))
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
self
.
course_run
=
factories
.
CourseRunFactory
(
course
=
self
.
course
)
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
_generate_seats
([
Seat
.
AUDIT
,
Seat
.
HONOR
,
Seat
.
VERIFIED
,
Seat
.
PROFESSIONAL
])
self
.
_generate_credit_seat
()
self
.
page_url
=
reverse
(
'publisher:publisher_course_run_detail'
,
args
=
[
self
.
course_run
.
id
])
...
...
@@ -731,11 +730,12 @@ class CourseRunDetailTests(TestCase):
target_status_code
=
302
)
def
test_page_without_data
_staff
(
self
):
""" Verify that
staff
user can access detail page without any data
def
test_page_without_data
(
self
):
""" Verify that user can access detail page without any data
available for that course-run.
"""
course_run
=
factories
.
CourseRunFactory
(
course
=
self
.
course
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE_RUN
,
self
.
user
,
self
.
organization_extension
)
page_url
=
reverse
(
'publisher:publisher_course_run_detail'
,
args
=
[
course_run
.
id
])
response
=
self
.
client
.
get
(
page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
...
...
@@ -746,20 +746,6 @@ class CourseRunDetailTests(TestCase):
response
=
self
.
client
.
get
(
page_url
)
self
.
assertEqual
(
response
.
status_code
,
404
)
def
test_details_page_non_staff
(
self
):
""" Verify that non staff user can't access detail page. """
non_staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertEqual
(
response
.
status_code
,
403
)
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course
)
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
def
_generate_seats
(
self
,
modes
):
""" Helper method to add seats for a course-run. """
for
mode
in
modes
:
...
...
@@ -771,7 +757,7 @@ class CourseRunDetailTests(TestCase):
def
test_course_run_detail_page_staff
(
self
):
""" Verify that detail page contains all the data for drupal, studio and
cat with
staff
user.
cat with
publisher admin
user.
"""
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
...
...
@@ -881,10 +867,11 @@ class CourseRunDetailTests(TestCase):
""" Verify that detail page contains all the data along with comments
for course.
"""
user
=
UserFactory
(
is_staff
=
True
,
is_superuser
=
True
)
self
.
client
.
logout
()
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
site
=
Site
.
objects
.
get
(
pk
=
settings
.
SITE_ID
)
comment
=
CommentFactory
(
content_object
=
self
.
course
,
user
=
user
,
site
=
site
)
comment
=
CommentFactory
(
content_object
=
self
.
course
,
user
=
self
.
user
,
site
=
site
)
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
_assert_credits_seats
(
response
,
self
.
wrapped_course_run
.
credit_seat
)
...
...
@@ -917,7 +904,7 @@ class CourseRunDetailTests(TestCase):
internal_user_group
.
user_set
.
add
(
*
(
self
.
user
,
pc_user
,
marketing_user
,
publisher_user
))
assign_perm
(
Course
.
VIEW_PERMISSION
,
internal_user_group
,
self
.
course
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE_RUN
,
internal_user_group
,
self
.
organization_extension
)
organization
=
OrganizationFactory
()
self
.
course
.
organizations
.
add
(
organization
)
...
...
@@ -939,14 +926,14 @@ class CourseRunDetailTests(TestCase):
self
.
assertEqual
(
list
(
response
.
context
[
'user_list'
]),
list
(
get_internal_users
()))
def
test_detail_page_role_assignment_with_non_internal_user
(
self
):
""" Verify that
non internal user can't see change role assignment widget
. """
""" Verify that
user can't see change role assignment widget without permissions
. """
# Create a
non internal
user and assign course view permission.
non_internal_
user
=
UserFactory
()
assign_perm
(
Course
.
VIEW_PERMISSION
,
non_internal_user
,
self
.
course
)
# Create a user and assign course view permission.
user
=
UserFactory
()
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
user
,
self
.
organization_extension
)
self
.
client
.
logout
()
self
.
client
.
login
(
username
=
non_internal_
user
.
username
,
password
=
USER_PASSWORD
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
USER_PASSWORD
)
response
=
self
.
client
.
get
(
self
.
page_url
)
...
...
@@ -970,7 +957,7 @@ class CourseRunDetailTests(TestCase):
""" Test that user can't see edit button on course run detail page
if there is no organization in course.
"""
_
=
self
.
_create_user_and_login
()
self
.
_create_user_and_login
()
self
.
assert_can_edit_permission
()
...
...
@@ -985,7 +972,7 @@ class CourseRunDetailTests(TestCase):
and return the user.
"""
user
=
UserFactory
()
assign_perm
(
Course
.
VIEW_PERMISSION
,
user
,
self
.
course
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
user
,
self
.
organization_extension
)
self
.
client
.
logout
()
self
.
client
.
login
(
username
=
user
.
username
,
password
=
USER_PASSWORD
)
...
...
@@ -999,7 +986,14 @@ class ChangeStateViewTests(TestCase):
def
setUp
(
self
):
super
(
ChangeStateViewTests
,
self
)
.
setUp
()
self
.
course
=
factories
.
CourseFactory
()
self
.
user
=
UserFactory
(
is_staff
=
True
)
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
user
=
UserFactory
()
self
.
publisher_admin_group
=
Group
.
objects
.
get
(
name
=
ADMIN_GROUP_NAME
)
self
.
user
.
groups
.
add
(
self
.
publisher_admin_group
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
self
.
course_run
=
factories
.
CourseRunFactory
(
course
=
self
.
course
)
self
.
page_url
=
reverse
(
'publisher:publisher_course_run_detail'
,
args
=
[
self
.
course_run
.
id
])
...
...
@@ -1020,8 +1014,9 @@ class ChangeStateViewTests(TestCase):
target_status_code
=
302
)
def
test_change_state_with_staff
(
self
):
""" Verify that staff user can change workflow state from detail page. """
def
test_change_state
(
self
):
""" Verify that user can change workflow state from detail page. """
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertContains
(
response
,
'Status:'
)
self
.
assertContains
(
response
,
State
.
DRAFT
.
title
())
...
...
@@ -1031,8 +1026,8 @@ class ChangeStateViewTests(TestCase):
# assert that state is changed to `NEEDS_REVIEW`
self
.
assertContains
(
response
,
State
.
NEEDS_REVIEW
.
title
()
.
replace
(
'_'
,
' '
))
def
test_change_state_not_allowed
_with_staff
(
self
):
""" Verify that
staff
user can't change workflow state from `DRAFT` to `PUBLISHED`. """
def
test_change_state_not_allowed
(
self
):
""" Verify that user can't change workflow state from `DRAFT` to `PUBLISHED`. """
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertContains
(
response
,
'Status:'
)
self
.
assertContains
(
response
,
State
.
DRAFT
.
title
())
...
...
@@ -1042,17 +1037,16 @@ class ChangeStateViewTests(TestCase):
self
.
assertNotContains
(
response
,
State
.
PUBLISHED
.
title
())
self
.
assertContains
(
response
,
'There was an error in changing state.'
)
def
test_change_state_with_no_
staff
(
self
):
def
test_change_state_with_no_
permissions
(
self
):
""" Tests change state for non staff user. """
non_staff_user
,
group
=
create_non_staff_user_and_login
(
self
)
non_staff_user
,
__
=
create_non_staff_user_and_login
(
self
)
response
=
self
.
client
.
post
(
self
.
change_state_url
,
data
=
{
'state'
:
State
.
NEEDS_REVIEW
},
follow
=
True
)
# verify that non staff user can't change workflow state without permission
self
.
assertEqual
(
response
.
status_code
,
403
)
# assign user a group and assign view permission on that group
non_staff_user
.
groups
.
add
(
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course
)
# assign user a group
non_staff_user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertContains
(
response
,
'Status:'
)
...
...
@@ -1064,6 +1058,7 @@ class ChangeStateViewTests(TestCase):
self
.
assertContains
(
response
,
State
.
NEEDS_REVIEW
.
title
()
.
replace
(
'_'
,
' '
))
# pylint: disable=attribute-defined-outside-init
class
DashboardTests
(
TestCase
):
""" Tests for the `Dashboard`. """
...
...
@@ -1147,7 +1142,11 @@ class DashboardTests(TestCase):
self
.
client
.
logout
()
user
=
UserFactory
()
self
.
client
.
login
(
username
=
user
.
username
,
password
=
USER_PASSWORD
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
factories
.
GroupFactory
(),
self
.
course_run_1
.
course
)
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
user
,
self
.
organization_extension
)
self
.
course_run_1
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
assert_dashboard_response
(
studio_count
=
0
,
published_count
=
0
,
progress_count
=
0
,
preview_count
=
0
)
def
test_with_permissions_with_data
(
self
):
...
...
@@ -1156,12 +1155,16 @@ class DashboardTests(TestCase):
"""
self
.
client
.
logout
()
user
=
UserFactory
()
group
=
factories
.
GroupFactory
()
user
.
groups
.
add
(
group
)
self
.
client
.
login
(
username
=
user
.
username
,
password
=
USER_PASSWORD
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course_run_1
.
course
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
group
,
self
.
course_run_2
.
course
)
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course_run_1
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
course_run_2
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
user
,
self
.
organization_extension
)
self
.
assert_dashboard_response
(
studio_count
=
0
,
published_count
=
0
,
progress_count
=
1
,
preview_count
=
1
)
def
test_studio_request_course_runs_as_pc
(
self
):
...
...
@@ -1305,18 +1308,25 @@ class UpdateCourseKeyViewTests(TestCase):
super
(
UpdateCourseKeyViewTests
,
self
)
.
setUp
()
self
.
course_run
=
factories
.
CourseRunFactory
()
self
.
user
=
UserFactory
(
is_staff
=
True
,
is_superuser
=
True
)
self
.
user
.
groups
.
add
(
Group
.
objects
.
get
(
name
=
INTERNAL_USER_GROUP_NAME
))
self
.
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
user
.
groups
.
add
(
self
.
organization_extension
.
group
)
assign_perm
(
Course
.
VIEW_PERMISSION
,
self
.
organization_extension
.
group
,
self
.
course_run
.
course
)
self
.
course_run
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
self
.
update_course_key_url
=
reverse
(
'publisher:publisher_course_run_detail'
,
kwargs
=
{
'pk'
:
self
.
course_run
.
id
}
)
# emails send using user course roles
factories
.
CourseUserRoleFactory
(
role
=
PublisherUserRole
.
PartnerCoordinator
,
course
=
self
.
course_run
.
course
,
user
=
self
.
user
)
factories
.
UserAttributeFactory
(
user
=
self
.
user
,
enable_email_notification
=
True
)
toggle_switch
(
'enable_publisher_email_notifications'
,
True
)
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
USER_PASSWORD
)
def
test_update_course_key_with_errors
(
self
):
""" Test that api returns error with invalid course key."""
...
...
@@ -1405,7 +1415,9 @@ class CourseListViewTests(TestCase):
def
test_courses_with_permission
(
self
):
""" Verify that user can see course with permission on course list page. """
assign_perm
(
Course
.
VIEW_PERMISSION
,
self
.
user
,
self
.
course
)
organization_extension
=
factories
.
OrganizationExtensionFactory
()
self
.
course
.
organizations
.
add
(
organization_extension
.
organization
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
user
,
organization_extension
)
self
.
assert_course_list_page
(
course_count
=
1
)
...
...
course_discovery/apps/publisher/views.py
View file @
626ea12f
...
...
@@ -59,9 +59,14 @@ class Dashboard(mixins.LoginRequiredMixin, ListView):
internal_user_courses
=
Course
.
objects
.
filter
(
course_user_roles__user
=
user
)
course_runs
=
CourseRun
.
objects
.
filter
(
course__in
=
internal_user_courses
)
.
select_related
(
'course'
)
.
all
()
else
:
# in future we will change permission from course to OrganizationExtension model
courses
=
get_objects_for_user
(
user
,
Course
.
VIEW_PERMISSION
,
Course
)
course_runs
=
CourseRun
.
objects
.
filter
(
course__in
=
courses
)
.
select_related
(
'course'
)
.
all
()
organizations
=
get_objects_for_user
(
user
,
OrganizationExtension
.
VIEW_COURSE
,
OrganizationExtension
,
use_groups
=
False
,
with_superuser
=
False
)
.
values_list
(
'organization'
)
course_runs
=
CourseRun
.
objects
.
filter
(
course__organizations__in
=
organizations
)
.
select_related
(
'course'
)
.
all
()
return
course_runs
...
...
@@ -201,8 +206,6 @@ class CreateCourseView(mixins.LoginRequiredMixin, CreateView):
OrganizationExtension
,
organization
=
course_form
.
data
[
'organization'
]
)
course
.
organizations
.
add
(
organization_extension
.
organization
)
# assign guardian permission.
course
.
assign_permission_by_group
(
organization_extension
.
group
)
messages
.
success
(
request
,
_
(
'Course created successfully.'
)
...
...
@@ -226,7 +229,7 @@ class UpdateCourseView(mixins.LoginRequiredMixin, mixins.ViewPermissionMixin, mi
""" Update Course View."""
model
=
Course
form_class
=
CourseForm
permission_required
=
Course
.
VIEW_PERMISSION
permission_required
=
OrganizationExtension
.
VIEW_COURSE
template_name
=
'publisher/course_form.html'
success_url
=
'publisher:publisher_courses_edit'
...
...
@@ -324,7 +327,7 @@ class UpdateCourseRunView(mixins.LoginRequiredMixin, mixins.ViewPermissionMixin,
""" Update Course Run View."""
model
=
CourseRun
form_class
=
CourseRunForm
permission_required
=
Course
.
VIEW_PERMISSION
permission_required
=
OrganizationExtension
.
VIEW_COURSE
template_name
=
'publisher/course_run_form.html'
success_url
=
'publisher:publisher_course_runs_edit'
change_state
=
True
...
...
@@ -361,7 +364,7 @@ class UpdateSeatView(mixins.LoginRequiredMixin, mixins.ViewPermissionMixin, mixi
""" Update Seat View."""
model
=
Seat
form_class
=
SeatForm
permission_required
=
Course
.
VIEW_PERMISSIO
N
permission_required
=
OrganizationExtension
.
EDIT_COURSE_RU
N
template_name
=
'publisher/seat_form.html'
success_url
=
'publisher:publisher_seats_edit'
...
...
@@ -383,7 +386,7 @@ class ChangeStateView(mixins.LoginRequiredMixin, View):
try
:
course_run
=
CourseRun
.
objects
.
get
(
id
=
course_run_id
)
if
not
mixins
.
check_
view_permission
(
request
.
user
,
course_run
.
course
):
if
not
mixins
.
check_
user_course_access
(
request
.
user
,
course_run
.
course
):
return
HttpResponseForbidden
()
course_run
.
change_state
(
target
=
state
,
user
=
self
.
request
.
user
)
...
...
@@ -425,6 +428,13 @@ class CourseListView(mixins.LoginRequiredMixin, ListView):
elif
is_internal_user
(
user
):
courses
=
Course
.
objects
.
filter
(
course_user_roles__user
=
user
)
.
distinct
()
else
:
courses
=
get_objects_for_user
(
user
,
Course
.
VIEW_PERMISSION
,
Course
)
organizations
=
get_objects_for_user
(
user
,
OrganizationExtension
.
VIEW_COURSE
,
OrganizationExtension
,
use_groups
=
False
,
with_superuser
=
False
)
.
values_list
(
'organization'
)
courses
=
Course
.
objects
.
filter
(
organizations__in
=
organizations
)
return
courses
course_discovery/apps/publisher_comments/emails.py
View file @
626ea12f
...
...
@@ -53,7 +53,7 @@ def send_email_for_comment(comment, created=False):
title
=
course
.
title
)
to_addresses
=
course
.
get_
group
_users_emails
()
to_addresses
=
course
.
get_
course
_users_emails
()
from_address
=
settings
.
PUBLISHER_FROM_EMAIL
context
=
{
...
...
course_discovery/apps/publisher_comments/tests/test_emails.py
View file @
626ea12f
...
...
@@ -34,23 +34,24 @@ class CommentsEmailTests(TestCase):
self
.
course_run
=
self
.
seat
.
course_run
self
.
course
=
self
.
course_run
.
course
# assign the role against a course
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
# NOTE: We intentionally do NOT create an attribute for user_2.
# By default this user WILL receive email notifications.
# add user in course-user-role table
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
MarketingReviewe
r
,
user
=
self
.
user
course
=
self
.
course
,
role
=
PublisherUserRole
.
PartnerCoordinato
r
,
user
=
self
.
user
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
PartnerCoordinator
,
user
=
self
.
user_2
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
P
ublishe
r
,
user
=
self
.
user_3
course
=
self
.
course
,
role
=
PublisherUserRole
.
P
artnerCoordinato
r
,
user
=
self
.
user_3
)
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
# NOTE: We intentionally do NOT create an attribute for user_2.
# By default this user WILL receive email notifications.
UserAttributeFactory
(
user
=
self
.
user
,
enable_email_notification
=
True
)
UserAttributeFactory
(
user
=
self
.
user_3
,
enable_email_notification
=
False
)
toggle_switch
(
'enable_publisher_email_notifications'
,
True
)
...
...
course_discovery/apps/publisher_comments/tests/test_views.py
View file @
626ea12f
...
...
@@ -31,7 +31,6 @@ class CommentsTests(TestCase):
self
.
seat
=
factories
.
SeatFactory
(
type
=
Seat
.
PROFESSIONAL
,
credit_hours
=
0
)
self
.
course_run
=
self
.
seat
.
course_run
self
.
course
=
self
.
course_run
.
course
self
.
course
.
organizations
.
add
(
self
.
organization_extension
.
organization
)
# assign the role against a course
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment