Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
def view_asset(request):
    """Handles the ``/parts/{pid}/files/name/assets/{filename}``
    URL, sending back the correct :class:`~wte.models.Asset`.

    Requires that the user has "view" rights on the :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    if part.type == 'page':
        part = part.parent
    asset = dbsession.query(Asset).join(Part.assets).\
        filter(and_(Asset.filename == request.matchdict['filename'],
                    Part.id == part.id)).first()
    if part and asset:
        if part.allow('view', request.current_user):
            if 'If-None-Match' in request.headers and request.headers[
                    'If-None-Match'] == asset.etag:
                raise HTTPNotModified()
            headerlist = [('Content-Type', str(asset.mimetype))]
            if asset.etag is not None:
                headerlist.append(('ETag', str(asset.etag)))
            if 'download' in request.params:
                if request.params['download'].lower() == 'true':
                    headerlist.append(
                        ('Content-Disposition',
                         str('attachment; filename="%s"' % (asset.filename))))
            return Response(body=asset.data, headerlist=headerlist)
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 3
0
def delete(request):
    """Handles the "/users/{uid}/delete" URL, providing the form and backend
    functionality for deleting a :class:`~wte.models.User`. Also deletes all
    the data that is linked to that :class:`~wte.models.User`.
    """
    dbsession = DBSession()
    user = dbsession.query(User).filter(
        User.id == request.matchdict['uid']).first()
    if user:
        if user.allow('delete', request.current_user):
            if request.method == 'POST':
                try:
                    CSRFSchema().to_python(request.params,
                                           State(request=request))
                    with transaction.manager:
                        dbsession.delete(user)
                    request.session.flash('The account has been deleted',
                                          queue='info')
                    if request.current_user.has_permission('admin.users.view'):
                        raise HTTPSeeOther(request.route_url('users'))
                    else:
                        raise HTTPSeeOther(request.route_url('root'))
                except Invalid as e:
                    return {
                        'errors':
                        e.error_dict,
                        'user':
                        user,
                        'crumbs':
                        create_user_crumbs(
                            request,
                            [{
                                'title': user.display_name,
                                'url': request.route_url('user.view',
                                                         uid=user.id)
                            }, {
                                'title':
                                'Delete',
                                'url':
                                request.route_url('user.delete', uid=user.id)
                            }])
                    }
            return {
                'user':
                user,
                'crumbs':
                create_user_crumbs(
                    request,
                    [{
                        'title': user.display_name,
                        'url': request.route_url('user.view', uid=user.id)
                    }, {
                        'title': 'Delete',
                        'url': request.route_url('user.delete', uid=user.id)
                    }])
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 4
0
def view_file(request):
    """Handles the ``parts/{ptid}/pages/{pid}/users/{uid}/files/name/{filename}``
    URL, sending back the correct :class:`~wte.models.Asset`.

    Requires that the user has "view" rights on the :class:`~wte.models.Part`.
    It will also only send 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.filename == request.matchdict['filename']:
                    if 'If-None-Match' in request.headers and request.headers[
                            'If-None-Match'] == user_file.etag:
                        raise HTTPNotModified()
                    headers = [('Content-Type', str(user_file.mimetype))]
                    if user_file.etag is not None:
                        headers.append(('ETag', str(user_file.etag)))
                    if 'download' in request.params:
                        headers.append(('Content-Disposition',
                                        str('attachment; filename="%s"' %
                                            (user_file.filename))))
                    return Response(body=user_file.data, headerlist=headers)
            raise HTTPNotFound()
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 5
0
def view_part_tasks(request):
    """Handles the ``parts/{pid}/timed-tasks`` URL, displaying the
    :class:`~wte.models.TimedTask`\ s for the 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': 'Edit Timed Actions',
                'url': request.current_route_url()
            })
            available_tasks = [('change_status', 'Change Status')]
            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()
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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()
Ejemplo n.º 9
0
def search(request):
    """Handles the ``/parts/{pid}/assets/search`` URL, searching
    for all :class:`~wte.models.Asset` that have a filename that
    matches the 'q' request parameter and that belong to either the
    current :class:`~wte.models.Part` or any of its ancestors.
    The current user must have the "view" permission on the current
    :class:`~wte.models.Part` to see any results.
    """
    dbsession = DBSession()
    part = dbsession.query(Part).filter(
        Part.id == request.matchdict['pid']).first()
    if part:
        if part.allow('view', request.current_user):
            assets = []
            if 'q' in request.params:
                while part is not None:
                    assets.extend([
                        asset for asset in part.assets
                        if request.params['q'] in asset.filename
                    ])
                    part = part.parent
            return [{
                'id': asset.filename,
                'value': asset.filename
            } for asset in assets]
        else:
            raise unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 10
0
def action(request):
    """Handles the ``parts/{pid}/users/action`` URL, loads the interface for changing
    :class:`~wte.models.User` registered for a :class:`~wte.models.Part`.

    Requires that the user has "users" 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('users', request.current_user):
            query_params = []
            for param in ['q', 'role', 'start']:
                if param in request.params and request.params[param]:
                    query_params.append((param, request.params[param]))
            try:
                params = ActionSchema().to_python(request.params,
                                                  State(request=request))
            except formencode.api.Invalid:
                request.session.flash('Please select the action you wish to apply ' +
                                      'and the users you wish to apply it to', queue='error')
                raise HTTPSeeOther(request.route_url('part.users', pid=part.id, _query=query_params))
            crumbs = create_part_crumbs(request,
                                        part,
                                        [{'title': 'Users',
                                         'url': request.route_url('part.users', pid=part.id)},
                                         {'title': 'Update',
                                          'url': request.current_route_url()}])
            users = dbsession.query(UserPartRole).filter(UserPartRole.id.in_(params['role_id'])).all()
            return {'part': part,
                    'params': params,
                    'query_params': query_params,
                    'users': users,
                    'crumbs': crumbs,
                    'help': ['user', 'teacher', 'module', 'users.html']}
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 11
0
def admin(request):
    """Handles the ``/admin`` URL, displaying all available administrative
    functions.
    """
    if request.current_user.has_permission('admin'):
        return {
            'crumbs': [{
                'title': 'Administration',
                'url': request.current_route_url(),
                'current': True
            }]
        }
    else:
        raise unauthorised_redirect(request)
