Skip to content

Commit

Permalink
fix #12 -- get rid of /save URLs
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
  • Loading branch information
Kwpolska committed Jan 6, 2015
1 parent f83a6f3 commit c5b6605
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 144 deletions.
220 changes: 94 additions & 126 deletions COMET/__init__.py
Expand Up @@ -180,7 +180,7 @@ def write_users():
'can_rebuild_site': user.can_rebuild_site,
}
with open(json_path, 'w') as fh:
json.dump(udict, fh, indent=4)
json.dump(udict, fh, indent=4, sort_keys=True, separators=(',', ': '))

read_users()

Expand Down Expand Up @@ -231,44 +231,34 @@ def setup():
@app.route('/edit/<path:path>', methods=['GET', 'POST'])
@login_required
def edit(path):
context = {'path': path}
context['site'] = _site
context['json'] = json
context = {'path': path, 'site': _site}
post = None
for p in _site.timeline:
if p.source_path == path:
post = p
break
if post is None:
return "No such post or page.", 404
with io.open(path, 'r', encoding='utf-8') as fh:
context['post_content'] = fh.read().split('\n\n', 1)[1]

if request.method == 'POST':
meta = {}
for k, v in request.form.items():
meta[k] = v
meta.pop('_wysihtml5_mode', '')
post.compiler.create_post(post.source_path, onefile=True, is_page=False, **meta)
init_site()
context['action'] = 'save'
context['post_content'] = meta['content']
else:
context['action'] = 'edit'
with io.open(path, 'r', encoding='utf-8') as fh:
context['post_content'] = fh.read().split('\n\n', 1)[1]

context['post'] = post
context['title'] = 'Editing {0}'.format(post.title())
context['permalink'] = '/edit/' + path
return render('comet_post_edit.tmpl', context)

@app.route('/save/<path:path>', methods=['POST'])
@login_required
def save(path):
# FIXME insecure pending defnull/bottle#411
context = {'path': path}
context['site'] = _site
post = None
for p in _site.timeline:
if p.source_path == path:
post = p
break
if post is None:
return "No such post or page.", 404
meta = {}
for k, v in request.form.items():
meta[k] = v
meta.pop('_wysihtml5_mode', '')
post.compiler.create_post(post.source_path, onefile=True, is_page=False, **meta)
init_site()
return redirect('/edit/' + path)

@app.route('/delete', methods=['POST'])
@login_required
def delete():
Expand All @@ -283,72 +273,62 @@ def delete():
init_site()
return redirect('/')

# Please do those in nginx if possible.
@app.route('/wysihtml/<path:path>')
def server_wysihtml(path):
def serve_wysihtml(path):
return send_from_directory(os.path.join(os.path.dirname(__file__), 'bower_components', 'wysihtml'), path)

@app.route('/comet_assets/<path:path>')
def serve_comet_assets(path):
return send_from_directory(os.path.join(os.path.dirname(__file__), 'comet_assets'), path)

@app.route('/assets/<path:path>')
def server_assets(path):
def serve_assets(path):
return send_from_directory(os.path.join(_site.config["OUTPUT_FOLDER"], 'assets'), path)

@app.route('/new/post', methods=['POST'])
@login_required
def new_post():
title = request.form['title']
try:
_site.commands.new_post(title=title, author=current_user.realname, content_format='html')
except SystemExit:
return "This post already exists!", 500
# reload post list and go to index
init_site()
return redirect('/')

@app.route('/new/page', methods=['POST'])
@app.route('/new/<obj>', methods=['POST'])
@login_required
def new_page():
def new_post(obj):
title = request.form['title']
try:
_site.config['ADDITIONAL_METADATA']['author.uid'] = current_user.uid
_site.commands.new_page(title=title, author=current_user.realname, content_format='html')
del _site.config['ADDITIONAL_METADATA']['author.uid']
if obj == 'post':
_site.commands.new_post(title=title, author=current_user.realname, content_format='html')
elif obj == 'page':
_site.commands.new_page(title=title, author=current_user.realname, content_format='html')
else:
return "Cannot create {0} — unknown type.".format(obj), 400
except SystemExit:
return "This post already exists!", 500
return "This {0} already exists!".format(obj), 500
# reload post list and go to index
init_site()
return redirect('/')

