示例#1
0
async def api_register_user(*, email, name, passwd):
    if not name or not name.strip():
        raise APIValueError('name')
    if not email or not _RE_EMAIL.match(email):
        raise APIValueError('email')
    if not passwd or not _RE_SHA1.match(passwd):
        raise APIValueError('passwd')
    users = await User.findAll('email=?', [email])
    if len(users) > 0:
        raise APIValueError('register:failed', 'email',
                            'Email is already in used.')
    uid = next_id()
    sha1_passwd = '%s:%s' % (uid, passwd)
    user = User(id=uid,
                name=name.strip(),
                email=email,
                passwd=hashlib.sha1(sha1_passwd.encode('utf-8')).hexdigest(),
                image='http://www.gravatar.com/avatar/%s?d=mm&s=120' %
                hashlib.md5(email.encode('utf-8')).hexdigest())
    await user.save()
    r = web.Response()
    r.set_cookie(COOKIE_NAME,
                 user2cookie(user, 86400),
                 max_age=86400,
                 httponly=True)
    user.passwd = '******'
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r
示例#2
0
async def authenticate(*, email, passwd):
    if not email:
        raise APIValueError('email', '请填写邮箱地址')
    if not passwd:
        raise APIValueError('passwd', '请填写密码')
    users = await User.findAll('email=?', [email])
    if len(users) == 0:
        raise APIValueError('email', '邮箱不存在')
    user = users[0]
    # check passwd:
    sha1 = hashlib.sha1()
    sha1.update(user.id.encode('utf-8'))
    sha1.update(b':')
    sha1.update(passwd.encode('utf-8'))
    if user.passwd != sha1.hexdigest():
        raise APIValueError('passwd', '密码错误')
    # authenticate ok, set cookie:
    r = web.Response()
    r.set_cookie(COOKIE_NAME,
                 user2cookie(user, 86400),
                 max_age=86400,
                 httponly=True)
    user.passwd = '******'
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r
示例#3
0
def api_ceate_user(*, name, password):
    '''
    Create user. Request url: [POST /api/users]

    Post data:

        name: user name

        password: user password
    '''
    if not name or not name.strip():
        raise APIValueError('name')
    if not password or not password.strip():
        raise APIValueError('password')

    name = name.strip()
    password = hashlib.sha1(password.strip().encode('utf-8')).hexdigest()
    users = yield from User.findall(where="name='%s'" % name)
    if len(users) > 0:
        raise APIError(errors.EUSER_ALREADY_EXISTS, 'User %s already exist' % name)

    user = User(id=uuid.uuid4().hex, name=name, password=password)
    yield from user.save()
    yield from log_event(logging.INFO, event_user, event_action_add,
                         'Add user %s' % name)
    return dict(retcode=0, user=user)
示例#4
0
def api_update_vg(id, request, *, name):
    '''
    Update volume group. Request url [POST /api/vgs/{id}]

    Post data:

        id: volume group id

        name: volume group name
    '''
    if not name or not name.strip():
        raise APIValueError('name:%s' % name)

    if not re.match(r'^[a-z_A-Z0-9]{1,20}', name):
        raise APIValueError("name")

    vg = yield from VG.find(id)
    if not vg:
        raise APIResourceNotFoundError('vg %s' % id)
    yield from _vg_rename(vg.name, name)
    vg.name = name
    yield from vg.update()
    yield from log_event(logging.INFO, event_vg, event_action_mod,
                         'Update volume group name to %s.' % (vg.name))
    return dict(retcode=0, vg=vg)
async def api_update_blog(id, request, *, name, summary, content):
    check_admin(request)
    blog = await Blog.find(id)
    if not name or not name.strip():
        raise APIValueError('name', 'name cannot be empty.')
    if not summary or not summary.strip():
        raise APIValueError('summary', 'summary cannot be empty.')
    if not content or not content.strip():
        raise APIValueError('content', 'content cannot be empty.')
    blog.name = name.strip()
    blog.summary = summary.strip()
    blog.content = content.strip()
    await blog.update()
    return blog
