示例#1
0
    def __init__(self, *args, **kw):
        # /event/url/submissions
        self.event = kw.get('event', None)
        # /event/url/lesson/id/submissions
        self.lesson = kw.get('lesson', None)
        # /event/url/sheet/id/assignment/id/submissions
        self.assignment = kw.get('assignment', None)
        # /event/url/sheet/id/submissions
        self.sheet = kw.get('sheet', None)
        if self.event:
            pass
        elif self.lesson:
            self.event = self.lesson.event
        elif self.assignment:
            self.event = self.assignment.sheet.event
        elif self.sheet:
            self.event = self.sheet.event
        else:
            log.warn('SubmissionController without any filter')
            flash('You can not view Submissions without any constraint.', 'error')
            abort(400)

        # Allow access for event teacher and lesson teacher
        self.allow_only = Any(
            has('teachers', self.event),
            has('tutors', self.lesson),
#             has_teacher(self.event),
#             has_teachers(self.event),
#             has_teacher(self.lesson),
            has_permission('manage'),
            msg=u'You have no permission to manage this Lesson'
        )

        self.table = SubmissionTable(DBSession)
        self.table_filler = SubmissionTableFiller(DBSession, lesson=self.lesson)
示例#2
0
    def __init__(self, event):
        self.event = event

        self.allow_only = Any(
            user_is_in('teachers', self.event),
            user_is_in('tutors', self.event),
            has_permission('manage'),
            msg=u'You have no permission to manage Lessons for this Event')
示例#3
0
    def __init__(self, sheet):
        self.sheet = sheet
        self.event = sheet.event
        self.assignments = AssignmentsController(sheet=self.sheet)
        c.sheet = self.sheet

        self.allow_only = Any(is_public(self.sheet),
                              user_is_in('teachers', self.event),
                              user_is_in('tutors', self.event),
                              has_permission('manage'),
                              msg=u'This Sheet is not public')

        self.submissions = SubmissionsController(sheet=self.sheet)
示例#4
0
    def __init__(self, assignment):
        self.assignment = assignment
        self.sheet = assignment.sheet
        self.event = self.sheet.event
        c.assignment = self.assignment

        self.allow_only = Any(is_public(self.assignment),
                              user_is_in('teachers', self.event),
                              user_is_in('tutors', self.event),
                              has_permission('manage'),
                              msg=u'This Assignment is not public')

        self.submissions = SubmissionsController(assignment=self.assignment)
        self.similarity = SimilarityController(assignment=self.assignment)
示例#5
0
    def __init__(self, event):
        self.event = event
        self.sheets = SheetsController(event=self.event)
        self.lessons = LessonsController(event=self.event)
        self.admin = EventAdminController(event=self.event)
        c.event = self.event

        self.allow_only = Any(
            is_public(self.event),
            has_teacher(self.event),
            has_permission('manage'),
            msg=u'This Event is not public'
        )

        c.sub_menu = menu(self.event, True)
示例#6
0
    def __init__(self, submission):

        self.submission = submission
        self.assignment = submission.assignment
        self.event = self.assignment.event

        predicates = (user_is_in('tutors', l) for l in submission.lessons)
        self.allow_only = Any(
            is_public(submission),
            user_is('user', self.submission),
            user_is_in('team', self.submission),
            user_is_in('teachers', self.event),
            has_permission('manage'),
            msg=u'You are not allowed to view this submission',
            *predicates
        )
示例#7
0
    def __init__(self, assignment):
        self.assignment = assignment
        self.submissions = sorted((s for s in self.assignment.submissions if s.source),
            key=lambda s: s.id)

        self.key = str(self.assignment.id)
        if self.submissions:
            self.key += '_' + '-'.join(str(s.id) for s in self.submissions)
            self.key += '_' + (max(self.submissions, key=lambda s: s.modified)
                .modified.strftime('%Y-%m-%d-%H-%M-%S'))

        self.allow_only = Any(
            user_is_in('teachers', self.assignment.sheet.event),
            user_is_in('tutors', self.assignment.sheet.event),
            has_permission('manage'),
            msg=u'You are not allowed to access this page.'
        )
示例#8
0
    def __init__(self, event, **kwargs):
        self.event = event

        menu_items = OrderedDict((
            ('./events/', 'Event'),
            ('./tutors/', 'Tutors'),
            ('./lessons/', 'Lessons'),
            ('./teams/', 'Teams'),
            ('./students/', 'Students'),
            ('./sheets/', 'Sheets'),
            ('./assignments/', 'Assignments'),
            ('./tests/', 'Tests'),
            ('./newsitems/', 'NewsItems'),
        ))
        self.menu_items = menu_items

        super(EventAdminController, self).__init__(**kwargs)

        self.events = EventsCrudController(
            inject=dict(teacher=request.user),
            query_modifier=lambda qry: qry.filter_by(id=self.event.id),
            menu_items=self.menu_items,
            allow_new=False,
            allow_delete=False,
            **kwargs)

        self.lessons = LessonsCrudController(
            inject=dict(event=self.event),
            query_modifier=lambda qry: qry.filter_by(event_id=self.event.id),
            query_modifiers={
                # Disabled so that the teacher can assign any users as tutors
                #'tutor': lambda qry: qry.filter(User.id.in_((t.id for t in self.event.tutors))),
                'teams':
                lambda qry: qry.join(Team.lesson).filter_by(event_id=self.event
                                                            .id),
            },
            menu_items=self.menu_items,
            **kwargs)

        self.teams = TeamsCrudController(
            #query_modifier=lambda qry: qry.filter(Team.lesson_id.in_((l.id for l in self.event.lessons))),
            query_modifier=lambda qry: qry.join(Team.lesson).filter_by(
                event_id=self.event.id),
            query_modifiers={
                'lesson': lambda qry: qry.filter_by(event_id=self.event.id),
                # Disabled so that the teacher can assign any users as members
                #'members': lambda qry: qry.filter(User.id.in_((u.id for u in self.lesson.event.members))),
            },
            menu_items=self.menu_items,
            hints=dict(event=self.event),
            **kwargs)

        self.students = StudentsCrudController(
            query_modifier=lambda qry: qry.select_from(
                union(
                    qry.join(event_members).join(Event).filter_by(
                        id=self.event.id).order_by(None),
                    qry.join(lesson_members).join(Lesson).filter_by(
                        event_id=self.event.id).order_by(None),
                    qry.join(team_members).join(Team).join(Lesson).filter_by(
                        event_id=self.event.id).order_by(None),
                )).order_by(User.user_name),
            query_modifiers={
                #'teams': lambda qry: qry.filter(Team.lesson_id.in_((l.id for l in self.event.lessons))),
                'teams':
                lambda qry: qry.join(Team.lesson).filter_by(event_id=self.event
                                                            .id),
                '_lessons':
                lambda qry: qry.filter_by(event_id=self.event.id),
            },
            menu_items=self.menu_items,
            hints=dict(event=self.event),
            **kwargs)

        self.tutors = TutorsCrudController(
            query_modifier=lambda qry: (qry.join(lesson_tutors).join(
                Lesson).filter_by(event_id=self.event.id).order_by(User.id)),
            query_modifiers={
                'tutored_lessons':
                lambda qry: qry.filter_by(event_id=self.event.id),
            },
            menu_items=self.menu_items,
            hints=dict(event=self.event),
            **kwargs)

        self.sheets = SheetsCrudController(
            inject=dict(event=self.event, _teacher=request.user),
            query_modifier=lambda qry: qry.filter_by(event_id=self.event.id),
            menu_items=self.menu_items,
            **kwargs)

        self.assignments = AssignmentsCrudController(
            inject=dict(_teacher=request.user),
            query_modifier=lambda qry: qry.join(Assignment.sheet).filter_by(
                event_id=self.event.id),
            query_modifiers={
                'sheet': lambda qry: qry.filter_by(event_id=self.event.id),
            },
            menu_items=self.menu_items,
            **kwargs)

        self.tests = TestsCrudController(
            inject=dict(user=request.user),
            query_modifier=lambda qry: (qry.join(Test.assignment).join(
                Assignment.sheet).filter_by(event_id=self.event.id)),
            query_modifiers={
                'assignment':
                lambda qry: qry.join(Assignment.sheet).filter_by(event_id=self.
                                                                 event.id),
            },
            menu_items=self.menu_items,
            **kwargs)

        self.newsitems = NewsItemController(
            inject=dict(user=request.user),
            query_modifier=lambda qry: qry.filter(
                or_(NewsItem.event == None, NewsItem.event == self.event)),
            query_modifiers={
                'event': lambda qry: qry.filter_by(id=self.event.id),
            },
            menu_items=self.menu_items,
            **kwargs)

        self.allow_only = Any(
            user_is_in('teachers', self.event),
            has_permission('manage'),
            msg=u'You have no permission to manage this Event')