@app.route('/account')
@app.route('/account', methods=['POST', 'GET'])
@login_required
def acp_user_account():
if request.args.get('status') == 'ok':
alert = ''
alert_status = ''
if request.method == 'POST':
data = request.form
if data['newpwd1']:
if data['newpwd1'] == data['newpwd2'] and check_password(current_user.password, data['oldpwd']):
current_user.password = password_hash(data['newpwd1'])
else:
alert = 'Passwords don’t match.'
alert_status = 'danger'
current_user.realname = data['realname']
current_user.wants_see_others_posts = 'wants_see_others_posts' in data
write_users()

alert = 'Account edited successfully.'
alert_status = 'success'
elif request.args.get('status') == 'pwdfail':
alert = 'Passwords don’t match.'
alert_status = 'danger'
else:
alert = ''
alert_status = ''

return render('comet_account.tmpl',
context={'title': 'My account',
'permalink': '/account',
'alert': alert,
'alert_status': alert_status})

@app.route('/account/save', methods=['POST'])
@login_required
def acp_user_account_save():
status = 'ok'
data = request.form
if data['newpwd1']:
if data['newpwd1'] == data['newpwd2'] and check_password(current_user.password, data['oldpwd']):
current_user.password = password_hash(data['newpwd1'])
else:
status = 'pwdfail'
current_user.realname = data['realname']
write_users()
return redirect('/account?status={0}'.format(status))

@app.route('/users')
@login_required
def acp_users():
Expand All @@ -371,73 +351,61 @@ def acp_users():
'alert': alert,
'alert_status': alert_status})

@app.route('/users/edit', methods=['GET', 'POST'])
@app.route('/users/edit', methods=['POST'])
@login_required
def acp_users_edit():
global USERS
if not current_user.is_admin:
return "Not authorized to edit users.", 401
data = request.form
action = data['action']

if action == 'new':
uid = max(USERS) + 1
USERS[uid] = User(uid, data['username'], '', '', True, False, True, True, True, True)
user = USERS[uid]
new = True
else:
if request.method == 'GET':
user = get_user(request.args.get('uid'))
else:
user = get_user(request.form['uid'])
if not user:
return "User does not exist.", 404
new = not user.password
if request.args.get('status') == 'ok':
alert = 'User changed successfully.'
alert_status = 'success'
elif request.args.get('status') == 'ok_new':
user = get_user(data['uid'])
new = False

if not user:
return "User does not exist.", 404

alert = ''
alert_status = ''

if action == 'save':
alert = 'User changed successfully.'
alert_status = 'success'
if new:
alert = 'User created successfully.'
alert_status = 'success'
elif request.args.get('status') == 'pwdfail':
alert = 'Passwords don’t match.'
alert_status = 'danger'
elif request.args.get('status') == 'nopwd':
if data['newpwd1']:
if data['newpwd1'] == data['newpwd2']:
user.password = password_hash(data['newpwd1'])
else:
alert = 'Passwords don’t match.'
alert_status = 'danger'
elif new:
alert = 'Must set a password.'
alert_status = 'danger'
else:
alert = ''
alert_status = ''
return render('comet_users_edit.tmpl',
context={'title': 'Edit user',
'permalink': '/users/edit',
'user': user,
'new': new,
'alert': alert,
'alert_status': alert_status})

@app.route('/users/save', methods=['POST'])
@login_required
def acp_users_save():
data = request.form
user = get_user(int(data['uid']))
new = user.password == ''
status = 'ok'
if new:
status = 'ok_new'
if data['newpwd1']:
if data['newpwd1'] == data['newpwd2']:
user.password = password_hash(data['newpwd1'])
else:
status = 'pwdfail'
elif new:
status = 'nopwd'
user.realname = data['realname']
if user != current_user:
user.is_admin = 'is_admin' in data
write_users()
return redirect('/users/edit?uid={0}&status={1}'.format(user.uid, status))