Ejemplo n.º 12
0
def view(request):
    """Handles the "/users/{uid}" URL, showing the user's profile.
    """
    dbsession = DBSession()
    user = dbsession.query(User).filter(
        User.id == request.matchdict['uid']).first()
    if user:
        if user.allow('view', request.current_user):
            return {
                'user':
                user,
                'crumbs':
                create_user_crumbs(
                    request,
                    [{
                        'title': user.display_name,
                        'url': request.route_url('user.view', uid=user.id)
                    }]),
                'help': ['user', 'user', 'profile.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 13
0
def content_regenerate(request):
    """Handles the ``/admin/content/regenerate`` URL, regenerating the
    ``compiled_content`` attribute for all :class:`~wte.models.Part`\ s.
    """
    if request.current_user.has_permission('admin.modules.edit'):
        if request.method == 'POST':
            dbsession = DBSession()
            with transaction.manager:
                for part in dbsession.query(Part):
                    if part.content:
                        part.compiled_content = compile_rst(
                            part.content, request, part)
            request.session.flash('Regeneration complete', queue='info')
        raise HTTPSeeOther(request.route_url('admin.content'))
    else:
        raise unauthorised_redirect(request)
Ejemplo n.º 14
0
def content_admin(request):
    """Handles the ``/admin/content`` URL, displaying all available administrative
    functions related to the content administrations.
    """
    if request.current_user.has_permission('admin.modules.view'):
        return {
            'crumbs': [{
                'title': 'Administration',
                'url': request.route_url('admin')
            }, {
                'title': 'Content',
                'url': request.current_route_url(),
                'current': True
            }]
        }
    else:
        raise unauthorised_redirect(request)
Ejemplo n.º 15
0
def content_list(request):
    """Handles the ``/admin/content/list`` URL providing administrative access
    to all :class:`~wte.models.Part`\ s.
    """
    if request.current_user.has_permission('admin.modules.view'):
        dbsession = DBSession()
        modules = dbsession.query(Part).filter(Part.parent_id == None)
        try:
            start = int(request.params['start'])
        except:
            start = 0
        if 'q' in request.params and request.params['q']:
            modules = modules.filter(Part.title.contains(request.params['q']))
        if 'status' in request.params and request.params['status']:
            modules = modules.filter(Part.status == request.params['status'])
        pages = paginate(request, 'admin.content.list', modules, start, 25)
        modules = modules.offset(start).limit(25)
        return {
            'modules':
            modules,
            'pages':
            pages,
            'crumbs': [{
                'title': 'Administration',
                'url': request.route_url('admin')
            }, {
                'title': 'Content',
                'url': request.route_url('admin.content')
            }, {
                'title': 'All Modules',
                'url': request.current_route_url(),
                'current': True
            }]
        }
    else:
        raise unauthorised_redirect(request)
Ejemplo n.º 16
0
def add(request):
    """Handles the ``parts/{pid}/users/add`` URL, providing the functionality for adding a
    :class:`~wte.models.User` to a :class:`~wte.models.Part`.

    Requires that the user has "users" 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('users', request.current_user):
            crumbs = create_part_crumbs(request,
                                        part,
                                        [{'title': 'Users',
                                         'url': request.route_url('part.users', pid=part.id)},
                                         {'title': 'Add',
                                          'url': request.current_route_url()}])
            users = None
            if 'q' in request.params:
                users = dbsession.query(User).outerjoin(UserPartRole).\
                    filter(or_(User.display_name.contains(request.params['q']),
                               User.email.contains(request.params['q']))).\
                    filter(User.id.notin_(dbsession.query(User.id).join(UserPartRole).
                                          join(Part).filter(Part.id == part.id)))
            start = 0
            if 'start' in request.params:
                try:
                    start = max(0, int(request.params['start']))
                except:
                    pass
            if users:
                total_users = users.count()
                users = users.offset(start).limit(20).all()
            else:
                total_users = 0
            pages = []
            if start == 0:
                pages.append({'type': 'prev'})
            else:
                pages.append({'type': 'prev',
                              'url': request.route_url('part.users',
                                                       pid=part.id,
                                                       _query=[('q', request.params['q']
                                                                if 'q' in request.params else ''),
                                                               ('start', max(start - 30, 0))])})
            for idx in range(0, int(math.ceil(total_users / 30.0))):
                if idx * 30 == start:
                    pages.append({'type': 'current',
                                  'label': idx + 1})
                else:
                    pages.append({'type': 'item',
                                  'label': idx + 1,
                                  'url': request.route_url('part.users',
                                                           pid=part.id,
                                                           _query=[('q', request.params['q']
                                                                    if 'q' in request.params else ''),
                                                                   ('start', idx * 30)])})
            if start + 30 >= total_users:
                pages.append({'type': 'next'})
            else:
                pages.append({'type': 'next',
                              'url': request.route_url('part.users',
                                                       pid=part.id,
                                                       _query=[('q', request.params['q']
                                                                if 'q' in request.params else ''),
                                                               ('start', start + 30)])})
            if request.method == 'POST':
                try:
                    params = AddUserSchema().to_python(request.params, State(request=request))
                    with transaction.manager:
                        dbsession.add(part)
                        for user_id in params['user_id']:
                            if not dbsession.query(UserPartRole).\
                                filter(and_(UserPartRole.part_id == part.id,
                                            UserPartRole.user_id == user_id)).first():
                                dbsession.add(UserPartRole(user_id=user_id,
                                                           part_id=part.id,
                                                           role=params['role']))
                    raise HTTPSeeOther(request.route_url('part.users', pid=request.matchdict['pid']))
                except formencode.api.Invalid as e:
                    e.params = request.params
                    return {'errors': e.error_dict,
                            'values': request.params,
                            'part': part,
                            'users': users,
                            'total_users': total_users,
                            'start': start,
                            'pages': pages,
                            'crumbs': crumbs,
                            'help': ['user', 'teacher', 'module', 'users.html']}
            return {'part': part,
                    'users': users,
                    'total_users': total_users,
                    'start': start,
                    'pages': pages,
                    'crumbs': crumbs,
                    'help': ['user', 'teacher', 'module', 'users.html']}
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 17
0
def users(request):
    """Handles the ``parts/{pid}/users`` URL, displaying the
    :class:`~wte.models.User` registered for a :class:`~wte.models.Part`.

    Requires that the user has "users" 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('users', request.current_user):
            crumbs = create_part_crumbs(request,
                                        part,
                                        {'title': 'Users',
                                         'url': request.current_route_url()})
            try:
                start = int(request.params['start']) if 'start' in request.params else 0
            except:
                start = 0
            query = dbsession.query(UserPartRole).join(UserPartRole.user, UserPartRole.part).\
                filter(Part.id == request.matchdict['pid'])
            query_params = []
            if 'role' in request.params:
                if request.params['role'] == 'active':
                    query = query.filter(UserPartRole.role != 'block')
                elif request.params['role']:
                    query = query.filter(UserPartRole.role == request.params['role'])
                    query_params.append(('role', request.params['role']))
            else:
                query = query.filter(UserPartRole.role != 'block')
            if 'q' in request.params and request.params['q']:
                query = query.filter(or_(User.display_name.contains(request.params['q']),
                                         User.email.contains(request.params['q'])))
                query_params.append(('q', request.params['q']))
            total_users = query.count()
            if total_users < start:
                start = 0
            if start >= 0:
                users = query.offset(start).limit(30)
            else:
                users = query
            pages = []
            if start == 0:
                pages.append({'type': 'prev'})
            else:
                pages.append({'type': 'prev',
                              'url': request.route_url('part.users',
                                                       pid=part.id,
                                                       _query=query_params + [('start', max(start - 30, 0))])})
            for idx in range(0, int(math.ceil(total_users / 30.0))):
                if idx * 30 == start:
                    pages.append({'type': 'current',
                                  'label': idx + 1})
                else:
                    pages.append({'type': 'item',
                                  'label': idx + 1,
                                  'url': request.route_url('part.users',
                                                           pid=part.id,
                                                           _query=query_params + [('start', idx * 30)])})
            if start + 30 >= total_users:
                pages.append({'type': 'next'})
            else:
                pages.append({'type': 'next',
                              'url': request.route_url('part.users',
                                                       pid=part.id,
                                                       _query=query_params + [('start', start + 30)])})
            current_page = max(0, start / 30)
            return {'part': part,
                    'users': users,
                    'pages': pages,
                    'current_page': current_page,
                    'total_users': total_users,
                    'crumbs': crumbs,
                    'help': ['user', 'teacher', 'module', 'users.html']}
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 18
0
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()
Ejemplo n.º 19
0
def edit(request):
    """Handles the ``/parts/{pid}/assets/{aid}/edit`` URL, providing
    the UI and backend for editing :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': 'Edit %s' % (asset.type.title()),
                    'url': request.current_route_url()
                })
            if request.method == 'POST':
                try:
                    params = EditAssetSchema().to_python(
                        request.params, State(request=request))
                    dbsession = DBSession()
                    with transaction.manager:
                        dbsession.add(asset)
                        asset.filename = params['filename']
                        if params['data'] is not None:
                            asset.data = params['data'].file.read()
                            asset.etag = hashlib.sha512(asset.data).hexdigest()
                            mimetype = guess_type(params['data'].filename)
                            if mimetype[0]:
                                mimetype = mimetype[0]
                            else:
                                if params['mimetype'] != 'other':
                                    mimetype = params['mimetype']
                                else:
                                    mimetype = params['mimetype_other']
                        elif params['content'] is not None:
                            asset.data = params['content'].encode('utf-8')
                            asset.etag = hashlib.sha512(asset.data).hexdigest()
                            if params['mimetype'] != 'other':
                                mimetype = params['mimetype']
                            else:
                                mimetype = params['mimetype_other']
                        else:
                            if params['mimetype'] != 'other':
                                mimetype = params['mimetype']
                            else:
                                mimetype = params['mimetype_other']
                        asset.mimetype = mimetype
                    dbsession.add(part)
                    dbsession.add(asset)
                    raise HTTPSeeOther(
                        request.route_url('part.view', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'asset': asset,
                        'crumbs': crumbs,
                        'help': ['user', 'teacher', 'asset', 'edit.html']
                    }
            return {
                'part': part,
                'asset': asset,
                'crumbs': crumbs,
                'help': ['user', 'teacher', 'asset', 'edit.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 20
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()
Ejemplo n.º 21
0
def update(request):
    """Handles the ``parts/{pid}/users`` URL, applying the changes select when the
    user views :func:`~wte.views.user_role.action`.

    Requires that the user has "users" rights on the
    :class:`~wte.models.Part`.
    """
    dbsession = DBSession()
    dbsession.add(request.current_user)
    part = dbsession.query(Part).filter(Part.id == request.matchdict['pid']).first()
    if part:
        if part.allow('users', request.current_user):
            query_params = []
            for param in ['q', 'role', 'start']:
                if param in request.params and request.params[param]:
                    query_params.append((param, request.params[param]))
            try:
                crumbs = create_part_crumbs(request,
                                            part,
                                            [{'title': 'Users',
                                              'url': request.route_url('part.users', pid=part.id)},
                                             {'title': 'Update',
                                              'url': request.current_route_url()}])
                users = []
                params = {}
                params = ActionSchema().to_python(request.params,
                                                  State(request=request))
                users = dbsession.query(UserPartRole).filter(UserPartRole.id.in_(params['role_id'])).all()
                if params['action'] == 'change_role':
                    params = ChangeRoleSchema().to_python(request.params, State(request=request))
                    with transaction.manager:
                        for role in users:
                            dbsession.add(role)
                            role.role = params['role']
                    raise HTTPSeeOther(request.route_url('part.users', pid=request.matchdict['pid'],
                                                         _query=query_params))
                elif params['action'] == 'remove':
                    schema = CSRFSchema()
                    schema.allow_extra_fields = True
                    schema.to_python(request.params, State(request=request))
                    with transaction.manager:
                        dbsession.add(part)
                        parts = get_all_parts(part)
                        for role in users:
                            dbsession.add(role)
                            for child_part in parts:
                                progress = dbsession.query(UserPartProgress).\
                                    filter(and_(UserPartProgress.part_id == child_part.id,
                                                UserPartProgress.user_id == role.user.id)).first()
                                if progress:
                                    dbsession.delete(progress)
                            dbsession.delete(role)
                    raise HTTPSeeOther(request.route_url('part.users', pid=request.matchdict['pid'],
                                                         _query=query_params))
                elif params['action'] == 'block':
                    schema = CSRFSchema()
                    schema.allow_extra_fields = True
                    schema.to_python(request.params, State(request=request))
                    with transaction.manager:
                        for role in users:
                            dbsession.add(role)
                            role.role = 'block'
                    raise HTTPSeeOther(request.route_url('part.users', pid=request.matchdict['pid'],
                                                         _query=query_params))
            except formencode.api.Invalid as e:
                return {'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'params': params,
                        'query_params': query_params,
                        'users': users,
                        'crumbs': crumbs,
                        'help': ['user', 'teacher', 'module', 'users.html']}
            return {'part': part,
                    'params': params,
                    'query_params': query_params,
                    'users': users,
                    'crumbs': crumbs,
                    'help': ['user', 'teacher', 'module', 'users.html']}
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()
Ejemplo n.º 22
0
def new(request):
    """Handles the ``/parts/{pid}/assets/new/{new_type}`` URL, providing the UI and
    backend for creating a new :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()
    if part:
        if part.allow('edit', request.current_user):
            crumbs = create_part_crumbs(
                request, part, {
                    'title': 'Add %s' %
                    (request.matchdict['new_type'].title()),
                    'url': request.current_route_url()
                })
            if request.method == 'POST':
                try:
                    schema = NewAssetSchema()
                    if request.matchdict['new_type'] == 'asset':
                        schema.fields['data'].not_empty = True
                    params = schema.to_python(request.params,
                                              State(request=request))
                    if not params['filename'] and params['data'] is None:
                        raise formencode.Invalid(
                            'You must specify either a file or filename',
                            None,
                            None,
                            error_dict={
                                'filename':
                                'You must specify either a file or filename',
                                'data':
                                'You must specify either a file or filename'
                            })
                    dbsession = DBSession()
                    progress = get_user_part_progress(dbsession,
                                                      request.current_user,
                                                      part)
                    with transaction.manager:
                        dbsession.add(part)
                        if progress:
                            dbsession.add(progress)
                        mimetype = 'application/binary'
                        if params['filename'] is not None:
                            mimetype = guess_type(params['filename'])
                        if params['data'] is not None:
                            mimetype = guess_type(params['data'].filename)
                            if params['filename'] is None:
                                params['filename'] = params['data'].filename
                        if request.matchdict['new_type'] == 'template':
                            new_order = [a.order for a in part.templates]
                        elif request.matchdict['new_type'] == 'asset':
                            new_order = [a.order for a in part.assets]
                        elif request.matchdict['new_type'] == 'file':
                            new_order = [a.order for a in progress.files
                                         ] if progress else []
                        new_order.append(0)
                        new_order = max(new_order) + 1
                        new_asset = Asset(
                            filename=params['filename'],
                            mimetype=mimetype[0]
                            if mimetype[0] else 'application/binary',
                            type=request.matchdict['new_type'],
                            order=new_order,
                            data=params['data'].file.read()
                            if params['data'] is not None else None,
                            etag=hashlib.sha512(
                                params['data'].file.read()).hexdigest()
                            if params['data'] is not None else None)
                        dbsession.add(new_asset)
                        part.all_assets.append(new_asset)
                    if request.is_xhr:
                        request.override_renderer = 'json'
                        dbsession.add(new_asset)
                        dbsession.add(part)
                        return {
                            'part': {
                                'id': part.id
                            },
                            'asset': {
                                'id': new_asset.id,
                                'filename': new_asset.filename
                            }
                        }
                    else:
                        dbsession.add(part)
                        raise HTTPSeeOther(
                            request.route_url('part.view', pid=part.id))
                except formencode.Invalid as e:
                    return {
                        'errors': e.error_dict,
                        'values': request.params,
                        'part': part,
                        'crumbs': crumbs,
                        'help': ['user', 'teacher', 'asset', 'new.html']
                    }
            return {
                'part': part,
                'crumbs': crumbs,
                'help': ['user', 'teacher', 'asset', 'new.html']
            }
        else:
            unauthorised_redirect(request)
    else:
        raise HTTPNotFound()