示例#9
0
class AdminController(ServiceController):
    """
        The admin controller is a central point for
        adminstrative tasks such as monitoring, data, user management, etc.
    """
    service_type = "admin"

    allow_only = Any(in_group("admin"), in_group('admins'))
    #allow_only = is_user('admin')

    #admin = BisqueAdminController([User, Group], DBSession)
    @expose("bq.admin_service.templates.manager")
    def manager(self):
        return dict()

    @expose(content_type='text/xml')
    def _default(self, *arg, **kw):
        """
            Returns some command information
        """
        log.info('admin/index')
        index_xml = etree.Element('resource', uri=str(request.url))
        users_xml = etree.SubElement(index_xml,
                                     'command',
                                     name='user',
                                     value='Lists all the users')
        users_xml = etree.SubElement(index_xml,
                                     'command',
                                     name='user/RESOURCE_UNIQ',
                                     value='Lists the particular user')
        users_xml = etree.SubElement(index_xml,
                                     'command',
                                     name='user/RESOURCE_UNIQ/login',
                                     value='Log in as user')

        etree.SubElement(index_xml,
                         'command',
                         name='notify_users',
                         value='sends message to all users')
        etree.SubElement(index_xml,
                         'command',
                         name='message_variables',
                         value='returns available message variables')
        return etree.tostring(index_xml)

    @expose(content_type='text/xml')
    def notify_users(self, *arg, **kw):
        """
          Sends message to all system users
        """
        log.info("notify_users")
        if request.method.upper() == 'POST' and request.body is not None:
            try:
                resource = etree.fromstring(request.body)
                message = resource.find('tag[@name="message"]').get('value')
                userlist = resource.find('tag[@name="users"]').get('value')
                self.do_notify_users(userlist, message)
                return '<resource type="message" value="sent" />'
            except Exception:
                log.exception("processing message")
                return abort(400, 'Malformed request document')

        abort(400, 'The request must contain message body')

    @expose(content_type='text/xml')
    def message_variables(self, **kw):
        """
          Sends message to all system users
        """
        log.info("message_variables")
        variables = self.get_variables()
        resp = etree.Element('resource', name='message_variables')
        for n, v in variables.iteritems():
            etree.SubElement(resp, 'tag', name=n, value=v)
        return etree.tostring(resp)

    def add_admin_info2node(self, user_node, view=None):
        """
            adds email and password tags and remove the email value
        """
        if view and 'short' not in view:
            tg_user = User.by_user_name(user_node.get('name'))
            email = user_node.attrib.get('value', '')
            etree.SubElement(user_node, 'tag', name='email', value=email)
            if tg_user is None:
                log.error("No tg_user was found for %s", user_node.get('name'))
            else:
                if 'password' in view:
                    password = tg_user.password
                else:
                    password = '******'
                etree.SubElement(user_node,
                                 'tag',
                                 name='password',
                                 value=password)
                etree.SubElement(user_node,
                                 'tag',
                                 name="groups",
                                 value=",".join(g.group_name
                                                for g in tg_user.groups
                                                if tg_user))
                etree.SubElement(user_node,
                                 'tag',
                                 name='user_name',
                                 value=tg_user.user_name)

        #try to remove value from user node
        user_node.attrib.pop('value', None)

        return user_node

    #@expose(content_type='text/json')
    @expose()
    def loggers(self, *arg, **kw):
        """
        Set logging level dynamically
        post /admin/loggers
        """
        view = kw.pop('view', 'short')
        fmt = kw.pop('format', 'xml')
        #filter = kw.pop ('filter', 'bq.')
        if fmt == 'json':
            response.headers['Content-Type'] = 'text/json'
        elif fmt == 'xml':
            response.headers['Content-Type'] = 'text/xml'

        if request.method == 'GET':
            loggers = [
                {
                    'name': ln,
                    'level': logging.getLevelName(lv.level)
                } for ln, lv in logging.Logger.manager.loggerDict.items()
                if hasattr(lv, 'level')  #and lv.level != logging.NOTSET
            ]

            # filter and sort loggers
            loggers.sort(key=lambda x: x['name'])

            if fmt == 'json':
                return json.dumps(loggers)
            elif fmt == 'xml':
                xml = etree.Element('resource',
                                    name='loggers',
                                    uri='/admin/loggers')
                for l in loggers:
                    etree.SubElement(xml,
                                     'logger',
                                     name=l.get('name'),
                                     value=l.get('level'))
                return etree.tostring(xml)

        elif request.method in ('POST', 'PUT'):

            if request.headers['Content-Type'] == 'text/json':
                loggers = json.loads(request.body)
            else:
                xml = etree.fromstring(request.body)
                loggers = [{
                    'name': l.get('name'),
                    'level': l.get('value')
                } for l in xml.xpath('logger')]

            for l in loggers:
                ln = l.get('name')
                lv = l.get('level')
                log.debug("Changing log level of %s to %s", ln, lv)
                lg = logging.getLogger(ln)
                lg.setLevel(lv)
            return ""

    @expose()
    def logs(self, *arg, **kw):
        """
        get /admin/logs/config or /admin/logs - log config, this will return a local or a remote url
        get /admin/logs/read - read local log lines, by default 1000 last lines
        get /admin/logs/read/172444095 - read local log lines starting from a given time stamp
        """

        # TODO dima: add timestamp based read

        #log.info ("STARTING table (%s): %s", datetime.now().isoformat(), request.url)
        path = request.path_qs.split('/')
        path = [unquote(p) for p in path if len(p) > 0]
        operation = path[2] if len(path) > 2 else ''

        log_url = config.get('bisque.logger')

        if operation == 'config' or operation == '':
            # dima: here we have to identify what kind of logs we are using
            if log_url is not None:
                log_url = urlutil.urljoin(request.url, log_url)
                xml = etree.Element('log',
                                    name='log',
                                    uri=log_url,
                                    type='remote')
            else:
                xml = etree.Element('log',
                                    name='log',
                                    uri='/admin/logs/read',
                                    type='local')
            response.headers['Content-Type'] = 'text/xml'
            return etree.tostring(xml)
        elif operation == 'read':
            # dima, this will only work for local logger
            if log_url is not None:
                redirect(log_url)
            try:
                fn = logging.getLoggerClass().root.handlers[0].stream.filename
                logs = tail(fn, 1000)
                response.headers['Content-Type'] = 'text/plain'
                return ''.join(logs)
            except Exception:
                abort(500, 'Error while reading the log')
        abort(400, 'not a supported operation')

    @expose(content_type='text/xml')
    def cache(self, *arg, **kw):
        """
            Deletes system cache

            DELETE cache
        """
        if request.method == 'DELETE':
            return self.clearcache()
        return '<resource/>'

    @expose(content_type='text/xml')
    def user(self, *arg, **kw):
        """
            Main user expose

            Merges the shadow user with the normal user for admins easy access to the password
            columns

            GET user: returns list of all users in xml info see get_all_users for format

            GET user/uniq: returns user in xml info see get_user for format

            GET user/uniq/login: logins in the admin as the user resource provided

            POST user: creates new user, see post_user for format

            PUT user/uniq: update info on user see put_user for format

            DELETE user/uniq: deletes user, see delete user for format

            DELETE user/uniq/image
                Deletes only the users image data and not the user itself
        """
        http_method = request.method.upper()

        if len(arg) == 1:
            if http_method == 'GET':
                return self.get_user(arg[0], **kw)
            elif http_method == 'PUT':
                if request.body:
                    return self.put_user(arg[0], request.body, **kw)
            elif request.method == 'DELETE':
                return self.delete_user(arg[0])
            else:
                abort(400)
        elif len(arg) == 2:
            if arg[1] == 'login':
                if http_method == 'GET':
                    return self.loginasuser(arg[0])
            elif arg[1] == 'image':
                if http_method == 'DELETE':
                    uniq = arg[0]
                    bquser = data_service.resource_load(uniq=uniq)
                    #bquser = DBSession.query(BQUser).filter(BQUser.resource_uniq == uniq).first()
                    if bquser:
                        self.deleteimages(bquser.get('name'),
                                          will_redirect=False)
                        return '<resource name="delete_images" value="Successful">'
                    else:
                        abort(404)
        else:
            if http_method == 'GET':
                return self.get_all_users(*arg, **kw)
            elif http_method == 'POST':
                if request.body:
                    return self.post_user(request.body, **kw)
        abort(400)

    def get_all_users(self, *arg, **kw):
        """
            Returns a list of all users in xml with password and diplay name.
            (Note: may be removed in version 0.6 due to redundant functionality
            of data_service)

            Limited command support, does not have view=deep,clean..

            document format:
                <resource>
                    <user name="user" owner="/data_service/00-aYnhJQA5BJVm4GDpuexc2G" permission="published"
                    resource_uniq="00-aYnhJQA5BJVm4GDpuexc2G" ts="2015-01-30T02:23:18.414000" uri="admin/user/00-aYnhJQA5BJVm4GDpuexc2G">
                        <tag name="email" value="*****@*****.**"/>
                        <tag name="display_name" value="user"/>
                    </user>
                    <user>...
                </resource>
        """

        kw['wpublic'] = 1
        users = data_service.query(resource_type='user', **kw)
        view = kw.pop('view', None)
        resource = etree.Element('resource', uri=str(request.url))
        for u in users:
            user = self.add_admin_info2node(u, view)
            resource.append(user)
        return etree.tostring(resource)

    def get_user(self, uniq, **kw):
        """
            Returns requested user in xml with password and diplay name.
            (Note: may be removed in version 0.6 due to redundant functionality
            of data_service)

            document format:
                <user name="user" owner="/data_service/00-aYnhJQA5BJVm4GDpuexc2G" permission="published"
                resource_uniq="00-aYnhJQA5BJVm4GDpuexc2G" ts="2015-01-30T02:23:18.414000" uri="/data_service/00-aYnhJQA5BJVm4GDpuexc2G">
                    <tag name="email" value="*****@*****.**"/>
                    <tag name="display_name" value="user"/>
                    <tag name="password" value="******"/> //everything will be served in plan text no password will be returned
                    ...
                </user>
        """
        view = kw.pop('view', 'short')
        user = data_service.resource_load(uniq, view=view)
        if user is not None and user.tag == 'user':
            user = self.add_admin_info2node(user, view)
            return etree.tostring(user)
        else:
            abort(403)

    def _update_groups(self, tg_user, groups):
        """
        @param tg_user : a tg User
        @param a list of group names
        """
        tg_user.groups = []
        for grp_name in groups:
            if not grp_name:
                continue
            grp = DBSession.query(Group).filter_by(group_name=grp_name).first()
            if grp is None:
                log.error("Unknown group %s used ", grp_name)
                continue
            tg_user.groups.append(grp)
        log.debug("updated groups %s", tg_user.groups)

    def post_user(self, doc, **kw):
        """
            Creates new user with tags, the owner of the tags is assigned to the user

            document format:
                <user name="user">
                    <tag name="password" value="12345"/>
                    <tag name="email" value="*****@*****.**"/>
                    <tag name="display_name" value="user"/>
                </user>
        """
        userxml = etree.fromstring(doc)
        required_tags = ['user_name', 'password', 'email', 'display_name']
        tags = {}
        if userxml.tag == 'user':
            user_name = userxml.attrib['name']
            if user_name:
                tags['user_name'] = user_name
                for t in userxml.xpath('tag'):
                    tags[t.get('name')] = t.get('value')
                    #if (t.attrib['name']=='password') or (t.attrib['name']=='email'):
                    if t.get('name') in REMOVE_TAGS:
                        t.getparent().remove(t)  #removes email and password
                        if t.attrib['name'] == 'email':
                            userxml.attrib['value'] = t.attrib[
                                'value']  #set it as value of the user
                if all(k in tags for k in required_tags):
                    log.debug("ADMIN: Adding user: %s", str(user_name))
                    u = User(user_name=tags['user_name'],
                             password=tags['password'],
                             email_address=tags['email'],
                             display_name=tags['display_name'])
                    DBSession.add(u)
                    self._update_groups(u, tags.get('groups', '').split(','))
                    try:
                        transaction.commit()
                    except IntegrityError:
                        abort(
                            405,
                            'Another user already has this user name or email address'
                        )
                    #r = BQUser.query.filter(BQUser.resource_name == tags['user_name']).first()
                    r = data_service.query(resource_type='user',
                                           name=tags['user_name'],
                                           wpublic=1)
                    if len(r) > 0:
                        admin = get_username()  #get admin user
                        set_current_user(
                            tags['user_name']
                        )  #change document as user so that all changes are owned by the new user
                        r = data_service.update_resource(
                            '/data_service/%s' %
                            r[0].attrib.get('resource_uniq'),
                            new_resource=userxml)
                        set_current_user(admin)  #set back to admin user
                        return self.get_user(
                            '%s' % r.attrib.get('resource_uniq'), **kw)
                    else:
                        abort(400)
        abort(400)

    def put_user(self, uniq, doc, **kw):
        """
            update user

            @param: uniq - resource uniq for the user
            @param: doc - document in the format shown below

            document format:
                <user name="user" resource_uniq="00-1235218954">
                    <tag name="password" value="12345"/> or <tag name="password" value="******"/>
                    <tag name="email" value="*****@*****.**"/>
                    <tag name="display_name" value="user"/>
                </user>
        """
        userxml = etree.fromstring(doc)
        required_tags = ['user_name', 'password', 'email', 'display_name']
        tags = {}
        if userxml.tag == 'user':
            user_name = userxml.attrib.get('name')
            if user_name:
                #tags['user_name'] = user_name
                for t in userxml.xpath('tag'):
                    tags[t.get('name')] = t.get('value')
                    #if t.attrib['name'] == 'password' or t.attrib['name']=='email':
                    if t.get('name') in REMOVE_TAGS:
                        t.getparent().remove(t)  #removes email and password
                        if t.attrib['name'] == 'email':
                            userxml.attrib['value'] = t.attrib.get(
                                'value')  #set it as value of the user

                if all(k in tags for k in required_tags
                       ):  #checks to see if all required tags are present
                    #update tg_user
                    #tg_user = DBSession.query(User).filter(User.user_name == tags.get('user_name')).first()
                    #tg_user = User.by_user_name(tags.get('user_name'))
                    tg_user = User.by_user_name(user_name)
                    if not tg_user:
                        log.debug(
                            'No user was found with name of %s. Please check core tables?',
                            user_name)
                        abort(404)
                    #reset values on tg user
                    tg_user.email_address = tags.get("email",
                                                     tg_user.email_address)

                    if tags['password'] and tags['password'].count('*') != len(
                            tags['password']
                    ):  #no password and ***.. not allowed passwords
                        tg_user.password = tags.get(
                            "password", tg_user.password
                        )  #just set it as itself if nothing is provided
                    #else:
                    #    tags.pop("password", None) #remove the invalid password

                    tg_user.display_name = tags.get("display_name",
                                                    tg_user.display_name)
                    self._update_groups(tg_user,
                                        tags.get('groups', '').split(','))
                    if tags.get('user_name') != user_name:
                        tg_user.user_name = tags.get('user_name')
                        userxml.set('name', tags['user_name'])
                    #del tags['user_name']

                    log.debug("ADMIN: Updated user: %s", str(user_name))
                    transaction.commit()
                    ### ALL loaded variables are detached

                    #userxml.attrib['resource_uniq'] = r.attrib['resource_uniq']
                    #reset BQUser
                    admin = get_username()  #get admin user
                    set_current_user(
                        tags['user_name']
                    )  #change document as user so that all changes are owned by the new user
                    r = data_service.update_resource(resource=userxml,
                                                     new_resource=userxml,
                                                     replace=True)
                    log.debug("Sent XML %s", etree.tostring(userxml))
                    set_current_user(admin)  #set back to admin user
                    #DBSession.flush()
                    return self.get_user(r.attrib['resource_uniq'], **kw)
        abort(400)

    def delete_user(self, uniq):
        """
            Deletes user

            @param uniq - resource uniq for the user

        """
        # Remove the user from the system for most purposes, but
        # leave the id for statistics purposes.
        bquser = DBSession.query(BQUser).filter(
            BQUser.resource_uniq == uniq).first()
        if bquser:
            log.debug("ADMIN: Deleting user: %s", str(bquser))
            user = DBSession.query(User).filter(
                User.user_name == bquser.resource_name).first()
            log.debug("Renaming internal user %s", str(user))

            if user:
                DBSession.delete(user)
                # delete the access permission
                for p in DBSession.query(TaggableAcl).filter_by(
                        user_id=bquser.id):
                    log.debug("KILL ACL %s", str(p))
                    DBSession.delete(p)
                self.deleteimages(bquser.resource_name, will_redirect=False)
                #DBSession.delete(bquser)

                #transaction.commit()
            data_service.del_resource(bquser)
            return '<resource>Delete User</resource>'

        abort(400)

    def deleteimage(self, imageid=None, **kw):
        log.debug("image: %s ", str(imageid))
        image = DBSession.query(Image).filter(Image.id == imageid).first()
        DBSession.delete(image)
        transaction.commit()
        redirect(request.headers.get("Referer", "/"))

    def deleteuser(self, username=None, **kw):
        #DBSession.autoflush = False

        # Remove the user from the system for most purposes, but
        # leave the id for statistics purposes.
        user = DBSession.query(User).filter(User.user_name == username).first()
        log.debug("Renaming internal user %s", str(user))
        if user:
            DBSession.delete(user)
            #user.display_name = ("(R)" + user.display_name)[:255]
            #user.user_name = ("(R)" + user.user_name)[:255]
            #user.email_address = ("(R)" + user.email_address)[:16]

        user = DBSession.query(BQUser).filter(
            BQUser.resource_name == username).first()
        log.debug("ADMIN: Deleting user: %s", str(user))
        # delete the access permission
        for p in DBSession.query(TaggableAcl).filter_by(user_id=user.id):
            log.debug("KILL ACL %s", str(p))
            DBSession.delete(p)
        #DBSession.flush()

        self.deleteimages(username, will_redirect=False)
        DBSession.delete(user)
        transaction.commit()
        redirect('/admin/users')

    def deleteimages(self, username=None, will_redirect=True, **kw):
        user = DBSession.query(BQUser).filter(
            BQUser.resource_name == username).first()
        log.debug("ADMIN: Deleting all images of: %s", str(user))
        images = DBSession.query(Image).filter(Image.owner_id == user.id).all()
        for i in images:
            log.debug("ADMIN: Deleting image: %s", str(i))
            DBSession.delete(i)
        if will_redirect:
            transaction.commit()
            redirect('/admin/users')
        return dict()

    def loginasuser(self, uniq):
        log.debug('forcing login as user')
        user = DBSession.query(BQUser).filter(
            BQUser.resource_uniq == uniq).first()
        if user:
            response.headers = request.environ['repoze.who.plugins'][
                'friendlyform'].remember(request.environ,
                                         {'repoze.who.userid': user.name})
            redirect("/client_service")
        else:
            abort(404)

    def clearcache(self):
        log.info("CLEARING CACHE")

        def clearfiles(folder):
            for the_file in os.listdir(folder):
                file_path = os.path.join(folder, the_file)
                try:
                    if os.path.isfile(file_path):
                        os.unlink(file_path)
                except OSError as e:
                    log.debug("unlinking failed: %s", file_path)
                except Exception as e:
                    log.exception('while removing %s' % file_path)

        server_cache = data_path('server_cache')
        clearfiles(server_cache)
        log.info("CLEARED CACHE")
        return '<resource name="cache_clear" value="finished">'

    def get_variables(self):
        #bisque_root = config.get ('bisque.root')
        bisque_root = request.application_url
        bisque_organization = config.get('bisque.organization', 'BisQue')
        bisque_email = config.get('bisque.admin_email', 'info@bisque')

        variables = {
            'service_name':
            bisque_organization,
            'service_url':
            '<a href="%s">%s</a>' % (bisque_root, bisque_organization),
            'user_name':
            'username',
            'email':
            'user@email',
            'display_name':
            'First Last',
            'bisque_email':
            bisque_email,
        }
        return variables

    def do_notify_users(self, userlist, message):
        log.debug(message)
        variables = self.get_variables()

        #for users
        users = data_service.query(resource_type='user',
                                   wpublic='true',
                                   view='full')
        for u in users:
            variables['user_name'] = u.get('name')
            variables['email'] = u.get('value')
            variables['display_name'] = u.find(
                'tag[@name="display_name"]').get('value')
            if variables['email'] not in userlist:
                continue

            msg = copy.deepcopy(message)
            msg = string.Template(msg).safe_substitute(variables)
            #for v,t in variables.iteritems():
            #    msg = msg.replace('$%s'%v, t)

            # send
            log.info('Sending message to: %s', variables['email'])
            log.info('Message:\n%s', msg)

            try:
                notify_service.send_mail(
                    variables['bisque_email'],
                    variables['email'],
                    'Notification from %s service' % variables['service_name'],
                    msg,
                )
            except Exception:
                log.exception("Mail not sent")

    @expose(content_type='text/xml')
    def group(self, *args, **kw):
        """
            GET /admin/group: returns list of all groups <resource> <group name="a" /> <group ... /> </resource>

            POST /admin/group: creates new group,
                  <group name="new_group" /> or <resource> <group ..> <group ../> </resource>
                  shortcut:  POST /group/new_group with no body
            PUT /admin/group  : same as POST

            DELETE /admin/group/group_name : delete the group

        """

        log.debug("GROUP %s %s", args, kw)
        reqformat = kw.pop('format', None)
        http_method = request.method.upper()
        if http_method == 'GET':
            resource = self.get_groups(*args, **kw)
        elif http_method == 'DELETE':
            resource = self.delete_group(*args, **kw)
        elif http_method in ('PUT', 'POST'):
            resource = self.new_group(*args, **kw)
        else:
            abort(400, "bad request")
        accept_header = request.headers.get('accept')
        formatter, content_type = find_formatter(reqformat, accept_header)
        response.headers['Content-Type'] = content_type
        return formatter(resource)

    def get_groups(self, *args, **kw):
        resource = etree.Element('resource')
        for group in DBSession.query(Group):
            etree.SubElement(resource, 'group', name=group.group_name)
        return resource

    def delete_group(self, *args, **kw):
        if len(args):
            group_name = args[0]
        else:
            content_type = request.headers.get('Content-Type')
            inputer = find_inputer(content_type)
            body = request.body_file.read()
            log.debug("DELETE content %s", body)
            els = inputer(body)
            group_name = els.xpath('//group/@name')[0]

        resource = etree.Element('resource')
        group = DBSession.query(Group).filter_by(group_name=group_name).first()
        if group:
            etree.SubElement(resource, 'group', name=group.group_name)
            DBSession.delete(group)

        return resource

    def new_group(self, *args, **kw):
        if len(args):
            group_names = args
        else:
            content_type = request.headers.get('Content-Type')
            inputer = find_inputer(content_type)
            els = inputer(request.body_file)
            group_names = els.xpath('//group/@name')
        resource = etree.Element('resource')
        for nm in group_names:
            g = Group(group_name=nm)
            DBSession.add(g)
            etree.SubElement(resource, 'group', name=nm)

        try:
            transaction.commit()
        except (IntegrityError, InvalidRequestError) as e:
            transaction.abort()
            abort(400, "Bad request %s" % e)

        return resource
