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 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 invited_user(email): # Validate email with https://github.com/JoshData/python-email-validator ? # Setup a temporary user so that we can add the ACL # Also setup the pre-registration info they can name = email.split('@', 1)[0] count = 1 check_name = name while True: user = DBSession.query(BQUser).filter_by( resource_name=check_name).first() if user is None: name = check_name break check_name = name + str(count) count += 1 password = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6)) log.debug('AUTH: tg_user name=%s email=%s display=%s', name, email, email) tg_user = User(user_name=name, password=password, email_address=email, display_name=email) try: DBSession.add(tg_user) DBSession.flush() data_service.cache_invalidate("/data_service/user") except sqlalchemy.exc.IntegrityError: log.exception('During user invitation') log.debug("AUTH: tg_user = %s", str(tg_user)) # we should have created the BQUser by now. user = DBSession.query(BQUser).filter_by(resource_name=name).first() return (user, password)
def load_uri(uri, query=False): '''Load the object specified by the root tree and return a rsource @type root: Element @param root: The db object root with a uri attribute @rtype: tag_model.Taggable @return: The resource loaded from the database ''' # Check that we are looking at the right resource. try: resource = None service, clname, ida, rest = parse_bisque_uri(uri) if service not in ('data_service', 'module_service'): return None if ida and is_uniq_code(ida): log.debug("loading resource_uniq %s", ida) resource = DBSession.query(Taggable).filter_by(resource_uniq=ida) elif clname: name, dbcls = dbtype_from_tag(clname) #log.debug("loading %s -> name/type (%s/%s)(%s) " , uri, name, str(dbcls), ida) #resource = DBSession.query(dbcls).get (int (ida)) resource = DBSession.query(dbcls).filter(dbcls.id == int(ida)) if not query: resource = resource.first() #log.debug ("loaded %s" % resource) return resource except Exception: log.exception("Failed to load uri %s", uri) return None
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 index(cls, node, parent, indx, cleared): """ Find an element in a subarray of parent """ xmlname = node.tag if xmlname in KNOWN_GOBJECTS: xmlname = 'gobject' #return cls.new(xmlname, parent) array, klass = cls.field_index_map.get(xmlname, (None, None)) if array: objarr = getattr(parent, array) # If values have been 'cleared', then arrary will be empty # this will get the log.debug("EXTEDNING from CURRENTLEN = %s to %s ", len(objarr), indx) objarr.extend([klass() for x in range(((indx + 1) - len(objarr)))]) for x in range(len(objarr), indx + 1): objarr[indx].indx = x objarr[indx].document = parent.document v = DBSession.query(klass).get((parent.id, indx)) # v = objarr[indx] #log.debug('indx %s fetched %s ' , indx, str(v)) #objarr.extend ([ klass() for x in range(((indx+1)-len(objarr)))]) if v is not None: objarr[indx] = v objarr[indx].document = parent.document #log.debug('ARRAY = %s' % [ str(x) for x in objarr ]) return objarr[indx]
def db2node(dbo, parent, view, baseuri, nodes, doc_id, **kw): #from bq.data_service.controllers.resource_query import resource_permission #log.debug ("db2node dbo=%s view=%s", str(dbo), view) if dbo is None: log.error("None pass to as DB object parent = %s", str(parent)) return None, nodes, doc_id if 'deep' in view: n, nodes, doc_id = resource2tree(dbo, parent, view, baseuri, nodes, doc_id) return n, nodes, doc_id node = xmlnode(dbo, parent, baseuri, view) if 'short' in view: return node, nodes, doc_id if "full" in view: q = dbo.childrenq #q = dbo.children # apply limit offsets if kw.has_key('offset'): q = q.offset(int(kw.pop('offset'))) if kw.has_key('limit'): q = q.limit(int(kw.pop('limit'))) # add immediate children _ = [xmlnode(x, node, view=view, baseuri=baseuri) for x in q] return node, nodes, doc_id # Allow a list of tags to be specified in the view parameter which # will be included the object if any('deep' in x for x in view): # are we fetching any deep tags ? n, nodes, doc_id = resource2tree(dbo, parent, view, baseuri, nodes, doc_id) #fv = filter (lambda x: x not in ('full','deep','short', 'canonical'), view) fv = [x for x in view if x not in ('full', 'deep', 'short', 'canonical')] for tag_name in fv: new_view = view if ':' in tag_name: tag_name, new_view = tag_name.split(':') log.debug("SPLIT %s %s", tag_name, new_view) tags = DBSession.query(Taggable).filter( Taggable.document_id == dbo.document_id, Taggable.resource_type == 'tag', Taggable.resource_name == tag_name, Taggable.resource_parent_id == dbo.id, ) for tag in tags: if 'deep' in new_view: log.debug('appending %s', tag.id) node.append(nodes[tag.id]) else: kid = xmlnode(tag, node, view=new_view, baseuri=baseuri) _ = [ xmlnode(x, kid, view=new_view, baseuri=baseuri) for x in tag.children ] return node, nodes, doc_id
def login_check(self, came_from='/', login='', **kw): log.debug("login_check %s from=%s ", login, came_from) login_urls = self.login_map() default_login = login_urls.values()[-1] if login: # Look up user user = DBSession.query(User).filter_by(user_name=login).first() # REDIRECT to registration page? if user is None: redirect( update_url(default_login['url'], dict(username=login, came_from=came_from))) # Find a matching identifier login_identifiers = [g.group_name for g in user.groups] for identifier in login_urls.keys(): if identifier in login_identifiers: login_url = login_urls[identifier]['url'] log.debug("redirecting to %s handler", identifier) redirect( update_url(login_url, dict(username=login, came_from=came_from))) log.debug("using default login handler %s", default_login) redirect( update_url(default_login, dict(username=login, came_from=came_from)))
def all_resources (): ''' Return the setof unique names that are taggable objects ''' #names = DBSession.query(UniqueName).filter(UniqueName.id == Taggable.tb_id).all() #log.debug ('all_resources' + str(names)) names = [ x[0] for x in DBSession.query(Taggable.resource_type).filter_by (resource_parent_id=None).distinct().all() if x[0] not in FILTERED ] return names
def resource_acl_query(resource, user_uniq=None, recurse=False, filter_resource_type=None, response=None): """Query a set of resource acl """ log.debug("ACL_QUERY %s %s", resource, user_uniq) if response is None: response = etree.Element('response') query = DBSession.query(TaggableAcl) if resource: query = query.filter(TaggableAcl.taggable_id == resource.id) if user_uniq: query = query.filter(TaggableAcl.user_id == Taggable.id, Taggable.resource_uniq == user_uniq) for auth in query: log.debug("Found %s with user %s", auth, auth.user) response.append(_aclelem(auth.resource, auth.user, auth)) if recurse: # look for filter_resource have a value of resource uniq related = data_service.query(resource_type=recurse, tag_query="*%s*" % auth.resource.resource_uniq) # For given a given resource return the list non-empty # auth records of associated resources (all the mexes # that points to the current resource) for relation in related: #resource = DBSession.query (Taggable).filter_by (resource_uniq = relation.get ('resource_uniq')).first() rq = DBSession.query(TaggableAcl).filter( TaggableAcl.taggable_id == Taggable.id, TaggableAcl.user_id == auth.user_id, Taggable.resource_uniq == relation.get('resource_uniq')).first() log.debug("LOADED %s %s", recurse, resource) if rq is not None: # Nested response relation.append(_aclelem(rq.resource, rq.user, rq)) response.append(relation) #resource_acl_query (resource, auth.user.resource_uniq, response=relation) # flat response #resource_acl_query (resource, auth.user.resource_uniq, response=response) return response
def authenticate(self, environ, identity): try: mex_token = identity['bisque.mex_token'] except KeyError: return None if not asbool(config.get('bisque.has_database')): environ['repoze.what.credentials'] = { 'repoze.who.userid': mex_token } identity['bisque.mex_auth'] = "%s:%s" % ( identity.get('bisque.mex_user'), mex_token) log.debug("NO DB mex_auth=%s", identity['bisque.mex_auth']) return mex_token from bq.data_service.model import ModuleExecution log.debug("MexAuthenticate:auth %s", identity) try: mex_id = int(mex_token) mex = DBSession.query(ModuleExecution).get(mex_id) except ValueError: mex = DBSession.query(ModuleExecution).filter_by( resource_uniq=mex_token).first() # NOTE: Commented out during system debugging # #if mex.closed(): # log.warn ('attempt with closed mex %s' % mex_id) # return None if mex: identity['bisque.mex'] = mex #owner = identity.get ('bisque.mex_user') or mex.owner.tguser.user_name owner = mex.owner.tguser.user_name identity['bisque.mex_auth'] = '%s:%s' % (owner, mex_token) request_owner = identity.get('bisque.mex_user') if request_owner is not None and owner != request_owner: log.error("Mex with bad owner reuqest %s != mex %s", request_owner, owner) return None log.info("MEX_IDENTITY %s->%s", mex_token, owner) return owner log.warn("Mex authentication failed due to invalid mex %s", mex_token) return None
def bquser_callback (tg_user, operation, **kw): # Deleted users will receive and update callback if tg_user is None: return if operation =='create': u = DBSession.query(BQUser).filter_by(resource_name=tg_user.user_name).first() if u is None: u = BQUser(tg_user=tg_user) DBSession.add(u) log.info ('created BQUSER %s' , u.name) return if operation == 'update': u = DBSession.query(BQUser).filter_by(resource_name=tg_user.user_name).first() if u is not None: u.value = tg_user.email_address dn = u.findtag('display_name', create=True) dn.value = tg_user.display_name dn.permission = 'published' log.info ('updated BQUSER %s' , u.name) return
def get_admin(): user_admin = None if hasattr(request, 'identity'): user_admin = request.identity.get('bisque.admin_user', None) if user_admin is None: from bq.data_service.model.tag_model import BQUser user_admin = DBSession.query(BQUser).filter_by( resource_name=u'admin').first() if hasattr(request, 'identity'): request.identity['bisque.admin_user'] = user_admin return user_admin
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 current_mex_id (): mex_id = None if hasattr(request,'identity'): mex_id = request.identity.get('bisque.mex_id', None) log.debug ("IDENTITY request %s" , (mex_id == 'None')) if mex_id is None: try: mex_id = session.get('mex_id', None) if mex_id is None and 'mex_uniq' in session : mex = DBSession.query(ModuleExecution).filter_by(resource_uniq = session['mex_uniq']).first() mex_id = session['mex_id'] = mex.id log.debug ("IDENTITY session %s" , ( mex_id == 'None')) except TypeError: # ignore bad session object pass if mex_id is None: log.debug("using initialization mex") if hasattr(request, 'initial_mex_id'): mex_id = request.initial_mex_id else: mex = DBSession.query(ModuleExecution).filter_by( resource_user_type = "initialization").first() if mex is None: log.error("No initialization (system) mex found: creating") #initial_mex = ModuleExecution() #initial_mex.mex = initial_mex #initial_mex.name = "initialization" #initial_mex.type = "initialization" #DBSession.add(initial_mex) #DBSession.flush() #DBSession.refresh(initial_mex) #mex = initial_mex mex_id = mex and mex.id if hasattr(request, 'identity') and mex_id is not None: request.identity['bisque.mex_id'] = mex_id log.debug ('IDENTITY mex_id %s' , mex_id) return mex_id
def match_user(user=None, user_uniq=None, email=None): """Match a user by user url or email creating a new one if needed. @return: tuple (new user, passwd if created otherwise None) """ if user is None: if user_uniq: # may be a user url or simply a uniq code user_uniq = posixpath.basename(user_uniq) user = DBSession.query(BQUser).filter_by( resource_uniq=user_uniq).first() if user is None and email: user = DBSession.query(BQUser).filter_by( resource_value=unicode(email)).first() # did we find a user? if user is not None: return (user, None) if email is None: raise IllegalOperation("Cannot determing user to share with") log.debug('AUTH: no user, sending invite %s', email) return invited_user(email)
def map_url (uri): '''Load the object specified by the root tree and return a rsource @type root: Element @param root: The db object root with a uri attribute @rtype: tag_model.Taggable @return: The resource loaded from the database ''' # Check that we are looking at the right resource. net, name, ida = parse_uri(uri) name, dbcls = dbtype_from_name(name) resource = DBSession.query(dbcls).get (ida) #log.debug("loading uri name (%s) type (%s) = %s" %(name, str(dbcls), str(resource))) return resource
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 load(self, token, **kw): """ Return a db records for resource, user, and acl @param token: A user uniq @return A triple (resource, user, acl) or None,None,None if not unable """ log.debug("Load %s", str(token)) # Can we read the ACLs at all? resource = check_access(request.bisque.parent, RESOURCE_READ) # token should be a resource_uniq of user .. so join Taggable(user) and TaggableAcl if resource is None: return (None, None, None) DBSession.flush() acl, user = DBSession.query(TaggableAcl, Taggable).filter( TaggableAcl.taggable_id == resource.id, TaggableAcl.user_id == Taggable.id, Taggable.resource_uniq == token).first() return resource, user, acl
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 set_current_user(self, user): """"Set the current user for authentication @param user: a username or :class:BQUser object @return: precious user or None """ if isinstance(user, basestring): from bq.data_service.model.tag_model import BQUser user = DBSession.query(BQUser).filter_by( resource_name=user).first() oldbquser = request.identity.pop('bisque.bquser', None) olduser = request.identity.pop('repoze.who.userid', None) if user is not None: request.identity['bisque.bquser'] = user request.identity['repoze.who.userid'] = user and user.resource_name return oldbquser
def resource_acls(resources, newauth, user=None, acl=None, notify=False, invalidate=True, action='append'): """ Update the list of resources with a new """ results = [] for resource in resources: uniq = posixpath.basename(resource) r = DBSession.query(Taggable).filter_by(resource_uniq=uniq).first() if r is None: log.warn("uniq %s was not a shareable resource", r) continue results.append( resource_acl(r, newauth, user, acl, notify, invalidate, action)) return results
def registration_hook(action, **kw): log.info ('regisration_hook %s -> %s' % (action, kw)) if action=="new_user": u = kw.pop('user', None) if u: BQUser.new_user (u.email_adress, u.password) elif action=="update_user": u = kw.pop('user', None) if u: bquser = DBSession.query(BQUser).filter_by(resource_value=u.email_address).first() if not bquser: bquser = BQUser.new_user (u.email_adress, u.password) dn = bquser.findtag('display_name', create=True) dn.value = u.display_name dn.permission = 'published' #bquser.display_name = u.display_name bquser.resource_name = u.user_name log.error('Fix the display_name') elif action =="delete_user": pass
def _get_bquser(self): if not request_valid(): return None bquser = request.identity.get('bisque.bquser') if bquser: if bquser not in DBSession: #pylint: disable=unsupported-membership-test bquser = DBSession.merge(bquser) request.identity['bisque.bquser'] = bquser return bquser user_name = self.get_username() if not user_name: return None from bq.data_service.model.tag_model import BQUser log.debug("fetch BQUser by name") bquser = DBSession.query(BQUser).filter_by( resource_name=user_name).first() request.identity['bisque.bquser'] = bquser #log.debug ("bq user = %s" % user) log.debug('user %s -> %s' % (user_name, bquser)) return bquser
def replace_all(self, resource, xml, notify=False, **kw): log.debug("REPLACE_ALL %s %s", request.url, xml) response = etree.Element('resource', uri=request.url) resource = check_access(resource, RESOURCE_EDIT) #log.debug ("REPLACE_ALL resource %s", resource) if resource is not None: #DBSession.autoflush = False newacls = [] #auth_list=etree.XML(xml) auth_list = xml # Update or add any that are listed in xml oldauths = DBSession.query(TaggableAcl).filter_by( taggable_id=resource.id).all() for newauth in auth_list: log.debug("checking %s", newauth) newacls.append( resource_acl(resource, newauth, notify=asbool(notify))) log.debug("Adding auth record %s", etree.tostring(newacls[-1])) # Remove any current acls not list in newacls authed_users = [posixpath.basename(x.get('user')) for x in newacls] for auth in oldauths: #log.debug ("Checking user %s in %s" , auth.user.resource_uniq , authed_users) # Carefull here: allowed_user is a list of uniq code while auth.user is db object if auth.user.resource_uniq not in authed_users: log.debug("removing %s", auth) delauth = _aclelem(resource, auth.user, auth) resource_acl(resource, delauth, user=auth.user, acl=auth, action="delete") #DBSession.delete (auth) formatter, content_type = find_formatter('xml') tg.response.headers['Content-Type'] = content_type return formatter(response)
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 resource2nodes(dbo, parent=None, view=[], baseuri=None, qfilter=None, **kw): 'load every element associated with dbo i.e load the document' from bq.data_service.controllers.resource_query import resource_permission doc_id = dbo.document_id if qfilter is None: qfilter = (Taggable.document_id == doc_id) docnodes = DBSession.query(Taggable).filter(qfilter) #docnodes = resource_permission(docnodes) #log.debug("reosurce2nodes: %s", str(docnodes)) #log.debug('resource2nodes: %s %s doc %s' , str(docnodes), dbo.id , doc_id) nodes = {} parents = {} for node in docnodes: nodes[node.id] = xmlnode(node, None, baseuri, view) parents[node.id] = (node.resource_parent_id, node.resource_index) # pull out items sorted by resource_index (k, (parent, index) ) for node_id, (parent_id, _) in sorted(parents.items(), key=lambda x: x[1][1]): try: # attached xml nodes in position if parent_id is not None: nodes[parent_id].append(nodes[node_id]) except KeyError: log.error( "Missing parent node %s (permission error?) in document %s", parent_id, doc_id) continue # for node in docnodes: # if node.resource_parent_id is not None: # try: # node_parent = nodes[node.resource_parent_id] # except KeyError: # log.error("Missing parent node %s (permission error?) in document %s" % (node.resource_parent_id, doc_id)) # continue # #elem = etree.SubElement(parent, node.resource_type) # elem = xmlnode (node, node_parent, baseuri, view) # nodes[node.id] = elem # else: # #elem = root = etree.Element(node.resource_type) # elem = root = xmlnode(node, None, baseuri, view) # nodes[node.id] = elem vnodes = DBSession.query(Value).filter( Value.document_id == doc_id).order_by(Value.resource_parent_id, Value.indx) for v in vnodes: if v.resource_parent_id in nodes and nodes[v.resource_parent_id].get( 'value') is None: xmlnode(v, parent=nodes[v.resource_parent_id], baseuri=baseuri, view=view) # pylint: disable=no-member vnodes = DBSession.query(Vertex).filter( Vertex.document_id == doc_id).order_by(Vertex.resource_parent_id, Vertex.indx) for v in vnodes: if v.resource_parent_id in nodes: xmlnode(v, parent=nodes[v.resource_parent_id], baseuri=baseuri, view=view) #log.debug('resource2nodes: doc %s read %d nodes ', doc_id, (len(nodes.keys()))) return nodes, doc_id
def by_email_address(cls, email): """Return the user object whose email address is ``email``.""" return DBSession.query(cls).filter_by(email_address=email).first()
def by_user_name(cls, username): """Return the user object whose user name is ``username``.""" return DBSession.query(cls).filter_by(user_name=username).first()
def resource_acl(resource, newauth, user=None, acl=None, notify=False, invalidate=True, action='append'): """Create or modify resource acls @param resource: resource (Taggable) @param newauth : an etree of the acl record or None if deleting @param user : the user (Taggable) of the acl or None (will be determined from newauth) @param acl : the acl (TaggableAcl) or None (will be found or created) @param notify : send an email on state change (boolean) @param invalidate: Invalidate caches (boolean) @parama delete : Append/modify or Delete record (boolean) @return an etree acl record """ log.debug("ACL SET %s", resource) user, passwd = match_user(user=user, user_uniq=newauth.get('user'), email=newauth.get('email')) if acl is None: try: DBSession.flush() # autoflush is off so flush before query except sqlalchemy.exc.IntegrityError: log.exception("while preparing for query") acl = DBSession.query(TaggableAcl).filter_by(taggable_id=resource.id, user_id=user.id).first() if acl is None: # Check if newauth is not None or delete is true??? acl = TaggableAcl() acl.taggable_id = resource.id acl.user_id = user.id acl.action = "read" DBSession.add(acl) if action == 'delete': log.debug("Removing %s from %s for %s", newauth.get('action', RESOURCE_READ), resource.resource_uniq, user.resource_uniq) # http://stackoverflow.com/questions/8306506/deleting-an-object-from-an-sqlalchemy-session-before-its-been-persisted if acl in DBSession.new: DBSession.expunge(acl) else: DBSession.delete(acl) else: log.debug("Changing share on %s for %s action=%s", resource.resource_uniq, user.resource_uniq, newauth.get('action', RESOURCE_READ)) acl.action = newauth.get('action', RESOURCE_READ) # # Special actions on sharing specific resource types # handler = SHARE_HANDLERS.get(resource.resource_type) if handler: log.debug("Special share handling with %s", handler) handler(resource.resource_uniq, user.resource_uniq, newauth, action) # Notify changes if needed if notify: try: notify_user(action, resource, user, passwd) except Exception: log.exception("While notifying share") if invalidate: Resource.hier_cache.invalidate_resource(None, user=user.id) # Return the new/updated auth element return _aclelem(resource, user, acl)