Beispiel #1
0
 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])
Beispiel #2
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"
Beispiel #3
0
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})
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
    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)
Beispiel #7
0
 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)
Beispiel #8
0
 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
Beispiel #9
0
 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)
Beispiel #10
0
 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
Beispiel #11
0
 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
Beispiel #12
0
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)
Beispiel #13
0
 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)
Beispiel #14
0
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()
Beispiel #15
0
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"
Beispiel #16
0
    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
Beispiel #17
0
    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
Beispiel #18
0
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)
Beispiel #19
0
 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
Beispiel #20
0
 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__()
Beispiel #21
0
    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__()
Beispiel #22
0
    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
Beispiel #23
0
 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)
Beispiel #24
0
 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
Beispiel #25
0
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)
Beispiel #26
0
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"
Beispiel #27
0
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
Beispiel #28
0
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)
    })
Beispiel #29
0
 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
Beispiel #30
0
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
Beispiel #31
0
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))
Beispiel #32
0
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]
Beispiel #33
0
 def __init__(self):
     self.cache = KeyValueDatabase()
     client = connect(cassandra_hosts)
     self.u = ColumnFamily(client, cassandra_keyspace, 
                                         'Users', super=True)
     self.error = Error()
Beispiel #34
0
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)
Beispiel #35
0
 def __init__(self):
     self.dict = Dictionary()
     self.authen = Authentication()
     self.course = Course()
     self.error = Error()
Beispiel #36
0
 def __init__(self):
     self.m = URIMapper()
     self.error = Error()