Exemple #1
0
def request_password_reset(email, user_language) :
	user_obj = db.users.find_one({'profile.email': email})
	if user_obj is None :
		raise UserError('EMAIL_NOT_EXIST')
	reset_key = random_bytes_str(16)
	rdb.set('passreset-' + reset_key, email)
	send_noreply(email, '找回密码', '点击下方的链接重置密码:\n%s%s' % ('https://patchyvideo.com/resetpassword?key=', reset_key))
Exemple #2
0
def require_session(session_type):
    # TODO: add challenge code to redis
    if session_type not in ['LOGIN', 'SIGNUP']:
        raise UserError('INCORRECT_SESSION_TYPE')
    sid = binascii.hexlify(bytearray(random_bytes(16))).decode()
    rdb.set(sid, session_type, ex=UserConfig.SESSION_EXPIRE_TIME)
    log(obj={'sid': sid})
    return sid
Exemple #3
0
def _updateUserRedisValue(user_id, updater) :
	redis_user_key_lookup_key = f"user-{str(user_id)}"
	redis_user_key_ttl = rdb.ttl(redis_user_key_lookup_key)
	redis_user_key = rdb.get(redis_user_key_lookup_key)
	if redis_user_key :
		redis_user_obj_json = rdb.get(redis_user_key)
		if redis_user_obj_json :
			redis_user_obj = loads(redis_user_obj_json)
			redis_user_obj = updater(redis_user_obj)
			rdb.set(redis_user_key, dumps(redis_user_obj), ex = redis_user_key_ttl)
Exemple #4
0
def require_session(session_type, **kwargs) :
	# TODO: add challenge code to redis
	if session_type not in ['LOGIN', 'SIGNUP', 'LOGIN_OR_SIGNUP_OPENID_QQ'] :
		raise UserError('INCORRECT_SESSION_TYPE')
	sid = binascii.hexlify(bytearray(random_bytes(16))).decode()
	session_obj = {
		'type': session_type,
		'openid_qq': kwargs['openid_qq'] if session_type == 'LOGIN_OR_SIGNUP_OPENID_QQ' else ''
	}
	rdb.set(sid, dumps(session_obj), ex = UserConfig.SESSION_EXPIRE_TIME)
	log(obj = {'sid': sid})
	return sid
Exemple #5
0
def request_password_reset(email, user_language) :
	user_obj = db.users.find_one({'profile.email': email})
	if user_obj is None :
		raise UserError('EMAIL_NOT_EXIST')
	reset_key = random_bytes_str(16)
	rdb.set('passreset-' + reset_key, email)
	if user_language not in ['CHS', 'ENG'] :
		user_language = 'ENG'
	template_file = f'PatchyVideo-passreset-{user_language}.html'
	title = get_template_attribute(template_file, 'get_title')
	html_doc = render_template(template_file, key = reset_key)
	send_noreply(email, str(title()), html_doc, mime = 'html')
async def upload_image(request):
    data = await request.post()
    try:
        file_field = data['file']
        type_field = data['type']
        if type_field == 'cover':
            resolution = (320, 200)
            dst = _COVER_PATH
        elif type_field == 'userphoto':
            resolution = (256, 256)
            dst = _USERPHOTO_PATH
        else:
            return web.json_response(
                makeResponseFailed('INCORRECT_UPLOAD_TYPE'), dumps=dumps)
        content = file_field.file.read()
    except:
        return web.json_response(makeResponseFailed('INCORRECT_REQUEST'),
                                 dumps=dumps)
    if len(content) > UploadConfig.MAX_UPLOAD_SIZE:
        return web.json_response(makeResponseFailed('FILE_TOO_LARGE'),
                                 dumps=dumps)
    try:
        img = Image.open(io.BytesIO(content))
        if img is None:
            raise Exception()
    except:
        return web.json_response(makeResponseFailed('UNRECOGNIZED_IMAGE_FILE'),
                                 dumps=dumps)
    if isinstance(img, PIL.GifImagePlugin.GifImageFile):
        filename = random_bytes_str(24) + ".gif"
        frames = ImageSequence.Iterator(img)
        frames = _gif_thumbnails(frames, resolution)
        om = next(frames)  # Handle first frame separately
        om.info = img.info  # Copy sequence info
        om.save(dst + filename,
                save_all=True,
                append_images=list(frames),
                loop=0)
    else:
        filename = random_bytes_str(24) + ".png"
        img.thumbnail(resolution, Image.ANTIALIAS)
        img.save(dst + filename)
    file_key = "upload-image-" + random_bytes_str(16)
    rdb.set(file_key, filename)
    log('fe_upload_image',
        obj={
            'filename': filename,
            'file_key': file_key,
            'size': len(content)
        })
    return web.json_response(makeResponseSuccess({'file_key': file_key}),
                             dumps=dumps)