示例#6
0
def post_comment(id, request, *, content):
    user = request.__user__
    blog = yield from Blogs.find(id)
    if not content or not content.strip():
        raise APIValueError('content', 'content can not be empty')
    if blog is None:
        raise APIValueError('BLOG',
                            'BLOG was not found, do not fu*k this site')
    new_content = content
    comment = Comment(blog_id=blog.id,
                      user_id=user.id,
                      user_name=user.name,
                      user_image=user.image,
                      content=new_content)
    yield from comment.save()
    return dict(status='success')
示例#7
0
async def api_create_blog(request, *, name, summary, content):
    check_admin(request)
    if not name or not name.strip():
        raise APIValueError('name', 'name cannot be empty.')
    if not summary or not summary.strip():
        raise APIValueError('summary', 'summary cannot be empty.')
    if not content or not content.strip():
        raise APIValueError('content', 'content cannot be empty.')
    blog = Blog(user_id=request.__user__.id,
                user_name=request.__user__.name,
                user_image=request.__user__.image,
                name=name.strip(),
                summary=summary.strip(),
                content=content.strip())
    await blog.save()
    return blog
示例#8
0
def api_create_vg(*, name, pv):
    '''
    Create volume group. Request url [POST /api/vgs]

    Post data:

        name: volume group name

        pv: physical volume array in json format. example: [/dev/md0, /dev/md1...]
    '''
    if not name or not name.strip():
        raise APIValueError('name')
    if not re.match(r'^[a-z_A-Z0-9]{1,20}', name):
        raise APIValueError("name")

    vg = yield from VG.findall(where="name='%s'" % name)
    if vg:
        return dict(retcode=501, message='Volume group %s already exists' % name)

    pvs_name = json.loads(pv)
    for pv_name in pvs_name:
            if not os.path.exists(pv_name):
                return dict(retcode=502, message='Invalid pv %s' % pv_name)

    if len(pvs_name) == 0:
        return dict(retcode=503, message='No physical volume')

    vgs = yield from _vg_create(name, pvs_name)
    if vgs is None or len(vgs) == 0:
        return dict(retcode=504, message='Create volume group %s failure' % name)

    for vg in vgs:
        if vg.name != name:
            continue
        # save vg
        yield from vg.save()
        yield from log_event(logging.INFO, event_vg, event_action_add,
                         'Create volume group %s.' % (vg.name))
        return dict(retcode=0, vg=vg)

    return dict(retcode=504, message='Create volume group %s failure' % name)
示例#9
0
def api_lvm_create(*, name, vgname, size):
    '''
    Create lvm. Request url:[POST /api/lvms]

    Post data:

        name: lvm name

        vgname: volume group name. reference:/api/vgs

        size: lvm size ends with unit, lvm size unit. [K, M, G, T, P]. example: 3.5T
    '''
    if not name or not name.strip():
        raise APIValueError('name')
    if not re.match(r'^[a-z_A-Z0-9]{1,20}', name):
        raise APIValueError("name")
    if not size or not size.strip():
        raise APIValueError('size')
    if not size[-1] in ['K', 'M', 'G', 'T', 'P']:
        raise APIValueError('size unit value should be [K,M,G,T,P]')

    # validate vg
    vgs = yield from _vg_display()
    vgs_name = [vg.name for vg in vgs]
    if vgname not in vgs_name:
        raise APIResourceNotFoundError("volumne group '%s' not found" % vgname)

    lvms = yield from _lvm_create(name, vgname, size)

    if lvms is None or len(lvms) == 0:
        return dict(retcode=604, message='create lvm failure')

    for lvm in lvms:
        if lvm.name != name:
            continue
        # save lvm
        yield from lvm.save()
        yield from log_event(logging.INFO, event_lvm, event_action_add,
                             'Create LVM %s, size:%s.' % (lvm.name, size))
        return dict(retcode=0, lvm=lvm)
    return dict(retcode=604, message='create lvm failure')