@app.route('/users/new', methods=['POST'])
@login_required
def acp_users_new():
uid = max(USERS) + 1
USERS[uid] = User(uid, request.form['username'], '', '', True, False, False)
print(USERS[uid])
return redirect('/users/{0}/edit'.format(request.form['username']))
user.realname = data['realname']
if user != current_user:
user.is_admin = 'is_admin' in data
user.wants_see_others_posts = 'wants_see_others_posts' in data
user.can_see_others_posts = 'can_see_others_posts' in data
user.can_upload_attachments = 'can_upload_attachments' in data
user.can_rebuild_site = 'can_rebuild_site' in data
write_users()

return render('comet_users_edit.tmpl',
context={'title': 'Edit user',
'permalink': '/users/edit',
'user': user,
'new': new,
'alert': alert,
'alert_status': alert_status})

@app.route('/users/delete', methods=['POST'])
@login_required
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion COMET/templates/jinja/comet_account.tmpl
Expand Up @@ -9,7 +9,7 @@
<div class="alert alert-{{ alert_status }}" role="alert">{{ alert }}</div>
{% endif %}

<form action="/account/save" method="POST" class="form-horizontal">
<form action="/account" method="POST" class="form-horizontal">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Profile</h3>
Expand Down
73 changes: 69 additions & 4 deletions COMET/templates/jinja/comet_post_edit.tmpl
Expand Up @@ -6,17 +6,82 @@
#toolbar, #post-meta-panel, #content-area {
margin-top: 10px;
}
#save-btn, #save-icon {
transition: all 0.5s ease;
}

@-webkit-keyframes fa-unspin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(-359deg);
transform: rotate(-359deg);
}
}

@keyframes fa-unspin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(-359deg);
transform: rotate(-359deg);
}
}

.comet-fa-spin {
-webkit-animation: fa-spin 0.7s infinite linear;
animation: fa-spin 0.7s infinite linear;
}

.comet-fa-unspin {
-webkit-animation: fa-unspin 0.7s infinite linear;
animation: fa-unspin 0.7s infinite linear;
}
</style>
{% endblock %}
{% block extra_js %}
{% if action == 'save' %}
<script>
$(document).ready(function() {
$("#save-btn").removeClass("btn-primary").addClass("btn-success");
$("#save-icon").removeClass("fa-save").addClass("fa-check");
setTimeout(function() {
$("#save-btn").removeClass("btn-success").addClass("btn-primary");
$("#save-icon").removeClass("fa-check").addClass("fa-save");
}, 2000);
});

$('#post-meta').on('show.bs.collapse', function () {
$("#meta-icon").addClass("comet-fa-spin");
})

$('#post-meta').on('hide.bs.collapse', function () {
$("#meta-icon").addClass("comet-fa-unspin");
})

$('#post-meta').on('shown.bs.collapse', function () {
$("#meta-icon").removeClass("comet-fa-spin");
})

$('#post-meta').on('hidden.bs.collapse', function () {
$("#meta-icon").removeClass("comet-fa-unspin");
})
</script>
{% endif %}
{% endblock %}
{% block content %}
<form method="POST" class="form-horizontal" role="form" id="form" action="/save/{{ post.source_path }}">
<form method="POST" class="form-horizontal" role="form" id="form" action="/edit/{{ post.source_path }}">
<input name="title" value="{{ post.title() }}" class="form-control title input-lg" placeholder="Title">
<div id="toolbar" class="btn-toolbar">
<div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-save"></i> Save</button>
<button type="submit" class="btn btn-sm btn-primary" id="save-btn"><i id="save-icon" class="fa fa-save fa-fw"></i> Save</button>
<button class="btn btn-sm btn-info" type="button" data-toggle="collapse"
data-target="#post-meta" aria-expanded="false"
aria-controls="post-meta"><i class="fa fa-cog"></i> Edit metadata</button>
aria-controls="post-meta" id="meta-btn"><i id="meta-icon" class="fa fa-cog fa-fw"></i> Edit metadata</button>
</div>

<div class="btn-group">
Expand Down Expand Up @@ -106,7 +171,7 @@
var editor = new wysihtml5.Editor('content-area', {
toolbar: 'toolbar',
parserRules: wysihtml5ParserRules,
stylesheets: ['/static/css/wysihtml5x.css']
stylesheets: ['/comet_assets/css/wysihtml5x.css']
});
</script>
{% endblock %}

0 comments on commit c5b6605

Please sign in to comment.