Commit 80631186064bd17aa5d2e8898c3bfb822c171f88

Add sign in functionality

  Right now this app, authenticates with the sweet store. The sweet store
implements a very naive authentication. It does not even send back a session
token! It only sends back a 200 if the auth was successful else a 403. Based on
that the client has to set some auth token. This should improve. The sweet
store can send back a session token which the client can store in its cookie,
which results in smoother auth mechanism. Right now there is no auth as such.
Sweet store sends back 200 if the auth was successful, and then subsequent
requests are made by the client injecting the 'who' parameter, and the server
accepts and agrees with the client. Here the client can tamper with the
username or 'who'. The correct way is, when the auth is successful, sweet store
sends back a auth token, which the client stores in the cookie. And subsequent
sweet store requests are made along with that cookie. Then the sweet store
should identify the username or 'who' from the cookie.
  • Diff rendering mode:
  • inline
  • side by side

swtr/static/css/swtmaker.css

1#swt-maker {1#swt-maker {
2}2}
3#signinview {
4 margin 0 20px;
5 padding: 10px;
6 text-align: center;
7}
3#img-annotation-wrapper {8#img-annotation-wrapper {
4 margin: 30px auto 0 auto;9 margin: 30px auto 0 auto;
5 /*border: 1px solid black;*/10 /*border: 1px solid black;*/

swtr/static/js/swtmaker.js

149 //TODO: move this to a annotation view or something149 //TODO: move this to a annotation view or something
150 anno.removeAll();150 anno.removeAll();
151 _.each(swtr.sweets.models, function(swt) {151 _.each(swtr.sweets.models, function(swt) {
152 swt.get('how')['editable'] = false;
152 if(!_.has(swt.get('how'), 'editable')) {
153 swt.get('how')['editable'] = false;
154 swt.get('how').text += '\n - by ' + swt.get('who');
155 }
153 anno.addAnnotation(swt.get('how'));156 anno.addAnnotation(swt.get('how'));
154 });157 });
155 //console.log(swtr.sweets.toJSON());158 //console.log(swtr.sweets.toJSON());
164 }164 }
165 });165 });
166 this.cleanUp();166 this.cleanUp();
167 return false;
167 },168 },
168 cleanUp: function() {169 cleanUp: function() {
169 console.log('cleaning up');
170 //console.log('cleaning up');
170 $(this.el).hide();171 $(this.el).hide();
171 }172 }
172 });173 });
176 el: $('#swt-maker'),176 el: $('#swt-maker'),
177 events: {177 events: {
178 'click #img-url-submit': 'setImage',178 'click #img-url-submit': 'setImage',
179 'click #sweet': 'sweet'
179 'click #sweet': 'sweet',
180 'click #signin-credentials': 'getSignInCredentials'
180 },181 },
181 initialize: function() {182 initialize: function() {
182 //var allElements = $('body *');183 //var allElements = $('body *');
218 getExistingAnnotations: function() {218 getExistingAnnotations: function() {
219 this.helpview.step(0);219 this.helpview.step(0);
220 this.$overlay.show();220 this.$overlay.show();
221 console.log('getting existing annotations of ', this.imgURL);
221 //console.log('getting existing annotations of ', this.imgURL);
222 swtr.sweets.getAll({222 swtr.sweets.getAll({
223 where: this.imgURL,223 where: this.imgURL,
224 success: function(data) {224 success: function(data) {
226 swtr.sweets.add(data);226 swtr.sweets.add(data);
227 _.each(data, function(swt) {227 _.each(data, function(swt) {
228 swt.how['editable'] = false;228 swt.how['editable'] = false;
229 swt.how.text+= '\n - by ' + swt.who;
229 swt.how.text += '\n - by ' + swt.who;
230 anno.addAnnotation(swt.how);230 anno.addAnnotation(swt.how);
231 });231 });
232 swtr.appView.$overlay.hide();232 swtr.appView.$overlay.hide();
235 },235 },
236 error: function(jqxhr, error, statusText) {236 error: function(jqxhr, error, statusText) {
237 if(jqxhr.status === 404) { //annotations don't exist for this image237 if(jqxhr.status === 404) { //annotations don't exist for this image
238 console.log('annotations don\'t exist for this image. Create one!');
238 //console.log('annotations don\'t exist for this image. Create one!');
239 }239 }
240 swtr.appView.$overlay.hide();240 swtr.appView.$overlay.hide();
241 swtr.appView.helpview.step(2);241 swtr.appView.helpview.step(2);
266 this.getSweets();266 this.getSweets();
267 this.showSweets();267 this.showSweets();
268 return false;268 return false;
269 },
270 getSignInCredentials: function(event) {
271 event.preventDefault();
272 if(swtr.who === 'Guest' && !$('#username').length) {
273 var template = _.template($('#signin-credentials-template').html());
274 $('#signin-msg').html(template());
275 }
276 else if($('#username').length && $('#username').val()) {
277 var username = $('#username').val();
278 var password = $('#password').val();
279 this.signIn(username, password);
280 }
281 return false;
282 },
283 signIn: function(username, password) {
284 this.$overlay.show();
285 $.ajax({
286 url: swtr.swtstoreURL() + swtr.endpoints.auth,
287 type: 'POST',
288 data: {user: username, hash: password},
289 success: function(data) {
290 swtr.appView.$overlay.hide();
291 swtr.who = username;
292 $('#signinview').html('You are signed in.');
293 },
294 error: function(jqxhr, status, error) {
295 swtr.appView.$overlay.hide();
296 if(error === 'FORBIDDEN') {
297 $('#signin-msg').html('Error signing in. Please check your username and password. ');
298 }
299 else {
300 $('#signin-msg').html('Error signin in. Please try again.');
301 }
302 }
303 });
269 }304 }
270 });305 });
271306
335 break;335 break;
336 }336 }
337 $(this.el).html(text);337 $(this.el).html(text);
338 $(window).scrollTop(0, 0);
338 }339 }
339 });340 });
340341

