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)
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')
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)
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)
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)
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 )
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.' )
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')
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
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')
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: