def prepare(self): super().prepare() cursor = self.db.posts.find() self.post_count = yield cursor.count() self.max_page = ceil(self.post_count / N_POST_PER_PAGE) logger.debug('prepare for post_count {}, max_page {}'.format( self.post_count, self.max_page))
def ramjet_login(self): """ GET 一个包含 source, id, username 的 token """ try: token = self.get_argument('token') d = validate_token(token) except Exception: logger.debug('ramjet_login validate error') self.http_400_bad_request(err='token validate error') return # login from twitter sid_str = '{}.id'.format(d['source']) # like "twitter.id" old_user = yield self.db.users.find_one({sid_str: d['id']}) username = old_user['username'] if old_user else d['username'] yield self.db.users.update({sid_str: d['id']}, { '$set': { 'username': username, sid_str: d['id'], 'last_update': utcnow() } }, upsert=True) user_docu = yield self.db.users.find_one({sid_str: d['id']}) token = generate_token({ 'username': d['username'], 'uid': user_docu['_id'] }) self.set_cookie('token', token, expires_days=30) self.write_json(msg=OK) self.finish()
def ramjet_login(self): """ GET 一个包含 source, id, username 的 token """ try: token = self.get_argument('token') d = validate_token(token) except Exception: logger.debug('ramjet_login validate error') self.http_400_bad_request(err='token validate error') return # login from twitter sid_str = '{}.id'.format(d['source']) # like "twitter.id" old_user = yield self.db.users.find_one({sid_str: d['id']}) username = old_user['username'] if old_user else d['username'] yield self.db.users.update( {sid_str: d['id']}, {'$set': {'username': username, sid_str: d['id'], 'last_update': utcnow()}}, upsert=True ) user_docu = yield self.db.users.find_one({sid_str: d['id']}) token = generate_token({'username': d['username'], 'uid': user_docu['_id']}) self.set_cookie('token', token, expires_days=30) self.write_json(msg=OK) self.finish()
def setup_db(self): logger.debug('connect database at {}:{}'.format( options.dbhost, options.dbport)) model = BaseBlogModel.make_connection(host=options.dbhost, port=options.dbport) self.conn = model.conn self.db = model.db self.mongo_conn = model.mongo_conn self.mongo_db = model.mongo_db # ensure index # posts # posts_idx = pymongo.IndexModel([('post_name',)], unique=True) # self.mongo_db.posts.create_indexes([posts_idx]) self.mongo_db.posts.ensure_index([('post_name', pymongo.ASCENDING)], unique=True) # PyMongo2.8 # users # account_idx = pymongo.IndexModel([('account',)], unique=True) # username_idx = pymongo.IndexModel([('username',)], unique=True) # self.mongo_db.users.create_indexes([account_idx, username_idx]) self.mongo_db.users.ensure_index([('account', pymongo.ASCENDING)], unique=True) # PyMongo2.8 self.mongo_db.users.ensure_index([('username', pymongo.ASCENDING)], unique=True) # PyMongo2.8
def write_not_accept(self, data): logger.debug('write_not_accept for Accept: {}'.format(self.accept)) _accept_map = self._get_accept_map() self.http_406_not_acceptable( 'Only Accept {}! But Got {}' .format(list(_accept_map.keys()), self.accept) )
def post_article_password(self): """Validate the password of locked article. """ logger.info("post_article_password") name = self.parse_post_name(self.get_argument('name', default='', strip=True)) password = self.get_argument('password', strip=True) logger.debug('post_article_password for name {}, password {}' .format(name, password)) post = yield ArticlesModel.get({'post_name': name}) if not post: self.set_status(202, 'Post name not exists.') self.write_json(msg='post_name 不存在', status=ERROR) self.finish() return elif password != post['post_password']: self.set_status(202, 'Password wrong.') self.write_json(msg='密码错误', status=ERROR) self.finish() return cookie_name = self.get_cookie_name(name) self.set_secure_cookie(cookie_name, password, expires_days=None) self.write_json(msg='ok')
def prepare(self): super().prepare() cursor = self.db.posts.find() self.post_count = yield cursor.count() self.max_page = ceil(self.post_count / N_POST_PER_PAGE) logger.debug('prepare for post_count {}, max_page {}' .format(self.post_count, self.max_page))
def get_post_by_keyword(self): logger.info('GET get_post_by_keyword') keyword = self.get_argument('keyword', strip=True) logger.debug('GET get_post_by_keyword for keyword {}'.format(keyword)) q = 'https://cse.google.com/cse/publicurl?cx=004733495569415005684:-c6y46kjqva&q={keyword}' self.redirect(q.format(keyword=keyword, permanent=True))
def get(self, url=None): logger.debug('GET PageNotFound for url {}'.format(url)) if url is None: self.render2('404.html', url=url) self.finish() return self.redirect_404()
async def get_cursor(self): col = self.get_col() query, projection = await self.pass_query_makers() if query is None: logger.debug('not get query') return cursor = col.find(query, projection) return await self.pass_filter(cursor)
def _get_resp_method(self): _accept_map = self._get_accept_map() for accept in self.accept: m = _accept_map.get(accept.name) if m: logger.debug('_get_resp_method {}'.format(m)) return m logger.debug('_get_resp_method fail') return self.write_not_accept
async def pass_filter(self, cursor): for f in (self._base_filters + getattr(self, '_filters', tuple())): try: cursor = await f.query_cursor(self, cursor) except FilterError as err: logger.debug(err) self.http_400_bad_request(err=err) return return cursor
async def parse_docus(self, docus): try: for p in (self._base_parsers + getattr(self, '_parsers', tuple())): docus = await p.parse_results(self, docus) except ParserError as err: logger.debug(err) self.http_400_bad_request(err=err) return None return docus
async def put(self, category=None): try: categories = self.get_argument('categories', strip=True) categories = json.loads(categories) except Exception as err: self.http_400_bad_request(err=err) return logger.debug('PostCategoriesAPIHandler PUT for categories %s', categories) await ArticlesModel.update_posts_categories(categories) return self.success(data='ok')
def extract_reveal_html(self, html): logger.debug('extract_reveal_html for html {}'.format(html[: 50])) tree = etree.HTML(html) node = tree.xpath('//div[@class="reveal"]') ret = etree.tostring(node[0], encoding='unicode') if '{{' in ret: return '{% raw %}' + ret + '{% endraw %}' else: return ret
def emit(self, record): logger.debug('LogMailHandler for record {}'.format(record)) delay_task( send_mail, mailhost=self.mailhost, mailport=self.mailport, username=self.username, passwd=self.password, from_addr=self.fromaddr, to_addrs=self.toaddrs, # 会自动被转换为列表 subject=self.subject, content=record.getMessage())
async def pass_query_makers(self): query, projection = {}, None try: for qm in (self._base_query_makers + getattr(self, '_query_makers', tuple())): query, projection = await qm.update_query(self, query, projection) except QueryMakerError as err: logger.debug(err) self.http_400_bad_request(err=err) return None, None return query, projection
def validate_post(self, create_new=False): try: post_title = self.get_argument('postTitle', strip=True) post_name = self.get_argument('postName', strip=True) post_name = urllib.parse.quote(post_name).lower() post_content = self.get_argument('postContent') post_type = self.get_argument('postType', strip=True, default='text') assert post_name, 'post_name cannot be empry!' except Exception as err: logger.exception(err) raise PostValidatorError('Post arguments error!') else: post_docu = { 'post_modified_gmt': utcnow(), 'post_status': 'publish', 'comment_status': 'open', 'post_title': post_title, 'post_name': post_name, 'post_type': post_type, } if create_new: post_docu.update({ 'post_author': self.current_user['_id'], 'post_created_at': utcnow(), }) logger.debug('validate_post for post_title {}, post_name {}, ' 'post_content {}, post_type {}' .format(post_title, post_name, post_content, post_type)) post_menu = None if post_type == 'slide': # extract slide body from the file generated by ipython nbconvert post_content = self.extract_reveal_html(post_content) elif post_type == 'markdown': # renfer github flavor markdown to html post_markdown = post_content post_content, post_menu = render_md_to_html(post_content, is_extract_menu=True) else: logger.debug('unknown post_type: {}'.format(post_type)) raise PostValidatorError('unknown post_type') post_docu.update({ 'post_content': post_content, 'post_menu': post_menu, }) if post_type == 'markdown': post_docu.update({ 'post_markdown': post_markdown, }) return post_docu
def emit(self, record): logger.debug('LogMailHandler for record {}'.format(record)) delay_task(send_mail, mailhost=self.mailhost, mailport=self.mailport, username=self.username, passwd=self.password, from_addr=self.fromaddr, to_addrs=self.toaddrs, # 会自动被转换为列表 subject=self.subject, content=record.getMessage() )
def update_posts_categories(cls, postid_category_map): """ Args: postname_category_map (dict): {post_id: category_id} """ logger.info('CategoriesModel.update_posts_categories') for post_id, cate in postid_category_map.items(): r = yield cls.collection.update_one( {'_id': cls.oid(post_id)}, {'$set': {'category': cls.oid(cate)}}, upsert=False ) logger.debug('update post %s category to %s for %s', post_id, cate, r.modified_count)
async def parse_results(cls, app, results): try: truncate = int(app.get_argument('truncate', default=-1)) except Exception as e: raise ParserError(e) else: logger.debug('TruncateParser.parse_results for truncate %s', truncate) if truncate >= 0: for docu in results: docu['post_content'] = docu.get('post_markdown', '')[:truncate] docu['post_markdown'] = '' return results
async def parse_results(cls, app, results): try: truncate = int(app.get_argument('truncate', default=-1)) except Exception as e: raise ParserError(e) else: logger.debug('TruncateParser.parse_results for truncate %s', truncate) if truncate >= 0: for docu in results: docu['post_content'] = docu['post_content'][:truncate] docu['post_markdown'] = '' return results
def update_posts_categories(cls, postid_category_map): """ Args: postname_category_map (dict): {post_id: category_id} """ logger.info('CategoriesModel.update_posts_categories') for post_id, cate in postid_category_map.items(): r = yield cls.collection.update_one( {'_id': cls.oid(post_id)}, {'$set': { 'category': cls.oid(cate) }}, upsert=False) logger.debug('update post %s category to %s for %s', post_id, cate, r.modified_count)
async def parse_results(cls, app, results): logger.debug('PostContentParser.parse_results') try: plaintext = app.get_argument('plaintext', default='false', strip=True) assert (plaintext in ['true', 'false']) except (ValueError, AssertionError) as err: raise ParserError(err) else: plaintext = plaintext == 'true' r = [] for docu in results: content = docu['post_content'] if docu.get('post_password'): content = '' else: if plaintext: content = app.plaintext_content(content) if 'category' in docu: category = (await app.db.categories.find_one( {'_id': ObjectId(docu['category'])})) or {} else: category = {} print(">>", docu.get("post_created_at"), type(docu.get("post_created_at"))) r.append({ 'post_tags': docu.get('post_tags', []), 'post_category': category.get('name'), 'post_title': docu['post_title'], 'post_type': docu.get('post_type', 'markdown'), 'link': app.hyperlink_postname(docu['post_name']), 'post_name': docu['post_name'], 'post_markdown': docu.get('post_markdown'), 'post_menu': docu.get('post_menu'), 'post_content': content, 'post_id': str(docu['_id']), 'post_author': str(docu['post_author']), 'post_modified_gmt': docu['post_modified_gmt'], 'post_created_at': docu['post_created_at'], 'post_status': docu['post_status'], }) return r
def login_api(self): email = self.get_argument('email', strip=True) passwd = self.get_argument('password') is_keep_login = self.get_argument('is_keep_login', bool=True) logger.debug('login_api with email %s, passwd %s, is_keep_login %s', email, passwd, is_keep_login) if not validate_email(email): logger.debug("invalidate email: %s", email) self.write_json(msg="invalidate email", status=ERROR) self.finish() return user_docu = (yield self.db.users.find_one({'email': email})) if not user_docu: logger.debug('email not existed: %s', email) self.http_400_bad_request(err='Wrong Account or Password') self.finish() return elif not validate_passwd(passwd, user_docu['password']): logger.debug('invalidate password: %s', passwd) self.http_400_bad_request(err='Wrong Account or Password') self.finish() return uid = str(user_docu['_id']) dtoken = { 'uid': uid, 'username': user_docu['username'], 'exp': utcnow() + datetime.timedelta(days=30) } token = generate_token(dtoken) yield self.db.users.update( {'_id': user_docu['_id']}, {'$set': { 'token': token, 'last_update': utcnow() }}) expires_days = 30 if is_keep_login else None self.set_cookie('token', token, expires_days=expires_days) logger.debug('set cookies with uid %s, token %s, expires_days %s', uid, token, expires_days) self.write_json(msg=OK) self.finish()
async def parse_results(cls, app, results): logger.debug('PostContentParser.parse_results') try: plaintext = app.get_argument('plaintext', default='false', strip=True) assert(plaintext in ['true', 'false']) except (ValueError, AssertionError) as err: raise ParserError(err) else: plaintext = plaintext == 'true' r = [] for docu in results: content = docu['post_content'] if docu.get('post_password'): content = '' else: if plaintext: content = app.plaintext_content(content) if 'category' in docu: category = (await app.db.categories.find_one({'_id': ObjectId(docu['category'])})) or {} else: category = {} print(">>", docu.get("post_created_at"), type(docu.get("post_created_at"))) r.append({ 'post_tags': docu.get('post_tags', []), 'post_category': category.get('name'), 'post_title': docu['post_title'], 'post_type': docu.get('post_type', 'markdown'), 'link': app.hyperlink_postname(docu['post_name']), 'post_name': docu['post_name'], 'post_markdown': docu.get('post_markdown'), 'post_menu': docu.get('post_menu'), 'post_content': content, 'post_id': str(docu['_id']), 'post_author': str(docu['post_author']), 'post_modified_gmt': docu['post_modified_gmt'], 'post_created_at': docu['post_created_at'], 'post_status': docu['post_status'], }) return r
def get_post_by_page(self): logger.info('GET get_post_by_page') try: page = int(self.get_argument('page', strip=True, default=1)) is_full = self.get_argument('is_full', strip=True, default=False) logger.debug('get_post_by_page for page {}'.format(page)) except ValueError as err: logger.error('when get_post_by_page: ', exc_info=err) self.finish() return skip = (page - 1) * N_POST_PER_PAGE cursor = self.db.posts.find() cursor.sort([('_id', pymongo.DESCENDING)]) \ .limit(N_POST_PER_PAGE) \ .skip(skip) posts = [] while (yield cursor.fetch_next): docu = cursor.next_object() docu = unquote_fr_mongo(docu) if not is_full: if docu.get('post_password'): docu['post_content'] = """ <div class="preview"> <span class="glyphicon glyphicon-lock" aria-hidden="true"></span> </div> """ else: docu['post_content'] = self.shortly_content(docu['post_content'], 500) posts.append(docu) # tags tags = (yield self.db.statistics.find_one( {'types': 'keyword'}, {'keywords': 1} ))['keywords'] self.render_post('archives/archives.html', posts=posts, current_page=page, tags=tags) self.finish()
def get_post_by_name(self, name): logger.info('get_post_by_name for name {}'.format(name)) name = self.parse_post_name(name) post = yield ArticlesModel.get({'post_name': name}) if not post: self.redirect_404() return if post.get('post_password'): cookie_name = self.get_cookie_name(name) cookie = self.get_secure_cookie(cookie_name) logger.debug('get cookie {}'.format(cookie)) if not cookie or cookie.decode() != post['post_password']: self.render2('archives/ajax/auth.html', post_name=post['post_name']) return post['post_type'] = post.get('post_type', 'text') self.render2('archives/article.html', post=post) self.finish()
def setup_db(self): logger.debug('connect database at {}:{}' .format(options.dbhost, options.dbport)) model = BaseBlogModel.make_connection(host=options.dbhost, port=options.dbport) self.conn = model.conn self.db = model.db self.mongo_conn = model.mongo_conn self.mongo_db = model.mongo_db # ensure index # posts # posts_idx = pymongo.IndexModel([('post_name',)], unique=True) # self.mongo_db.posts.create_indexes([posts_idx]) self.mongo_db.posts.ensure_index([('post_name', pymongo.ASCENDING)], unique=True) # PyMongo2.8 # users # account_idx = pymongo.IndexModel([('account',)], unique=True) # username_idx = pymongo.IndexModel([('username',)], unique=True) # self.mongo_db.users.create_indexes([account_idx, username_idx]) self.mongo_db.users.ensure_index([('account', pymongo.ASCENDING)], unique=True) # PyMongo2.8 self.mongo_db.users.ensure_index([('username', pymongo.ASCENDING)], unique=True) # PyMongo2.8
async def update_query(cls, app, query, projection): try: category = app.get_argument('category', default=None, strip=True) if category and category != 'null': if is_objectid(category): category = ObjectId(category) else: docu = await app.db.categories.find_one({'name': category}) if docu: category = docu['_id'] except Exception as err: raise QueryMakerError(err) if 'category' not in query and category: logger.debug('CategoryFilterMaker.update_query for category %s', category) if category == 'null': query['category'] = {'$exists': False} else: query['category'] = category return query, projection
def get_post_by_id(self): try: is_full = self.get_argument('is_full', strip=True, default=False) _id = self.get_argument('id', strip=True) except ValueError: self.finish() return else: logger.debug('get_post_by_id for _id {}, is_full {}'.format(_id, is_full)) docu = yield self.db.posts.find_one({'_id': ObjectId(_id)}) if docu: docu['post_created_gmt'] = \ docu['_id'].generation_time.timestamp() * 1000 docu['_id'] = str(docu['_id']) docu['post_modified_gmt'] = \ docu['post_modified_gmt'].timestamp() * 1000 if not is_full: docu['post_content'] = docu['post_content'][: 1000] self.write_json(data=docu) self.finish()
def login_api(self): email = self.get_argument('email', strip=True) passwd = self.get_argument('password') is_keep_login = self.get_argument('is_keep_login', bool=True) logger.debug('login_api with email %s, passwd %s, is_keep_login %s', email, passwd, is_keep_login) if not validate_email(email): logger.debug("invalidate email: %s", email) self.write_json(msg="invalidate email", status=ERROR) self.finish() return user_docu = (yield self.db.users.find_one({'email': email})) if not user_docu: logger.debug('email not existed: %s', email) self.http_400_bad_request(err='Wrong Account or Password') self.finish() return elif not validate_passwd(passwd, user_docu['password']): logger.debug('invalidate password: %s', passwd) self.http_400_bad_request(err='Wrong Account or Password') self.finish() return uid = str(user_docu['_id']) dtoken = {'uid': uid, 'username': user_docu['username'], 'exp': utcnow() + datetime.timedelta(days=30)} token = generate_token(dtoken) yield self.db.users.update( {'_id': user_docu['_id']}, {'$set': {'token': token, 'last_update': utcnow()}}) expires_days = 30 if is_keep_login else None self.set_cookie('token', token, expires_days=expires_days) logger.debug('set cookies with uid %s, token %s, expires_days %s', uid, token, expires_days) self.write_json(msg=OK) self.finish()
def login_page(self): logger.debug('login_page') self.render2('login/index.html') self.finish()
def write_json(self, data): logger.debug('Resp: {}'.format(str(data)[: 50])) resp = json.dumps(data) self.set_header('Content-Type', 'application/json; charset=utf-8') self.write(resp)