Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d93ea21
Change characterization of a missing template file as a warning inste…
pjewald Feb 2, 2017
38e98d6
Merge pull request #19 from zfi/demo
zfi Feb 2, 2017
947d00b
Add artifacts from package operation to the .gitignore file.
pjewald Feb 7, 2017
41fbd19
Syncing local repo with parallaxinc demo branch
zfi Feb 7, 2017
c733908
Add example configuration file to project
pjewald Feb 27, 2017
ac628e3
Merge pull request #21 from zfi/demo
zfi Feb 27, 2017
61df32f
Refactor minor details
pjewald Apr 27, 2017
bdf5f0f
Add code for birthdate and parent email
pjewald Apr 27, 2017
d1223e8
Add application version number
pjewald Apr 27, 2017
45b4b4d
Add more COPPA fields
pjewald Apr 28, 2017
04f03fd
Correct error in date selection
pjewald Apr 28, 2017
4a11ee5
Add trap for missing SMTP server
pjewald May 3, 2017
8b6a76a
Add missing mustache templates to project. Update missing SMTP server…
pjewald May 5, 2017
53557d4
Correct missing COPPA data block
pjewald May 8, 2017
6621b41
Add SponsorType enum to make code more readable
pjewald May 11, 2017
db7b859
Add code to send registration confirmation email to the correct email…
pjewald May 11, 2017
39224fc
Add templates for teachers and parent emails. Moved SponsorType to em…
pjewald May 11, 2017
3bfd977
Create parent templates. Rename teacher template path
pjewald May 12, 2017
9627ff9
Update code to handle COPPA compliant email templates
pjewald May 12, 2017
5eb6e21
Add logging to help track code paths.
pjewald May 12, 2017
afd17dd
Complete draft email to teacher to register a student.
pjewald May 12, 2017
6fe37c1
Updates to make the COPPA parent email work
pjewald May 16, 2017
49aec57
Bumping up the version number. 1.1.0 include support for US COPPA reg…
pjewald May 16, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
*.sqlite
*.log
venv/
build.sh
CloudSession-Pkg.tar.gz

#################
## NetBeans
Expand All @@ -16,3 +18,6 @@ nbactions.xml
#################

.idea
build
deploy-test
/CloudSession-Templates.tar.gz
3 changes: 1 addition & 2 deletions app/AuthToken/controllers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# Import the database object from the main app module
import json
import logging
import uuid
import datetime

import Failures

from app import db
from app.User import services as user_service

Expand Down
1 change: 0 additions & 1 deletion app/AuthToken/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# We will define this inside /app/__init__.py in the next sections.
from app import db


class AuthenticationToken(db.Model):
id = db.Column(db.BigInteger, primary_key=True)
id_user = db.Column(db.BigInteger, db.ForeignKey('user.id'))
Expand Down
10 changes: 6 additions & 4 deletions app/Authenticate/controllers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# Import the database object from the main app module
import logging
import uuid
import datetime

import Failures

from app import db
from app.User import services as user_services
from app.RateLimiting import services as rate_limiting_services
Expand Down Expand Up @@ -66,7 +64,11 @@ def post(self):
'email': user.email,
'locale': user.locale,
'screenname': user.screen_name,
'authentication-source': user.auth_source
'authentication-source': user.auth_source,
'bdmonth': user.birth_month,
'bdyear': user.birth_year,
'parent-email': user.parent_email,
'parent-email-source': user.parent_email_source
}}

api.add_resource(AuthenticateLocalUser, '/local')
81 changes: 70 additions & 11 deletions app/Email/services.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,92 @@
from app import mail, app, db

from app import mail, app
from os.path import expanduser, isfile

from flask.ext.mail import Message
from app.User.coppa import Coppa, SponsorType

import pystache
import logging


"""
TODO: System documentation goes here
"""


def send_email_template_for_user(id_user, template, server, **kwargs):
from app.User.services import get_user

logging.info("Sending email to user: %s (%s)", id_user, template)
# Get a copy of the user record
logging.info("Checking for a valid user record for user ID: %s", id_user)
user = get_user(id_user)

if user is None:
logging.error("Cannot send email: Invalid user record")
return False
else:
logging.info("Email template received user: %s", user.id)

logging.info("Sending email to user: %s using template (%s)", user.id, template)

params = {}
for key, value in kwargs.items():
logging.debug("Logging parameter %s = %s", key, value)
params[key] = value

user = get_user(id_user)
if user is None:
return False

# The elements in the params array represent the data elements that are
# available to the email templates.
params['screenname'] = user.screen_name
params['email'] = user.email
params['registrant-email'] = user.email
params['sponsoremail'] = user.parent_email

#Default the recipient email address
user_email = user.email
coppa = Coppa()

# Send email to parent if user is under 13 years old
if template == 'confirm' and coppa.is_coppa_covered(user.birth_month, user.birth_year):
# Send email only to the sponsor address
user_email = user.parent_email
logging.info("COPPA account has a sponsor type of %s", user.parent_email_source)

if user.parent_email_source == SponsorType.TEACHER:
# Teacher handles the account confirmation
send_email_template_to_address(user_email, 'confirm-teacher', server, user.locale, params)
elif user.parent_email_source == SponsorType.PARENT or\
user.parent_email_source == SponsorType.GUARDIAN:
# Parent handles the account confirmation
send_email_template_to_address(user_email, 'confirm-parent', server, user.locale, params)
else:
logging.info("COPPA account %s has invalid sponsor type [%s]", user.id, user.parent_email_source)

return
else:
# Registration not subject to COPPA regulations
send_email_template_to_address(user_email, template, server, user.locale, params)

send_email_template_to_address(user.email, template, server, user.locale, params)
return


def send_email_template_to_address(recipient, template, server, locale, params=None, **kwargs):
# Read templates
params = params or {}

# Add any supplied arguments to the parameter dictionary
for key, value in kwargs.items():
params[key] = value

params['email'] = recipient
params['locale'] = locale

# Read templates
(subject, plain, rich) = _read_templates(template, server, locale, params)

logging.info("Sending email to %s", recipient)
send_email(recipient, subject, plain, rich)


def send_email(recipient, subject, email_text, rich_email_text=None):

msg = Message(
recipients=[recipient],
subject=subject.rstrip(),
Expand All @@ -59,15 +106,27 @@ def _read_templates(template, server, locale, params):


def _read_template(template, server, locale, part, params, none_if_missing=False):
"""
Render a mustache template.

:param template: Base template name
:param server: Host server
:param locale: Language designator
:param part: Generic message type descriptor
:param params: Text string to replace tags embedded within the template
:param none_if_missing: Return 'none' if the requested template is not found

:return: Upon success, return a Renderer object. Return none or a general
error message if the none_is_missing flag is false
"""
template_file = expanduser("~/templates/%s/%s/%s/%s.mustache" % (locale, template, server, part))
if isfile(template_file):
logging.debug('Looking for template file: %s', template_file)
renderer = pystache.Renderer()
rendered = renderer.render_path(template_file, params)
#print(rendered)
return rendered
else:
logging.error('Looking for template file: %s, but the file is missing', template_file)
logging.warn('Looking for template file: %s, but the file is missing', template_file)
if none_if_missing:
return None
else:
Expand Down
23 changes: 16 additions & 7 deletions app/LocalUser/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def post(self):

confirm_token = ConfirmToken.query.filter_by(token=token).first()
if confirm_token is None:
# Unkown token
# Unknown token
return {'success': False, 'code': 510}
if confirm_token.id_user != user.id:
# Token is not for this user
Expand All @@ -65,9 +65,11 @@ def post(self):
class RequestConfirm(Resource):

def get(self, email):
# Get values
# Get server URL
server = request.headers.get('server')

logging.info("Requesting email confirmation for %s from server %s", email, server)

# Validate required fields
validation = Validation()
validation.add_required_field('email', email)
Expand Down Expand Up @@ -95,11 +97,18 @@ def get(self, email):
else:
if code == 10:
return Failures.rate_exceeded()
return {
'success': False,
'message': message,
'code': 520
}
elif code == 99:
return {
'success': False,
'message': message,
'code': 540
}
else:
return {
'success': False,
'message': message,
'code': 520
}


class PasswordReset(Resource):
Expand Down
Loading