async def upload_image_url(request):
    data = await request.json()
    try:
        url = data['url']
        if data['type'] == 'cover':
            resolution = (320, 200)
            dst = _COVER_PATH
        elif data['type'] == 'userphoto':
            resolution = (256, 256)
            dst = _USERPHOTO_PATH
        else:
            return web.json_response(
                makeResponseFailed('INCORRECT_UPLOAD_TYPE'), dumps=dumps)
    except:
        return web.json_response(makeResponseFailed('INCORRECT_REQUEST'),
                                 dumps=dumps)
    async with ClientSession() as session:
        async with session.get(url) as resp:
            if resp.status == 200:
                try:
                    img = Image.open(io.BytesIO(await resp.read()))
                    if isinstance(img, PIL.GifImagePlugin.GifImageFile):
                        filename = random_bytes_str(24) + ".gif"
                        frames = ImageSequence.Iterator(img)
                        frames = _gif_thumbnails(frames, resolution)
                        om = next(frames)  # Handle first frame separately
                        om.info = img.info  # Copy sequence info
                        om.save(dst + filename,
                                save_all=True,
                                append_images=list(frames),
                                loop=0)
                    else:
                        filename = random_bytes_str(24) + ".png"
                        img.thumbnail(resolution, Image.ANTIALIAS)
                        img.save(dst + filename)
                except:
                    return web.json_response(
                        makeResponseFailed('INCORRECT_UPLOAD_TYPE'),
                        dumps=dumps)
            else:
                return web.json_response(
                    makeResponseFailed('INCORRECT_UPLOAD_TYPE'), dumps=dumps)
    file_key = "upload-image-" + random_bytes_str(16)
    rdb.set(file_key, filename)
    log('fe_upload_image_url',
        obj={
            'filename': filename,
            'file_key': file_key
        })
    return web.json_response(makeResponseSuccess({'file_key': file_key}),
                             dumps=dumps)