swtr/templates/index.html

1616
17 <div id="swt-maker" class="container">17 <div id="swt-maker" class="container">
18 <div id="helpview" class="alert alert-info"></div>18 <div id="helpview" class="alert alert-info"></div>
19 <div class="row" id="signinview">
20 <form class="form-inline" role="form">
21 <span id="signin-msg">You are not signed in. </span>
22 <button class="btn btn-sm btn-primary" id="signin-credentials">
23 Sign In
24 </button>
25 </form>
26 </div>
19 <div id="img-input">27 <div id="img-input">
20 <div class="form-group">28 <div class="form-group">
21 <input type="text" placeholder="Enter URL of the image"29 <input type="text" placeholder="Enter URL of the image"
52 <script>52 <script>
53 window.swtr = window.swtr || {};53 window.swtr = window.swtr || {};
54 swtr.swtstoreURL = function() { return '{{ conf.swtstoreURL }}'; }54 swtr.swtstoreURL = function() { return '{{ conf.swtstoreURL }}'; }
55 swtr.endpoints = {'get': '/sweets/q', 'post': '/sweets'};
55 swtr.endpoints = {'get': '/sweets/q', 'post': '/sweets', 'auth':
56 '/authenticate'};
56 window.onload = function() {57 window.onload = function() {
57 swtr.init();58 swtr.init();
58 };59 };
71 /<a href="<%= where %>"><%= where.substr(0, 30) + '...' %></a>71 /<a href="<%= where %>"><%= where.substr(0, 30) + '...' %></a>
72 <%= how %>72 <%= how %>
73 </li>73 </li>
74 </script>
75 <script type="text/template" id="signin-credentials-template">
76 <div class="form-group">
77 <label class="sr-only" for="username">Username</label>
78 <input type="text" class="form-control" id="username" placeholder="Enter username">
79 </div>
80 <div class="form-group">
81 <label class="sr-only" for="password">Password</label>
82 <input type="password" class="form-control" id="password" placeholder="Password">
83 </div>
74 </script>84 </script>
75 </body>85 </body>
76</html>86</html>