示例#10
0
def api_create_blog(request, *, blog_title, blog_tag, summary, content):
    check_user_admin_flag(request)
    if not blog_title or not blog_title.strip():
        raise APIValueError('blog_title', 'blog_title can not be empty')
    if not summary or not summary.strip():
        raise APIValueError('summary', 'summary can not be empty')
    if not content or not content.strip():
        raise APIValueError('content', 'content can not be empty')
    if not blog_tag or not blog_tag.strip():
        blog_tag = '默认分类'
    # 注意 这里请求了request 的user 等信息 实际上是因为在上面进行了确认
    blog = Blogs(user_id=request.__user__.id,
                 user_name=request.__user__.name,
                 user_image=request.__user__.image,
                 blog_title=blog_title.strip(),
                 summary=summary.strip(),
                 content=content.strip(),
                 tag=blog_tag)
    yield from blog.save()
    # 现在需要新增一个 保存后返回文章链接的功能
    blogs = yield from Blogs.find_all(OrderBy='created_time desc')
    recent_blog = blogs[0]
    blog_url = '/index.html?item=' + recent_blog['id']
    return {'new_url': blog_url}
示例#11
0
def api_register_user(*, email, name, password):
    if not name or not name.strip():
        raise APIValueError('name')
    if not password or not _re_sha1.match(password):
        raise APIValueError('password')
    if not email or not _re_email.match(email):
        raise APIValueError('email')
    users = yield from User.find_all('email=?', [email])
    # 排除注册过的email
    if len(users) > 0:
        raise APIError('register failed ', 'email',
                       'The email has already existed')
    uid = next_id()
    row_password_string = '%s:%s' % (uid, password)
    # 这个email 是因为用了gravatar的服务 只要email在上面有头像 你的博客里面就可以出现了 虽然没有什么叼用
    user = User(id=uid,
                name=name.strip(),
                email=email,
                password=hashlib.sha1(
                    row_password_string.encode('utf-8')).hexdigest(),
                image='/static/images/default-user.jpg')
    # % hashlib.md5(email.encode('utf-8')).hexdigest()
    yield from user.save()
    r = web.Response()
    encode_str = user.name + '-' + user.email
    fake_string = base64.b64encode(encode_str.encode(encoding="utf-8"))
    r.set_cookie('FakeCookie',
                 fake_string.decode('utf-8'),
                 max_age=86400,
                 httponly=False)
    r.set_cookie(COOKIE_NAME,
                 user2cookie(user, 86400),
                 max_age=86400,
                 httponly=True)
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    return r
示例#12
0
def authenticate(*, email, password):
    if not email:
        raise APIValueError('email')
    if not password:
        raise APIValueError('password')
    users = yield from User.find_all('email=?', [email])
    if len(users) == 0:
        raise APIValueError('email', 'email not found')
    user = users[0]
    sha1 = hashlib.sha1()
    # 这里根据加密方式还原
    sha1.update(user.id.encode('utf-8'))
    sha1.update(':'.encode('utf-8'))
    sha1.update(password.encode('utf-8'))
    if user.password != sha1.hexdigest():
        raise APIValueError('password', 'Invalid password')
    # 确认ok那么就开始设置cookie
    r = web.Response()
    # 这个http only 是为了防止跨域 xss 漏洞
    # 很尴尬的是 我弃用jinja模板现在又要给他启用 否则我要启用session验证(原因是为了安全)
    encode_str = user.name + '-' + user.email
    fake_string = base64.b64encode(encode_str.encode(encoding="utf-8"))
    r.set_cookie('FakeCookie',
                 fake_string.decode('utf-8'),
                 max_age=86400,
                 httponly=False)
    r.set_cookie(COOKIE_NAME,
                 user2cookie(user, 86400),
                 max_age=86400,
                 httponly=True)
    # 我测试看能不能设置多个cookie 一个仅仅用于前端的某些显示使用 结果证实是可以的 我可以不用session验证啦
    user.password = '******'
    r.content_type = 'application/json'
    r.body = json.dumps(user, ensure_ascii=False).encode('utf-8')
    # 有点意思 其实这里用dict 返回一样可以被jinja 模板给encode 被js 解析
    return r