Exemple #8
0
def login(username, password, challenge, login_session_id) :
	log(obj = {'username': username, 'challenge': challenge, 'login_session_id': login_session_id})
	if len(username) > UserConfig.MAX_USERNAME_LENGTH :
		raise UserError('USERNAME_TOO_LONG')
	if len(username) < UserConfig.MIN_USERNAME_LENGTH :
		raise UserError('USERNAME_TOO_SHORT')
	if len(password) > UserConfig.MAX_PASSWORD_LENGTH :
		raise UserError('PASSWORD_TOO_LONG')
	if len(password) < UserConfig.MIN_PASSWORD_LENGTH :
		raise UserError('PASSWORD_TOO_SHORT')
	if verify_session(login_session_id, 'LOGIN') :
		user_obj = db.users.find_one({'profile.username': username})
		if not user_obj :
			log(level = 'SEC', obj = {'msg': 'USER_NOT_EXIST'})
			raise UserError('INCORRECT_LOGIN')
		if not verify_password_PBKDF2(password, user_obj['crypto']['salt1'], user_obj['crypto']['password_hashed']) :
			log(level = 'SEC', obj = {'msg': 'WRONG_PASSWORD'})
			raise UserError('INCORRECT_LOGIN')
		user_id = str(user_obj['_id'])
		redis_user_key_lookup_key = f"user-{user_id}"
		redis_user_key = rdb.get(redis_user_key_lookup_key)
		logged_in = False
		if redis_user_key :
			# user already logged in on some other machines
			redis_user_obj_json_str = rdb.get(redis_user_key)
			if redis_user_obj_json_str :
				logged_in = True
				# reset expire time
				rdb.set(redis_user_key, redis_user_obj_json_str, ex = UserConfig.LOGIN_EXPIRE_TIME)
				rdb.set(redis_user_key_lookup_key, redis_user_key, ex = UserConfig.LOGIN_EXPIRE_TIME)

		if logged_in :
			return redis_user_key, user_obj['profile']

		common_user_obj = {
			'_id': user_obj['_id'],
			'profile': {
				'username': user_obj['profile']['username'],
				'image': user_obj['profile']['image'],
				'desc': user_obj['profile']['desc']
			},
			'access_control': user_obj['access_control'],
			'settings': user_obj['settings']
		}
		redis_user_value = dumps(common_user_obj)
		redis_user_key = binascii.hexlify(bytearray(random_bytes(16))).decode()
		redis_user_key_lookup_key = f"user-{user_obj['_id']}"
		rdb.set(redis_user_key, redis_user_value, ex = UserConfig.LOGIN_EXPIRE_TIME)
		rdb.set(redis_user_key_lookup_key, redis_user_key, ex = UserConfig.LOGIN_EXPIRE_TIME)
		log(obj = {'redis_user_key': redis_user_key, 'user': common_user_obj})
		return redis_user_key, common_user_obj['profile']
	raise UserError('INCORRECT_SESSION')
async def put_task(queue, param_json):
    task_id = random_bytes_str(16)
    param_json_for_user = copy.deepcopy(param_json)
    del param_json_for_user['user']
    del param_json_for_user['event_id']
    log_e(param_json['event_id'],
          param_json['user'],
          op='put_task',
          obj={'task_id': task_id})
    ret_json = dumps({
        'finished': False,
        'key': task_id,
        'data': None,
        'params': param_json_for_user
    })
    rdb.set(f'task-playlist-{task_id}', ret_json)
    key = 'post-playlist-tasks-' + str(param_json['user']['_id'])
    rdb.lpush(key, task_id)
    await queue.put((param_json, task_id))
    return task_id
Exemple #10
0
def do_login(user_obj) :
	user_id = str(user_obj['_id'])
	redis_user_key_lookup_key = f"user-{user_id}"
	redis_user_key = rdb.get(redis_user_key_lookup_key)
	logged_in = False
	if redis_user_key :
		# user already logged in on some other machines
		redis_user_obj_json_str = rdb.get(redis_user_key)
		if redis_user_obj_json_str :
			logged_in = True
			# reset expire time
			rdb.set(redis_user_key, redis_user_obj_json_str, ex = UserConfig.LOGIN_EXPIRE_TIME)
			rdb.set(redis_user_key_lookup_key, redis_user_key, ex = UserConfig.LOGIN_EXPIRE_TIME)

	if logged_in :
		profile = user_obj['profile']
		profile['access_control_status'] = user_obj['access_control']['status']
		return redis_user_key, profile

	openid_qq = user_obj['profile']['openid_qq'] if 'openid_qq' in user_obj['profile'] else None
	common_user_obj = {
		'_id': user_obj['_id'],
		'profile': {
			'uid': str(user_obj['_id']),
			'username': user_obj['profile']['username'],
			'image': user_obj['profile']['image'],
			'desc': user_obj['profile']['desc'],
			'email': user_obj['profile']['email'],
			'bind_qq': True if openid_qq else False
		},
		'access_control': user_obj['access_control'],
		'settings': user_obj['settings']
	}
	redis_user_value = dumps(common_user_obj)
	redis_user_key = binascii.hexlify(bytearray(random_bytes(16))).decode()
	redis_user_key_lookup_key = f"user-{user_obj['_id']}"
	rdb.set(redis_user_key, redis_user_value, ex = UserConfig.LOGIN_EXPIRE_TIME)
	rdb.set(redis_user_key_lookup_key, redis_user_key, ex = UserConfig.LOGIN_EXPIRE_TIME)
	log(obj = {'redis_user_key': redis_user_key, 'user': common_user_obj})
	profile = common_user_obj['profile']
	profile['access_control_status'] = user_obj['access_control']['status']
	return redis_user_key, profile
