def login(): if current_user.is_authenticated: return redirect(url_for('wiki.home')) form = LoginForm() if form.validate_on_submit(): user = WikiUser.objects(name=form.username.data).first() if user is not None and user.verify_password(form.password.data): user_id_dict = convert_user_ids_to_dict(session.get('user_id')) user_id_dict[g.wiki_group] = user.id user.id = convert_dict_to_user_ids(user_id_dict) login_user(user, form.remember_me.data) WikiLoginRecord(username=form.username.data, browser=request.user_agent.browser, platform=request.user_agent.platform, details=request.user_agent.string, ip=request.remote_addr).save() # details on `url_parse` and `netloc`: # https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins next_page = request.args.get('next') if not next_page or url_parse(next_page).netloc != '': next_page = url_for('wiki.home') return redirect(next_page) flash('Invalid username or password.', 'danger') else: flash_errors(form) return render_template('auth/login.html', form=form)
def manage_user(wiki_user_id): user = WikiUser.objects(id=wiki_user_id).first() if user is None: return redirect(url_for('.all_users')) form = ManageUserForm(username=user.name, email=user.email, is_admin=user.is_admin) if form.validate_on_submit(): if form.remove.data: user.delete() flash('User removed.', 'warning') else: user.name = form.username.data user.email = form.email.data user.is_admin = form.is_admin.data if form.password.data: user.set_password(form.password.data) user.save() flash('User updated.', 'success') return redirect(url_for('.all_users')) else: flash_errors(form) return render_template('admin/manage_user.html', form=form)
def rename(wiki_page_id): wiki_page = WikiPage.objects.only('title').get_or_404(id=wiki_page_id) if wiki_page.title == 'Home': return redirect(url_for('.home')) form = RenameForm(new_title=wiki_page.title) if form.validate_on_submit(): new_title = form.new_title.data if wiki_page.title == new_title: flash('The page name is not changed.', 'warning') elif WikiPage.objects(title=new_title).count() > 0: flash('The new page title has already been taken.', 'danger') else: old_md = '[[{}]]'.format(wiki_page.title) new_md = '[[{}]]'.format(new_title) old_html = render_wiki_page(wiki_page.id, wiki_page.title) new_html = render_wiki_page(wiki_page.id, new_title) # update the markdown of referencing wiki page wiki_referencing_pages = (WikiPage.objects( refs__contains=wiki_page_id).only('md', 'html', 'comments').all()) for ref in wiki_referencing_pages: new_md_content = ref.md.replace(old_md, new_md) new_html_content = ref.html.replace(old_html, new_html) (WikiPage.objects(id=ref.id).update_one( set__md=new_md_content, set__html=new_html_content)) # update renamed page title in comments for wp in WikiPage.objects( comments__md__contains=old_md).only('comments'): for comment in wp.comments: comment.md = comment.md.replace(old_md, new_md) comment.html = comment.html.replace(old_html, new_html) WikiPage.objects(id=wp.id).update_one(comments=wp.comments) # update the diff of related wiki page versions for pv in WikiPageVersion.objects.search_text(old_md).all(): pv.diff = pv.diff.replace(old_md, new_md) pv.save() (WikiPage.objects(id=wiki_page.id).update_one( set__title=new_title)) return redirect(url_for('.page', wiki_page_id=wiki_page.id)) else: flash_errors(form) return render_template('wiki/rename.html', wiki_page=wiki_page, form=form)
def home(): """Manage wiki groups.""" all_wiki_groups = WikiGroup.objects.all() form = AddWikiGroupForm() # Create a new wiki group with its own database and static file directory if form.validate_on_submit(): new_wiki_group_name = form.wiki_group_name.data new_db_name = new_wiki_group_name.replace(' ', '') # Save the name of the new wiki group in database `_admin` # Remove whitespaces in the wiki group name. # Then use it to name the database which is about to be initialized. new_group = WikiGroup(name=new_wiki_group_name, db_name=new_db_name, active=True) # Initialize a new database for the just-created group # Make sure the new group name is not occupied. if new_group.db_name in db.connection.database_names(): flash('Wiki group already exists', 'danger') else: try: os.mkdir( os.path.join(current_app.config['UPLOAD_PATH'], new_group.db_name)) new_group.save() db.register_connection( alias=new_group.db_name, name=new_group.db_name, host=current_app.config['MONGODB_SETTINGS']['host'], port=current_app.config['MONGODB_SETTINGS']['port']) new_user = WikiUser(name=form.username.data, email=form.email.data, is_admin=True) new_user.set_password(form.password.data) new_user.switch_db(new_group.db_name).save() WikiPage(title='Home').switch_db(new_group.db_name).save() flash('New wiki group added', 'success') return redirect(url_for('.home')) except FileExistsError: flash('Upload directory already exists', 'danger') else: flash_errors(form) return render_template('super_admin/home.html', form=form, all_wiki_groups=all_wiki_groups)
def change_password(): form = ChangePwdForm() if form.validate_on_submit(): if not current_user.verify_password(form.old_password.data): flash('Password Verification Failed.', 'danger') elif form.new_password.data != form.confirm_password.data: flash('Please confirm new password again.', 'danger') else: current_user.set_password(form.new_password.data) (WikiUser.objects(name=current_user.name).update_one( set__password_hash=current_user.password_hash)) flash('Password changed.', 'success') else: flash_errors(form) return render_template('auth/change_password.html', form=form)
def keypage_edit(): wiki_keypages = (WikiPage.objects( keypage__exists=True).only('title').order_by('+keypage')) keypage_titles = [wiki_keypage.title for wiki_keypage in wiki_keypages] form = KeyPageEditForm(textArea='\n'.join(keypage_titles)) if form.validate_on_submit(): (WikiPage.objects(keypage__exists=True).update(unset__keypage=1)) new_titles = form.textArea.data.splitlines() for i, new_title in enumerate(new_titles): (WikiPage.objects(title=new_title).update_one(set__keypage=i + 1)) return redirect(url_for('wiki.home')) else: flash_errors(form) return render_template('admin/keypage_edit.html', form=form)
def all_users(): form = NewUserForm() if form.validate_on_submit(): user = WikiUser.objects(name=form.username.data).first() if not user: new_user = WikiUser(name=form.username.data, email=form.email.data, is_admin=form.is_admin.data) new_user.set_password(form.password.data) new_user.save() flash('New user added', 'success') return redirect(url_for('.all_users')) else: flash('User already exists.', 'danger') else: flash_errors(form) all_wiki_users = WikiUser.objects.order_by('+id').all() return render_template('admin/all_users.html', form=form, all_wiki_users=all_wiki_users)
def login(): if current_user.is_authenticated: return redirect(url_for('.home')) form = LoginForm() if form.validate_on_submit(): user = WikiUser.objects(name=form.username.data).first() if user is not None and user.verify_password(form.password.data): user_id_dict = {g.wiki_group: user.id} user.id = convert_dict_to_user_ids(user_id_dict) login_user(user, form.remember_me.data) WikiLoginRecord(username=form.username.data, browser=request.user_agent.browser, platform=request.user_agent.platform, details=request.user_agent.string, ip=request.remote_addr).save() return redirect(url_for('.home')) flash('Invalid username or password.', 'danger') else: flash_errors(form) return render_template('auth/login.html', form=form)
def history(wiki_page_id): fields = [ 'title', 'md', 'current_version', 'modified_on', 'modified_by', 'versions' ] wiki_page = (WikiPage.objects.only(*fields).get_or_404(id=wiki_page_id)) if wiki_page.current_version == 1: return redirect(url_for('.page', wiki_page_id=wiki_page_id)) form = HistoryRecoverForm() if form.validate_on_submit(): if form.version.data >= wiki_page.current_version: flash('Please enter an old version number.', 'danger') else: old_to_current = wiki_page.versions[(form.version.data - 1):] old_to_current_patches = [pv.diff for pv in old_to_current[::-1]] recovered_content = apply_patches(wiki_page.md, old_to_current_patches, revert=True) diff = make_patch(wiki_page.md, recovered_content) if diff: toc, html = markdown(wiki_page, recovered_content) wiki_page.update_db(diff, recovered_content, html, toc=toc) return redirect(url_for('.page', wiki_page_id=wiki_page.id)) else: flash_errors(form) old_ver_num = request.args.get('version', default=wiki_page.current_version - 1, type=int) new_ver_num = old_ver_num + 1 if new_ver_num > wiki_page.current_version: return redirect( url_for('.history', wiki_page_id=wiki_page_id, version=wiki_page.current_version - 1)) wiki_page_versions = wiki_page.versions[old_ver_num - 1:] old_to_current_patches = [pv.diff for pv in wiki_page_versions[::-1]] new_markdown = apply_patches(wiki_page.md, old_to_current_patches[:-1], revert=True) old_markdown = apply_patches(new_markdown, [old_to_current_patches[-1]], revert=True) diff = difflib.HtmlDiff() diff_table = diff.make_table(old_markdown.splitlines(), new_markdown.splitlines()) diff_table = diff_table.replace(' ', ' ').replace(' nowrap="nowrap"', '') kwargs = dict() get_pagination_kwargs(kwargs, old_ver_num, wiki_page.current_version - 1) return render_template('wiki/history.html', wiki_page=wiki_page, form=form, wiki_page_versions=wiki_page_versions, old_ver_num=old_ver_num, new_ver_num=new_ver_num, diff_table=diff_table, **kwargs)