def reorder_page(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if experiment and page:
        try:
            params = ReorderSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                visible_idx = 1
                for idx, qid in enumerate(params['item']):
                    question = dbsession.query(Question).filter(and_(Question.id == qid,
                                                                     Question.page == page)).first()
                    if question is not None:
                        dbsession.add(question.q_type)
                        question.order = idx
                        if question['frontend', 'visible'] and question['frontend', 'title']:
                            question['frontend', 'question_number'] = visible_idx
                            visible_idx = visible_idx + 1
            return {'status': 'ok'}
        except formencode.Invalid:
            return {'status': 'error'}
    else:
        raise HTTPNotFound()
def save_file(request):
    """Handles the ``/parts/{pid}/files/id/{fid}/save``
    URL, updating the :class:`~wte.models.Asset`'s content.

    Requires that the user has "view" rights on the :class:`~wte.models.Part`.
    It will also only update an :class:`~wte.models.Asset` belonging to the
    current :class:`~wte.models.User`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    if part:
        if part.allow('view', request.current_user):
            progress = get_user_part_progress(dbsession, request.current_user,
                                              part)
            for user_file in progress.files:
                if user_file.id == int(request.matchdict['fid']):
                    if 'content' in request.params:
                        with transaction.manager:
                            dbsession.add(user_file)
                            user_file.data = request.params['content'].encode(
                                'utf-8')
                            user_file.etag = hashlib.sha512(
                                user_file.data).hexdigest()
                        return {'status': 'saved'}
                    else:
                        return {'status': 'no-changes'}
            raise HTTPNotFound()
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
def add_transition(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if experiment and page:
        try:
            with transaction.manager:
                dbsession.add(page)
                if page.next:
                    order = max([t.order for t in page.next]) + 1
                else:
                    order = 1
                transition = Transition(source=page, order=order)
                dbsession.add(transition)
            dbsession.add(experiment)
            dbsession.add(page)
            dbsession.add(transition)
            raise HTTPFound(request.route_url('experiment.page.transition',
                                              eid=experiment.id, pid=page.id,
                                              _anchor='transition-%i' % transition.id))
        except formencode.Invalid:
            raise HTTPFound(request.route_url('experiment.page.transition', eid=experiment.id, pid=page.id))
    else:
        raise HTTPNotFound()
def edit_question(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if page:
        question = dbsession.query(Question).filter(and_(Question.id == request.matchdict['qid'],
                                                         Question.page == page)).first()
    else:
        question = None
    if experiment and page and question:
        try:
            params = QuestionEditSchema(question['backend', 'fields']).to_python(request.params,
                                                                                 State(request=request,
                                                                                       dbsession=dbsession))
            with transaction.manager:
                dbsession.add(question)
                # Update question parameters
                for key, value in params.items():
                    if isinstance(value, list):
                        new_value = []
                        for sub_value in value:
                            if isinstance(sub_value, dict):
                                if len([v for v in sub_value.values() if v is None]) == 0:
                                    new_value.append(sub_value)
                            else:
                                if sub_value is not None:
                                    new_value.append(sub_value)
                        value = new_value
                    if key != 'csrf_token':
                        question[key] = value
                # Update all question numbering
                dbsession.add(page)
                visible_idx = 1
                for q in page.questions:
                    if q['frontend', 'visible'] and q['frontend', 'title']:
                        q['frontend', 'question_number'] = visible_idx
                        visible_idx = visible_idx + 1
            dbsession.add(experiment)
            dbsession.add(page)
            dbsession.add(question)
            data = render_to_response('ess:templates/page/edit_question.kajiki',
                                      {'experiment': experiment,
                                       'page': page,
                                       'question': question,
                                       'participant': Participant(id=-1)},
                                      request=request)
            return {'status': 'ok',
                    'fragment': data.body.decode('utf-8')}
        except formencode.Invalid as e:
            return {'status': 'error',
                    'errors': e.unpack_errors()}
    else:
        raise HTTPNotFound()
Exemple #5
0
def action(request):
    """Handles the ``/users/action`` URL, applying the given action to the
    list of selected users. Requires that the current
    :class:`~wte.models.User` has the "admin.users.view"
    :class:`~wte.models.Permission`.
    """
    dbsession = DBSession()
    try:
        query_params = []
        for param in ['q', 'status', 'start']:
            if param in request.params and request.params[param]:
                query_params.append((param, request.params[param]))
        params = ActionSchema().to_python(request.params,
                                          State(request=request))
        if params['action'] != 'delete' or params['confirm']:
            with transaction.manager:
                for user in dbsession.query(User).filter(
                        User.id.in_(params['user_id'])):
                    if params['action'] == 'validate':
                        if user.status == 'unconfirmed' and user.allow(
                                'edit', request.current_user):
                            user.status = 'active'
                    elif params['action'] == 'delete':
                        if user.allow('delete', request.current_user):
                            dbsession.delete(user)
                    elif params['action'] == 'password':
                        if user.status == 'active' and user.allow(
                                'edit', request.current_user):
                            token = TimeToken(
                                user.id, 'reset_password',
                                datetime.now() + timedelta(seconds=1200))
                            dbsession.add(token)
                            dbsession.flush()
                            if 'user.password_reset' in active_callbacks:
                                active_callbacks['user.password_reset'](
                                    request, user, token)
            raise HTTPSeeOther(request.route_url('users', _query=query_params))
        else:
            return {
                'params':
                params,
                'users':
                dbsession.query(User).filter(User.id.in_(params['user_id'])),
                'query_params':
                query_params,
                'crumbs':
                create_user_crumbs(request, [{
                    'title': 'Confirm',
                    'url': request.current_route_url()
                }])
            }
    except Invalid as e:
        print(e)
        request.session.flash(
            'Please select the action you wish to apply and the users to apply it to',
            queue='error')
        raise HTTPSeeOther(request.route_url('users', _query=query_params))
def import_experiment(request):
    if request.method == 'POST':
        try:
            params = ImportExperimentSchema().to_python(
                request.params, State(request=request))
            dbsession = DBSession()
            with transaction.manager:
                experiment, errors = ExperimentIOSchema(include_schemas=[s for s in all_io_schemas
                                                                         if s != ExperimentIOSchema]).\
                    loads(params['source'].file.read().decode('utf-8'))
                if errors:
                    raise formencode.Invalid(
                        '. '.join([
                            '%s: %s' % (e['source']['pointer'], e['detail'])
                            for e in errors['errors']
                        ]), None, None)
                for page in experiment.pages:
                    replace_questions(page, dbsession)
                experiment.owner = request.current_user
                experiment.external_id = uuid.uuid1().hex,
                experiment.status = 'develop'
                dbsession.add(experiment)
                dbsession.flush()
                for latin_square in experiment.latin_squares:
                    fix_latinsquare(latin_square, experiment.data_sets)
                for page in experiment.pages:
                    for transition in page.next:
                        fix_transition(transition, experiment.pages)
            dbsession.add(experiment)
            raise HTTPFound(
                request.route_url('experiment.view', eid=experiment.id))
        except formencode.Invalid as e:
            return {
                'crumbs': [{
                    'title': 'Experiments',
                    'url': request.route_url('dashboard')
                }, {
                    'title': 'Import',
                    'url': request.route_url('experiment.import')
                }],
                'errors': {
                    'source': str(e)
                },
                'values':
                request.params
            }
    return {
        'crumbs': [{
            'title': 'Experiments',
            'url': request.route_url('dashboard')
        }, {
            'title': 'Import',
            'url': request.route_url('experiment.import')
        }]
    }
def delete_part_task(request):
    """Handles the ``parts/{pid}/timed-tasks/{tid}/delete`` URL, providing the UI
    and backend for deleting an existing :class:`~wte.models.TimedTask` that
    belongs to a :class:`~wte.models.Part`.

    Requires that the user has "edit" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    task = dbsession.query(TimedTask).filter(
        TimedTask.id == request.matchdict['tid']).first()
    if part and task:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(
                request, part,
                [{
                    'title': 'Timed Actions',
                    'url': request.route_url('part.timed_task', pid=part.id)
                }, {
                    'title': 'Delete',
                    'url': request.current_route_url
                }])
            if request.method == 'POST':
                try:
                    CSRFSchema().to_python(request.params,
                                           State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.delete(task)
                    dbsession.add(part)
                    raise HTTPSeeOther(
                        request.route_url('part.timed_task', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'part': part,
                        'task': task,
                        'crumbs': crumbs,
                        'include_footer': True,
                        'help': ['user', 'teacher', 'timed_actions.html']
                    }
            return {
                'part': part,
                'task': task,
                'crumbs': crumbs,
                'include_footer': True,
                'help': ['user', 'teacher', 'timed_actions.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
class DBTester(object):
    """The :class:`~ess_test.conftest.DBTester` provides functionality for interacting with the
    database..
    """

    def __init__(self):
        self._dbsession = DBSession()

    def get_model(self, name, query_params = None):
        """Retrieve a single instance of the model ``name``, filtered by the ``query``.

        :param name: The name of the model to get the instance for
        :type name: ``unicode``
        :param query: The query to use for selecting the instance as a tuple of ``(field, comparator, value)``
        :type query: ``tuple``
        :return: The result of the query
        """
        cls = getattr(models, name)
        query = self._dbsession.query(cls)
        if query_params:
            if query_params[1] == '==':
                query = query.filter(getattr(cls, query_params[0]) == query_params[2])
        return query.first()

    def create_model(self, name, params):
        """Create a new instance of the model ``name`` with the given ``params``.

        :param name: The name of the model to create the instance of
        :type name: ``unicode``
        :param params: The initial parameters to use for creating the instance
        :type params: ``dict``
        :return: The new instance
        """
        cls = getattr(models, name)
        loaded = list(self._dbsession.identity_map.values())
        with transaction.manager:
            model = cls(**params)
            self._dbsession.add(model)
        self._dbsession.add(model)
        self._dbsession.add_all(loaded)
        return model

    def update(self, obj, **kwargs):
        """Update the given ``obj`` with the key/value parameters.

        :param obj: The obj to update
        :type obj: :class:`pywebtools.sqlalchemy.Base`
        """
        loaded = list(self._dbsession.identity_map.values())
        with transaction.manager:
            self._dbsession.add(obj)
            for key, value in kwargs.items():
                if isinstance(value, Base):
                    self._dbsession.add(value)
                setattr(obj, key, value)
        self._dbsession.add_all(loaded)

    def flush(self):
        """Flush the session."""
        self._dbsession.flush()
def initialise_database(args):
    settings = get_appsettings(args.configuration)
    setup_logging(args.configuration)
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    if args.drop_existing:
        Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    dbsession = DBSession()
    with transaction.manager:
        user = User(email='*****@*****.**',
                    display_name='Admin',
                    status='active')
        user.new_password('password')
        group = PermissionGroup(title='Site administrator')
        group.permissions.append(
            Permission(name='admin.users.view', title='View all users'))
        group.permissions.append(
            Permission(name='admin.users.edit', title='Edit all users'))
        group.permissions.append(
            Permission(name='admin.users.delete', title='Delete all users'))
        group.permissions.append(
            Permission(name='admin.users.permissions',
                       title='Edit all user\'s permissions'))
        user.permission_groups.append(group)
        group = PermissionGroup(title='Developer')
        group.permissions.append(
            Permission(name='experiment.create',
                       title='Create new experiments'))
        user.permission_groups.append(group)
        dbsession.add(user)
        group = PermissionGroup(title='Content administrator')
        group.permissions.append(
            Permission(name='experiment.view', title='View all experiments'))
        group.permissions.append(
            Permission(name='experiment.edit', title='Edit all experiments'))
        group.permissions.append(
            Permission(name='experiment.delete',
                       title='Delete all experiments'))
        dbsession.add(group)
        question_types = load(QuestionTypeIOSchema(many=True),
                              json.loads(resource_string('ess',
                                                         'scripts/templates/default_question_types.json').\
            decode('utf-8')))
        dbsession.add_all(question_types)
    alembic_config = config.Config(args.configuration, ini_section='app:main')
    alembic_config.set_section_option('app:main', 'script_location',
                                      'ess:migrations')
    command.stamp(alembic_config, "head")
def delete(request):
    """Handles the ``/parts/{pid}/assets/{aid}/delete`` URL,
    providing the UI and backend for deleting :class:`~wte.models.Asset`.

    Requires that the user has "edit" rights on the current :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    asset = dbsession.query(Asset).join(Part.all_assets).\
        filter(and_(Asset.id == request.matchdict['aid'],
                    Part.id == request.matchdict['pid'])).first()
    if part and asset:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(request, part, {
                'title': 'Delete Asset',
                'url': request.current_route_url()
            })
            if request.method == 'POST':
                try:
                    CSRFSchema().to_python(request.params,
                                           State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.add(asset)
                        asset.parts = []
                        dbsession.delete(asset)
                    dbsession.add(part)
                    raise HTTPSeeOther(
                        request.route_url('part.view', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'part': part,
                        'asset': asset,
                        'crumbs': crumbs,
                        'help': ['user', 'teacher', 'asset', 'delete.html']
                    }
            return {
                'part': part,
                'asset': asset,
                'crumbs': crumbs,
                'help': ['user', 'teacher', 'asset', 'delete.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Exemple #11
0
def run_change_status(task_id):
    """Run the status change task for the :class:`~wte.models.TimedTask` with the
    id ``task_id``. It changes the :class:`~wte.models.TimedTask`\ s status to the
    value of the "target_status" key in the :attr:`~wte.models.TimedTask.options`.
    """
    dbsession = DBSession()
    task = dbsession.query(TimedTask).filter(TimedTask.id == task_id).first()
    if task:
        part = dbsession.query(Part).filter(Part.id == task.part_id).first()
        if part and 'target_status' in task.options:
            with transaction.manager:
                dbsession.add(part)
                dbsession.add(task)
                part.status = task.options['target_status']
            with transaction.manager:
                dbsession.add(task)
                task.status = 'completed'
def create(request):
    if request.method == 'POST':
        try:
            params = CreateExperimentSchema().to_python(
                request.params, State(request=request))
            dbsession = DBSession()
            with transaction.manager:
                experiment = Experiment(title=params['title'],
                                        summary='',
                                        styles='',
                                        scripts='',
                                        status='develop',
                                        language='en',
                                        external_id=uuid.uuid1().hex,
                                        owned_by=request.current_user.id,
                                        public=False)
                dbsession.add(experiment)
            dbsession.add(experiment)
            raise HTTPFound(
                request.route_url('experiment.view', eid=experiment.id))
        except formencode.Invalid as e:
            return {
                'crumbs': [{
                    'title': 'Experiments',
                    'url': request.route_url('dashboard')
                }, {
                    'title': 'Create',
                    'url': request.route_url('experiment.create')
                }],
                'errors':
                e.error_dict,
                'values':
                request.params
            }
    return {
        'crumbs': [{
            'title': 'Experiments',
            'url': request.route_url('dashboard')
        }, {
            'title': 'Create',
            'url': request.route_url('experiment.create')
        }]
    }
Exemple #13
0
def set_answers(request):
    """Handles the "/parts/{pid}/quiz/set_answers" URL and stores the answers to a
    :class:`~wte.text_formatter.docutils_ext.QuizQuestion`.

    If no previous :class:`~wte.models.QuizAnswer` exists, creates one and sets
    the initial answers / correctness to the data supplied. If one exists,
    then sets the final answer / correctness and updates the attempts count.
    """
    try:
        dbsession = DBSession()
        part = dbsession.query(Part).filter(
            Part.id == request.matchdict['pid']).first()
        if part and part.has_role('student', request.current_user):
            params = SetAnswersSchema().to_python(request.params,
                                                  State(request=request))
            with transaction.manager:
                quiz = dbsession.query(Quiz).filter(
                    and_(Quiz.part_id == request.matchdict['pid'],
                         Quiz.name == params['quiz'])).first()
                if quiz:
                    answer = dbsession.query(QuizAnswer).filter(
                        and_(QuizAnswer.user_id == request.current_user.id,
                             QuizAnswer.quiz_id == quiz.id, QuizAnswer.question
                             == params['question'])).first()
                    if answer:
                        if not answer.initial_correct and not answer.final_correct:
                            answer.attempts = answer.attempts + 1
                            answer.final_answer = json.dumps(params['answer'])
                            answer.final_correct = params['correct']
                    else:
                        dbsession.add(
                            QuizAnswer(user_id=request.current_user.id,
                                       quiz=quiz,
                                       question=params['question'],
                                       initial_answer=json.dumps(
                                           params['answer']),
                                       initial_correct=params['correct'],
                                       final_answer=None,
                                       final_correct=None,
                                       attempts=1))
        return {}
    except Invalid as e:
        return {'errors': e.error_dict}
def add_question(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    qtype = dbsession.query(QuestionType).filter(QuestionType.id == request.matchdict['qtid']).first()
    if experiment and page and qtype:
        try:
            params = AddQuestionSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                dbsession.add(page)
                if params['order'] is None:
                    params['order'] = len(page.questions)
                question = Question(q_type=qtype,
                                    page=page,
                                    order=params['order'])
                if question['frontend', 'visible']:
                    visible_idx = [q['frontend', 'question_number']
                                   for q in page.questions
                                   if q['frontend', 'visible'] and
                                   q['frontend', 'title'] and
                                   q['frontend', 'question_number']]
                    if visible_idx:
                        visible_idx = max(visible_idx) + 1
                    else:
                        visible_idx = 1
                    question['frontend', 'question_number'] = visible_idx
                dbsession.add(question)
            dbsession.add(experiment)
            dbsession.add(page)
            dbsession.add(question)
            raise HTTPFound(request.route_url('experiment.page.edit',
                                              eid=experiment.id, pid=page.id,
                                              _anchor='question-%i' % question.id))
        except formencode.Invalid:
            raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
    else:
        raise HTTPNotFound()
def data(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        data_sets = dbsession.query(DataSet).filter(DataSet.experiment_id == experiment.id)
        if request.method == 'POST':
            try:
                schema = DataAttachmentSchema()
                mode = ''
                if 'data_set' in request.params and \
                        request.params['data_set'] in [str(ds.id) for ds in data_sets if ds.type == 'dataset']:
                    schema.add_field('data_items', formencode.validators.Int(not_empty=True))
                    mode = 'dataset'
                params = schema.to_python(request.params, State(request=request,
                                                                dbsession=dbsession,
                                                                experiment=experiment))
                with transaction.manager:
                    dbsession.add(page)
                    page.dataset_id = params['data_set']
                    if mode == 'dataset':
                        page['data'] = {'type': 'dataset',
                                        'item_count': params['data_items']}
                dbsession.add(experiment)
                dbsession.add(page)
                raise HTTPFound(request.route_url('experiment.page.data', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'page': page,
                        'data_sets': data_sets,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': '%s (%s)' % (page.title, page.name)
                                    if page.title else 'No title (%s)' % page.name,
                                    'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                                   {'title': 'Data',
                                    'url': request.route_url('experiment.page.data', eid=experiment.id, pid=page.id)}],
                        'errors': e.error_dict,
                        'values': request.params}
        return {'experiment': experiment,
                'page': page,
                'data_sets': data_sets,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': '%s (%s)' % (page.title, page.name)
                            if page.title else 'No title (%s)' % page.name,
                            'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                           {'title': 'Data',
                            'url': request.route_url('experiment.page.data', eid=experiment.id, pid=page.id)}]}
    else:
        raise HTTPNotFound()
def import_page(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                params = ImportPageSchema().to_python(request.params, State(request=request,
                                                                            dbsession=dbsession))
                with transaction.manager:
                    dbsession.add(experiment)
                    page, errors = PageIOSchema(include_data=('questions', 'questions.q_type',
                                                              'questions.q_type.parent',
                                                              'questions.q_type.q_type_group',
                                                              'questions.q_type.q_type_group.parent',
                                                              'questions.q_type.parent.q_type_group',
                                                              'questions.q_type.parent.q_type_group.parent')).\
                        loads(params['source'].file.read().decode('utf-8'))
                    if errors:
                        raise formencode.Invalid('. '.join(['%s: %s' % (e['source']['pointer'], e['detail'])
                                                            for e in errors['errors']]), None, None)
                    dbsession.add(page)
                    replace_questions(page, dbsession)
                    page.experiment = experiment
                dbsession.add(experiment)
                dbsession.add(page)
                raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': 'Import a Page',
                                    'url': request.route_url('experiment.page.import', eid=experiment.id)}],
                        'errors': {'source': str(e)},
                        'values': request.params}
        return {'experiment': experiment,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': 'Import a Page',
                            'url': request.route_url('experiment.page.import', eid=experiment.id)}]}
    else:
        raise HTTPNotFound()
def data_item_delete(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == 'dataset')).first()
    data_item = dbsession.query(DataItem).filter(
        and_(DataItem.id == request.matchdict['diid'],
             DataItem.dataset_id == request.matchdict['did'])).first()
    if experiment and data_set and data_item:
        with transaction.manager:
            dbsession.delete(data_item)
        dbsession.add(experiment)
        dbsession.add(data_set)
        raise HTTPFound(
            request.route_url('experiment.data.view',
                              eid=experiment.id,
                              did=data_set.id))
    else:
        raise HTTPNotFound()
def settings(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        if request.method == 'POST':
            try:
                params = PageSettingsSchema().to_python(request.params,
                                                        State(request=request,
                                                              dbsession=dbsession,
                                                              experiment=experiment,
                                                              page_id=request.matchdict['pid']))
                with transaction.manager:
                    dbsession.add(page)
                    page.name = params['name']
                    page.title = params['title']
                    page.styles = params['styles']
                    page.scripts = params['scripts']
                    page['number_questions'] = params['number_questions']
                dbsession.add(page)
                dbsession.add(experiment)
                raise HTTPFound(request.route_url('experiment.page.settings', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'page': page,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': '%s (%s)' % (page.title, page.name)
                                    if page.title else 'No title (%s)' % page.name,
                                    'url': request.route_url('experiment.page.edit',
                                                             eid=experiment.id,
                                                             pid=page.id)},
                                   {'title': 'Settings',
                                    'url': request.route_url('experiment.page.settings',
                                                             eid=experiment.id,
                                                             pid=page.id)}],
                        'values': request.params,
                        'errors': e.error_dict}
        return {'experiment': experiment,
                'page': page,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': '%s (%s)' % (page.title, page.name)
                            if page.title else 'No title (%s)' % page.name,
                            'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                           {'title': 'Settings',
                            'url': request.route_url('experiment.page.settings', eid=experiment.id, pid=page.id)}]}
    else:
        raise HTTPNotFound()
Exemple #19
0
def initialise_database(args):
    """Initialises the database schema and adds the default
    :class:`~wte.models.Permission`, :class:`~wte.models.PermissionGroup`, and
    :class:`~wte.models.User` to the database.
    """
    settings = get_appsettings(args.configuration)
    setup_logging(args.configuration)
    engine = engine_from_config(settings, 'sqlalchemy.')
    if args.drop_existing:
        Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)

    DBSession.configure(bind=engine)
    dbsession = DBSession()
    with transaction.manager:
        admin_user = User(email='*****@*****.**',
                          display_name='Admin',
                          password='******')
        dbsession.add(admin_user)

        admin_permission = Permission(name='admin',
                                      title='Administration Access')

        group = init_auth_permissions(dbsession)
        group.permissions.append(admin_permission)
        admin_user.permission_groups.append(group)

        group = PermissionGroup(title='Content Administration')
        dbsession.add(group)
        group.permissions.append(admin_permission)
        create_module_perm = Permission(name='modules.create',
                                        title='Create a new module')
        group.permissions.append(create_module_perm)
        group.permissions.append(
            Permission(name='admin.modules.view', title='View all modules'))
        group.permissions.append(
            Permission(name='admin.modules.edit', title='Edit all modules'))
        group.permissions.append(
            Permission(name='admin.modules.delete',
                       title='Delete all modules'))
        admin_user.permission_groups.append(group)

        group = PermissionGroup(title='Teacher')
        dbsession.add(group)
        group.permissions.append(create_module_perm)

        group = PermissionGroup(title='Student')
        dbsession.add(group)
def new_part_task(request):
    """Handles the ``parts/{pid}/timed-tasks/new`` URL, providing the UI and
    backend for creating a new :class:`~wte.models.TimedTask`\ s for
    a given :class:`~wte.models.Part`.

    Requires that the user has "edit" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    if part:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(request, part, {
                'title': 'Timed Actions',
                'url': request.current_route_url()
            })
            available_tasks = [('change_status', 'Change Status')]
            if request.method == 'POST':
                try:
                    params = NewTimedTaskSchema().to_python(
                        request.params, State(request=request))
                    with transaction.manager:
                        title = 'Unknown Task'
                        if params['name'] == 'change_status':
                            title = 'Change Status'
                        new_task = TimedTask(name=params['name'],
                                             part_id=part.id,
                                             title=title,
                                             status='new')
                        dbsession.add(new_task)
                    dbsession.add(part)
                    dbsession.add(new_task)
                    raise HTTPSeeOther(
                        request.route_url('part.timed_task.edit',
                                          pid=part.id,
                                          tid=new_task.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'crumbs': crumbs,
                        'available_tasks': available_tasks,
                        'include_footer': True,
                        'help': ['user', 'teacher', 'timed_actions.html']
                    }
            return {
                'part': part,
                'crumbs': crumbs,
                'available_tasks': available_tasks,
                'include_footer': True,
                'help': ['user', 'teacher', 'timed_actions.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
def delete_transition(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                                 Page.experiment == experiment)).first()
    else:
        page = None
    if page:
        transition = dbsession.query(Transition).filter(and_(Transition.id == request.matchdict['tid'],
                                                             Transition.source == page)).first()
    else:
        transition = None
    if experiment and page and transition:
        try:
            with transaction.manager:
                dbsession.delete(transition)
            dbsession.add(experiment)
            dbsession.add(page)
            raise HTTPFound(request.route_url('experiment.page.transition', eid=experiment.id, pid=page.id))
        except formencode.Invalid:
            raise HTTPFound(request.route_url('experiment.page.transition', eid=experiment.id, pid=page.id))
    else:
        raise HTTPNotFound()
def data_delete(request):
    mode = 'latinsquare' if 'latinsquare' in request.matched_route.name else 'dataset'
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == mode)).first()
    if experiment and data_set:
        try:
            CSRFSchema().to_python(request.params, State(request=request))
            with transaction.manager:
                dbsession.delete(data_set)
            dbsession.add(experiment)
            raise HTTPFound(
                request.route_url('experiment.%s' % mode, eid=experiment.id))
        except formencode.Invalid:
            raise HTTPFound(
                request.route_url('experiment.%s.view' % mode,
                                  eid=experiment.id,
                                  did=data_set.id))
    else:
        raise HTTPNotFound()
def create(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                params = CreatePageSchema().to_python(request.params, State(request=request,
                                                                            dbsession=dbsession,
                                                                            experiment=experiment))
                with transaction.manager:
                    page = Page(experiment=experiment,
                                name=params['name'],
                                title=params['title'],
                                styles='',
                                scripts='')
                    dbsession.add(page)
                    dbsession.add(experiment)
                    if experiment.start is None:
                        experiment.start = page
                dbsession.add(experiment)
                dbsession.add(page)
                raise HTTPFound(request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': 'Add a Page',
                                    'url': request.route_url('experiment.page.create', eid=experiment.id)}],
                        'errors': e.error_dict,
                        'values': request.params}
        return {'experiment': experiment,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': 'Add a Page',
                            'url': request.route_url('experiment.page.create', eid=experiment.id)}]}
    else:
        raise HTTPNotFound()
def delete(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(Experiment.id == request.matchdict['eid']).first()
    page = dbsession.query(Page).filter(and_(Page.id == request.matchdict['pid'],
                                             Page.experiment_id == request.matchdict['eid'])).first()
    if experiment and page:
        if request.method == 'POST':
            try:
                DeleteSchema().to_python(request.params,
                                         State(request=request,
                                               dbsession=dbsession))
                with transaction.manager:
                    dbsession.add(experiment)
                    dbsession.add(page)
                    if experiment.start == page:
                        experiment.start = None
                    dbsession.delete(page)
                dbsession.add(experiment)
                raise HTTPFound(request.route_url('experiment.page', eid=experiment.id))
            except formencode.Invalid as e:
                return {'experiment': experiment,
                        'page': page,
                        'crumbs': [{'title': 'Experiments',
                                    'url': request.route_url('dashboard')},
                                   {'title': experiment.title,
                                    'url': request.route_url('experiment.view', eid=experiment.id)},
                                   {'title': 'Pages',
                                    'url': request.route_url('experiment.page', eid=experiment.id)},
                                   {'title': '%s (%s)' % (page.title, page.name)
                                    if page.title else 'No title (%s)' % page.name,
                                    'url': request.route_url('experiment.page.edit',
                                                             eid=experiment.id,
                                                             pid=page.id)},
                                   {'title': 'Delete',
                                    'url': request.route_url('experiment.page.delete',
                                                             eid=experiment.id,
                                                             pid=page.id)}],
                        'values': request.params,
                        'errors': e.error_dict}
        return {'experiment': experiment,
                'page': page,
                'crumbs': [{'title': 'Experiments',
                            'url': request.route_url('dashboard')},
                           {'title': experiment.title,
                            'url': request.route_url('experiment.view', eid=experiment.id)},
                           {'title': 'Pages',
                            'url': request.route_url('experiment.page', eid=experiment.id)},
                           {'title': '%s (%s)' % (page.title, page.name)
                            if page.title else 'No title (%s)' % page.name,
                            'url': request.route_url('experiment.page.edit', eid=experiment.id, pid=page.id)},
                           {'title': 'Delete',
                            'url': request.route_url('experiment.page.delete', eid=experiment.id, pid=page.id)}]}
    else:
        raise HTTPNotFound()
def data_item_add(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    data_set = dbsession.query(DataSet).filter(
        and_(DataSet.id == request.matchdict['did'],
             DataSet.experiment_id == request.matchdict['eid'],
             DataSet.type == 'dataset')).first()
    if experiment and data_set:
        try:
            schema = DynamicSchema()
            schema.add_field('csrf_token', CSRFValidator())
            for column in data_set['columns']:
                schema.add_field(
                    column,
                    formencode.validators.UnicodeString(if_empty='',
                                                        if_missing=''))
            params = schema.to_python(request.params, State(request=request))
            with transaction.manager:
                dbsession.add(data_set)
                order = dbsession.query(func.max(DataItem.order)).filter(
                    DataItem.dataset_id == data_set.id).first()
                if order[0] is None:
                    order = 1
                else:
                    order = order[0] + 1
                data_item = DataItem(dataset_id=data_set.id, order=order)
                data = {}
                for column in data_set['columns']:
                    data[column] = params[column]
                data_item['values'] = data
                dbsession.add(data_item)
            dbsession.add(data_item)
            return {
                'status': 'ok',
                'id': data_item.id,
                'order': data_item.order,
                'values': data_item['values']
            }
        except formencode.Invalid as e:
            return {'status': 'error', 'errors': e.unpack_errors()}
    else:
        raise HTTPNotFound()
Exemple #26
0
def reset(request):
    dbsession = DBSession()
    experiment = dbsession.query(Experiment).filter(
        Experiment.id == request.matchdict['eid']).first()
    if experiment:
        if request.method == 'POST':
            try:
                ResetSchema().to_python(request.params, State(request=request))
                with transaction.manager:
                    dbsession.add(experiment)
                    experiment.participants = []
                dbsession.add(experiment)
                raise HTTPFound(
                    request.route_url('experiment.results', eid=experiment.id))
            except formencode.Invalid as e:
                return {
                    'experiment':
                    experiment,
                    'values':
                    request.params,
                    'errors':
                    e.error_dict,
                    'crumbs': [{
                        'title': 'Experiments',
                        'url': request.route_url('dashboard')
                    }, {
                        'title':
                        experiment.title,
                        'url':
                        request.route_url('experiment.view', eid=experiment.id)
                    }, {
                        'title':
                        'Results',
                        'url':
                        request.route_url('experiment.results',
                                          eid=experiment.id)
                    }, {
                        'title':
                        'Reset',
                        'url':
                        request.route_url('experiment.results.reset',
                                          eid=experiment.id)
                    }]
                }
        return {
            'experiment':
            experiment,
            'crumbs': [{
                'title': 'Experiments',
                'url': request.route_url('dashboard')
            }, {
                'title':
                experiment.title,
                'url':
                request.route_url('experiment.view', eid=experiment.id)
            }, {
                'title':
                'Results',
                'url':
                request.route_url('experiment.results', eid=experiment.id)
            }, {
                'title':
                'Clear',
                'url':
                request.route_url('experiment.results.reset',
                                  eid=experiment.id)
            }]
        }
    else:
        raise HTTPNotFound()
def edit_part_task(request):
    """Handles the ``parts/{pid}/timed-tasks/{tid}/edit`` URL, providing the UI
    and backend for editing an existing :class:`~wte.models.TimedTask` that
    belongs to a :class:`~wte.models.Part`.

    Requires that the user has "edit" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    task = dbsession.query(TimedTask).filter(
        TimedTask.id == request.matchdict['tid']).first()
    if part and task:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(
                request, part,
                [{
                    'title': 'Timed Actions',
                    'url': request.route_url('part.timed_task', pid=part.id)
                }, {
                    'title': 'Edit',
                    'url': request.current_route_url
                }])
            if request.method == 'POST':
                try:
                    options = []
                    if task.name == 'change_status':
                        status = ['available', 'unavailable']
                        if part.type == 'module':
                            status.append('archived')
                        options.append(('target_status',
                                        formencode.validators.OneOf(status)))
                    params = EditTimedTaskSchema(options).to_python(
                        request.params, State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.add(task)
                        task.timestamp = datetime.combine(
                            params['date'], params['time'])
                        if 'options' in params and params['options']:
                            task.options = params['options']
                            task.status = 'ready'
                    dbsession.add(part)
                    raise HTTPSeeOther(
                        request.route_url('part.timed_task', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'task': task,
                        'crumbs': crumbs,
                        'include_footer': True,
                        'help': ['user', 'teacher', 'timed_actions.html']
                    }
            return {
                'part': part,
                'task': task,
                'crumbs': crumbs,
                'include_footer': True,
                'help': ['user', 'teacher', 'timed_actions.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
def database():
    """The :func:`~ess_test.conftest.database` fixture initialises the database specified
    in the "testing.ini", removes any existing data, creates the standard permissions, and
    four test users:

    * admin - user with full administrative permissions
    * developer - user with full experiment development permissions
    * content - user with full editing permissions
    * general - user with no permissions
    """
    global dbsession_initialised

    # Load settings
    settings = get_appsettings('testing.ini')
    setup_logging('testing.ini')

    # Init the DB
    engine = engine_from_config(settings, 'sqlalchemy.')
    if not dbsession_initialised:
        DBSession.configure(bind=engine)
        dbsession_initialised = True
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)

    dbsession = DBSession()

    # Create Test Users
    with transaction.manager:
        admin_user = User(email='*****@*****.**', display_name='Admin', password='******')
        developer_user = User(email='*****@*****.**', display_name='Developer', password='******')
        content_user = User(email='*****@*****.**', display_name='Content', password='******')
        general_user = User(email='*****@*****.**', display_name='General', password='******')
        dbsession.add(general_user)
        group = PermissionGroup(title='Site administrator')
        group.permissions.append(Permission(name='admin.users', title='Administer the users'))
        group.permissions.append(Permission(name='admin.groups', title='Administer the permission groups'))
        group.permissions.append(Permission(name='admin.question_types', title='Administer the question types'))
        admin_user.permission_groups.append(group)
        group = PermissionGroup(title='Developer')
        group.permissions.append(Permission(name='survey.new', title='Create new experiments'))
        admin_user.permission_groups.append(group)
        developer_user.permission_groups.append(group)
        group = PermissionGroup(title='Content administrator')
        group.permissions.append(Permission(name='survey.view-all', title='View all experiments'))
        group.permissions.append(Permission(name='survey.edit-all', title='Edit all experiments'))
        group.permissions.append(Permission(name='survey.delete-all', title='Delete all experiments'))
        content_user.permission_groups.append(group)
        dbsession.add(admin_user)
        dbsession.add(developer_user)
        dbsession.add(content_user)
        question_types = QuestionTypeIOSchema(include_schemas=(QuestionTypeGroupIOSchema,), many=True).\
            loads(resource_string('ess','scripts/templates/default_question_types.json'))
        dbsession.add_all(question_types.data)

    # Alembic Stamp
    alembic_config = config.Config('testing.ini', ini_section='app:main')
    alembic_config.set_section_option('app:main', 'script_location', 'ess:migrations')
    command.stamp(alembic_config, "head")

    dbsession.close()
    DBSession.close_all()

    yield DBSession
Exemple #29
0
def permissions(request):
    """Handles the "/users/{uid}/permissions" URL, providing the form and
    backend functionality for setting the :class:`~wte.models.Permission` and
    :class:`~wte.models.PermissionGroup` that the :class:`~wte.models.User`
    belongs to.
    """
    dbsession = DBSession()
    user = dbsession.query(User).filter(
        User.id == request.matchdict['uid']).first()
    if user:
        permission_groups = dbsession.query(PermissionGroup).order_by(
            PermissionGroup.title)
        permissions = dbsession.query(Permission).order_by(Permission.title)
        if request.method == 'POST':
            try:
                CSRFSchema(allow_extra_fields=True).to_python(
                    request.params, State(request=request))
                with transaction.manager:
                    dbsession.add(user)
                    ids = request.params.getall('permission_group')
                    if ids:
                        user.permission_groups = dbsession.query(PermissionGroup).\
                            filter(PermissionGroup.id.in_(ids)).all()
                    else:
                        user.permission_groups = []
                    ids = request.params.getall('permission')
                    if ids:
                        user.permissions = dbsession.query(Permission).filter(
                            Permission.id.in_(ids)).all()
                    else:
                        user.permissions = []
                dbsession.add(user)
                dbsession.add(request.current_user)
                if request.current_user.has_permission('admin.users.view'):
                    raise HTTPSeeOther(request.route_url('users'))
                else:
                    raise HTTPSeeOther(
                        request.route_url('user.view', uid=user.id))
            except Invalid as e:
                return {
                    'errors':
                    e.error_dict,
                    'user':
                    user,
                    'permission_groups':
                    permission_groups,
                    'permissions':
                    permissions,
                    'crumbs':
                    create_user_crumbs(
                        request,
                        [{
                            'title': user.display_name,
                            'url': request.route_url('user.view', uid=user.id)
                        }, {
                            'title':
                            'Permissions',
                            'url':
                            request.route_url('user.permissions', uid=user.id)
                        }])
                }
        return {
            'user':
            user,
            'permission_groups':
            permission_groups,
            'permissions':
            permissions,
            'crumbs':
            create_user_crumbs(
                request,
                [{
                    'title': user.display_name,
                    'url': request.route_url('user.view', uid=user.id)
                }, {
                    'title': 'Permissions',
                    'url': request.route_url('user.permissions', uid=user.id)
                }])
        }
    else:
        raise HTTPNotFound()
Exemple #30
0
def edit(request):
    """Handles the "/users/{uid}/edit" URL, providing the form and backend
    functionality to update the user's profile.
    """
    dbsession = DBSession()
    user = dbsession.query(User).filter(
        User.id == request.matchdict['uid']).first()
    if user:
        if user.allow('edit', request.current_user):
            crumbs = create_user_crumbs(
                request, [{
                    'title': user.display_name,
                    'url': request.route_url('user.view', uid=user.id)
                }, {
                    'title': 'Edit',
                    'url': request.route_url('user.edit', uid=user.id)
                }])
            if request.method == 'POST':
                try:
                    params = EditSchema().to_python(
                        request.params,
                        State(dbsession=dbsession,
                              userid=user.id,
                              email_domains=get_config_setting(
                                  request,
                                  key='registration.domains',
                                  target_type='list',
                                  default=None),
                              user_class=User,
                              request=request))
                    with transaction.manager:
                        dbsession.add(user)
                        user.email = params['email']
                        user.display_name = params['display_name']
                        if params['password']:
                            user.new_password(params['password'])
                        options = {}
                        if params['option']:
                            for key, value in params['option'].items():
                                if isinstance(value, list):
                                    options[key] = value[-1]
                                else:
                                    options[key] = value
                        user.options = options
                    raise HTTPSeeOther(
                        request.route_url('user.view',
                                          uid=request.matchdict['uid']))
                except Invalid as e:
                    print(e)
                    return {
                        'e': e.error_dict,
                        'values': request.params,
                        'user': user,
                        'crumbs': crumbs,
                        'help': ['user', 'user', 'profile.html']
                    }
            return {
                'user': user,
                'crumbs': crumbs,
                'help': ['user', 'user', 'profile.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()