Exemple #11
0
 async def _add_to_playlist(self, dst_playlist, event_id, user_global):
     if self.playlist_map[dst_playlist]:
         dst_rank = self.playlist_map[dst_playlist]['rank']
         playlist_ordered = self.playlist_map[dst_playlist]['all']
         try:
             # fast method
             async with RedisLockAsync(
                     rdb, "playlistEdit:" +
                     dst_playlist), MongoTransaction(client) as s:
                 cur_rank = 0
                 playlist = playlist_db.retrive_item(dst_playlist,
                                                     session=s())
                 if playlist is None:
                     raise UserError('PLAYLIST_NOT_EXIST')
                 if playlist["item"]["videos"] + len(
                         self.playlist_map[dst_playlist]
                     ['succeed']) > PlaylistConfig.MAX_VIDEO_PER_PLAYLIST:
                     raise UserError('VIDEO_LIMIT_EXCEEDED')
                 playlist_videos = playlist["item"]['videos']
                 for unique_id in playlist_ordered:
                     if unique_id in self.playlist_map[dst_playlist][
                             'succeed']:
                         (video_id, _, user) = self.playlist_map[
                             dst_playlist]['succeed'][unique_id]
                         if dst_rank == -1:
                             if filterOperation('editPlaylist', user,
                                                playlist, False):
                                 if addVideoToPlaylistLockFree(
                                         dst_playlist,
                                         video_id,
                                         user,
                                         playlist_videos,
                                         session=s()):
                                     playlist_videos += 1
                         else:
                             if filterOperation('editPlaylist', user,
                                                playlist, False):
                                 if insertIntoPlaylistLockFree(dst_playlist,
                                                               video_id,
                                                               dst_rank +
                                                               cur_rank,
                                                               user,
                                                               session=s()):
                                     cur_rank += 1
                 s.mark_succeed()
         except UserError as ue:
             # UserError, rereaise to upper level
             log_e(event_id, user_global, '_add_to_playlist', 'ERR', {
                 'ex': str(ex),
                 'tb': traceback.format_exc()
             })
             del self.playlist_map[dst_playlist]
             rdb.set(f'playlist-batch-post-event-{dst_playlist}', b'done')
             raise ue
         except Exception as ex:
             # if anything goes wrong, fallback to slow method
             log_e(event_id, user_global, '_add_to_playlist', 'ERR', {
                 'ex': str(ex),
                 'tb': traceback.format_exc()
             })
             cur_rank = 0
             for unique_id in playlist_ordered:
                 if unique_id in self.playlist_map[dst_playlist]['succeed']:
                     (video_id, _, user) = self.playlist_map[dst_playlist][
                         'succeed'][unique_id]
                     # ignore error, add next video
                     try:
                         if dst_rank == -1:
                             addVideoToPlaylist(dst_playlist, video_id,
                                                user)
                         else:
                             insertIntoPlaylist(dst_playlist, video_id,
                                                dst_rank + cur_rank, user)
                         cur_rank += 1
                     except:
                         pass
         log_e(
             event_id, user_global, '_add_to_playlist', 'MSG', {
                 'succedd': len(self.playlist_map[dst_playlist]['succeed']),
                 'all': len(self.playlist_map[dst_playlist]['all']),
                 'pid': dst_playlist
             })
         del self.playlist_map[dst_playlist]
         rdb.set(f'playlist-batch-post-event-{dst_playlist}', b'done')