def _authenticate(self): start = perf.start() if "Authorization" not in cherrypy.request.headers and "token" not in cherrypy.request.params: raise worker.ServiceException( 403, "Request must contain Authorization header or parameter") if "Authorization" in cherrypy.request.headers: authorization_header = cherrypy.request.headers["Authorization"] a = authorization_header.split(" ") if len(a) != 2 or a[0] != "Bearer": raise worker.ServiceException( 403, "Invalid format for Authorization header") token_value = a[1] else: token_value = cherrypy.request.params["token"] del cherrypy.request.params["token"] if token_value in user_cache: user_handle = user_cache[token_value] else: user_handle = processor.get_user_for_token(token_value) user_cache[token_value] = user_handle if user_handle is None: raise worker.ServiceException(403, "Not a valid authentication token") perf.end(__name__, start) return user_handle
def list_child_items(self, item_id): start = perf.start() sql = "select id, name, type_id, public_data from items where parent_id=$1 order by name" ps = self.connection.prepare(sql) rows = ps(item_id) perf.end(__name__, start) return rows
def count_items(self): start = perf.start() sql = "select count(id) from items" ps = self.connection.prepare(sql) rows = ps() perf.end(__name__, start) return rows[0][0]
def execute(self, item_path, verb, user_handle, args): start = perf.start() if isinstance(user_handle, str): user_handle = self.item_finder.find(user_handle) item_handle = self.item_finder.find(item_path, user_handle) if not item_handle.exists(): if verb == "put": # Supplied path doesn't exist so... # ... take the name from that path that was supplied name = posixpath.basename(item_path) args["name"] = name # ... and try use the parent item path item_path = posixpath.dirname(item_path) item_handle = self.item_finder.find(item_path, user_handle) else: raise ServiceException(404, "bad path:" + item_path) item = self.item_loader.load(item_handle) user_auth_name = item_handle.get_auth_name() worker = Worker(self, item, user_handle) item.modified = False try: result, return_type = item.invoke(verb, user_auth_name, [worker], **args) except NoAuthorizedActionException: raise ServiceException(403, "No matching action") if item.modified: version = self.item_saver.save(item, user_handle) result["version"] = version perf.end(__name__, start) return result, return_type
def delete_trailing_file_blocks(self, item_id, file_version, block_number): start = perf.start() sql = ("delete from file_blocks " "where item_id=$1 and file_version=$2 and block_number>$3") ps = self.connection.prepare(sql) perf.end(__name__, start) ps(item_id, file_version, block_number)
def get_private(self, item_id): start = perf.start() sql = ("select private_data from items " "where id=$1 ") ps = self.connection.prepare(sql) rows = ps(item_id) perf.end(__name__, start) return rows[0][0]
def delete_item(self, item_id): start = perf.start() sql = "delete from items where id=$1 and deletable=true returning id" ps = self.connection.prepare(sql) rows = ps(item_id) perf.end(__name__, start) return len(rows) > 0
def update_private(self, item_id, private_data, user_id): start = perf.start() sql = ("update items " "set private_data=$2, saved_at=now(), saved_by=$3 " "where id=$1 ") ps = self.connection.prepare(sql) ps(item_id, private_data, user_id) perf.end(__name__, start)
def create_file_block(self, item_id, file_version, block_number, block_hash, block_data): start = perf.start() sql = ("insert into file_blocks " "(item_id, file_version, block_number, length, hash, created_at, data) " "values ($1, $2, $3, $4, $5, now(), $6)") ps = self.connection.prepare(sql) perf.end(__name__, start) ps(item_id, file_version, block_number, len(block_data), block_hash, block_data)
def set_file_version_length_hash(self, item_id, file_version, file_length, file_hash): start = perf.start() sql = ("update file_versions " "set length=$3, hash=$4 " "where item_id=$1 and file_version=$2") ps = self.connection.prepare(sql) ps(item_id, file_version, file_length, file_hash) perf.end(__name__, start)
def set_file_version_length(self, item_id, file_version, file_length): start = perf.start() sql = ("update file_versions " "set length=$3 " "where item_id=$1 and file_version=$2") ps = self.connection.prepare(sql) ps(item_id, file_version, file_length) perf.end(__name__, start)
def update_file_block(self, item_id, file_version, block_number, block_hash, block_data): start = perf.start() sql = ("update file_blocks " "set length=$4, hash=$5, created_at=now(), data=$6, data_file_version=null " "where item_id=$1 and file_version=$2 and block_number=$3") ps = self.connection.prepare(sql) perf.end(__name__, start) ps(item_id, file_version, block_number, len(block_data), block_hash, block_data)
def get_file_block_data_file_version(self, item_id, file_version, block_number): start = perf.start() sql = ("select data_file_version " "from file_blocks " "where item_id=$1 and file_version=$2 and block_number=$3") ps = self.connection.prepare(sql) rows = ps(item_id, file_version, block_number) perf.end(__name__, start) return rows[0][0]
def save_item_version(self, item_id): start = perf.start() sql = ("insert into item_versions " "select id, version, type_id, public_data, saved_at, saved_by " "from items " "where id=$1") ps = self.connection.prepare(sql) ps(item_id) perf.end(__name__, start)
def post_set_password(self, worker, password): private_data = worker.get_private() start = perf.start() salt = bcrypt.gensalt(2) password_hash = "bcrypt:" + bcrypt.hashpw(password, salt) private_data[PASSWORD_HASH_KEY] = password_hash worker.set_private(private_data) perf.end(__name__, start) return {}
def create_token(self, item_id, token_value, json_data, expires_at): start = perf.start() sql = ("insert into tokens " "(item_id, token_value, json_data, created_at, expires_at) " "values " "($1, $2::text, $3, now(), $4::text::timestamp)") ps = self.connection.prepare(sql) ps(item_id, token_value, json_data, expires_at) perf.end(__name__, start)
def get_file_block_data(self, item_id, file_version, block_number): start = perf.start() sql = ("select data " "from file_blocks " "where item_id=$1 and file_version=$2 and block_number=$3") ps = self.connection.prepare(sql) rows = ps(item_id, file_version, block_number) perf.end(__name__, start) return rows[0][0]
def set_item_type_user(self, item_id, type_id, type_id_path, user_id): start = perf.start() sql = ("update public.items " "set type_id=$1, type_path=text2ltree($2), created_by=$3, saved_by=$3 " "where" " id=$4") ps = self.connection.prepare(sql) ps(type_id, type_id_path, user_id, item_id) perf.end(__name__, start)
def get_item_name(self, item_id): start = perf.start() sql = "select name from items where id=$1" ps = self.connection.prepare(sql) rows = ps(item_id) perf.end(__name__, start) if len(rows) > 0: return rows[0][0] else: return None
def create_file_version(self, item_id, previous_version, user_id): start = perf.start() sql = ("insert into file_versions " "(item_id, file_version, previous_version, created_at, created_by) " "select $1, coalesce(max(file_version) + 1, 0), $2, now(), $3 from file_versions " "returning file_versions.file_version") ps = self.connection.prepare(sql) rows = ps(item_id, previous_version, user_id) perf.end(__name__, start) return rows[0][0]
def list_file_version_blocks(self, item_id, start_version, end_version): start = perf.start() sql = ("select file_version, block_number, data_file_version, length, hash, created_at " "from file_blocks " "where item_id=$1 and file_version >= $2 and file_version <= $3" "order by file_version, block_number asc") ps = self.connection.prepare(sql) rows = ps(item_id, start_version, end_version) perf.end(__name__, start) return rows
def set_item_type_user(self, item_id, type_id, type_id_path, user_id): start = perf.start() sql = ( "update public.items " "set type_id=$1, type_path=text2ltree($2), created_by=$3, saved_by=$3 " "where" " id=$4") ps = self.connection.prepare(sql) ps(type_id, type_id_path, user_id, item_id) perf.end(__name__, start)
def update_item(self, item_id, public_data, user_id): start = perf.start() sql = ("update public.items " "set version=version+1, public_data=$2, saved_at=now(), saved_by=$3 " "where id=$1 " "returning version") ps = self.connection.prepare(sql) rows = ps(item_id, public_data, user_id) perf.end(__name__, start) return rows[0][0]
def update_item(self, item_id, public_data, user_id): start = perf.start() sql = ( "update public.items " "set version=version+1, public_data=$2, saved_at=now(), saved_by=$3 " "where id=$1 " "returning version") ps = self.connection.prepare(sql) rows = ps(item_id, public_data, user_id) perf.end(__name__, start) return rows[0][0]
def find_token(self, token_value): start = perf.start() sql = ("select item_id, json_data from tokens " "where token_value=$1 and expires_at > now()") ps = self.connection.prepare(sql) rows = ps(token_value) perf.end(__name__, start) if len(rows) > 0: return rows[0][0], rows[0][1] else: return None, None
def create_file_version(self, item_id, previous_version, user_id): start = perf.start() sql = ( "insert into file_versions " "(item_id, file_version, previous_version, created_at, created_by) " "select $1, coalesce(max(file_version) + 1, 0), $2, now(), $3 from file_versions " "returning file_versions.file_version") ps = self.connection.prepare(sql) rows = ps(item_id, previous_version, user_id) perf.end(__name__, start) return rows[0][0]
def create_file_block(self, item_id, file_version, block_number, block_hash, block_data): start = perf.start() sql = ( "insert into file_blocks " "(item_id, file_version, block_number, length, hash, created_at, data) " "values ($1, $2, $3, $4, $5, now(), $6)") ps = self.connection.prepare(sql) perf.end(__name__, start) ps(item_id, file_version, block_number, len(block_data), block_hash, block_data)
def update_file_block(self, item_id, file_version, block_number, block_hash, block_data): start = perf.start() sql = ( "update file_blocks " "set length=$4, hash=$5, created_at=now(), data=$6, data_file_version=null " "where item_id=$1 and file_version=$2 and block_number=$3") ps = self.connection.prepare(sql) perf.end(__name__, start) ps(item_id, file_version, block_number, len(block_data), block_hash, block_data)
def list_file_version_blocks(self, item_id, start_version, end_version): start = perf.start() sql = ( "select file_version, block_number, data_file_version, length, hash, created_at " "from file_blocks " "where item_id=$1 and file_version >= $2 and file_version <= $3" "order by file_version, block_number asc") ps = self.connection.prepare(sql) rows = ps(item_id, start_version, end_version) perf.end(__name__, start) return rows
def get_file_version(self, item_id, file_version): start = perf.start() sql = ("select length, hash, previous_version from file_versions " "where item_id=$1 and file_version=$2") ps = self.connection.prepare(sql) rows = ps(item_id, file_version) perf.end(__name__, start) if len(rows) > 0: return rows[0][0], rows[0][1], rows[0][2] else: return None, None, None, None
def check_login(self, item_path, verb, args): start = perf.start() if (not verb == "post") or (not "name" in args) or (not "password" in args): result = None else: # We are doing a "get" and supplying a name and password -> we are trying to log in result, _ = self.execute(item_path, verb, self.item_finder.find_system_user(), args) perf.end(__name__, start) return result
def list_file_versions(self, item_id): start = perf.start() sql = ("select " " file_version, previous_version, length, hash, created_at, created_by " "from file_versions " "where item_id=$1 " "order by file_version asc") ps = self.connection.prepare(sql) rows = ps(item_id) perf.end(__name__, start) return rows
def get_file_block_hash(self, item_id, file_version, block_number): start = perf.start() sql = ("select hash " "from file_blocks " "where item_id=$1 and file_version=$2 and block_number=$3") ps = self.connection.prepare(sql) rows = ps(item_id, file_version, block_number) perf.end(__name__, start) if len(rows) > 0: return rows[0][0] else: return None
def list_file_versions(self, item_id): start = perf.start() sql = ( "select " " file_version, previous_version, length, hash, created_at, created_by " "from file_versions " "where item_id=$1 " "order by file_version asc") ps = self.connection.prepare(sql) rows = ps(item_id) perf.end(__name__, start) return rows
def copy_file_blocks(self, item_id, file_version, previous_version): start = perf.start() sql = ("insert into file_blocks" "(item_id, file_version, block_number, data_file_version, length, hash, created_at) " "select item_id, $3, block_number, " " case when $2 = 0 then 0 else coalesce(data_file_version, $2) end, " " length, hash, now()" "from file_blocks " "where item_id = $1 and file_version = $2") ps = self.connection.prepare(sql) perf.end(__name__, start) rows = ps(item_id, previous_version, file_version)
def create_item_initial(self, parent_id, name, id_path, public_data, search_text): start = perf.start() sql = ("insert into public.items" "(parent_id, name, deletable, id_path, public_data, created_at, saved_at, search_text)" "values" "( $1, $2, false, " " text2ltree(case when $1::int is null then '1' else $3::text || '.' || currval('items_id_seq') end)," " $4, now(), now(), $5)" "returning id") ps = self.connection.prepare(sql) rows = ps(parent_id, name, id_path, public_data, search_text) perf.end(__name__, start) return rows[0][0]
def copy_file_blocks(self, item_id, file_version, previous_version): start = perf.start() sql = ( "insert into file_blocks" "(item_id, file_version, block_number, data_file_version, length, hash, created_at) " "select item_id, $3, block_number, " " case when $2 = 0 then 0 else coalesce(data_file_version, $2) end, " " length, hash, now()" "from file_blocks " "where item_id = $1 and file_version = $2") ps = self.connection.prepare(sql) perf.end(__name__, start) rows = ps(item_id, previous_version, file_version)
def put_login(self, worker, password): start = perf.start() private_data = worker.get_private() if PASSWORD_HASH_KEY in private_data: password_hash = private_data[PASSWORD_HASH_KEY] stored_hash = password_hash.split(":")[1] supplied_hash = bcrypt.hashpw(password, stored_hash) if supplied_hash == stored_hash: token, expires_at = worker.create_security_token() perf.end(__name__, start) return {"user_path": self.handle.path, "token": token, "expires_at": expires_at} perf.end(__name__, start) raise ServiceException(403, "Bad password")
def create_item_initial(self, parent_id, name, id_path, public_data, search_text): start = perf.start() sql = ( "insert into public.items" "(parent_id, name, deletable, id_path, public_data, created_at, saved_at, search_text)" "values" "( $1, $2, false, " " text2ltree(case when $1::int is null then '1' else $3::text || '.' || currval('items_id_seq') end)," " $4, now(), now(), $5)" "returning id") ps = self.connection.prepare(sql) rows = ps(parent_id, name, id_path, public_data, search_text) perf.end(__name__, start) return rows[0][0]
def get_first_parent_of_type(self, item_id, type_id): start = perf.start() sql = ("with recursive search_parents(id, type_id, parent_id, height) as ( " " select id, type_id, parent_id, 1 from items where id=$1 " " union " " select it.id, it.type_id, it.parent_id, height + 1 " " from items it " " join search_parents parents on parents.parent_id = it.id) " "select id from search_parents where type_id=$2 and id != $1 order by height asc limit 1") ps = self.connection.prepare(sql) rows = ps(item_id, type_id) perf.end(__name__, start) if len(rows) > 0: return rows[0][0] else: return None
def put_login(self, worker, password): start = perf.start() private_data = worker.get_private() if PASSWORD_HASH_KEY in private_data: password_hash = private_data[PASSWORD_HASH_KEY] stored_hash = password_hash.split(":")[1] supplied_hash = bcrypt.hashpw(password, stored_hash) if supplied_hash == stored_hash: token, expires_at = worker.create_security_token() perf.end(__name__, start) return { "user_path": self.handle.path, "token": token, "expires_at": expires_at } perf.end(__name__, start) raise ServiceException(403, "Bad password")
def authorize(self, item_auth, user_handle): start = perf.start() if user_handle is None: return AuthLevels["reader"] auth_level = AuthLevels["reader"] for auth_id, auth_level_name in item_auth: if type(auth_id) is str: if auth_id == "everyone": auth_level = AuthLevels[auth_level_name] else: auth_user_handle = self.find(auth_id) auth_id = auth_user_handle.item_id if user_handle.item_id == auth_id: auth_level = AuthLevels[auth_level_name] break perf.end(__name__, start) return auth_level
def load(self, item_id): start = perf.start() sql = ("select " " type_id, " " name, " " public_data, " " created_at, " " saved_at, " " deletable " "from items " "where id = $1") ps = self.connection.prepare(sql) rows=ps(item_id) perf.end(__name__, start) if len(rows) == 0: return None, None, None, None, None, None else: return rows[0]
def get_first_parent_of_type(self, item_id, type_id): start = perf.start() sql = ( "with recursive search_parents(id, type_id, parent_id, height) as ( " " select id, type_id, parent_id, 1 from items where id=$1 " " union " " select it.id, it.type_id, it.parent_id, height + 1 " " from items it " " join search_parents parents on parents.parent_id = it.id) " "select id from search_parents where type_id=$2 and id != $1 order by height asc limit 1" ) ps = self.connection.prepare(sql) rows = ps(item_id, type_id) perf.end(__name__, start) if len(rows) > 0: return rows[0][0] else: return None
def create_item(self, parent_id, name, id_path, type_id, type_path, public_data, created_by, search_text): start = perf.start() sql = ("insert into public.items" "(parent_id, name, id_path, type_id, type_path, public_data," " created_at, created_by, saved_at, saved_by, search_text)" "values" "( $1, $2, " " text2ltree($3::text || '.' || currval('items_id_seq'))," " $4, text2ltree($5), $6, now(), $7, now(), $7, $8)" "returning id") ps = self.connection.prepare(sql) try: rows = ps(parent_id, name, id_path, type_id, type_path, public_data, created_by, search_text) return rows[0][0] except postgresql.exceptions.UniqueError as ex: return None finally: perf.end(__name__, start)
def _authenticate(self): start = perf.start() if "Authorization" not in cherrypy.request.headers and "token" not in cherrypy.request.params: raise worker.ServiceException(403, "Request must contain Authorization header or parameter") if "Authorization" in cherrypy.request.headers: authorization_header = cherrypy.request.headers["Authorization"] a = authorization_header.split(" ") if len(a) != 2 or a[0] != "Bearer": raise worker.ServiceException(403, "Invalid format for Authorization header") token_value = a[1] else: token_value = cherrypy.request.params["token"] del cherrypy.request.params["token"] if token_value in user_cache: user_handle = user_cache[token_value] else: user_handle = processor.get_user_for_token(token_value) user_cache[token_value] = user_handle if user_handle is None: raise worker.ServiceException(403, "Not a valid authentication token") perf.end(__name__, start) return user_handle