login.py 5.09 KB
from datetime import datetime
from pyramid.response import Response
from pyramid.view import view_config
from pyramid.httpexceptions import (
    HTTPFound,
    HTTPForbidden,
    )
from pyramid.security import (
    remember,
    forget,
    authenticated_userid,
    )
from pyramid.i18n import TranslationStringFactory
import transaction
import colander
from deform import (
    Form,
    ValidationFailure,
    widget,
    Button,
    )
from ziggurat_foundations.models.services.user import UserService
from ..tools.waktu import create_now
from ..models import DBSession
from ..models.ziggurat import User


_ = TranslationStringFactory('login')


class Login(colander.Schema):
    username = colander.SchemaNode(colander.String(), title=_('Username'))
    password = colander.SchemaNode(
            colander.String(), widget=widget.PasswordWidget(),
            title=_('Password'))


# http://deformdemo.repoze.org/interfield/
def login_validator(form, value):
    user = form.user
    if not user or \
        not user.status or \
        not user.user_password or \
        not UserService.check_password(user, value['password']):
        raise colander.Invalid(form, _('Login failed'))

def get_login_headers(request, user):
    headers = remember(request, user.id)
    user.last_login_date = create_now()
    DBSession.add(user)
    DBSession.flush()
    transaction.commit()
    return headers

@view_config(context=HTTPForbidden, renderer='templates/login.pt')
@view_config(route_name='login', renderer='templates/login.pt')
def view_login(request):
    if authenticated_userid(request):
        return HTTPFound(location=request.route_url('home'))
    if '_LOCALE_' in request.GET:
        resp = Response()
        resp.set_cookie('_LOCALE_', request.GET['_LOCALE_'], 31536000)
        return HTTPFound(
            location=request.route_url('login'), headers=resp.headers)
    resp = dict(title=_('Login'))
    schema = Login(validator=login_validator)
    btn_submit = Button('submit', _('Submit'))
    form = Form(schema, buttons=(btn_submit,))
    if 'submit' in request.POST: 
        controls = request.POST.items()
        identity = request.POST.get('username')
        if identity.find('@') > -1:
            q = DBSession.query(User).filter_by(email=identity)
        else:
            q = DBSession.query(User).filter_by(user_name=identity)
        schema.user = user = q.first()
        try:
            c = form.validate(controls)
        except ValidationFailure:
            resp['form'] = form.render()
            return resp
        headers = get_login_headers(request, user)        
        return HTTPFound(location=request.route_url('home'),
                          headers=headers)
    resp['form'] = form.render()
    return resp


@view_config(route_name='logout')
def view_logout(request):
    headers = forget(request)
    return HTTPFound(location = request.route_url('home'),
                      headers = headers)    


###################
# Change password #
###################
class Password(colander.Schema):
    old_password = colander.SchemaNode(colander.String(),
                                       title="Kata Sandi Lama",
                                       widget=widget.PasswordWidget())
    new_password = colander.SchemaNode(colander.String(),
                                       title="Kata Sandi Baru",
                                       widget=widget.PasswordWidget())
    retype_password = colander.SchemaNode(colander.String(),
                                       title="Ketik Ulang Kata Sandi",
                                       widget=widget.PasswordWidget())

                                          
def password_validator(form, value):
    if not form.request.user.check_password(value['old_password']):
        raise colander.Invalid(form, 'Invalid old password.')
    if value['new_password'] != value['retype_password']:
        raise colander.Invalid(form, 'Retype mismatch.')
                                          

@view_config(route_name='password', renderer='templates/password.pt',
             permission='view')
def view_password(request):
    schema = Password(validator=password_validator)
    form = Form(schema, buttons=('simpan','batal'))
    if request.POST:
        if 'simpan' in request.POST:
            schema.request = request
            controls = request.POST.items()
            try:
                c = form.validate(controls)
            except ValidationFailure as e:
                request.session['invalid password'] = e.render()
                return HTTPFound(location=request.route_url('password'))
            user = request.user
            user.password = c['new_password']
            DBSession.add(user)
            DBSession.flush()
            transaction.commit()
            #request.session.flash('Your password has been changed.')
            request.session.flash('Password telah berhasil diubah.')
        return HTTPFound(location=request.route_url('home'))
    elif 'invalid password' in request.session:
        r = dict(form=request.session['invalid password'])
        del request.session['invalid password']
        return r
    return dict(form=form.render())