示例#13
0
def api_update_lvm(id, request, *, name):
    '''
    Update lvm. Request url [POST /api/lvms/{id}]

    Post data:

        id: lvm id

        name: lvm name
    '''
    if not name or not name.strip():
        raise APIValueError('name:%s' % name)
    if not re.match(r'^[a-z_A-Z0-9]{1,20}', name):
        raise APIValueError("name")

    lvm = yield from LVM.find(id)
    if not lvm:
        raise APIResourceNotFoundError('vg %s' % id)
    yield from _lvm_rename(lvm.path, name)
    lvm.name = name
    yield from lvm.update()
    yield from log_event(logging.INFO, event_lvm, event_action_mod,
                         'Update LVM name to %s.' % (lvm.name))
    return dict(retcode=0, lvm=lvm)
示例#14
0
async def api_create_comment(id, request, *, content):
    user = request.__user__
    if user is None:
        raise APIPermissionError('Please signin first.')
    if not content or not content.strip():
        raise APIValueError('content')
    blog = await Blog.find(id)
    if blog is None:
        raise APIResourceNotFoundError('Blog')
    comment = Comment(blog_id=blog.id,
                      user_id=user.id,
                      user_name=user.name,
                      user_image=user.image,
                      content=content.strip())
    await comment.save()
    return comment
示例#15
0
def api_update_user(id, request, *, password):
    '''
    Update user. Request url: [POST /api/users/{id}]

    Post data:

        password: user new password
    '''
    user = yield from User.find(id)

    if user is None:
        raise APIResourceNotFoundError(id)
    if not password or not password.strip():
        raise APIValueError('Password can not be empty')

    user.password = hashlib.sha1(password.encode('utf-8')).hexdigest()
    yield from user.update()
    yield from log_event(logging.INFO, event_user, event_action_mod,
                         'Update user %s password' % user.name)
    return dict(retcode=0, user=user)
示例#16
0
def api_create_target(*, name, tid, type, lun):
    '''
    Create target. Request url:[POST /api/targets]

    Post data:

        name: target name

        tid: target id in numeric. ensure the tid is unique when exists multiple ipsan server

        type: 1-lvm; 2-disk;

        lun: lun device array. example: [/dev/vg0/lv0,...]
        ...
    '''
    if name is None or not name.strip():
        raise APIValueError('name')
    if not _re_target_name.match(name):
        raise APIValueError('name')

    if not type.isnumeric():
        raise APIValueError("type")

    if not tid.isnumeric():
        raise APIValueError("target id")

    tid = int(tid)

    if tid <= 0 or tid > 1000:  # assume max tid is 1000
        raise APIValueError("target id(number)")

    ct = int(type)

    # valid lun
    luns = json.loads(lun)
    if not luns or len(luns) == 0:
        raise APIValueError("lun")

    for lun in luns:
        if not os.path.exists(lun):
            raise APIValueError('Lun %s not exists' % lun)

    target = yield from Target.findall(where="tid=%s" % tid)
    if target and len(target) > 0:
        return dict(retcode=701, message='target id %s already exists' % tid)

    target = yield from Target.findall(where="name='%s'" % name)
    if target and len(target) > 0:
        return dict(retcode=700, message='target %s already exists' % name)

    # get tid from user input
    # tid = yield from _get_next_tid()
    # if tid is None:
    #    return dict(retcode=703, message='too many targets in this server')

    name = _iqn % name
    cmd = _tgtadm_new_target % (str(tid), name)
    # create target
    r = subprocess.call(cmd.split(' '))

    if r != 0:
        return dict(retcode=701, message='create target error')
    # enable all client to access target
    cmd = _tgtadm_acl_all % str(tid)
    r = subprocess.call(cmd.split(' '))
    if r != 0:
        return dict(retcode=701, message='enable target ACL to all failure')

    # add lun
    lid = 0  #lun id start from 1
    for lun in luns:
        lid += 1
        cmd = _tgtadm_new_lun % (str(tid), str(lid), lun)
        r = subprocess.call(cmd.split(' '))
        if r != 0:
            return dict(retcode=702,
                        message='add lun %s to target error' % lun)

    targets = yield from _get_targets()
    for target in targets:
        if target.iqn == name:
            target.id = uuid.uuid4().hex
            yield from target.save()
            for lun in target.luns:
                lun.id = uuid.uuid4().hex
                lun.tid = target.id
                yield from lun.save()
                if ct == 2:
                    r = yield from Disk.findall(where="device='%s'" % lun.name)
                    if r and len(r) > 0:
                        disk = r[0]
                        disk.used_by = target.id
                        disk.used_for = 2  # used for target
                        yield from disk.update()

            # save target
            _save_target(target)
            yield from log_event(logging.INFO, event_target, event_action_add,
                                 'Create target %s.' % (target.iqn))
            return dict(retcode=0, target=target)

    # create target error
    return dict(retcode=701, target='create target error')
