Changeset - a3d9d24acbec
[Not reviewed]
celery
0 10 2
Marcin Kuzminski - 15 years ago 2010-09-13 01:27:41
marcin@python-works.com
Implemented password reset(forms/models/ tasks) and mailing tasks.
Added smtp mailer, configurations, cleaned user model
12 files changed with 429 insertions and 49 deletions:
0 comments (0 inline, 0 general)
celeryconfig.py
Show inline comments
 
@@ -5,12 +5,13 @@ sys.path.append(os.getcwd())
 
CELERY_IMPORTS = ("pylons_app.lib.celerylib.tasks", )
 

	
 
## Result store settings.
 
CELERY_RESULT_BACKEND = "database"
 
CELERY_RESULT_DBURI = "sqlite:///hg_app.db"
 

	
 
BROKER_CONNECTION_MAX_RETRIES = 30
 

	
 
## Broker settings.
 
BROKER_HOST = "localhost"
 
BROKER_PORT = 5672
 
BROKER_VHOST = "rabbitmqhost"
 
BROKER_USER = "rabbitmq"
development.ini
Show inline comments
 
################################################################################
 
################################################################################
 
# pylons_app - Pylons environment configuration                                #
 
# hg-app - Pylons environment configuration                                    #
 
#                                                                              # 
 
# The %(here)s variable will be replaced with the parent directory of this file#
 
################################################################################
 

	
 
[DEFAULT]
 
debug = true
 
############################################
 
## Uncomment and replace with the address ##
 
## which should receive any error reports ##
 
############################################
 
################################################################################
 
## Uncomment and replace with the address which should receive                ## 
 
## any error reports after application crash								  ##
 
## Additionally those settings will be used by hg-app mailing system          ##
 
################################################################################
 
#email_to = admin@localhost
 
#error_email_from = paste_error@localhost
 
#app_email_from = hg-app-noreply@localhost
 
#error_message =
 

	
 
#smtp_server = mail.server.com
 
#error_email_from = paste_error@localhost
 
#smtp_username = 
 
#smtp_password = 
 
#error_message = 'mercurial crash !'
 
#smtp_password =
 
#smtp_port = 
 
#smtp_use_tls = 
 

	
 
[server:main]
 
##nr of threads to spawn
 
threadpool_workers = 5
 

	
 
##max request before
 
threadpool_max_requests = 2
 
threadpool_max_requests = 6
 

	
 
##option to use threads of process
 
use_threadpool = true
 
use_threadpool = false
 

	
 
use = egg:Paste#http
 
host = 127.0.0.1
 
port = 5000
 

	
 
[app:main]
pylons_app/config/routing.py
Show inline comments
 
@@ -107,16 +107,17 @@ def make_map(config):
 
        m.connect('admin_home', '', action='index')#main page
 
        m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
 
                  action='add_repo')
 
    #SEARCH
 
    map.connect('search', '/_admin/search', controller='search')
 
    
 
    #LOGIN/LOGOUT
 
    #LOGIN/LOGOUT/REGISTER/SIGN IN
 
    map.connect('login_home', '/_admin/login', controller='login')
 
    map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
 
    map.connect('register', '/_admin/register', controller='login', action='register')
 
    map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
 
        
 
    #FEEDS
 
    map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
 
                controller='feed', action='rss',
 
                conditions=dict(function=check_repo))
 
    map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
pylons_app/controllers/login.py
Show inline comments
 
@@ -25,13 +25,15 @@ login controller for pylons
 
