def get_vm_by_uuid(self, vm_uuid): if not vm_uuid: raise Error(ERR_VM_UUID) vm = DBVm.objects.filter(uuid=vm_uuid) if not vm.exists(): raise Error(ERR_VM_UUID) return VM(vm[0])
def mods_upload(): """ Creates a new mod in the system **Example Request**: .. sourcecode:: http POST /mods/upload **Example Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript "ok" :query file file: The file submitted (Must be ZIP) :type: zip """ file = request.files.get('file') if not file: raise ApiException([Error(ErrorCode.UPLOAD_FILE_MISSING)]) if not file_allowed(file.filename): raise ApiException([Error(ErrorCode.UPLOAD_INVALID_FILE_EXTENSION, *ALLOWED_EXTENSIONS)]) filename = secure_filename(file.filename) file.save(os.path.join(app.config['MOD_UPLOAD_PATH'], filename)) return "ok"
def search(): city = request.json.get("city") if not city: raise Error("A value for 'city' is required.", 422) location_names = request.json.get("locations") if not location_names: raise Error("A list of values for 'locations' is required.", 422) index = Yelp(os.environ.get("SEARCH_INDEX_YELP_API_KEY")) locations = [] for name in location_names: try: locations.append(index.search(name, city)) except Exception as e: pass # Sort locations by highest rating and then most reviews. locations = sorted(locations, key=lambda location: (location["rating"], location["reviews"]), reverse=True) return jsonify({"city": city, "locations": locations})
def decrypt_token(action: str, token: str): """ Decrypts a token and returns the data in a list of strings Throws exception when the action does not fit or the token expired :param action: a unique identifier for the action associated with this token :param token: the crypted token :return: list of strings which contains the data given on creating the token """ # F**k you urlsafe_b64encode & padding and f**k you overzealous http implementations token = token.replace('%3d', '=') token = token.replace('%3D', '=') ciphertext = base64.urlsafe_b64decode(token.encode()) plaintext = Fernet(CRYPTO_KEY).decrypt(ciphertext).decode("utf-8") token_action, expiry, *result = plaintext.split(',') if token_action != action: raise ApiException([Error(ErrorCode.TOKEN_INVALID)]) if (float(expiry) < time.time()): raise ApiException([Error(ErrorCode.TOKEN_EXPIRED)]) return result
def validate_email(email: str) -> bool: """ Checks correctness of a username Throws exception if the syntax does not fit, the domain is blacklistet or is already in use :email name: Users email (Case sensitive) :return: true if no error occured """ # check for correct email syntax if not EMAIL_REGEX.match(email): raise ApiException([Error(ErrorCode.INVALID_EMAIL, email)]) # check for blacklisted email domains (we don't like disposable email) with db.connection: cursor = db.connection.cursor() cursor.execute("SELECT lower(domain) FROM email_domain_blacklist") rows = cursor.fetchall() # Get list of blacklisted domains (so we can suffix-match incoming emails # in sublinear time) blacklisted_email_domains = marisa_trie.Trie(map(lambda x: x[0], rows)) domain = email.split("@")[1].lower() if domain in blacklisted_email_domains: raise ApiException([Error(ErrorCode.BLACKLISTED_EMAIL, email)]) # ensue that email adress is unique cursor.execute("SELECT id FROM `login` WHERE LOWER(`email`) = %s", (email.lower(),)) if cursor.fetchone() is not None: raise ApiException([Error(ErrorCode.EMAIL_REGISTERED, email)]) return True
def create(self, pool_id, size, group_id=None): cephpool = self.storage_api.get_pool_by_id(pool_id) if not cephpool: raise Error(ERR_VOLUME_CREATE_NOPOOL) if type(size) != int or size <= 0: raise Error(ERR_INT_VOLUME_SIZE) return self.manager.create_volume(cephpool, size, group_id)
def resize(self, volume_id, size): volume = self.get_volume_by_id(volume_id) if not self.quota.group_quota_validate(volume.group_id, size, volume.size): raise Error(ERR_VOLUME_QUOTA_G) if not self.quota.volume_quota_validate(volume.group_id, size): raise Error(ERR_VOLUME_QUOTA_V) if self.storage_api.resize(volume.cephpool_id, volume.id, size): return volume.resize(size) else: raise Error(ERR_CEPH_RESIZE)
def restore_disk(self, image_id, archive_disk_name): try: disk_name = archive_disk_name[2:38] except: raise Error(ERR_DISK_NAME) if not self._valid_diskname(disk_name): raise Error(ERR_DISK_NAME) image = self.manager.get_image_by_id(image_id) if self.storage_api.mv(image.cephpool_id, archive_disk_name, disk_name): return True return False
def create(self, group_id, size): group = self.group_api.get_group_by_id(group_id) if not self.quota.group_quota_validate(group_id, size): raise Error(ERR_VOLUME_QUOTA_G) if not self.quota.volume_quota_validate(group_id, size): raise Error(ERR_VOLUME_QUOTA_V) cephpool = self.storage_api.get_volume_pool_by_center_id( group.center_id) if not cephpool: raise Error(ERR_VOLUME_CREATE_NOPOOL) if type(size) != int or size <= 0: raise Error(ERR_INT_VOLUME_SIZE) return self.manager.create_volume(cephpool, size, group_id)
def restore_disk(self, image_id, archive_disk_name, disk_name=None): try: if not disk_name: disk_name = archive_disk_name[17:] except: raise Error(ERR_DISK_NAME) if not self._valid_diskname(disk_name): raise Error(ERR_DISK_NAME) image = self.manager.get_image_by_id(image_id) if self.storage_api.mv(image.cephpool_id, archive_disk_name, disk_name): self._batch_update_disk_of_disk_snap(archive_disk_name, disk_name) return True return False
def rm_disk(self, image_id, disk_name): image = self.manager.get_image_by_id(image_id) if not self._valid_diskname(disk_name): raise Error(ERR_DISK_NAME) if self.storage_api.rm(image.cephpool_id, disk_name): return self._batch_delete_snaps_db_by_disk_name(disk_name) return False
def login(*args, **kwargs): if request.method == 'GET': kwargs['next'] = request.values.get('next') return render_template('login.html', **kwargs) username = request.form.get('username') # TODO implement salt as soon as available password = request.form.get('password') is_banned, ban_reason = User.is_banned(username) if is_banned: raise ApiException([Error(ErrorCode.LOGIN_DENIED_BANNED, ban_reason)]) user = User.get_by_username(username) hashed_password = password if len(password) == 64 else sha256( password.encode()).hexdigest() if user is None or user.password != hashed_password: kwargs['next'] = request.values.get('next') return render_template('login.html', **kwargs) login_user(user, remember=True) redirect_url = request.values.get('next') if not redirect_url_is_valid(redirect_url): return abort(400) return redirect(redirect_url)
def get_domain(self, host_ipv4, vm_uuid): conn = self._get_connection(host_ipv4) try: d = conn.lookupByUUIDString(vm_uuid) return d except: raise Error(ERR_VM_MISSING)
class URIMapper: def __init__(self): self.dict = Dictionary() self.authen = Authentication() self.course = Course() self.error = Error() def execute(self, environ): path = environ['PATH_INFO'] #----- dictionary group ----- if path.startswith('/lookup:'): return self.dict.lookup(environ) #----- authentication group ----- elif path.startswith('/register:'): return self.authen.register(environ) elif path.startswith('/login:'******'/logout:'): return self.authen.logout(environ) #----- learning group ----- elif path.startswith('/levels:'): return self.course.levels(environ) elif path.startswith('/lessons:'): return self.course.lessons(environ) elif path.startswith('/listen:'): return self.course.listen(environ) else: return self.error.bad_request()
def maps_upload(): """ Creates a new map in the system **Example Request**: .. sourcecode:: http POST /maps/upload **Example Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript "ok" :query file file: The file submitted (Must be ZIP) :type: zip """ file = request.files.get('file') metadata_string = request.form.get('metadata') if not file: raise ApiException([Error(ErrorCode.UPLOAD_FILE_MISSING)]) if not metadata_string: raise ApiException([Error(ErrorCode.UPLOAD_METADATA_MISSING)]) if not file_allowed(file.filename): raise ApiException([ Error(ErrorCode.UPLOAD_INVALID_FILE_EXTENSION, *ALLOWED_EXTENSIONS) ]) metadata = json.loads(metadata_string) with tempfile.TemporaryDirectory() as temp_dir: temp_map_path = os.path.join(temp_dir, secure_filename(file.filename)) file.save(temp_map_path) process_uploaded_map(temp_map_path, metadata.get('is_ranked', False)) return "ok"
def delete(self, volume_id, force=False): volume = self.get_volume_by_id(volume_id) if volume.vm: raise Error(ERR_DEL_MOUNTED_VOLUME) cephpool_id = volume.cephpool_id tmp_volume_name = 'x_' + volume_id if self.storage_api.mv(cephpool_id, volume_id, tmp_volume_name): if not volume.delete(): self.storage_api.mv(cephpool_id, tmp_volume_name, volume_id) return False if force == True: if not self.storage_api.rm(cephpool_id, tmp_volume_name): print(ERR_CEPH_RM) else: raise Error(ERR_CEPH_MV) return True
def migrate_vm(self, vm_uuid, host_id): #参数验证 vm = self.manager.get_vm_by_uuid(vm_uuid) host = self.host_api.get_host_by_id(host_id) #判断是否在同一个center if vm.center_id != host.center_id: raise Error(ERR_VM_MIGRATE_DIFF_CEPH) #是否关机 if vm.is_running(): raise Error(ERR_VM_MIGRATE_LIVING) #在新宿主机上创建 image_info = self.image_api.get_image_info_by_id(vm.image_id) xml_tpl = self.image_api.get_xml_tpl(vm.image_id) xml_desc = xml_tpl % { 'name': vm_uuid, 'uuid': vm_uuid, 'mem': vm.mem, 'vcpu': vm.vcpu, 'ceph_uuid': image_info['ceph_uuid'], 'ceph_pool': image_info['ceph_pool'], 'diskname': vm.disk, 'ceph_host': image_info['ceph_host'], 'ceph_port': image_info['ceph_port'], 'ceph_username': image_info['ceph_username'], 'mac': vm.mac, 'bridge': vm.br } if self.host_api.host_claim(host_id, vm.vcpu, vm.mem, 1): try: old_host_id = vm.host_id if self.manager.migrate(vm_uuid, host_id, host.ipv4, xml_desc): self.host_api.host_release(old_host_id, vm.vcpu, vm.mem, 1) return True except Exception as e: self.host_api.host_release(host_id, vm.vcpu, vm.mem, 1) if type(e) == Error: raise e else: self.host_api.host_release(host_id, vm.vcpu, vm.mem, 1) return False
def update_steps(achievement_id, player_id, steps, steps_function): """Increments the steps of an achievement. This function is NOT an endpoint. :param achievement_id: ID of the achievement to increment :param player_id: ID of the player to increment the achievement for :param steps: The number of steps to increment :param steps_function: The function to use to calculate the new steps value. Two parameters are passed; the current step count and the parameter ``steps`` :return: If successful, this method returns a dictionary with the following structure:: { "current_steps": integer, "current_state": string, "newly_unlocked": boolean, } """ achievement = achievements_get(achievement_id)['data']['attributes'] if achievement['type'] != 'INCREMENTAL': raise ApiException([Error(ErrorCode.ACHIEVEMENT_CANT_INCREMENT_STANDARD, achievement_id)]) with db.connection: cursor = db.connection.cursor(db.pymysql.cursors.DictCursor) cursor.execute("""SELECT current_steps, state FROM player_achievements WHERE achievement_id = %s AND player_id = %s""", (achievement_id, player_id)) player_achievement = cursor.fetchone() new_state = 'REVEALED' newly_unlocked = False current_steps = player_achievement['current_steps'] if player_achievement else 0 new_current_steps = steps_function(current_steps, steps) if new_current_steps >= achievement['total_steps']: new_state = 'UNLOCKED' new_current_steps = achievement['total_steps'] newly_unlocked = player_achievement['state'] != 'UNLOCKED' if player_achievement else True cursor.execute("""INSERT INTO player_achievements (player_id, achievement_id, current_steps, state) VALUES (%(player_id)s, %(achievement_id)s, %(current_steps)s, %(state)s) ON DUPLICATE KEY UPDATE current_steps = VALUES(current_steps), state = VALUES(state)""", { 'player_id': player_id, 'achievement_id': achievement_id, 'current_steps': new_current_steps, 'state': new_state, }) return dict(current_steps=new_current_steps, current_state=new_state, newly_unlocked=newly_unlocked)
def define(self, host_ipv4, xml_desc): conn = self._get_connection(host_ipv4) try: dom = conn.defineXML(xml_desc) # print(dom) except Exception as e: print(e) raise Error(ERR_VM_DEFINE) return dom
def __init__(self, db=None, volume_id=None): if db: self._db = db elif volume_id: try: self._db = DBCephVolume.objects.get(pk=volume_id) except: raise Error(ERR_VOLUME_ID) super().__init__()
def __init__(self, db=None, db_id=None): if db: self._db = db elif db_id: try: self._db = DBGPU.objects.get(pk=db_id) except: raise Error(ERR_GPU_ID) address = self._db.address.split(':') if len(address) != 4: raise Error(ERR_GPU_ADDRESS) self._domain = address[0] self._bus = address[1] self._slot = address[2] self._function = address[3] super().__init__()
def delete(self, volume_id, force=False): volume = self.get_volume_by_id(volume_id) if volume.vm: raise Error(ERR_DEL_MOUNTED_VOLUME) cephpool_id = volume.cephpool_id tmp_volume_name = 'x_{}_{}'.format( datetime.now().strftime("%Y%m%d%H%M%S"), volume_id) if self.storage_api.mv(cephpool_id, volume_id, tmp_volume_name): if not volume.delete(): self.storage_api.mv(cephpool_id, tmp_volume_name, volume_id) return False if force == True: if not self.storage_api.rm(cephpool_id, tmp_volume_name): print(ERR_CEPH_RM) else: raise Error(ERR_CEPH_MV) return True
def create_volume(self, cephpool, size, group_id, volume_id=None): if not volume_id: volume_id = str(uuid.uuid4()) create_success = cephpool.create(volume_id, size) if create_success: try: db = DBCephVolume() db.uuid = volume_id db.size = size db.cephpool_id = cephpool.id db.group_id = group_id db.save() except Exception as e: cephpool.rm(volume_id) raise Error(ERR_VOLUME_CREATE_DB) else: return volume_id else: raise Error(ERR_CEPH_CREATE)
def archive_disk(self, image_id, disk_name, archive_disk_name=None): if archive_disk_name == None: archive_disk_name = 'x_' + str( disk_name) + '_' + datetime.now().strftime("%Y%m%d%H%M%S%f") else: if not self._valid_diskname(disk_name): raise Error(ERR_DISK_NAME) image = self.manager.get_image_by_id(image_id) if self.storage_api.mv(image.cephpool_id, disk_name, archive_disk_name): return archive_disk_name return False
def unlock_achievement(achievement_id, player_id): """Unlocks a standard achievement. This function is NOT an endpoint. :param achievement_id: ID of the achievement to unlock :param player_id: ID of the player to unlock the achievement for :return: If successful, this method returns a dictionary with the following structure:: { "newly_unlocked": boolean, } """ newly_unlocked = False with db.connection: cursor = db.connection.cursor(db.pymysql.cursors.DictCursor) cursor.execute( 'SELECT type FROM achievement_definitions WHERE id = %s', achievement_id) achievement = cursor.fetchone() if achievement['type'] != 'STANDARD': raise ApiException([ Error(ErrorCode.ACHIEVEMENT_CANT_UNLOCK_INCREMENTAL, achievement_id) ]) cursor.execute( """SELECT state FROM player_achievements WHERE achievement_id = %s AND player_id = %s""", (achievement_id, player_id)) player_achievement = cursor.fetchone() new_state = 'UNLOCKED' newly_unlocked = not player_achievement or player_achievement[ 'state'] != 'UNLOCKED' cursor.execute( """INSERT INTO player_achievements (player_id, achievement_id, state) VALUES (%(player_id)s, %(achievement_id)s, %(state)s) ON DUPLICATE KEY UPDATE state = VALUES(state)""", { 'player_id': player_id, 'achievement_id': achievement_id, 'state': new_state, }) return dict(newly_unlocked=newly_unlocked)
def mods_upload(): """ Uploads a new mod into the system. **Example Request**: .. sourcecode:: http POST /mods/upload **Example Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: text/javascript "ok" :query file file: The file submitted (Must be ZIP) :type: zip """ file = request.files.get('file') if not file: raise ApiException([Error(ErrorCode.UPLOAD_FILE_MISSING)]) if not file_allowed(file.filename): raise ApiException([ Error(ErrorCode.UPLOAD_INVALID_FILE_EXTENSION, *ALLOWED_EXTENSIONS) ]) with tempfile.TemporaryDirectory() as temp_dir: temp_mod_path = os.path.join(temp_dir, secure_filename(file.filename)) file.save(temp_mod_path) process_uploaded_mod(temp_mod_path) return "ok"
def validate_username(name: str) -> bool: """ Checks correctness of a username Throws exception if the syntax does not fit or is already in use :param name: FAF username (Case sensitive) :return: true if no error occured """ # check for correct syntax if not USERNAME_REGEX.match(name): raise ApiException([Error(ErrorCode.INVALID_USERNAME, name)]) with db.connection: cursor = db.connection.cursor() # ensure that username is unique cursor.execute("SELECT id FROM `login` WHERE LOWER(`login`) = %s", (name.lower(),)) if cursor.fetchone() is not None: raise ApiException([Error(ErrorCode.USERNAME_TAKEN, name)]) return True
def extract(): url = request.json.get("url") if not url: raise Error("A value for 'url' is required.", 422) extractor = Extractor() extractor.fetch(url) extractor.parse() return jsonify({ "city": extractor.city, "locations": list(extractor.locations) })
def reset_vm(self, vm_uuid): vm = self.manager.get_vm_by_uuid(vm_uuid) if vm.is_running(): raise Error(ERR_VM_RESET_LIVING) archive_disk_name = self.image_api.archive_disk(vm.image_id, vm.disk) if archive_disk_name != False: init_disk_success = self.image_api.init_disk(vm.image_id, vm.disk) if init_disk_success: if vm.start(): return True self.image_api.rm_disk(vm.image_id, vm.disk) self.image_api.restore_disk(vm.image_id, archive_disk_name) return False
def get_page_attributes(max_page_size, request): raw_page_size = request.values.get('page[size]', max_page_size) try: page_size = int(raw_page_size) if page_size > max_page_size: raise ApiException( [Error(ErrorCode.QUERY_INVALID_PAGE_SIZE, page_size)]) except ValueError: raise ApiException( [Error(ErrorCode.QUERY_INVALID_PAGE_SIZE, raw_page_size)]) raw_page = request.values.get('page[number]', 1) try: page = int(raw_page) if page < 1: raise ApiException( [Error(ErrorCode.QUERY_INVALID_PAGE_NUMBER, page)]) except ValueError: raise ApiException( [Error(ErrorCode.QUERY_INVALID_PAGE_NUMBER, raw_page)]) return page, page_size
def get_order_by(sort_expression, valid_fields): """ Converts the `sort_expression` into an "order by" if all fields are in `field_expression_dict` Example usage:: sort_expression = 'likes,-timestamp' field_expression_dict = { 'id': 'map.uid', 'timestamp': 'UNIX_TIMESTAMP(t.date)', 'likes': 'feature.likes' } get_order_by(sort_expression, field_expression_dict) Result:: "ORDER BY likes ASC, timestamp DESC" :param sort_expression: a json-api conform sort expression (see example above) :param valid_fields: a list of valid sort fields :return: an MySQL conform ORDER BY string (see example above) or an empty string if `sort_expression` is None or empty """ if not sort_expression: return '' sort_expressions = sort_expression.split(',') order_bys = [] for expression in sort_expressions: if not expression or expression == '-': continue if expression[0] == '-': order = 'DESC' column = expression[1:] else: order = 'ASC' column = expression if column not in valid_fields: raise ApiException( [Error(ErrorCode.QUERY_INVALID_SORT_FIELD, column)]) order_bys.append('`{}` {}'.format(column, order)) if not order_bys: return '' return 'ORDER BY {}'.format(', '.join(order_bys))
class Handler: """Bộ điều khiển truy vấn và xác thực qua API. Các API key được quản lý qua công cụ api_manager trong gói admin kèm trong mã nguồn. Theo mặc định, API key chỉ có duy nhất 1 và không giới hạn lượt truy cập và độ trễ giữa mỗi lần truy câp. """ def __init__(self): self.m = URIMapper() self.error = Error() def _parse_request(self, path): try: info = path.split(':') request = info[1][:-1].replace("'&", '"&') # Normalize params = {} for keyword in request.split('"&'): pair = keyword.split("=") params[pair[0]] = urllib.unquote(pair[1][1:]) return params except: return 400 # Bad request def request_handler(self, environ, start_response): try: # check method if environ['REQUEST_METHOD'] != 'GET': info = '<error status_code="405" \ description="Phương thức này không được hệ thống hỗ trợ"/>' response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(info)))] start_response(status, response_headers) return [info] #-- get uri -- path = environ['PATH_INFO'].lstrip('/') path = urllib.unquote(path) # some tweak :-) if path == 'favicon.ico': response_headers = [('Content-type', 'text/xml'), ('Content-Length', 0)] start_response(status, response_headers) return [''] if path.startswith('about'): info = """<about author="AloneRoad" full_name="Phạm Tuấn Anh" email="*****@*****.**" mobile_phone="+84 167 345 0 799" message="Cảm ơn vì đã quan tâm ⍣ "/>""" response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(info)))] start_response(status, response_headers) return [info] #------ for documents------ elif path == '': # return api developer's guide doc = open(os.path.join(os.path.dirname(__file__), 'doc/build/html/index.html')).read() response_headers = [('Content-type', 'text/html'), ('Content-Length', str(len(doc)))] start_response(status, response_headers) return [doc] elif path in ['_static/nature.css', '_static/pygments.css', '_static/basic.css']: doc = open(os.path.join(os.path.dirname(__file__), 'doc/build/html/', path)).read() response_headers = [('Content-type', 'text/css'), ('Content-Length', str(len(doc)))] start_response(status, response_headers) return [doc] elif path in ['_static/jquery.js', '_static/doctools.js', '_static/jquery.js']: doc = open(os.path.join(os.path.dirname(__file__), 'doc/build/html/', path)).read() response_headers = [('Content-type', 'text/javascript'), ('Content-Length', str(len(doc)))] start_response(status, response_headers) return [doc] #----- end developer's guide ----- #----- get remote ip ----- ip_request = environ['REMOTE_ADDR'] ip_key = 'api::address="%s"?last_request' % ip_request _time = datetime.now() last_request = API_DB.get(ip_key) # get info if last_request: last_request = datetime.strptime(last_request, '%Y-%m-%d %H:%M:%S.%f') else: last_request = _time API_DB.set(ip_key, str(_time)) # set new info #----- Parse request ----- _params = self._parse_request(path) if _params == 400: xml = """<error status_code="400" description="Yêu cầu không hợp lệ"/>""" xml = __description__ % xml xml = pretty_xml(xml) response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml] else: try: key = 'api::api_key="%s"?last_call' % (_params['api_key']) except KeyError: xml = self.error.authen_error("Thiếu api_key") xml = __description__ % xml xml = pretty_xml(xml) response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml] API_DB.set(key, _time) total_key = 'api::api_key="%s"?total_request_per_day' % (_params['api_key']) total = API_DB.get(total_key) if total is None: xml = """<error status_code="401" description="api_key không hợp lệ"/>""" xml = __description__ % xml xml = pretty_xml(xml) response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml] delay_key = 'api::api_key="%s"?delay' % (_params['api_key']) limit = API_DB.get(delay_key) total_call_key = 'api::api_key="%s"?total_call' % (_params['api_key']) total_call = API_DB.get(total_call_key) delta = _time - last_request if delta.days != 0: API_DB.set(total_call_key, 0) # Check sum requests if int(total_call) >= int(total) and int(total) != 0: message = """ api_key này chỉ được phép sử dụng %s lần một ngày """ % total xml = """ <error status_code="403" description="%s"/> """ % message xml = __description__ % xml xml = pretty_xml(xml) response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml] # Limit time per request elif (delta.seconds * 1e6 + delta.microseconds) < limit: message = """ Khoảng thời gian tối thiểu giữa 2 lần request phải lớn hơn %s mili-giây """ % (limit / 1000) xml = """ <error status_code="403" description="%s"/> """ % message xml = __description__ % xml xml = pretty_xml(xml) response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml] else: # accept request API_DB.set(total_call_key, int(total_call) + 1) # incr total call environ['request'] = self._parse_request(path) xml = self.m.execute(environ) xml = __description__ % xml xml = pretty_xml(xml) response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml] # Debug off | (on when KeyboardInterrupt) except KeyboardInterrupt: # pylint: disable-msg=W0702 message = """ Hệ thống gặp một lỗi chưa rõ nguyên nhân. Vui lòng báo lại cho bộ phận quản trị nếu gặp thông báo này """ xml = """ <error status_code="500" description="%s"/> """ % message xml = __description__ % xml response_headers = [('Content-type', 'text/xml'), ('Content-Length', str(len(xml)))] start_response(status, response_headers) return [xml]
def __init__(self): self.cache = KeyValueDatabase() client = connect(cassandra_hosts) self.u = ColumnFamily(client, cassandra_keyspace, 'Users', super=True) self.error = Error()
class Course: def __init__(self): self.cache = KeyValueDatabase() client = connect(cassandra_hosts) self.u = ColumnFamily(client, cassandra_keyspace, 'Users', super=True) self.error = Error() def refresh(self): self.cache.flush() def _levels(self, lang='en'): key = 'levels_%s' % (lang) results = self.cache.get(key) if results: return results try: parent_folder = unicode(os.path.join(data_folder, lang)) _levels = os.listdir(parent_folder) if _levels == []: return self.error.not_found("Chưa có dữ liệu") results = [] # get only folder names for level in _levels: if os.path.isdir(os.path.join(parent_folder, level)): results.append(level) results = sorted(results) self.cache.set(key, results) return results except OSError: return 404 def _lessons(self, level, lang='en'): key = 'lessons_%s_%s' % (level, lang) results = self.cache.get(key) if results: return results try: parent_folder = unicode(os.path.join(data_folder, lang)) parent_folder = os.path.join(parent_folder, level) _lessons = os.listdir(parent_folder) if _lessons == []: return self.error.not_found("Chưa có dữ liệu") results = [] for lesson in _lessons: if os.path.isdir(os.path.join(parent_folder, lesson)): results.append(lesson) results = sorted(results) self.cache.set(key, results) return results except OSError: return 404 def _listen(self, level, lesson, lang='en'): key = 'listen_%s_%s_%s' % (level, lesson, lang) results = self.cache.get(key) if results: return results try: parent_folder = unicode(os.path.join(data_folder, lang, level, lesson)) audio = os.listdir(parent_folder) if audio == []: return self.error.not_found("Chưa có dữ liệu") results = [] for i in audio: title = None description = None if i.endswith('.inf'): # add '\t' to detect end string when replace i = i + '\t' amr = os.path.join(parent_folder, i.replace('.inf\t', '.amr')) if not os.path.exists(amr): # check amr file exist return 404 i = i.replace('\t', '') # restore i # file inf chứa 2 biến là title và description cmd = open(os.path.join(parent_folder, i)) exec(cmd) # thực hiện chuỗi như là 1 lệnh info = {'title': title, 'description': description, 'audio_file': amr.replace(data_folder, '')} results.append(info) results = sorted(results) self.cache.set(key, results) return results except OSError: return 404 def levels(self, environ): try: lang = environ['request']['lang'] if lang not in ('en', 'vi'): return self.error.param_error("Hệ thống chỉ hỗ trợ 2 ngôn ngữ là en và vi") session_id = environ['request']['session_id'] except KeyError: return self.error.authen_error() try: self.u.get('session_id', super_column=session_id) except (NotFoundException, InvalidRequestException): return self.error.authen_error() results = self._levels(lang) if results == 404: return self.error.not_found("Cấu hình hệ thống sai") xml = ['<level name="%s"/>' % result for result in results] return '\n\t'.join(xml) def lessons(self, environ): try: level = environ['request']['level'] lang = environ['request']['lang'] if lang not in ('en', 'vi'): return self.error.param_error("Hệ thống chỉ hỗ trợ 2 ngôn ngữ là en và vi") session_id = environ['request']['session_id'] except KeyError: return self.error.authen_error() try: self.u.get('session_id', super_column=session_id) except (NotFoundException, InvalidRequestException): return self.error.authen_error() results = self._lessons(level, lang) if results == 404: return self.error.not_found("Cấu hình hệ thống sai") xml = ['<lesson name="%s"/>' % result for result in results] return '\n\t'.join(xml) def listen(self, environ): try: level = environ['request']['level'] lang = environ['request']['lang'] if lang not in ('en', 'vi'): return self.error.param_error("Hệ thống chỉ hỗ trợ 2 ngôn ngữ là en và vi") lesson = environ['request']['lesson'] session_id = environ['request']['session_id'] except KeyError: return self.error.authen_error() try: self.u.get('session_id', super_column=session_id) except (NotFoundException, InvalidRequestException): return self.error.authen_error() results = self._listen(level, lesson, lang) if results == 404: return self.error.not_found("Cấu hình hệ thống sai") xml = ['<audio title="%s" description="%s" link="%s"/>' \ % (x['title'], x['description'], audio_url_prefix + x['audio_file']) \ for x in results] return '\n\t'.join(xml)
def __init__(self): self.dict = Dictionary() self.authen = Authentication() self.course = Course() self.error = Error()
def __init__(self): self.m = URIMapper() self.error = Error()