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 __init__(self, user_name=None, password=None, email_address=None, display_name=None, create_tg=False, tg_user = None, create_store=True,**kw): super(BQUser, self).__init__() if not display_name: display_name = user_name if create_tg and tg_user is None: tg_user = User() tg_user.user_name = user_name tg_user.email_address = email_address tg_user.password = password tg_user.display_name = display_name DBSession.add(tg_user) self.permission = 'published' self.resource_name = tg_user.user_name self.resource_value = tg_user.email_address dn = Tag (parent = self) dn.name = 'display_name' dn.value = tg_user.display_name or tg_user.user_name dn.owner = self self.owner = self self.permission = 'published' if create_store: #from bq.commands.stores import init_stores #init_stores (tg_user.user_name) root_store = BQStore(owner_id = self) root_store.resource_name='(root)' root_store.resource_unid='(root)' DBSession.add(root_store)
def flushchanges(self, *args): from bq.core.model import DBSession #transaction.commit() #for r in args: # if r: # DBSession.merge(r) DBSession.flush()
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 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 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 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 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 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 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_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 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 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 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 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 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 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 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 new_user (cls, email, password, create_tg = False): bquser = cls( user_name= email, email_address=email, display_name=email, password = password) DBSession.add (bquser) DBSession.flush() DBSession.refresh(bquser) bquser.owner_id = bquser.id if create_tg: tg_user = User() tg_user.user_name = email tg_user.email_address = email tg_user.password = password tg_user.display_name = email #tg_user.dough_user_id = self.id DBSession.add(tg_user) DBSession.flush() return bquser
def bisquik2db_internal(inputs, parent, resource, replace): '''Parse a document (either as a doc, or an etree. Verify against xmlschema if present ''' results = [] if parent is not None: parent = DBSession.merge(parent) if resource is not None: resource = DBSession.merge(resource) ts = datetime.now() for el in inputs: node = updateDB(root=el, parent=parent, resource=resource, replace=replace, ts=ts) log.debug("returned %s ", str(node)) log.debug('modified : new (%d), dirty (%d), deleted(%d)', len(DBSession.new), len(DBSession.dirty), len(DBSession.deleted)) # pylint: disable=no-member if node not in DBSession: # pylint: disable=unsupported-membership-test # pylint: disable=no-member DBSession.add(node) #log.debug ("node.document = %s" , str( node.document)) node.document.ts = ts results.append(node) #DBSession.flush() #for node in results: # DBSession.refresh(node) if log.isEnabledFor(logging.DEBUG): log.debug('modifyed : new (%d), dirty (%d), deleted(%d)', len(DBSession.new), len(DBSession.dirty), len(DBSession.deleted)) # pylint: disable=no-member log.debug("Bisquik2db last_node %s of document %s ", str(node), str(node.document)) if len(results) == 1: return node return results
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 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 _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 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 setbasicauth(self, username, passwd, **kw): log.debug("Set basic auth %s", kw) if not identity.is_admin() and username != identity.get_username(): return "<error msg='failed: not allowed to change password of others' />" user = tg.request.identity.get('user') log.debug("Got user %s", user) if user and user.user_name == username: # sanity check user = DBSession.merge(user) user.password = passwd log.info("Setting new basicauth password for %s", username) #transaction.commit() return "<success/>" log.error("Could not set basicauth password for %s", username) return "<error msg='Failed to set password'/>"
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 resource_output(self, resource, response=None, view=None, format=None, progressive=False, **kw): #if response is None: log.debug("resource_outtput %s", self.uri) DBSession.flush() if isinstance(resource, list): response = etree.Element('resource') db2tree(resource, view=view, parent=response, baseuri=self.uri) elif resource is not None: response = db2tree(resource, view=view, parent=response, baseuri=self.uri, **kw) #transaction.commit() accept_header = tg.request.headers.get('accept') formatter, content_type = find_formatter(format, accept_header) tg.response.headers['Content-Type'] = content_type return formatter(response, view=view)
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 setUp(self): """Prepare model test fixture.""" try: new_attrs = {} new_attrs.update(self.attrs) new_attrs.update(self.do_get_dependencies()) self.obj = self.klass(**new_attrs) #pylint: disable=not-callable DBSession.add(self.obj) DBSession.flush() return self.obj except Exception: DBSession.rollback() raise