"""
 
from formencode import htmlfill
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons_app.lib.auth import AuthUser, HasPermissionAnyDecorator
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.forms import LoginForm, RegisterForm
 
import pylons_app.lib.helpers as h 
 
from pylons.i18n.translation import _
 
from pylons_app.model.forms import LoginForm, RegisterForm, PasswordResetForm
 
from pylons_app.model.user_model import UserModel
 
import formencode
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
@@ -39,13 +41,13 @@ class LoginController(BaseController):
 

	
 
    def __before__(self):
 
        super(LoginController, self).__before__()
 

	
 
    def index(self):
 
        #redirect if already logged in
 
        c.came_from = request.GET.get('came_from',None)
 
        c.came_from = request.GET.get('came_from', None)
 
        
 
        if c.hg_app_user.is_authenticated:
 
            return redirect(url('hg_home'))
 
        
 
        if request.POST:
 
            #import Login Form validator class
 
@@ -79,13 +81,13 @@ class LoginController(BaseController):
 
                    errors=errors.error_dict or {},
 
                    prefix_error=False,
 
                    encoding="UTF-8")
 
                        
 
        return render('/login.html')
 
    
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', 
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
 
                               'hg.register.manual_activate')
 
    def register(self):
 
        user_model = UserModel()
 
        c.auto_active = False
 
        for perm in user_model.get_default().user_perms:
 
            if perm.permission.permission_name == 'hg.register.auto_activate':
 
@@ -96,23 +98,47 @@ class LoginController(BaseController):
 
                
 
            register_form = RegisterForm()()
 
            try:
 
                form_result = register_form.to_python(dict(request.POST))
 
                form_result['active'] = c.auto_active
 
                user_model.create_registration(form_result)
 
                h.flash(_('You have successfully registered into hg-app'),
 
                            category='success')                
 
                return redirect(url('login_home'))
 
                               
 
            except formencode.Invalid as errors:
 
                return htmlfill.render(
 
                    render('/register.html'),
 
                    defaults=errors.value,
 
                    errors=errors.error_dict or {},
 
                    prefix_error=False,
 
                    encoding="UTF-8")
 
        
 
        return render('/register.html')
 
    
 

	
 
    def password_reset(self):
 
        user_model = UserModel()
 
        if request.POST:
 
                
 
            password_reset_form = PasswordResetForm()()
 
            try:
 
                form_result = password_reset_form.to_python(dict(request.POST))
 
                user_model.reset_password(form_result)
 
                h.flash(_('Your new password was sent'),
 
                            category='success')                 
 
                return redirect(url('login_home'))
 
                               
 
            except formencode.Invalid as errors:
 
                return htmlfill.render(
 
                    render('/password_reset.html'),
 
                    defaults=errors.value,
 
                    errors=errors.error_dict or {},
 
                    prefix_error=False,
 
                    encoding="UTF-8")
 
        
 
        return render('/password_reset.html')
 
        
 
    def logout(self):
 
        session['hg_app_user'] = AuthUser()
 
        session.save()
 
        log.info('Logging out and setting user as Empty')
 
        redirect(url('hg_home'))
pylons_app/lib/auth.py
Show inline comments
 
@@ -31,15 +31,42 @@ from pylons_app.model.db import User, Re
 
    UserToPerm
 
from sqlalchemy.exc import OperationalError
 
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 
import bcrypt
 
from decorator import decorator
 
import logging
 
import random
 

	
 
log = logging.getLogger(__name__) 
 

	
 
class PasswordGenerator(object):
 
    """This is a simple class for generating password from
 
        different sets of characters
 
        usage:
 
        passwd_gen = PasswordGenerator()
 
        #print 8-letter password containing only big and small letters of alphabet
 
        print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)        
 
    """
 
    ALPHABETS_NUM = r'''1234567890'''#[0]
 
    ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
 
    ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
 
    ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''    #[3]
 
    ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
 
    ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
 
    ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
 
    ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
 
    ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
 
            
 
    def __init__(self, passwd=''):
 
        self.passwd = passwd
 

	
 
    def gen_password(self, len, type):
 
        self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
 
        return self.passwd
 

	
 
    
 
def get_crypt_password(password):
 
    """Cryptographic function used for password hashing based on sha1
 
    @param password: password to hash
 
    """    
 
    return bcrypt.hashpw(password, bcrypt.gensalt(10))
 

	
 
@@ -228,15 +255,15 @@ class LoginRequired(object):
 
            return func(*fargs, **fkwargs)
 
        else:
 
            log.warn('user %s not authenticated', user.username)
 

	
 
            p = request.environ.get('PATH_INFO')
 
            if request.environ.get('QUERY_STRING'):
 
                p+='?'+request.environ.get('QUERY_STRING')
 
            log.debug('redirecting to login page with %s',p)                
 
            return redirect(url('login_home',came_from=p))
 
                p += '?' + request.environ.get('QUERY_STRING')
 
            log.debug('redirecting to login page with %s', p)                
 
            return redirect(url('login_home', came_from=p))
 

	
 
class PermsDecorator(object):
 
    """Base class for decorators"""
 
    
 
    def __init__(self, *required_perms):
 
        available_perms = config['available_permissions']
pylons_app/lib/celerylib/__init__.py
Show inline comments
 
from vcs.utils.lazy import LazyProperty
 
import logging
 
import os
 
import sys
 
import traceback
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ResultWrapper(object):
 
    def __init__(self, task):
 
        self.task = task
 
        
 
    @LazyProperty
 
    def result(self):
 
        return self.task
 

	
 
def run_task(task,async,*args,**kwargs):
 
def run_task(task,*args,**kwargs):
 
    try:
 
        t = task.delay(*args,**kwargs)
 
        log.info('running task %s',t.task_id)
 
        if not async:
 
            t.wait()
 
        return t
 
    except:
 
        log.error(traceback.format_exc())
 
        #pure sync version
 
        return ResultWrapper(task(*args,**kwargs))
 
    
 
\ No newline at end of file
pylons_app/lib/celerylib/tasks.py
Show inline comments
 
from celery.decorators import task
 
from celery.task.sets import subtask
 
from datetime import datetime, timedelta
 
from os.path import dirname as dn
 
from pylons.i18n.translation import _
 
from pylons_app.lib.celerylib import run_task
 
from pylons_app.lib.helpers import person
 
from pylons_app.lib.smtp_mailer import SmtpMailer
 
from pylons_app.lib.utils import OrderedDict
 
from time import mktime
 
from vcs.backends.hg import MercurialRepository
 
import ConfigParser
 
import calendar
 
import logging
 
from vcs.backends.hg import MercurialRepository
 
import os
 
import traceback
 

	
 

	
 
root = dn(dn(dn(dn(os.path.realpath(__file__)))))
 
config = ConfigParser.ConfigParser({'here':root})
 
config.read('%s/development.ini' % root)
 

	
 
__all__ = ['whoosh_index', 'get_commits_stats',
 
           'reset_user_password', 'send_email']
 

	
 
def get_session():
 
    from sqlalchemy import engine_from_config
 
    from sqlalchemy.orm import sessionmaker, scoped_session
 
    engine = engine_from_config(dict(config.items('app:main')), 'sqlalchemy.db1.')
 
    sa = scoped_session(sessionmaker(bind=engine))
 
    return sa
 

	
 
log = logging.getLogger(__name__)
 
def get_hg_settings():
 
    from pylons_app.model.db import HgAppSettings
 
    try:
 
        sa = get_session()
 
        ret = sa.query(HgAppSettings).all()
 
    finally:
 
        sa.remove()
 
        
 
    if not ret:
 
        raise Exception('Could not get application settings !')
 
    settings = {}
 
    for each in ret:
 
        settings['hg_app_' + each.app_settings_name] = each.app_settings_value    
 
    
 
    return settings
 

	
 
@task()
 
def whoosh_index(repo_location,full_index):
 
def get_hg_ui_settings():
 
    from pylons_app.model.db import HgAppUi
 
    try:
 
        sa = get_session()
 
        ret = sa.query(HgAppUi).all()
 
    finally:
 
        sa.remove()
 
        
 
    if not ret:
 
        raise Exception('Could not get application ui settings !')
 
    settings = {}
 
    for each in ret:
 
        k = each.ui_key
 
        v = each.ui_value
 
        if k == '/':
 
            k = 'root_path'
 
        
 
        if k.find('.') != -1:
 
            k = k.replace('.', '_')
 
        
 
        if each.ui_section == 'hooks':
 
            v = each.ui_active
 
        
 
        settings[each.ui_section + '_' + k] = v  
 
    
 
    return settings   
 

	
 
@task
 
def whoosh_index(repo_location, full_index):
 
    log = whoosh_index.get_logger()
 
    from pylons_app.lib.indexers import DaemonLock
 
    from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon,LockHeld
 
    from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon, LockHeld
 
    try:
 
        l = DaemonLock()
 
        WhooshIndexingDaemon(repo_location=repo_location)\
 
            .run(full_index=full_index)
 
        l.release()
 
        return 'Done'
 
    except LockHeld:
 
        log.info('LockHeld')
 
        return 'LockHeld'    
 

	
 
@task()
 
@task
 
def get_commits_stats(repo):
 
    log = get_commits_stats.get_logger()
 
    aggregate = OrderedDict()
 
    repo = MercurialRepository('/home/marcink/hg_repos/'+repo)
 
    repos_path = get_hg_ui_settings()['paths_root_path'].replace('*','')
 
    repo = MercurialRepository(repos_path + repo)
 
    #graph range
 
    td = datetime.today() + timedelta(days=1) 
 
    y, m, d = td.year, td.month, td.day
 
    ts_min = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
 
                        d, 0, 0, 0, 0, 0, 0,))
 
    ts_max = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
 
@@ -87,6 +153,63 @@ def get_commits_stats(repo):
 
                      } for x in aggregate[author]]))
 
    if d == '':
 
        d = '"%s":{label:"%s",data:[[0,1],]}' \
 
            % (author_key_cleaner(repo.contact),
 
               author_key_cleaner(repo.contact))
 
    return (ts_min, ts_max, d)    
 

	
 
@task
 
def reset_user_password(user_email):
 
    log = reset_user_password.get_logger()
 
    from pylons_app.lib import auth
 
    from pylons_app.model.db import User
 
    
 
    try:
 
        
 
        try:
 
            sa = get_session()
 
            user = sa.query(User).filter(User.email == user_email).scalar()
 
            new_passwd = auth.PasswordGenerator().gen_password(8,
 
                             auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
 
            user.password = auth.get_crypt_password(new_passwd)
 
            sa.add(user)
 
            sa.commit()
 
            log.info('change password for %s', user_email)
 
            if new_passwd is None:
 
                raise Exception('unable to generate new password')
 
            
 
        except:
 
            log.error(traceback.format_exc())
 
            sa.rollback()
 
        
 
        run_task(send_email, user_email,
 
                 "Your new hg-app password",
 
                 'Your new hg-app password:%s' % (new_passwd))
 
        log.info('send new password mail to %s', user_email)
 
        
 
        
 
    except:
 
        log.error('Failed to update user password')
 
        log.error(traceback.format_exc())
 
    return True
 

	
 
@task    
 
def send_email(recipients, subject, body):
 
    log = send_email.get_logger()
 
    email_config = dict(config.items('DEFAULT')) 
 
    mail_from = email_config.get('app_email_from')
 
    user = email_config.get('smtp_username')
 
    passwd = email_config.get('smtp_password')
 
    mail_server = email_config.get('smtp_server')
 
    mail_port = email_config.get('smtp_port')
 
    tls = email_config.get('smtp_use_tls')
 
    ssl = False
 
    
 
    try:
 
        m = SmtpMailer(mail_from, user, passwd, mail_server, 
 
                       mail_port, ssl, tls)
 
        m.send(recipients, subject, body)  
 
    except:
 
        log.error('Mail sending failed')
 
        log.error(traceback.format_exc())
 
        return False
 
    return True
pylons_app/lib/smtp_mailer.py
Show inline comments
 
new file 100644
 
import logging
 
import smtplib
 
import mimetypes
 
from email.mime.multipart import MIMEMultipart
 
from email.mime.image import MIMEImage
 
from email.mime.audio import MIMEAudio
 
from email.mime.base import MIMEBase
 
from email.mime.text import MIMEText
 
from email.utils import formatdate
 
from email import encoders
 

	
 
class SmtpMailer(object):
 
    """simple smtp mailer class
 
    
 
    mailer = SmtpMailer(mail_from, user, passwd, mail_server, mail_port, ssl, tls)
 
    mailer.send(recipients, subject, body, attachment_files)    
 
    
 
    :param recipients might be a list of string or single string
 
    :param attachment_files is a dict of {filename:location} 
 
    it tries to guess the mimetype and attach the file
 
    """
 

	
 
    def __init__(self, mail_from, user, passwd, mail_server,
 
                    mail_port=None, ssl=False, tls=False):
 
        
 
        self.mail_from = mail_from
 
        self.mail_server = mail_server
 
        self.mail_port = mail_port
 
        self.user = user
 
        self.passwd = passwd
 
        self.ssl = ssl
 
        self.tls = tls
 
        self.debug = False
 
        
 
    def send(self, recipients=[], subject='', body='', attachment_files={}):
 

	
 
        if isinstance(recipients, basestring):
 
            recipients = [recipients]
 
        if self.ssl:
 
            smtp_serv = smtplib.SMTP_SSL(self.mail_server, self.mail_port)
 
        else:
 
            smtp_serv = smtplib.SMTP(self.mail_server, self.mail_port)
 

	
 
        if self.tls:
 
            smtp_serv.starttls()
 
         
 
        if self.debug:    
 
            smtp_serv.set_debuglevel(1)
 

	
 
        smtp_serv.ehlo("mailer")
 

	
 
        #if server requires authorization you must provide login and password
 
        smtp_serv.login(self.user, self.passwd)
 

	
 
        date_ = formatdate(localtime=True)
 
        msg = MIMEMultipart()
 
        msg['From'] = self.mail_from
 
        msg['To'] = ','.join(recipients)
 
        msg['Date'] = date_
 
        msg['Subject'] = subject
 
        msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
 

	
 
        msg.attach(MIMEText(body))
 

	
 
        if attachment_files:
 
            self.__atach_files(msg, attachment_files)
 

	
 
        smtp_serv.sendmail(self.mail_from, recipients, msg.as_string())
 
        logging.info('MAIL SEND TO: %s' % recipients)
 
        smtp_serv.quit()
 

	
 

	
 
    def __atach_files(self, msg, attachment_files):
 
        if isinstance(attachment_files, dict):
 
            for f_name, msg_file in attachment_files.items():
 
                ctype, encoding = mimetypes.guess_type(f_name)
 
                logging.info("guessing file %s type based on %s" , ctype, f_name)
 
                if ctype is None or encoding is not None:
 
                    # No guess could be made, or the file is encoded (compressed), so
 
                    # use a generic bag-of-bits type.
 
                    ctype = 'application/octet-stream'
 
                maintype, subtype = ctype.split('/', 1)
 
                if maintype == 'text':
 
                    # Note: we should handle calculating the charset
 
                    file_part = MIMEText(self.get_content(msg_file), 
 
                                         _subtype=subtype)
 
                elif maintype == 'image':
 
                    file_part = MIMEImage(self.get_content(msg_file), 
 
                                          _subtype=subtype)
 
                elif maintype == 'audio':
 
                    file_part = MIMEAudio(self.get_content(msg_file), 
 
                                          _subtype=subtype)
 
                else:
 
                    file_part = MIMEBase(maintype, subtype)
 
                    file_part.set_payload(self.get_content(msg_file))
 
                    # Encode the payload using Base64
 
                    encoders.encode_base64(msg)
 
                # Set the filename parameter
 
                file_part.add_header('Content-Disposition', 'attachment', 
 
                                     filename=f_name)
 
                file_part.add_header('Content-Type', ctype, name=f_name)
 
                msg.attach(file_part)
 
        else:
 
            raise Exception('Attachment files should be' 
 
                            'a dict in format {"filename":"filepath"}')    
 

	
 
    def get_content(self, msg_file):
 
        '''
 
        Get content based on type, if content is a string do open first
 
        else just read because it's a probably open file object
 
        @param msg_file:
 
        '''
 
        if isinstance(msg_file, str):
 
            return open(msg_file, "rb").read()
 
        else:
 
            #just for safe seek to 0
 
            msg_file.seek(0)
 
            return msg_file.read()
pylons_app/model/forms.py
Show inline comments
 
@@ -99,13 +99,13 @@ class ValidAuth(formencode.validators.Fa
 
        if user is None:
 
            raise formencode.Invalid(self.message('invalid_password',
 
                                     state=State_obj), value, state,
 
                                     error_dict=self.e_dict)            
 
        if user:
 
            if user.active:
 
                if user.username == username and check_password(password, 
 
                if user.username == username and check_password(password,
 
                                                                user.password):
 
                    return value
 
                else:
 
                    log.warning('user %s not authenticated', username)
 
                    raise formencode.Invalid(self.message('invalid_password',
 
                                             state=State_obj), value, state,
 
@@ -205,13 +205,26 @@ class ValidPath(formencode.validators.Fa
 
            msg = _('This is not a valid path') 
 
        else:
 
            msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
 
        
 
        raise formencode.Invalid(msg, value, state,
 
                                     error_dict={'paths_root_path':msg})            
 
                       
 

	
 
class ValidSystemEmail(formencode.validators.FancyValidator):
 
    def to_python(self, value, state):
 
        sa = meta.Session
 
        try:
 
            user = sa.query(User).filter(User.email == value).scalar()
 
            if  user is None:
 
                raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
 
                                         value, state)
 
        finally:
 
            meta.Session.remove()
 
            
 
        return value     
 

	
 
#===============================================================================
 
# FORMS        
 
#===============================================================================
 
class LoginForm(formencode.Schema):
 
    allow_extra_fields = True
 
    filter_extra_fields = True
 
@@ -252,14 +265,20 @@ def UserForm(edit=False, old_data={}):
 
        lastname = UnicodeString(strip=True, min=3, not_empty=True)
 
        email = Email(not_empty=True)
 
        
 
    return _UserForm
 

	
 
RegisterForm = UserForm
 
    
 
    
 

	
 
def PasswordResetForm():
 
    class _PasswordResetForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 
        email = All(ValidSystemEmail(), Email(not_empty=True))             
 
    return _PasswordResetForm
 

	
 
def RepoForm(edit=False, old_data={}):
 
    class _RepoForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
 
        description = UnicodeString(strip=True, min=3, not_empty=True)
pylons_app/model/user_model.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# Model for users
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
@@ -20,16 +20,18 @@
 

	
 
"""
 
