def _get_user(ctx: rest.Context, bump_login: bool) -> Optional[model.User]: if not ctx.has_header('Authorization'): return None auth_token = None try: auth_type, credentials = ctx.get_header('Authorization').split(' ', 1) if auth_type.lower() == 'basic': username, password = base64.decodebytes( credentials.encode('ascii')).decode('utf8').split(':', 1) auth_user = _authenticate_basic_auth(username, password) elif auth_type.lower() == 'token': username, token = base64.decodebytes( credentials.encode('ascii')).decode('utf8').split(':', 1) auth_user, auth_token = _authenticate_token(username, token) else: raise HttpBadRequest( 'ValidationError', 'Only basic or token HTTP authentication is supported.') except ValueError as err: msg = ( 'Authorization header values are not properly formed. ' 'Supplied header {0}. Got error: {1}') raise HttpBadRequest( 'ValidationError', msg.format(ctx.get_header('Authorization'), str(err))) if bump_login and auth_user.user_id: users.bump_user_login_time(auth_user) if auth_token is not None: user_tokens.bump_usage_time(auth_token) ctx.session.commit() return auth_user
def _get_user(ctx: rest.Context, bump_login: bool) -> Optional[model.User]: if not ctx.has_header('Authorization'): return None auth_token = None try: auth_type, credentials = ctx.get_header('Authorization').split(' ', 1) if auth_type.lower() == 'basic': username, password = base64.decodebytes( credentials.encode('ascii')).decode('utf8').split(':', 1) auth_user = _authenticate_basic_auth(username, password) elif auth_type.lower() == 'token': username, token = base64.decodebytes( credentials.encode('ascii')).decode('utf8').split(':', 1) auth_user, auth_token = _authenticate_token(username, token) else: raise HttpBadRequest('ValidationError', '기본 및 토큰 HTTP 인증만을 지원합니다.') except ValueError as err: msg = ('인증 헤더 값이 적절한 형식이 아닙니다. ' '전달된 헤더 {0}. 오류: {1}') raise HttpBadRequest( 'ValidationError', msg.format(ctx.get_header('Authorization'), str(err))) if bump_login and auth_user.user_id: users.bump_user_login_time(auth_user) if auth_token is not None: user_tokens.bump_usage_time(auth_token) ctx.session.commit() return auth_user
def update_tag(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: tag = _get_tag(params) versions.verify_version(tag, ctx) versions.bump_version(tag) if ctx.has_param('names'): auth.verify_privilege(ctx.user, 'tags:edit:names') tags.update_tag_names(tag, ctx.get_param_as_string_list('names')) if ctx.has_param('category'): auth.verify_privilege(ctx.user, 'tags:edit:category') tags.update_tag_category_name( tag, ctx.get_param_as_string('category')) if ctx.has_param('description'): auth.verify_privilege(ctx.user, 'tags:edit:description') tags.update_tag_description( tag, ctx.get_param_as_string('description')) if ctx.has_param('suggestions'): auth.verify_privilege(ctx.user, 'tags:edit:suggestions') suggestions = ctx.get_param_as_string_list('suggestions') _create_if_needed(suggestions, ctx.user) tags.update_tag_suggestions(tag, suggestions) if ctx.has_param('implications'): auth.verify_privilege(ctx.user, 'tags:edit:implications') implications = ctx.get_param_as_string_list('implications') _create_if_needed(implications, ctx.user) tags.update_tag_implications(tag, implications) tag.last_edit_time = datetime.utcnow() ctx.session.flush() snapshots.modify(tag, ctx.user) ctx.session.commit() return _serialize(ctx, tag)
def update_tag(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: tag = _get_tag(params) versions.verify_version(tag, ctx) versions.bump_version(tag) if ctx.has_param("names"): auth.verify_privilege(ctx.user, "tags:edit:names") tags.update_tag_names(tag, ctx.get_param_as_string_list("names")) if ctx.has_param("category"): auth.verify_privilege(ctx.user, "tags:edit:category") tags.update_tag_category_name(tag, ctx.get_param_as_string("category")) if ctx.has_param("description"): auth.verify_privilege(ctx.user, "tags:edit:description") tags.update_tag_description(tag, ctx.get_param_as_string("description")) if ctx.has_param("suggestions"): auth.verify_privilege(ctx.user, "tags:edit:suggestions") suggestions = ctx.get_param_as_string_list("suggestions") _create_if_needed(suggestions, ctx.user) tags.update_tag_suggestions(tag, suggestions) if ctx.has_param("implications"): auth.verify_privilege(ctx.user, "tags:edit:implications") implications = ctx.get_param_as_string_list("implications") _create_if_needed(implications, ctx.user) tags.update_tag_implications(tag, implications) tag.last_edit_time = datetime.utcnow() ctx.session.flush() snapshots.modify(tag, ctx.user) ctx.session.commit() return _serialize(ctx, tag)
def process_request(ctx: rest.Context) -> None: ''' Bind the user to request. Update last login time if needed. ''' auth_user = _get_user(ctx) if auth_user: ctx.user = auth_user if ctx.get_param_as_bool('bump-login', default=False) and ctx.user.user_id: users.bump_user_login_time(ctx.user) ctx.session.commit()
def create_comment(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'comments:create') text = ctx.get_param_as_string('text') post_id = ctx.get_param_as_int('postId') post = posts.get_post_by_id(post_id) comment = comments.create_comment(ctx.user, post, text) ctx.session.add(comment) ctx.session.commit() return _serialize(ctx, comment)
def create_comment( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'comments:create') text = ctx.get_param_as_string('text') post_id = ctx.get_param_as_int('postId') post = posts.get_post_by_id(post_id) comment = comments.create_comment(ctx.user, post, text) ctx.session.add(comment) ctx.session.commit() return _serialize(ctx, comment)
def create_pool_category(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, "pool_categories:create") name = ctx.get_param_as_string("name") color = ctx.get_param_as_string("color") category = pool_categories.create_category(name, color) ctx.session.add(category) ctx.session.flush() snapshots.create(category, ctx.user) ctx.session.commit() return _serialize(ctx, category)
def create_tag_category( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'tag_categories:create') name = ctx.get_param_as_string('name') color = ctx.get_param_as_string('color') category = tag_categories.create_category(name, color) ctx.session.add(category) ctx.session.flush() snapshots.create(category, ctx.user) ctx.session.commit() return _serialize(ctx, category)
def create_tag_category( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'tag_categories:create') name = ctx.get_param_as_string('name') color = ctx.get_param_as_string('color') category = tag_categories.create_category(name, color) ctx.session.add(category) ctx.session.flush() snapshots.create(category, ctx.user) ctx.session.commit() tags.export_to_json() return _serialize(ctx, category)
def merge_tags(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: source_tag_name = ctx.get_param_as_string("remove") target_tag_name = ctx.get_param_as_string("mergeTo") source_tag = tags.get_tag_by_name(source_tag_name) target_tag = tags.get_tag_by_name(target_tag_name) versions.verify_version(source_tag, ctx, "removeVersion") versions.verify_version(target_tag, ctx, "mergeToVersion") versions.bump_version(target_tag) auth.verify_privilege(ctx.user, "tags:merge") tags.merge_tags(source_tag, target_tag) snapshots.merge(source_tag, target_tag, ctx.user) ctx.session.commit() return _serialize(ctx, target_tag)
def merge_tags( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: source_tag_name = ctx.get_param_as_string('remove') target_tag_name = ctx.get_param_as_string('mergeTo') source_tag = tags.get_tag_by_name(source_tag_name) target_tag = tags.get_tag_by_name(target_tag_name) versions.verify_version(source_tag, ctx, 'removeVersion') versions.verify_version(target_tag, ctx, 'mergeToVersion') versions.bump_version(target_tag) auth.verify_privilege(ctx.user, 'tags:merge') tags.merge_tags(source_tag, target_tag) snapshots.merge(source_tag, target_tag, ctx.user) ctx.session.commit() return _serialize(ctx, target_tag)
def merge_pools(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: source_pool_id = ctx.get_param_as_string("remove") target_pool_id = ctx.get_param_as_string("mergeTo") source_pool = pools.get_pool_by_id(source_pool_id) target_pool = pools.get_pool_by_id(target_pool_id) versions.verify_version(source_pool, ctx, "removeVersion") versions.verify_version(target_pool, ctx, "mergeToVersion") versions.bump_version(target_pool) auth.verify_privilege(ctx.user, "pools:merge") pools.merge_pools(source_pool, target_pool) snapshots.merge(source_pool, target_pool, ctx.user) ctx.session.commit() return _serialize(ctx, target_pool)
def merge_posts( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: source_post_id = ctx.get_param_as_int('remove') target_post_id = ctx.get_param_as_int('mergeTo') source_post = posts.get_post_by_id(source_post_id) target_post = posts.get_post_by_id(target_post_id) replace_content = ctx.get_param_as_bool('replaceContent') versions.verify_version(source_post, ctx, 'removeVersion') versions.verify_version(target_post, ctx, 'mergeToVersion') versions.bump_version(target_post) auth.verify_privilege(ctx.user, 'posts:merge') posts.merge_posts(source_post, target_post, replace_content) snapshots.merge(source_post, target_post, ctx.user) ctx.session.commit() return _serialize_post(ctx, target_post)
def execute_and_serialize( self, ctx: rest.Context, serializer: Callable[[model.Base], rest.Response]) -> rest.Response: query = ctx.get_param_as_string('query', default='') offset = ctx.get_param_as_int('offset', default=0, min=0) limit = ctx.get_param_as_int('limit', default=100, min=1, max=100) count, entities = self.execute(query, offset, limit) return { 'query': query, 'offset': offset, 'limit': limit, 'total': count, 'results': list([serializer(entity) for entity in entities]), }
def merge_posts(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: source_post_id = ctx.get_param_as_int('remove') target_post_id = ctx.get_param_as_int('mergeTo') source_post = posts.get_post_by_id(source_post_id) target_post = posts.get_post_by_id(target_post_id) replace_content = ctx.get_param_as_bool('replaceContent') versions.verify_version(source_post, ctx, 'removeVersion') versions.verify_version(target_post, ctx, 'mergeToVersion') versions.bump_version(target_post) auth.verify_privilege(ctx.user, 'posts:merge') posts.merge_posts(source_post, target_post, replace_content) snapshots.merge(source_post, target_post, ctx.user) ctx.session.commit() return _serialize_post(ctx, target_post)
def execute_and_serialize( self, ctx: rest.Context, serializer: Callable[[model.Base], rest.Response] ) -> rest.Response: query = ctx.get_param_as_string('query', default='') offset = ctx.get_param_as_int('offset', default=0, min=0) limit = ctx.get_param_as_int('limit', default=100, min=1, max=100) count, entities = self.execute(query, offset, limit) return { 'query': query, 'offset': offset, 'limit': limit, 'total': count, 'results': list([serializer(entity) for entity in entities]), }
def set_post_score(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: auth.verify_privilege(ctx.user, 'posts:score') post = _get_post(params) score = ctx.get_param_as_int('score') scores.set_score(post, ctx.user, score) ctx.session.commit() return _serialize_post(ctx, post)
def execute_and_serialize( self, ctx: rest.Context, serializer: Callable[[model.Base], rest.Response], ) -> rest.Response: query = ctx.get_param_as_string("query", default="") offset = ctx.get_param_as_int("offset", default=0, min=0) limit = ctx.get_param_as_int("limit", default=100, min=1, max=100) count, entities = self.execute(query, offset, limit) return { "query": query, "offset": offset, "limit": limit, "total": count, "results": list([serializer(entity) for entity in entities]), }
def verify_version(entity: model.Base, context: rest.Context, field_name: str = 'version') -> None: actual_version = context.get_param_as_int(field_name) expected_version = entity.version if actual_version != expected_version: raise errors.IntegrityError('다른 누군가 이미 수정하고 있습니다. ' + '다시 시도해 보세요.')
def create_user_token(ctx: rest.Context, params: Dict[str, str] = {}) -> rest.Response: user = users.get_user_by_name(params['user_name']) infix = 'self' if ctx.user.user_id == user.user_id else 'any' auth.verify_privilege(ctx.user, 'user_tokens:create:%s' % infix) enabled = ctx.get_param_as_bool('enabled', True) user_token = user_tokens.create_user_token(user, enabled) if ctx.has_param('note'): note = ctx.get_param_as_string('note') user_tokens.update_user_token_note(user_token, note) if ctx.has_param('expirationTime'): expiration_time = ctx.get_param_as_string('expirationTime') user_tokens.update_user_token_expiration_time(user_token, expiration_time) ctx.session.add(user_token) ctx.session.commit() return _serialize(ctx, user_token)
def create_pool(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, "pools:create") names = ctx.get_param_as_string_list("names") category = ctx.get_param_as_string("category") description = ctx.get_param_as_string("description", default="") posts = ctx.get_param_as_int_list("posts", default=[]) pool = pools.create_pool(names, category, posts) pool.last_edit_time = datetime.utcnow() pools.update_pool_description(pool, description) ctx.session.add(pool) ctx.session.flush() snapshots.create(pool, ctx.user) ctx.session.commit() return _serialize(ctx, pool)
def create_user_token( ctx: rest.Context, params: Dict[str, str] = {}) -> rest.Response: user = users.get_user_by_name(params['user_name']) infix = 'self' if ctx.user.user_id == user.user_id else 'any' auth.verify_privilege(ctx.user, 'user_tokens:create:%s' % infix) enabled = ctx.get_param_as_bool('enabled', True) user_token = user_tokens.create_user_token(user, enabled) if ctx.has_param('note'): note = ctx.get_param_as_string('note') user_tokens.update_user_token_note(user_token, note) if ctx.has_param('expirationTime'): expiration_time = ctx.get_param_as_string('expirationTime') user_tokens.update_user_token_expiration_time( user_token, expiration_time) ctx.session.add(user_token) ctx.session.commit() return _serialize(ctx, user_token)
def set_comment_score(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: auth.verify_privilege(ctx.user, "comments:score") score = ctx.get_param_as_int("score") comment = _get_comment(params) scores.set_score(comment, ctx.user, score) ctx.session.commit() return _serialize(ctx, comment)
def create_user_token(ctx: rest.Context, params: Dict[str, str] = {}) -> rest.Response: user = users.get_user_by_name(params["user_name"]) infix = "self" if ctx.user.user_id == user.user_id else "any" auth.verify_privilege(ctx.user, "user_tokens:create:%s" % infix) enabled = ctx.get_param_as_bool("enabled", True) user_token = user_tokens.create_user_token(user, enabled) if ctx.has_param("note"): note = ctx.get_param_as_string("note") user_tokens.update_user_token_note(user_token, note) if ctx.has_param("expirationTime"): expiration_time = ctx.get_param_as_string("expirationTime") user_tokens.update_user_token_expiration_time(user_token, expiration_time) ctx.session.add(user_token) ctx.session.commit() return _serialize(ctx, user_token)
def verify_version(entity: model.Base, context: rest.Context, field_name: str = 'version') -> None: actual_version = context.get_param_as_int(field_name) expected_version = entity.version if actual_version != expected_version: raise errors.IntegrityError( 'Someone else modified this in the meantime. ' + 'Please try again.')
def execute_and_serialize( self, ctx: rest.Context, serializer: Callable[[model.Base], rest.Response]) -> rest.Response: query = ctx.get_param_as_string('query', default='') page = ctx.get_param_as_int('page', default=1, min=1) page_size = ctx.get_param_as_int('pageSize', default=100, min=1, max=100) count, entities = self.execute(query, page, page_size) return { 'query': query, 'page': page, 'pageSize': page_size, 'total': count, 'results': [serializer(entity) for entity in entities], }
def update_tag_category( ctx: rest.Context, params: Dict[str, str]) -> rest.Response: category = tag_categories.get_category_by_name( params['category_name'], lock=True) versions.verify_version(category, ctx) versions.bump_version(category) if ctx.has_param('name'): auth.verify_privilege(ctx.user, 'tag_categories:edit:name') tag_categories.update_category_name( category, ctx.get_param_as_string('name')) if ctx.has_param('color'): auth.verify_privilege(ctx.user, 'tag_categories:edit:color') tag_categories.update_category_color( category, ctx.get_param_as_string('color')) ctx.session.flush() snapshots.modify(category, ctx.user) ctx.session.commit() return _serialize(ctx, category)
def update_pool_category(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: category = pool_categories.get_category_by_name(params["category_name"], lock=True) versions.verify_version(category, ctx) versions.bump_version(category) if ctx.has_param("name"): auth.verify_privilege(ctx.user, "pool_categories:edit:name") pool_categories.update_category_name(category, ctx.get_param_as_string("name")) if ctx.has_param("color"): auth.verify_privilege(ctx.user, "pool_categories:edit:color") pool_categories.update_category_color(category, ctx.get_param_as_string("color")) ctx.session.flush() snapshots.modify(category, ctx.user) ctx.session.commit() return _serialize(ctx, category)
def create_temporary_file(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'uploads:create') content = ctx.get_file('content', allow_tokens=False, use_video_downloader=auth.has_privilege( ctx.user, 'uploads:use_downloader')) token = file_uploads.save(content) return {'token': token}
def _get_user(ctx: rest.Context, bump_login: bool) -> Optional[model.User]: if not ctx.has_header("Authorization"): return None auth_token = None try: auth_type, credentials = ctx.get_header("Authorization").split(" ", 1) if auth_type.lower() == "basic": username, password = ( base64.decodebytes(credentials.encode("ascii")) .decode("utf8") .split(":", 1) ) auth_user = _authenticate_basic_auth(username, password) elif auth_type.lower() == "token": username, token = ( base64.decodebytes(credentials.encode("ascii")) .decode("utf8") .split(":", 1) ) auth_user, auth_token = _authenticate_token(username, token) else: raise HttpBadRequest( "ValidationError", "Only basic or token HTTP authentication is supported.", ) except ValueError as err: msg = ( "Authorization header values are not properly formed. " "Supplied header {0}. Got error: {1}" ) raise HttpBadRequest( "ValidationError", msg.format(ctx.get_header("Authorization"), str(err)), ) if bump_login and auth_user.user_id: users.bump_user_login_time(auth_user) if auth_token is not None: user_tokens.bump_usage_time(auth_token) ctx.session.commit() return auth_user
def verify_version( entity: model.Base, context: rest.Context, field_name: str = 'version') -> None: actual_version = context.get_param_as_int(field_name) expected_version = entity.version if actual_version != expected_version: raise errors.IntegrityError( 'Someone else modified this in the meantime. ' + 'Please try again.')
def update_tag_category( ctx: rest.Context, params: Dict[str, str]) -> rest.Response: category = tag_categories.get_category_by_name( params['category_name'], lock=True) versions.verify_version(category, ctx) versions.bump_version(category) if ctx.has_param('name'): auth.verify_privilege(ctx.user, 'tag_categories:edit:name') tag_categories.update_category_name( category, ctx.get_param_as_string('name')) if ctx.has_param('color'): auth.verify_privilege(ctx.user, 'tag_categories:edit:color') tag_categories.update_category_color( category, ctx.get_param_as_string('color')) ctx.session.flush() snapshots.modify(category, ctx.user) ctx.session.commit() tags.export_to_json() return _serialize(ctx, category)
def get_around_and_serialize( self, ctx: rest.Context, entity_id: int, serializer: Callable[[model.Base], rest.Response]) -> rest.Response: entities = self.get_around( ctx.get_param_as_string('query', default=''), entity_id) return { 'prev': serializer(entities[0]), 'next': serializer(entities[1]), }
def _get_user(ctx: rest.Context) -> Optional[model.User]: if not ctx.has_header('Authorization'): return None try: auth_type, credentials = ctx.get_header('Authorization').split(' ', 1) if auth_type.lower() != 'basic': raise HttpBadRequest( 'ValidationError', 'Only basic HTTP authentication is supported.') username, password = base64.decodebytes( credentials.encode('ascii')).decode('utf8').split(':') return _authenticate(username, password) except ValueError as err: msg = ('Basic authentication header value are not properly formed. ' 'Supplied header {0}. Got error: {1}') raise HttpBadRequest( 'ValidationError', msg.format(ctx.get_header('Authorization'), str(err)))
def update_comment(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: comment = _get_comment(params) versions.verify_version(comment, ctx) versions.bump_version(comment) infix = 'own' if ctx.user.user_id == comment.user_id else 'any' text = ctx.get_param_as_string('text') auth.verify_privilege(ctx.user, 'comments:edit:%s' % infix) comments.update_comment_text(comment, text) comment.last_edit_time = datetime.utcnow() ctx.session.commit() return _serialize(ctx, comment)
def create_tag( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'tags:create') names = ctx.get_param_as_string_list('names') category = ctx.get_param_as_string('category') description = ctx.get_param_as_string('description', default='') suggestions = ctx.get_param_as_string_list('suggestions', default=[]) implications = ctx.get_param_as_string_list('implications', default=[]) _create_if_needed(suggestions, ctx.user) _create_if_needed(implications, ctx.user) tag = tags.create_tag(names, category, suggestions, implications) tags.update_tag_description(tag, description) ctx.session.add(tag) ctx.session.flush() snapshots.create(tag, ctx.user) ctx.session.commit() return _serialize(ctx, tag)
def create_tag(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, "tags:create") names = ctx.get_param_as_string_list("names") category = ctx.get_param_as_string("category") description = ctx.get_param_as_string("description", default="") suggestions = ctx.get_param_as_string_list("suggestions", default=[]) implications = ctx.get_param_as_string_list("implications", default=[]) _create_if_needed(suggestions, ctx.user) _create_if_needed(implications, ctx.user) tag = tags.create_tag(names, category, suggestions, implications) tags.update_tag_description(tag, description) ctx.session.add(tag) ctx.session.flush() snapshots.create(tag, ctx.user) ctx.session.commit() return _serialize(ctx, tag)
def finish_password_reset(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: user_name = params['user_name'] user = users.get_user_by_name_or_email(user_name) good_token = auth.generate_authentication_token(user) token = ctx.get_param_as_string('token') if _hash(token) != _hash(good_token): raise errors.ValidationError('Invalid password reset token.') new_password = users.reset_user_password(user) versions.bump_version(user) ctx.session.commit() return {'password': new_password}
def set_featured_post(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'posts:feature') post_id = ctx.get_param_as_int('id') post = posts.get_post_by_id(post_id) featured_post = posts.try_get_featured_post() if featured_post and featured_post.post_id == post.post_id: raise posts.PostAlreadyFeaturedError('짤 %r 는 이미 대문짤임.' % post_id) posts.feature_post(post, ctx.user) snapshots.modify(post, ctx.user) ctx.session.commit() return _serialize_post(ctx, post)
def get_around_and_serialize( self, ctx: rest.Context, entity_id: int, serializer: Callable[[model.Base], rest.Response] ) -> rest.Response: entities = self.get_around( ctx.get_param_as_string('query', default=''), entity_id) return { 'prev': serializer(entities[0]), 'next': serializer(entities[1]), }
def get_around_and_serialize( self, ctx: rest.Context, entity_id: int, serializer: Callable[[model.Base], rest.Response], ) -> rest.Response: entities = self.get_around( ctx.get_param_as_string("query", default=""), entity_id) return { "prev": serializer(entities[0]), "next": serializer(entities[1]), }
def finish_password_reset( ctx: rest.Context, params: Dict[str, str]) -> rest.Response: user_name = params['user_name'] user = users.get_user_by_name_or_email(user_name) good_token = auth.generate_authentication_token(user) token = ctx.get_param_as_string('token') if _hash(token) != _hash(good_token): raise errors.ValidationError('Invalid password reset token.') new_password = users.reset_user_password(user) versions.bump_version(user) ctx.session.commit() return {'password': new_password}
def set_featured_post( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'posts:feature') post_id = ctx.get_param_as_int('id') post = posts.get_post_by_id(post_id) featured_post = posts.try_get_featured_post() if featured_post and featured_post.post_id == post.post_id: raise posts.PostAlreadyFeaturedError( 'Post %r is already featured.' % post_id) posts.feature_post(post, ctx.user) snapshots.modify(post, ctx.user) ctx.session.commit() return _serialize_post(ctx, post)
def create_user( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: if ctx.user.user_id is None: auth.verify_privilege(ctx.user, 'users:create:self') else: auth.verify_privilege(ctx.user, 'users:create:any') name = ctx.get_param_as_string('name') password = ctx.get_param_as_string('password') email = ctx.get_param_as_string('email', default='') user = users.create_user(name, password, email) if ctx.has_param('rank'): users.update_user_rank(user, ctx.get_param_as_string('rank'), ctx.user) if ctx.has_param('avatarStyle'): users.update_user_avatar( user, ctx.get_param_as_string('avatarStyle'), ctx.get_file('avatar', default=b'')) ctx.session.add(user) ctx.session.commit() return _serialize(ctx, user, force_show_email=True)
def get_posts_by_image( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: auth.verify_privilege(ctx.user, 'posts:reverse_search') content = ctx.get_file('content') try: lookalikes = posts.search_by_image(content) except (errors.ThirdPartyError, errors.ProcessingError): lookalikes = [] return { 'exactPost': _serialize_post(ctx, posts.search_by_image_exact(content)), 'similarPosts': [ { 'distance': lookalike.distance, 'post': _serialize_post(ctx, lookalike.post), } for lookalike in lookalikes ], }
def update_user_token( ctx: rest.Context, params: Dict[str, str] = {}) -> rest.Response: user = users.get_user_by_name(params['user_name']) infix = 'self' if ctx.user.user_id == user.user_id else 'any' auth.verify_privilege(ctx.user, 'user_tokens:edit:%s' % infix) user_token = user_tokens.get_by_user_and_token(user, params['user_token']) versions.verify_version(user_token, ctx) versions.bump_version(user_token) if ctx.has_param('enabled'): auth.verify_privilege(ctx.user, 'user_tokens:edit:%s' % infix) user_tokens.update_user_token_enabled( user_token, ctx.get_param_as_bool('enabled')) if ctx.has_param('note'): auth.verify_privilege(ctx.user, 'user_tokens:edit:%s' % infix) note = ctx.get_param_as_string('note') user_tokens.update_user_token_note(user_token, note) if ctx.has_param('expirationTime'): auth.verify_privilege(ctx.user, 'user_tokens:edit:%s' % infix) expiration_time = ctx.get_param_as_string('expirationTime') user_tokens.update_user_token_expiration_time( user_token, expiration_time) user_tokens.update_user_token_edit_time(user_token) ctx.session.commit() return _serialize(ctx, user_token)
def get_serialization_options(ctx: rest.Context) -> List[str]: return ctx.get_param_as_list('fields', default=[])
def update_user(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: user = users.get_user_by_name(params['user_name']) versions.verify_version(user, ctx) versions.bump_version(user) infix = 'self' if ctx.user.user_id == user.user_id else 'any' if ctx.has_param('name'): auth.verify_privilege(ctx.user, 'users:edit:%s:name' % infix) users.update_user_name(user, ctx.get_param_as_string('name')) if ctx.has_param('password'): auth.verify_privilege(ctx.user, 'users:edit:%s:pass' % infix) users.update_user_password( user, ctx.get_param_as_string('password')) if ctx.has_param('email'): auth.verify_privilege(ctx.user, 'users:edit:%s:email' % infix) users.update_user_email(user, ctx.get_param_as_string('email')) if ctx.has_param('rank'): auth.verify_privilege(ctx.user, 'users:edit:%s:rank' % infix) users.update_user_rank( user, ctx.get_param_as_string('rank'), ctx.user) if ctx.has_param('avatarStyle'): auth.verify_privilege(ctx.user, 'users:edit:%s:avatar' % infix) users.update_user_avatar( user, ctx.get_param_as_string('avatarStyle'), ctx.get_file('avatar', default=b'')) ctx.session.commit() return _serialize(ctx, user)
def create_post( ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: anonymous = ctx.get_param_as_bool('anonymous', default=False) if anonymous: auth.verify_privilege(ctx.user, 'posts:create:anonymous') else: auth.verify_privilege(ctx.user, 'posts:create:identified') content = ctx.get_file('content') tag_names = ctx.get_param_as_string_list('tags', default=[]) safety = ctx.get_param_as_string('safety') source = ctx.get_param_as_string('source', default='') if ctx.has_param('contentUrl') and not source: source = ctx.get_param_as_string('contentUrl', default='') relations = ctx.get_param_as_int_list('relations', default=[]) notes = ctx.get_param_as_list('notes', default=[]) flags = ctx.get_param_as_string_list('flags', default=[]) post, new_tags = posts.create_post( content, tag_names, None if anonymous else ctx.user) if len(new_tags): auth.verify_privilege(ctx.user, 'tags:create') posts.update_post_safety(post, safety) posts.update_post_source(post, source) posts.update_post_relations(post, relations) posts.update_post_notes(post, notes) posts.update_post_flags(post, flags) posts.test_sound(post, content) if ctx.has_file('thumbnail'): posts.update_post_thumbnail(post, ctx.get_file('thumbnail')) ctx.session.add(post) ctx.session.flush() create_snapshots_for_post(post, new_tags, None if anonymous else ctx.user) alternate_format_posts = posts.generate_alternate_formats(post, content) for alternate_post, alternate_post_new_tags in alternate_format_posts: create_snapshots_for_post( alternate_post, alternate_post_new_tags, None if anonymous else ctx.user) ctx.session.commit() return _serialize_post(ctx, post)
def update_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: post = _get_post(params) versions.verify_version(post, ctx) versions.bump_version(post) if ctx.has_file('content'): auth.verify_privilege(ctx.user, 'posts:edit:content') posts.update_post_content(post, ctx.get_file('content')) if ctx.has_param('tags'): auth.verify_privilege(ctx.user, 'posts:edit:tags') new_tags = posts.update_post_tags( post, ctx.get_param_as_string_list('tags')) if len(new_tags): auth.verify_privilege(ctx.user, 'tags:create') db.session.flush() for tag in new_tags: snapshots.create(tag, ctx.user) if ctx.has_param('safety'): auth.verify_privilege(ctx.user, 'posts:edit:safety') posts.update_post_safety(post, ctx.get_param_as_string('safety')) if ctx.has_param('source'): auth.verify_privilege(ctx.user, 'posts:edit:source') posts.update_post_source(post, ctx.get_param_as_string('source')) elif ctx.has_param('contentUrl'): posts.update_post_source(post, ctx.get_param_as_string('contentUrl')) if ctx.has_param('relations'): auth.verify_privilege(ctx.user, 'posts:edit:relations') posts.update_post_relations( post, ctx.get_param_as_int_list('relations')) if ctx.has_param('notes'): auth.verify_privilege(ctx.user, 'posts:edit:notes') posts.update_post_notes(post, ctx.get_param_as_list('notes')) if ctx.has_param('flags'): auth.verify_privilege(ctx.user, 'posts:edit:flags') posts.update_post_flags(post, ctx.get_param_as_string_list('flags')) if ctx.has_file('thumbnail'): auth.verify_privilege(ctx.user, 'posts:edit:thumbnail') posts.update_post_thumbnail(post, ctx.get_file('thumbnail')) post.last_edit_time = datetime.utcnow() ctx.session.flush() snapshots.modify(post, ctx.user) ctx.session.commit() return _serialize_post(ctx, post)
def process_request(ctx: rest.Context) -> None: ''' Bind the user to request. Update last login time if needed. ''' bump_login = ctx.get_param_as_bool('bump-login', default=False) auth_user = _get_user(ctx, bump_login) if auth_user: ctx.user = auth_user