示例#10
0
    def __init__(self, lesson, **kw):
        self.lesson = lesson

        menu_items = OrderedDict((
            ('./lessons/', 'Lesson'),
            ('./tutors/', 'Tutor'),
            ('./teams/', 'Teams'),
            ('./students/', 'Students'),
            #('./submissions/', 'Submissions'),
        ))
        self.menu_items = menu_items

        super(LessonController, self).__init__(**kw)

        self.lessons = LessonsCrudController(
            inject=dict(tutor=request.user, event=self.lesson.event),
            query_modifier=lambda qry: qry.filter_by(id=self.lesson.id),
            query_modifiers={
                # Tutors can only delegate ownership to other tutors
                #'tutor': lambda qry: qry.filter(User.id.in_((t.id for t in self.lesson.event.tutors))),
                'tutor': lambda qry: qry.join(User.tutored_lessons).filter_by(event_id=self.lesson.event.id)
            },
            allow_new=False, allow_delete=False,
            menu_items=self.menu_items,
            **kw)
        self.students = StudentsCrudController(
            inject=dict(_lessons=[self.lesson]),
            query_modifier=lambda qry: (qry.join(lesson_members).filter_by(lesson_id=self.lesson.id)
                .union(qry.join(team_members).join(Team).filter_by(lesson_id=self.lesson.id))
                .distinct().order_by(User.id)),
            query_modifiers={
                'teams': lambda qry: qry.filter_by(lesson_id=self.lesson.id),
                '_lessons': lambda qry: qry.filter_by(id=self.lesson.id),
            },
            menu_items=self.menu_items,
            **kw)
        self.teams = TeamsCrudController(
            inject=dict(lesson=self.lesson),
            query_modifier=lambda qry: qry.filter_by(lesson_id=self.lesson.id),
            query_modifiers={
                #'members': lambda qry: qry.filter(User.id.in_((u.id for u in self.lesson.event.members))),
                'members': lambda qry: (qry.join(lesson_members).join(Lesson).filter_by(event_id=self.lesson.event.id)
                    .union(qry.join(team_members).join(Team).join(Team.lesson).filter_by(event_id=self.lesson.event.id))
                    .distinct().order_by(User.id)),
                'lesson': lambda qry: qry.filter_by(id=self.lesson.id),
            },
            menu_items=self.menu_items,
            **kw)
        self.tutors = TutorsCrudController(
            query_modifier=lambda qry: (qry.join(lesson_tutors).filter_by(lesson_id=self.lesson.id)
                .order_by(User.id)),
            query_modifiers={
                'tutored_lessons': lambda qry: qry.filter(Lesson.id.in_((l.id for l in self.lesson.event.lessons))),
            },
            menu_items=self.menu_items, allow_new=False, allow_delete=False,
            **kw)

        self.submissions = SubmissionsController(lesson=self.lesson, menu_items=self.menu_items, **kw)

        # Allow access for event teacher and lesson teacher
        self.allow_only = Any(
            has('teachers', self.lesson.event),
            has('tutors', self.lesson),
#             has_teacher(self.lesson.event),
#             has_teacher(self.lesson),
            has_permission('manage'),
            msg=u'You have no permission to manage this Lesson')