Created on April 9, 2010
 
Model for users
 
@author: marcink
 
"""
 

	
 
from pylons_app.lib import auth
 
from pylons.i18n.translation import _
 
from pylons_app.lib.celerylib import tasks, run_task
 
from pylons_app.model.db import User
 
from pylons_app.model.meta import Session
 
from pylons.i18n.translation import _
 
import traceback
 
import logging
 
log = logging.getLogger(__name__)
 

	
 
class DefaultUserException(Exception):pass
 

	
 
class UserModel(object):
 
@@ -40,39 +42,39 @@ class UserModel(object):
 
    def get_default(self):
 
        return self.sa.query(User).filter(User.username == 'default').scalar()
 
    
 
    def get_user(self, id):
 
        return self.sa.query(User).get(id)
 
    
 
    def get_user_by_name(self,name):
 
    def get_user_by_name(self, name):
 
        return self.sa.query(User).filter(User.username == name).scalar()
 
    
 
    def create(self, form_data):
 
        try:
 
            new_user = User()
 
            for k, v in form_data.items():
 
                setattr(new_user, k, v)
 
                
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
        except Exception as e:
 
            log.error(e)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise      
 
    
 
    def create_registration(self, form_data):
 
        try:
 
            new_user = User()
 
            for k, v in form_data.items():
 
                if k != 'admin':
 
                    setattr(new_user, k, v)
 
                
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
        except Exception as e:
 
            log.error(e)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise      
 
    
 
    def update(self, uid, form_data):
 
        try:
 
            new_user = self.sa.query(User).get(uid)
 
@@ -85,14 +87,14 @@ class UserModel(object):
 
                    new_user.password = v
 
                else:
 
                    setattr(new_user, k, v)
 
                
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
        except Exception as e:
 
            log.error(e)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise      
 
        
 
    def update_my_account(self, uid, form_data):
 
        try:
 
            new_user = self.sa.query(User).get(uid)
 
@@ -106,26 +108,28 @@ class UserModel(object):
 
                else:
 
                    if k not in ['admin', 'active']:
 
                        setattr(new_user, k, v)
 
                
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
        except Exception as e:
 
            log.error(e)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise 
 
                
 
    def delete(self, id):
 
        
 
        try:
 
            
 
            user = self.sa.query(User).get(id)
 
            if user.username == 'default':
 
                raise DefaultUserException(
 
                                _("You can't remove this user since it's" 
 
                                  " crucial for entire application"))
 
            self.sa.delete(user)
 
            self.sa.commit()            
 
        except Exception as e:
 
            log.error(e)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise        
 

	
 
    def reset_password(self, data):
 
        run_task(tasks.reset_user_password, data['email'])
pylons_app/templates/login.html
Show inline comments
 
@@ -57,13 +57,13 @@
 
                            ${h.submit('sign_in','Sign In',class_="ui-button ui-widget ui-state-default ui-corner-all")}
 
                        </div>
 
                    </div>
 
                    <!-- end fields -->
 
                    <!-- links -->
 
                    <div class="links">
 
                        ${h.link_to(_('Forgot your password ?'),h.url('#'))}
 
                        ${h.link_to(_('Forgot your password ?'),h.url('reset_password'))}
 
                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
 
	                         / 
 
	                        ${h.link_to(_("Don't have an account ?"),h.url('register'))}
 
                        %endif
 
                    </div>
 

	
pylons_app/templates/password_reset.html
Show inline comments
 
new file 100644
 
## -*- coding: utf-8 -*-
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
 
    <head>
 
        <title>${_('Reset You password to hg-app')}</title>
 
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 
        <link rel="icon" href="/images/hgicon.png" type="image/png" />
 
        <meta name="robots" content="index, nofollow"/>
 
            
 
        <!-- stylesheets -->
 
        <link rel="stylesheet" type="text/css" href="/css/reset.css" />
 
        <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
 
        <link id="color" rel="stylesheet" type="text/css" href="/css/colors/blue.css" />
 

	
 
        <!-- scripts -->
 

	
 
    </head>
 
    <body>
 
		<div id="register">
 
			
 
			<div class="title">
 
				<h5>${_('Reset You password to hg-app')}</h5>
 
                <div class="corner tl"></div>
 
                <div class="corner tr"></div>				
 
			</div>
 
			<div class="inner">
 
			    ${h.form(url('password_reset'))}
 
			    <div class="form">
 
			        <!-- fields -->
 
			        <div class="fields">
 
			            
 
			             <div class="field">
 
			                <div class="label">
 
			                    <label for="email">${_('Email address')}:</label>
 
			                </div>
 
			                <div class="input">
 
			                    ${h.text('email')}
 
			                </div>
 
			             </div>
 
			                        
 
			            <div class="buttons">
 
				            <div class="nohighlight">
 
				              ${h.submit('send','Reset my password',class_="ui-button ui-widget ui-state-default ui-corner-all")}
 
							  	<div class="activation_msg">${_('Your new password will be send to matching email address')}</div>
 
				            </div>
 
			            </div>             
 
			    	</div>
 
			    </div>
 
			    ${h.end_form()}
 
			</div>    
 
	    </div>
 
    </body>
 
</html>
 

	
0 comments (0 inline, 0 general)