Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx-platform
Commits
ebeaaaad
Commit
ebeaaaad
authored
Nov 26, 2014
by
Stephen Sanchez
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6073 from edx/sanchez/add_email_optin_api_endpoint
Create new API endpoint for email optin
parents
9fd2b001
62143651
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
136 additions
and
3 deletions
+136
-3
common/djangoapps/user_api/api/profile.py
+49
-2
common/djangoapps/user_api/tests/test_profile_api.py
+83
-1
lms/envs/common.py
+4
-0
No files found.
common/djangoapps/user_api/api/profile.py
View file @
ebeaaaad
...
...
@@ -5,11 +5,16 @@ but does NOT include basic account information such as username, password, and
email address.
"""
import
datetime
from
django.conf
import
settings
from
django.db
import
IntegrityError
import
logging
from
pytz
import
UTC
from
user_api.models
import
User
,
UserProfile
,
UserPreference
from
user_api.models
import
User
,
UserProfile
,
UserPreference
,
UserOrgTag
from
user_api.helpers
import
intercept_errors
log
=
logging
.
getLogger
(
__name__
)
class
ProfileRequestError
(
Exception
):
""" The request to the API was not valid. """
...
...
@@ -155,3 +160,45 @@ def update_preferences(username, **kwargs):
else
:
for
key
,
value
in
kwargs
.
iteritems
():
UserPreference
.
set_preference
(
user
,
key
,
value
)
@intercept_errors
(
ProfileInternalError
,
ignore_errors
=
[
ProfileRequestError
])
def
update_email_opt_in
(
username
,
org
,
optin
):
"""Updates a user's preference for receiving org-wide emails.
Sets a User Org Tag defining the choice to opt in or opt out of organization-wide
emails.
Args:
username (str): The user to set a preference for.
org (str): The org is used to determine the organization this setting is related to.
optin (boolean): True if the user is choosing to receive emails for this organization. If the user is not
the correct age to receive emails, email-optin is set to False regardless.
Returns:
None
Raises:
ProfileUserNotFound: Raised when the username specified is not associated with a user.
"""
try
:
user
=
User
.
objects
.
get
(
username
=
username
)
except
User
.
DoesNotExist
:
raise
ProfileUserNotFound
profile
=
UserProfile
.
objects
.
get
(
user
=
user
)
of_age
=
(
profile
.
year_of_birth
is
None
or
# If year of birth is not set, we assume user is of age.
datetime
.
datetime
.
now
(
UTC
)
.
year
-
profile
.
year_of_birth
>=
# pylint: disable=maybe-no-member
getattr
(
settings
,
'EMAIL_OPTIN_MINIMUM_AGE'
,
13
)
)
try
:
preference
,
_
=
UserOrgTag
.
objects
.
get_or_create
(
user
=
user
,
org
=
org
,
key
=
'email-optin'
)
preference
.
value
=
str
(
optin
and
of_age
)
preference
.
save
()
except
IntegrityError
as
err
:
log
.
warn
(
u"Could not update organization wide preference due to IntegrityError: {}"
.
format
(
err
.
message
))
common/djangoapps/user_api/tests/test_profile_api.py
View file @
ebeaaaad
# -*- coding: utf-8 -*-
""" Tests for the profile API. """
from
django.contrib.auth.models
import
User
from
django.test
import
TestCase
import
ddt
from
django.test.utils
import
override_settings
from
nose.tools
import
raises
from
dateutil.parser
import
parse
as
parse_datetime
from
xmodule.modulestore.tests.factories
import
CourseFactory
import
datetime
from
user_api.api
import
account
as
account_api
from
user_api.api
import
profile
as
profile_api
from
user_api.models
import
UserProfile
from
user_api.models
import
UserProfile
,
UserOrgTag
@ddt.ddt
...
...
@@ -94,6 +98,84 @@ class ProfileApiTest(TestCase):
preferences
=
profile_api
.
preference_info
(
self
.
USERNAME
)
self
.
assertEqual
(
preferences
[
'preference_key'
],
'preference_value'
)
@ddt.data
(
# Check that a 27 year old can opt-in
(
27
,
True
,
u"True"
),
# Check that a 32-year old can opt-out
(
32
,
False
,
u"False"
),
# Check that someone 13 years old can opt-in
(
13
,
True
,
u"True"
),
# Check that someone 12 years old cannot opt-in
(
12
,
True
,
u"False"
)
)
@ddt.unpack
@override_settings
(
EMAIL_OPTIN_MINIMUM_AGE
=
13
)
def
test_update_email_optin
(
self
,
age
,
option
,
expected_result
):
# Create the course and account.
course
=
CourseFactory
.
create
()
account_api
.
create_account
(
self
.
USERNAME
,
self
.
PASSWORD
,
self
.
EMAIL
)
# Set year of birth
user
=
User
.
objects
.
get
(
username
=
self
.
USERNAME
)
profile
=
UserProfile
.
objects
.
get
(
user
=
user
)
year_of_birth
=
datetime
.
datetime
.
now
()
.
year
-
age
# pylint: disable=maybe-no-member
profile
.
year_of_birth
=
year_of_birth
profile
.
save
()
profile_api
.
update_email_opt_in
(
self
.
USERNAME
,
course
.
id
.
org
,
option
)
result_obj
=
UserOrgTag
.
objects
.
get
(
user
=
user
,
org
=
course
.
id
.
org
,
key
=
'email-optin'
)
self
.
assertEqual
(
result_obj
.
value
,
expected_result
)
def
test_update_email_optin_no_age_set
(
self
):
# Test that the API still works if no age is specified.
# Create the course and account.
course
=
CourseFactory
.
create
()
account_api
.
create_account
(
self
.
USERNAME
,
self
.
PASSWORD
,
self
.
EMAIL
)
user
=
User
.
objects
.
get
(
username
=
self
.
USERNAME
)
profile_api
.
update_email_opt_in
(
self
.
USERNAME
,
course
.
id
.
org
,
True
)
result_obj
=
UserOrgTag
.
objects
.
get
(
user
=
user
,
org
=
course
.
id
.
org
,
key
=
'email-optin'
)
self
.
assertEqual
(
result_obj
.
value
,
u"True"
)
@ddt.data
(
# Check that a 27 year old can opt-in, then out.
(
27
,
True
,
False
,
u"False"
),
# Check that a 32-year old can opt-out, then in.
(
32
,
False
,
True
,
u"True"
),
# Check that someone 13 years old can opt-in, then out.
(
13
,
True
,
False
,
u"False"
),
# Check that someone 12 years old cannot opt-in, then explicitly out.
(
12
,
True
,
False
,
u"False"
)
)
@ddt.unpack
@override_settings
(
EMAIL_OPTIN_MINIMUM_AGE
=
13
)
def
test_change_email_optin
(
self
,
age
,
option
,
second_option
,
expected_result
):
# Create the course and account.
course
=
CourseFactory
.
create
()
account_api
.
create_account
(
self
.
USERNAME
,
self
.
PASSWORD
,
self
.
EMAIL
)
# Set year of birth
user
=
User
.
objects
.
get
(
username
=
self
.
USERNAME
)
profile
=
UserProfile
.
objects
.
get
(
user
=
user
)
year_of_birth
=
datetime
.
datetime
.
now
()
.
year
-
age
# pylint: disable=maybe-no-member
profile
.
year_of_birth
=
year_of_birth
profile
.
save
()
profile_api
.
update_email_opt_in
(
self
.
USERNAME
,
course
.
id
.
org
,
option
)
profile_api
.
update_email_opt_in
(
self
.
USERNAME
,
course
.
id
.
org
,
second_option
)
result_obj
=
UserOrgTag
.
objects
.
get
(
user
=
user
,
org
=
course
.
id
.
org
,
key
=
'email-optin'
)
self
.
assertEqual
(
result_obj
.
value
,
expected_result
)
@raises
(
profile_api
.
ProfileUserNotFound
)
def
test_retrieve_and_update_preference_info_no_user
(
self
):
preferences
=
profile_api
.
preference_info
(
self
.
USERNAME
)
...
...
lms/envs/common.py
View file @
ebeaaaad
...
...
@@ -1365,6 +1365,10 @@ BULK_EMAIL_LOG_SENT_EMAILS = False
# parallel, and what the SES rate is.
BULK_EMAIL_RETRY_DELAY_BETWEEN_SENDS
=
0.02
############################# Email Opt In ####################################
# Minimum age for organization-wide email opt in
EMAIL_OPTIN_MINIMUM_AGE
=
13
############################## Video ##########################################
...
...
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