Commit 5185b44df4afa40c07338b62985bf393fd6ab53a
Fix: A user who owns a sweet can edit the sweet, after logging in to
sweet store. Admin can edit sweets of others.
Adding new bootstrap and changing icons to glyphicons, re-styled
login.html to adapt to the changes in bootstrap.
/login now allows users to login too.
FIXME: macro of jinja templates is an alternative to underscore
templates. Refactor show_posts.html to use macros.
Comments:
| | | | 53 | | 53 | |
---|
54 | def validateSweet(payload): | 54 | def validateSweet(payload): |
---|
55 | for i in payload: | 55 | for i in payload: |
---|
| | 56 | print i |
---|
56 | try: | 57 | try: |
---|
57 | if len(i['who']) and len(i['what']) and len(i['where']) and\ | 58 | if len(i['who']) and len(i['what']) and len(i['where']) and\ |
---|
58 | len(i['how']) and len(i['created']): | 59 | len(i['how']) and len(i['created']): |
---|
… | | … | |
---|
97 | def show_entries(): | 97 | def show_entries(): |
---|
98 | print 'request:' | 98 | print 'request:' |
---|
99 | print request.method | 99 | print request.method |
---|
100 | res = g.collection.find().sort('_id',direction=-1) | | res = g.collection.find().sort('_id',direction=-1) |
---|
| | 100 | print session | | | 101 | res = g.collection.find().sort('_id', direction=-1) |
---|
101 | entries = make_list(res) | 102 | entries = make_list(res) |
---|
102 | return render_template('show_entries.html', entries=entries) | 103 | return render_template('show_entries.html', entries=entries) |
---|
103 | | 104 | |
---|
… | | … | |
---|
131 | try: | 131 | try: |
---|
132 | payload = [{'who': request.form['who'], 'what': request.form['what'], | 132 | payload = [{'who': request.form['who'], 'what': request.form['what'], |
---|
133 | 'where': request.form['where'], 'how': request.form['how']}] | 133 | 'where': request.form['where'], 'how': request.form['how']}] |
---|
| | 134 | print payload |
---|
134 | except: | 135 | except: |
---|
135 | try: | 136 | try: |
---|
136 | payload = request.json | 137 | payload = request.json |
---|
137 | except: | 138 | except: |
---|
138 | payload = json.loads(request.data) | 139 | payload = json.loads(request.data) |
---|
139 | | 140 | |
---|
| | 141 | if type(payload) is dict: |
---|
| | 142 | payload = [payload] |
---|
140 | | 143 | |
---|
141 | valid = validateSweet(payload) | 144 | valid = validateSweet(payload) |
---|
142 | if not valid: | 145 | if not valid: |
---|
… | | … | |
---|
166 | def login(): | 166 | def login(): |
---|
167 | error = None | 167 | error = None |
---|
168 | if request.method == 'POST': | 168 | if request.method == 'POST': |
---|
| | 169 | db = g.connection[app.config['DATABASE']] |
---|
| | 170 | collection = db['sweet_users'] |
---|
| | 171 | for i in collection.find(): |
---|
| | 172 | if i['user'] == request.form['username'] and i['key'] == request.form['password']: |
---|
| | 173 | session['logged_in'] = True |
---|
| | 174 | session['username'] = request.form['username'] |
---|
| | 175 | flash('You were logged in') |
---|
| | 176 | res = g.collection.find({'who': request.form['username']}) |
---|
| | 177 | |
---|
| | 178 | if res.count() < 1: |
---|
| | 179 | return render_template('show_entries.html', entries=[]) |
---|
| | 180 | swt_list = [] |
---|
| | 181 | for swt in res: |
---|
| | 182 | _id = swt['_id'] |
---|
| | 183 | del(swt['_id']) |
---|
| | 184 | swt['id'] = str(_id) |
---|
| | 185 | swt_list.append(swt) |
---|
| | 186 | return render_template('show_entries.html', entries=swt_list) |
---|
| | 187 | else: |
---|
| | 188 | pass |
---|
| | 189 | |
---|
169 | if request.form['username'] != app.config['USERNAME']: | 190 | if request.form['username'] != app.config['USERNAME']: |
---|
170 | error = 'Invalid username' | 191 | error = 'Invalid username' |
---|
171 | elif request.form['password'] != app.config['PASSWORD']: | 192 | elif request.form['password'] != app.config['PASSWORD']: |
---|
172 | error = 'Invalid password' | 193 | error = 'Invalid password' |
---|
173 | else: | 194 | else: |
---|
174 | session['logged_in'] = True | 195 | session['logged_in'] = True |
---|
| | 196 | session['isAdmin'] = True |
---|
175 | flash('You were logged in') | 197 | flash('You were logged in') |
---|
176 | return redirect(url_for('show_entries')) | 198 | return redirect(url_for('show_entries')) |
---|
177 | return render_template('login.html', error=error) | 199 | return render_template('login.html', error=error) |
---|
… | | … | |
---|
261 | | 261 | |
---|
262 | | 262 | |
---|
263 | | 263 | |
---|
264 | @app.route('/posts/<post_id>',methods=['GET']) | | @app.route('/posts/<post_id>',methods=['GET']) |
---|
| | 264 | @app.route('/posts/<post_id>', methods=['GET', 'POST']) | 265 | def show_specific_entry(post_id): | 265 | def show_specific_entry(post_id): |
---|
266 | try: | | try: |
---|
267 | res = g.collection.find({'_id':ObjectId(post_id)}) | | res = g.collection.find({'_id':ObjectId(post_id)}) |
---|
268 | if(res.count() > 0): | | if(res.count() > 0): |
---|
269 | #entries = make_list(res) | | #entries = make_list(res) |
---|
270 | entries = [] | | entries = [] |
---|
271 | for i in res: | | for i in res: |
---|
272 | _id = i['_id'] | | _id = i['_id'] |
---|
273 | del(i['_id']) | | del(i['_id']) |
---|
274 | i['id'] = _id | | i['id'] = _id |
---|
275 | entries.append(i) | | entries.append(i) |
---|
276 | return render_template('show_posts.html', entries=entries, str=str) | | return render_template('show_posts.html', entries=entries, str=str) |
---|
277 | else: | | else: |
---|
| | 266 | if request.method == 'GET': | | | 267 | try: |
---|
| | 268 | res = g.collection.find({'_id': ObjectId(post_id)}) |
---|
| | 269 | if(res.count() > 0): |
---|
| | 270 | #entries = make_list(res) |
---|
| | 271 | entries = [] |
---|
| | 272 | for i in res: |
---|
| | 273 | _id = i['_id'] |
---|
| | 274 | del(i['_id']) |
---|
| | 275 | i['id'] = _id |
---|
| | 276 | entries.append(i) |
---|
| | 277 | return render_template('show_posts.html', entries=entries, str=str) |
---|
| | 278 | else: |
---|
| | 279 | abort(404) |
---|
| | 280 | except InvalidId: |
---|
278 | abort(404) | 281 | abort(404) |
---|
279 | except InvalidId: | | except InvalidId: |
---|
280 | abort(404) | | abort(404) |
---|
| | 282 | else: | | | 283 | how = {} |
---|
| | 284 | for item in request.form: |
---|
| | 285 | how[item] = request.form[item] |
---|
| | 286 | try: |
---|
| | 287 | g.collection.update({'_id': ObjectId(post_id)}, {"$set":{'how':how}}) |
---|
| | 288 | response = make_response() |
---|
| | 289 | return response |
---|
| | 290 | except: |
---|
| | 291 | abort(404) |
---|
281 | | 292 | |
---|
282 | | | |
---|
283 | @app.route('/posts/delete/', methods=['POST']) | 293 | @app.route('/posts/delete/', methods=['POST']) |
---|
284 | def delete_post(): | 294 | def delete_post(): |
---|
285 | try: | 295 | try: |
---|
286 | g.collection.remove({'_id':ObjectId(request.form['post_id'])}) | | g.collection.remove({'_id':ObjectId(request.form['post_id'])}) |
---|
| | 296 | g.collection.remove({'_id': ObjectId(request.form['post_id'])}) | 287 | return jsonify(status='ok') | 297 | return jsonify(status='ok') |
---|
288 | except: | 298 | except: |
---|
289 | abort(500) | 299 | abort(500) |
---|
… | | … | |
---|
301 | @app.route('/logout') | 301 | @app.route('/logout') |
---|
302 | def logout(): | 302 | def logout(): |
---|
303 | session.pop('logged_in', None) | 303 | session.pop('logged_in', None) |
---|
| | 304 | session.pop('username', None) |
---|
| | 305 | session.pop('isAdmin', None) |
---|
304 | flash('You were logged out') | 306 | flash('You were logged out') |
---|
305 | return redirect(url_for('show_entries')) | 307 | return redirect(url_for('show_entries')) |
---|
306 | | 308 | |
---|
… | | … | |
---|
351 | return render_template("users.html", users=users) | 351 | return render_template("users.html", users=users) |
---|
352 | | 352 | |
---|
353 | | 353 | |
---|
354 | @app.route('/authenticate', methods=['POST','GET']) | | @app.route('/authenticate', methods=['POST','GET']) |
---|
| | 354 | @app.route('/authenticate', methods=['POST', 'GET']) | 355 | def authenticate(): | 355 | def authenticate(): |
---|
356 | if request.method == "POST": | 356 | if request.method == "POST": |
---|
357 | response = make_response() | 357 | response = make_response() |
---|
| | | | 3 | <head> | 3 | <head> |
---|
4 | <title>SWeeT Store</title> | 4 | <title>SWeeT Store</title> |
---|
5 | <link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}"> | 5 | <link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}"> |
---|
6 | <link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/bootstrap.min.css') }}"> | | <link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/bootstrap.min.css') }}"> |
---|
| | 6 | <link rel=stylesheet type=text/css href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> | | | 7 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> |
---|
| | 8 | <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> |
---|
| | 9 | <script type="text/javascript" src="//underscorejs.org/underscore-min.js"></script> |
---|
7 | {% block head %}{% endblock %} | 10 | {% block head %}{% endblock %} |
---|
8 | </head> | 11 | </head> |
---|
9 | <body> | 12 | <body> |
---|
… | | … | |
---|
29 | {% block body %}{% endblock %} | 29 | {% block body %}{% endblock %} |
---|
30 | </div> | 30 | </div> |
---|
31 | </div> | 31 | </div> |
---|
32 | <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | | <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> |
---|
| | 32 | <!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> --> | 33 | <!--script>window.jQuery || document.write('<script src="{{ url_for('static', filename='js/jquery-1.9.1.min.js')}}"><\/script>')</script--> | 33 | <!--script>window.jQuery || document.write('<script src="{{ url_for('static', filename='js/jquery-1.9.1.min.js')}}"><\/script>')</script--> |
---|
34 | </body> | 34 | </body> |
---|
35 | </html> | 35 | </html> |
---|
| | | | 2 | {% block body %} | 2 | {% block body %} |
---|
3 | <h2>Login</h2> | 3 | <h2>Login</h2> |
---|
4 | {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %} | 4 | {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %} |
---|
5 | <form action="{{ url_for('login') }}" method=post> | | <form action="{{ url_for('login') }}" method=post> |
---|
6 | <dl> | | <dl> |
---|
7 | <dt>Username: | | <dt>Username: |
---|
8 | <dd><input type=text name=username> | | <dd><input type=text name=username> |
---|
9 | <dt>Password: | | <dt>Password: |
---|
10 | <dd><input type=password name=password> | | <dd><input type=password name=password> |
---|
11 | <dd><input type=submit value=Login> | | <dd><input type=submit value=Login> |
---|
12 | </dl> | | </dl> |
---|
| | 5 | <form class="form-horizontal" role="form" action="{{ url_for('login') }}" method=post> | | | 6 | <div class="form-group"> |
---|
| | 7 | <label for="username" class="col-sm-2 control-label">Username</label> |
---|
| | 8 | <div class="col-sm-10"> |
---|
| | 9 | <input type="text" class="form-control" name="username" id="username" placeholder="murugan"> |
---|
| | 10 | </div> |
---|
| | 11 | </div> |
---|
| | 12 | <div class="form-group"> |
---|
| | 13 | <label for="password" class="col-sm-2 control-label">Password</label> |
---|
| | 14 | <div class="col-sm-10"> |
---|
| | 15 | <input type="password" class="form-control" id="password" name="password" placeholder="Password"> |
---|
| | 16 | </div> |
---|
| | 17 | </div> |
---|
| | 18 | <div class="form-group"> |
---|
| | 19 | <div class="col-sm-offset-2 col-sm-10"> |
---|
| | 20 | <button type="submit" class="btn btn-default">Sign in</button> |
---|
| | 21 | </div> |
---|
| | 22 | </div> |
---|
13 | </form> | 23 | </form> |
---|
14 | {% endblock %} | 24 | {% endblock %} |
---|
| | | | 18 | <small>created: {{entry.created }} UTC</small> | 18 | <small>created: {{entry.created }} UTC</small> |
---|
19 | {% endif %} | 19 | {% endif %} |
---|
20 | <a class="pull-right" href={{ "/posts/" + entry.id }}> | 20 | <a class="pull-right" href={{ "/posts/" + entry.id }}> |
---|
21 | <i class="icon-share-alt"></i> | | <i class="icon-share-alt"></i> |
---|
| | 21 | <i class="glyphicon glyphicon-share-alt"></i> | 22 | </a> | 22 | </a> |
---|
23 | </li> | 23 | </li> |
---|
24 | {% endif %} | 24 | {% endif %} |
---|
| | | | 13 | } | 13 | } |
---|
14 | return false; | 14 | return false; |
---|
15 | } | 15 | } |
---|
| | 16 | function editPost(entry) { |
---|
| | 17 | t = _.template($("#editTemplate").html()); |
---|
| | 18 | $(".modal-body").append(t(items=entry)); |
---|
| | 19 | $("input").each(function(item) { |
---|
| | 20 | $(this).val(entry[$(this).attr('for')]); |
---|
| | 21 | |
---|
| | 22 | }, this); |
---|
| | 23 | $("#editModal").modal(); |
---|
| | 24 | } |
---|
16 | </script> | 25 | </script> |
---|
17 | <ul class="entries"> | 26 | <ul class="entries"> |
---|
18 | {% for entry in entries %} | 27 | {% for entry in entries %} |
---|
… | | … | |
---|
29 | @<b>{{ entry.who }}</b> | 29 | @<b>{{ entry.who }}</b> |
---|
30 | <b>#{{ entry.what }}</b> /{{ entry.where }} {{ entry.how|safe }} | 30 | <b>#{{ entry.what }}</b> /{{ entry.where }} {{ entry.how|safe }} |
---|
31 | {% if session.logged_in %} | 31 | {% if session.logged_in %} |
---|
| | 32 | {% if session.isAdmin or session.username == entry.who %} |
---|
| | 33 | <button class="right btn btn-sm btn-default" onclick='editPost({{entry.how|tojson|safe}})'> |
---|
| | 34 | <i class="glyphicon glyphicon-edit"></i> |
---|
| | 35 | </button> |
---|
32 | <a class="pull-right" href="#" onclick='deletePost({{entry.id|string|tojson|safe}})'> | 36 | <a class="pull-right" href="#" onclick='deletePost({{entry.id|string|tojson|safe}})'> |
---|
33 | <i class="icon-trash"></i> | | <i class="icon-trash"></i> |
---|
| | 37 | <i class="glyphicon glyphicon-trash"></i> | 34 | </a> | 38 | </a> |
---|
35 | {% endif %} | 39 | {% endif %} |
---|
| | 40 | {% endif %} |
---|
36 | </li> | 41 | </li> |
---|
37 | {% endfor %} | 42 | {% endfor %} |
---|
38 | </ul> | 43 | </ul> |
---|
| | 44 | |
---|
| | 45 | <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true"> |
---|
| | 46 | <div class="modal-dialog modal-lg"> |
---|
| | 47 | <div class="modal-content"> |
---|
| | 48 | <div class="modal-header"> |
---|
| | 49 | <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
---|
| | 50 | <h4 class="modal-title">Edit SWeeT</h4> |
---|
| | 51 | </div> |
---|
| | 52 | <div class="modal-body row"> |
---|
| | 53 | |
---|
| | 54 | </div> |
---|
| | 55 | <div class="modal-footer"> |
---|
| | 56 | <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> |
---|
| | 57 | </div> |
---|
| | 58 | </div><!-- /.modal-content --> |
---|
| | 59 | </div><!-- /.modal-dialog --> |
---|
| | 60 | </div><!-- /.modal --> |
---|
| | 61 | |
---|
| | 62 | <script type="text/template" id="editTemplate"> |
---|
| | 63 | <form action="" method="post"> |
---|
| | 64 | <% _.each(items, function(item, key) { %> |
---|
| | 65 | <div class="input-group col-md-12"> |
---|
| | 66 | <label> <%= key %> </label> |
---|
| | 67 | <input name=<%= key %> for=<%= key %> class="form-control" type="text"> </input> |
---|
| | 68 | </div> |
---|
| | 69 | </br> |
---|
| | 70 | <% }) %> |
---|
| | 71 | <button class="btn btn-default" type="submit">Save</button> |
---|
| | 72 | </form> |
---|
| | 73 | </script> |
---|
39 | {% endblock %} | 74 | {% endblock %} |
---|