示例#11
0
class ConnoisseurController(ServiceController):
    #Uncomment this line if your controller requires an authenticated user
    #allow_only = predicates.not_anonymous()

    service_type = "connoisseur"

    allow_only = Any(in_group("admin"), in_group('admins'),
                     in_group(service_type))

    def __init__(self, server_url):
        super(ConnoisseurController, self).__init__(server_url)
        self.basepath = os.path.dirname(inspect.getfile(
            inspect.currentframe()))
        self.workdir = config.get('bisque.connoisseur.models',
                                  data_path('connoisseur'))
        #_mkdir (self.workdir)

        self.path_models = os.path.join(self.workdir, 'models')
        self.path_templates = os.path.join(self.workdir, 'templates')
        self.path_images = os.path.join(self.workdir, 'images')
        _mkdir(self.path_models)
        _mkdir(self.path_templates)
        _mkdir(self.path_images)

        self.adapters_gobs = PluginManager(
            'adapters_gobs', os.path.join(self.basepath, 'adapters_gobs'),
            AdapterGobjectsBase)
        self.adapters_pixels = PluginManager(
            'adapters_pixels', os.path.join(self.basepath, 'adapters_pixels'),
            AdapterPixelsBase)

        # frameworks available in the system
        self.frameworks = PluginManager(
            'frameworks', os.path.join(self.basepath, 'frameworks'),
            FrameworkBase)

        # classifiers available to the system, requested with method argument
        self.classifiers = PluginManager(
            'classifiers', os.path.join(self.basepath, 'classifiers'),
            ClassifierBase)

        # importers are matched by their input mime and output mime
        self.importers = PluginManager(
            'importers', os.path.join(self.basepath, 'importers'),
            ImporterBase)
        self.importers_by_mime = {
            '%s;%s' % (e.mime_input, e.mime_type): e
            for k, e in self.importers.plugins.iteritems()
        }
        #log.debug('Importers: %s', self.importers_by_mime)

        # exporters are matched by their input mime and output mime
        self.exporters = PluginManager(
            'exporters', os.path.join(self.basepath, 'exporters'),
            ExporterBase)
        self.exporters_by_mime = {
            '%s;%s' % (e.mime_input, e.mime_type): e
            for k, e in self.exporters.plugins.iteritems()
        }
        #log.debug('Exporters: %s', self.exporters_by_mime)

        # loaded models hashed by their ID
        self.models_loaded_max = 10
        self.models = {}

        log.info('Connoisseur service started, using temp space at: %s' %
                 self.workdir)

    #----------------------------------------------------------------------------------------------
    # RESTful API
    #----------------------------------------------------------------------------------------------

    #@expose('bq.connoisseur.templates.index')
    @expose(content_type='text/xml')
    def index(self, **kw):
        """Add your service description here """
        self.log_start()
        try:
            return self.info()
        finally:
            self.log_finish()

    @expose()
    @require(predicates.not_anonymous(msg='Requires authenticated users'))
    def _default(self, *args, **kw):
        """find export plugin and run export"""
        self.log_start()
        path = request.path_qs.replace(self.baseuri, '', 1).split('/')
        path = [urllib.parse.unquote(p) for p in path if len(p) > 0]
        log.debug("Path: %s", path)

        #GET /connoisseur/MODEL_ID/classify:IMAGE_ID
        #GET /connoisseur/MODEL_ID/classify:IMAGE_ID/points:100

        #GET /connoisseur/MODEL_ID/train
        #GET /connoisseur/MODEL_ID/class:3/sample:1

        if len(path) < 1:
            #abort(responses.BAD_REQUEST, 'resource ID is required as a first parameter, ex: /connoisseur/MODEL_ID/classify:IMAGE_ID' )
            return self.info()
        model_uniq = path.pop(0)

        # parse URL: read all operations and arguments
        args = {}
        while len(path) > 0:
            o = path.pop(0)
            try:
                n, v = o.split(':', 1)
                args[n.lower()] = v
            except ValueError:
                args[o.lower()] = None

        # operations not requiring model uniq id
        op = model_uniq.lower()
        if op in ['info', 'api', 'devices', 'templates', 'template', 'create']:
            try:
                if op in ['info', 'api']:
                    return self.info()
                elif op in ['devices']:
                    return self.devices()
                elif op in ['templates']:
                    return self.templates(args)
                elif op in ['template']:
                    return self.template(args)
                elif op in ['create']:
                    return self.create(args)
            except ConnoisseurException, e:
                abort(e.code, e.message)
            except Exception:
                log.exception('Error processing %s', op)
                abort(responses.INTERNAL_SERVER_ERROR, 'Server error')
            finally: