aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPriit Laes <plaes@plaes.org>2010-07-18 17:28:56 +0300
committerPriit Laes <plaes@plaes.org>2010-07-18 17:28:56 +0300
commit2cef376ac68af60b64b91bce93fb88ebf54206c4 (patch)
tree073621fe1b475053f1a8039c26335698ff06ca7a
parentAdded Flask-OpenID to dependencies (diff)
downloadgsoc2010-grumpy-2cef376ac68af60b64b91bce93fb88ebf54206c4.tar.gz
gsoc2010-grumpy-2cef376ac68af60b64b91bce93fb88ebf54206c4.tar.bz2
gsoc2010-grumpy-2cef376ac68af60b64b91bce93fb88ebf54206c4.zip
Implement registration token generation and email sending
-rw-r--r--grumpy/models.py15
-rw-r--r--grumpy/templates/email/registration.txt7
-rw-r--r--grumpy/utils.py62
-rw-r--r--grumpy/webapp.py9
4 files changed, 86 insertions, 7 deletions
diff --git a/grumpy/models.py b/grumpy/models.py
index 55019f0..d5fd6de 100644
--- a/grumpy/models.py
+++ b/grumpy/models.py
@@ -14,7 +14,7 @@ from datetime import datetime
from flaskext.sqlalchemy import SQLAlchemy
from sqlalchemy.sql import func
-import json
+import json, random, string
db = SQLAlchemy(app)
@@ -193,11 +193,20 @@ class User(db.Model):
__tablename__ = 'users'
id = db.Column('id', db.Integer, primary_key=True)
- regtoken = db.Column('token', db.String)
openid = db.Column('openid', db.String)
email = db.Column('user', db.String, unique=True)
+ apitoken = db.Column('apitoken', db.String)
+ regtoken = db.Column('regtoken', db.String)
+ created_on = db.Column('created_on', db.DateTime, default=func.now())
def __init__(self, email, openid):
self.email = email
self.openid = openid
- # TODO, generate token
+ # API token
+ self.apitoken = None
+ # Registration token
+ self.regtoken = self.generate_token(8)
+
+ def generate_token(self, length):
+ return ''.join([random.choice(string.ascii_letters + \
+ string.digits) for x in xrange(length)])
diff --git a/grumpy/templates/email/registration.txt b/grumpy/templates/email/registration.txt
new file mode 100644
index 0000000..1d6efab
--- /dev/null
+++ b/grumpy/templates/email/registration.txt
@@ -0,0 +1,7 @@
+Hey!
+
+You have signed up on `TODO: site address` but your account is not yet activated.
+You have to follow the following link to finish the registration and
+activate your account:
+
+`TODO: Figure out url:` {{ user.regtoken }}
diff --git a/grumpy/utils.py b/grumpy/utils.py
index a70fd95..3fe7506 100644
--- a/grumpy/utils.py
+++ b/grumpy/utils.py
@@ -3,12 +3,14 @@
grumpy.utils
~~~~~~~~~~~~
- Miscellaneous utils for authentication and pagination.
+ Miscellaneous utils for authentication, mailing and pagination.
:copyright: (c) 2010 Priit Laes
"""
+from email.mime.text import MIMEText
from flask import request, Response
from functools import wraps
+from smtplib import SMTP, SMTPException
from . import app
@@ -31,3 +33,61 @@ def requires_auth_basic(f):
return authenticate()
return f(*args, **kwargs)
return decorated
+
+def send_email(recipients, subject, text):
+ """Send mail using EMail class."""
+ return EMail(recipients, subject, text).send()
+
+class EMail(object):
+
+ def __init__(self, recipients=None, subject=None, text=''):
+ # FIXME: Use app.config for from address
+ self.from_addr = 'noreply-grumpy@example.com'
+ self.subject = u' '.join(subject.splitlines())
+ self.to_addr = []
+ if isinstance(recipients, basestring):
+ self.to_addr.append(recipients)
+ else:
+ for addr in recipients:
+ self.to_addr.append(addr)
+ self.text = text
+
+ def as_message(self):
+ """Return the email as MIMEText object."""
+ if not self.subject or not self.text or not self.to_addr:
+ raise RuntimeError("Not all mailing parameters filled in")
+
+ msg = MIMEText(self.text.encode('utf-8'))
+
+ # We set these ourself
+ del msg['Content-Transfer-Encoding']
+ del msg['Content-Type']
+
+ msg['From'] = self.from_addr.encode('utf-8')
+ msg['To'] = ', '.join(x.encode('utf-8') for x in self.to_addr)
+ msg['Subject'] = self.subject.encode('utf-8')
+ msg['Content-Transfer-Encoding'] = '8bit'
+ msg['Content-Type'] = 'text/plain; charset=utf-8'
+ return msg
+
+ def format(self, sep='\r\n'):
+ """Convert the message into long string"""
+ return sep.join(self.as_message().as_string().splitlines())
+
+ def send(self):
+ try:
+ # TODO: Make configurable?
+ smtp = SMTP('localhost')
+ except SMTPException, e:
+ raise RuntimeError(str(e))
+
+ # TODO: Handle authentication and/or TLS
+
+ try:
+ try:
+ return smtp.sendmail(self.from_addr, self.to_addr, self.format())
+ except SMTPException, e:
+ raise RuntimeError(str(e))
+ finally:
+ # Close SMTP connection
+ smtp.quit()
diff --git a/grumpy/webapp.py b/grumpy/webapp.py
index b426cc8..81e5e58 100644
--- a/grumpy/webapp.py
+++ b/grumpy/webapp.py
@@ -10,7 +10,7 @@
"""
from . import app
from .models import db, Category, Package, User
-from .utils import requires_auth_basic
+from .utils import requires_auth_basic, send_email
from flask import (flash, g, jsonify, redirect, render_template, request, \
session, url_for)
@@ -94,9 +94,12 @@ def create_profile():
flash(u'You need to be a valid Gentoo developer to sign up')
else:
flash(u'Profile successfully created')
- db.session.add(User(email, session['openid']))
- # TODO: send confirmation token with email
+ user = User(email, session['openid'])
+ db.session.add(user)
db.session.commit()
+ send_email(email, u'Gentoo Grumpy registration confirmation', \
+ render_template('email/registration.txt', user=user))
+ return redirect(oid.get_next_url())
return render_template('create_profile.html', next=oid.get_next_url())
@app.route('/_api/1.0/tinderbox/')