def update_(request):
    'Update account'
    params = request.params
    if params.get('token') != request.session.get_csrf_token():
        return dict(isOk=0, message='Invalid token')
    userID = authenticated_userid(request)
    # If the user is trying to update account information, send confirmation email
    if 'username' in params:
        return save_user_(request, dict(params), 'update', db.query(User).get(userID))
    # Load
    smsAddressAction = params.get('smsAddressAction')
    # If the user is adding an SMS address,
    if 'add' == smsAddressAction:
        # Make sure it is a valid email address
        validateEmail = validators.Email().to_python
        try:
            smsAddressEmail = validateEmail(params.get('smsAddressEmail', ''))
        except Invalid, error:
            return dict(isOk=0, message=str(error))
        # Check for duplicates
        smsAddress = db.query(SMSAddress).filter(
            (SMSAddress.email == smsAddressEmail) & 
            (SMSAddress.user_id == userID)).first()
        if smsAddress:
            return dict(isOk=0, message='You already added this SMS address')
        # Add it to the database
        smsAddress = SMSAddress(email=smsAddressEmail, user_id=userID, code=make_random_string(CODE_LEN))
        db.add(smsAddress)
        # Send confirmation code
        get_mailer(request).send_to_queue(Message(
            recipients=[smsAddress.email],
            body=smsAddress.code))
        # Return smsAddresses
        return dict(isOk=1, content=render('users/smsAddresses.mak', update(request), request))
def initialize_sql(engine):
    'Create tables and insert data'
    # Create tables
    db.configure(bind=engine)
    Base.metadata.bind = engine
    Base.metadata.create_all(engine)
    # If the tables are empty,
    if not db.query(User).count():
        # Prepare data
        userPacks = [
            (u'admin', make_random_string(PASSWORD_LEN_MAX), u'Admin', u'*****@*****.**', True),
            (u'user', make_random_string(PASSWORD_LEN_MAX), u'User', u'*****@*****.**', False), 
        ]
        # Insert data
        userTemplate = '\nUsername\t%s\nPassword\t%s\nNickname\t%s\nEmail\t\t%s'
        for username, password, nickname, email, is_super in userPacks:
            print userTemplate % (username, password, nickname, email)
            db.add(User(username=username, password_=hash(password), nickname=nickname, email=email, is_super=is_super))
        print
        transaction.commit()
def reset(request):
    'Reset password'
    # Get email
    email = request.params.get('email')
    # Try to load the user
    user = db.query(User).filter(User.email==email).first()
    # If the email is not in our database,
    if not user: 
        return dict(isOk=0)
    # Reset account
    return save_user_(request, dict(
        username=user.username, 
        password=make_random_string(PASSWORD_LEN_MAX),
        nickname=user.nickname,
        email=user.email), 'reset', user)
def main(global_config, **settings):
    'Return a Pyramid WSGI application'
    # Load sensitive configuration
    if '__file__' in global_config:
        configFolder, configName = os.path.split(global_config['__file__'])
        configParser = ConfigParser(global_config)
        if configParser.read(os.path.join(configFolder, '.' + configName)):
            for section in configParser.sections():
                settings.update(configParser.items(section))
    if 'hashlib.secret' in settings:
        tools.secret1 = settings['hashlib.secret']
    if 'ciphers.secret' in settings:
        tools.secret2 = settings['ciphers.secret']
    # Connect to database
    sqlalchemyURL = settings['sqlalchemy.url'].strip()
    initialize_sql(engine_from_config(settings, 'sqlalchemy.', 
        poolclass=NullPool if sqlalchemyURL.startswith('sqlite:///') else QueuePool))
    # Define methods
    def get_groups(userID, request):
        'Return a list of groups associated with the authenticated user'
        identity = authenticationPolicy.cookie.identify(request)
        if identity:
            return identity['tokens'][1:]
    def make_renderer_globals(system):
        'Define template constants'
        identity = authenticationPolicy.cookie.identify(system['request'])
        if identity:
            userID = identity['userid']
            nickname, offset, groups = users.parse_tokens(identity['tokens'])
        else:
            userID = None
            nickname, offset, groups = u'', MINUTES_OFFSET, []
        return dict(
            SITE_NAME=SITE_NAME, 
            SITE_VERSION=SITE_VERSION,
            USER_ID=userID,
            USER_NICKNAME=nickname,
            USER_OFFSET=offset,
            IS_SUPER='s' in groups)
    # Prepare configuration
    if 'authtkt.secret' not in settings:
        settings['authtkt.secret'] = tools.make_random_string(SECRET_LEN)
    authenticationPolicy = AuthTktAuthenticationPolicy(settings['authtkt.secret'], 
        callback=get_groups, http_only=True)
    config = Configurator(
        settings=settings,
        authentication_policy=authenticationPolicy,
        authorization_policy=ACLAuthorizationPolicy(),
        default_permission='protected',
        renderer_globals_factory=make_renderer_globals,
        root_factory='scout.RootFactory')
    config.add_settings({
        'mako.directories': 'scout:templates',
        'mako.default_filters': 'h',
        'cache.regions': 'short, medium, long',
    })
    # Configure transaction manager and mailer
    config.include('pyramid_tm')
    config.include('pyramid_mailer')
    # Configure sessions and caching
    if 'session.secret' not in settings:
        settings['session.secret'] = tools.make_random_string(SECRET_LEN)
    config.set_session_factory(session_factory_from_settings(settings))
    set_cache_regions_from_settings(settings)
    # Configure static assets
    config.add_static_view('static', 'scout:static')
    # Configure routes for user account management
    config.include(users)
    # Configure routes that demonstrate access control
    config.include(pages)
    # Configure routes for IMAP accounts
    config.include(accounts)
    # Configure routes for IMAP messages
    config.include(messages)
    # Configure routes for IMAP searches
    config.include(searches)
    # Return WSGI app
    return config.make_wsgi_app()