示例#17
0
def api_create_array(*, name, level, chunk, disk, spare):
    '''
    Create array. Request url[POST /api/arrays]

    Post data:
        name: array name.

        level: array level. support RAID0, RAID1, RAID5, RAID6, RAID10.

        chunk: array chunk size. such as 64K,128K, 256K,512K. power of 2.

        disks: disk device array in json format. such as [/dev/sdb, /dev/sdc, /dev/sdd...]

        spares: spare disk device array in json format.
    '''

    if not re.match(r'^[a-z_A-Z0-9]{1,20}', name):
        raise APIValueError("name")
    array = yield from Array.findall(where="name='%s'" % name)
    if array:
        return dict(retcode=401, message='Array %s already exists' % name)

    data_devname= json.loads(disk)
    spare_devname = json.loads(spare)

    disks = []
    spares = []

    # valid disk
    for dev in data_devname:
        r = yield from Disk.findall(where="device='%s'" % dev)
        if not r or len(r) == 0:
            raise APIResourceNotFoundError('%s' % dev)
        disks.append(r[0])

    for dev in spares:
        r = yield from Disk.findall(where="device='%s'" % dev)
        if not r or len(r) == 0:
            raise APIResourceNotFoundError('%s' % dev)
        spares.append(r[0])

    if len(disks) == 0:
        return dict(retcode=403, message='No available data disk')

    if not level.isnumeric():
        raise APIValueError('level')
    at_least_disk = {0: 2, 1: 2, 5: 3, 6: 3, 10: 2}
    level = int(level)
    if level not in at_least_disk:
        return dict(retcode=402, message='Invalid raid level %s' % level)
    if len(disks) < at_least_disk[level]:
        return dict(retcode=404, message='Raid %s need at least %s disks' %
                    (level, at_least_disk[level]))

    array_device = yield from _array_create(level, data_devname, chunk, spare_devname)

    if array_device is None:
        return dict(retcode=405, message='Create array failure.No available device')

    array = Array(name=name, device=array_device, level=level, chunk_size=chunk, created_at=int(time.time()))
    array = yield from _array_detail(array)
    yield from array.save()

    # update array id of each array disk
    for disk in  disks:
        disk.used_by = array.id
        disk.used_for = 1 # 1 for raid
        yield from disk.update()

    yield from log_event(logging.INFO, event_array, event_action_add,
                         'Create array %s.level:%s,data disk:%s,spare:%s' % (name, level, ','.join(data_devname), ','.join(spare_devname)))
    return dict(retcode=0, array=array)