git.fiddlerwoaroof.com
Browse code

Avatars and hashed passwords

- Added gravatars
- Added bcrypt passwords through postgresql

fiddlerwoaroof authored on 22/03/2015 09:10:02
Showing 10 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 bin
2 2
 bower_components
3 3
 include
4
-lib
4
+/lib
5 5
 local
6 6
 *.pyc
7 7
 .*.swp
... ...
@@ -182,4 +182,19 @@ BEGIN
182 182
   DELETE FROM user_ak WHERE user_id=uid AND user_ak.ak=supplied_ak RETURNING user_ak.ak INTO result;
183 183
   RETURN result;
184 184
 END
185
-$$ LANGUAGE plpgsql
185
+$$ LANGUAGE plpgsql;
186
+
187
+DROP FUNCTION IF EXISTS check_password(text,text);
188
+CREATE OR REPLACE FUNCTION check_password(username text, provided_pass text) RETURNS bool
189
+AS $$
190
+DECLARE
191
+  uid INT;
192
+  stored_hash TEXT;
193
+  hash TEXT;
194
+  result BOOL;
195
+BEGIN
196
+  SELECT id,password INTO uid,stored_hash FROM users WHERE users.name = username;
197
+  SELECT stored_hash = crypt(provided_pass, stored_hash) INTO result;
198
+  RETURN result;
199
+END
200
+$$ LANGUAGE plpgsql;
... ...
@@ -83,7 +83,7 @@ def adduser():
83 83
             username = username.strip().lower()
84 84
             password = password.strip()
85 85
             try:
86
-                cur.execute('INSERT INTO users (name,password,email) VALUES (%s,%s,%s)',
86
+                cur.execute("INSERT INTO users (name,password,email) VALUES (%s,crypt(%s, gen_salt('bf', 11)),%s)",
87 87
                             (username, password, 'abc@def.com'))
88 88
                 session['username'] = username
89 89
                 result['status'] = True
... ...
@@ -147,19 +147,23 @@ def login():
147 147
     username = username.strip().lower()
148 148
     password = password.strip()
149 149
     user = users.get(username, {})
150
-    rightPassword = user.get('password',None)
151
-    if password == rightPassword:
152
-        if 'ak' in request.args and request.args['ak']:
153
-            ak = base64.b64encode(os.urandom(24))
154
-            with database.get_db() as db:
155
-                with db.cursor() as cur:
156
-                    cur.callproc('put_ak', (username, ak))
157
-            result = {'success': True, 'ak': ak}
158
-        else:
159
-            session['username'] = username
160
-            result['status'] = True
161
-    else:
162
-        result['message'] = 'Wrong Username or Password'
150
+    rightPassword = user.get('password',object())
151
+    with database.get_db() as db:
152
+        with db.cursor() as cur:
153
+            cur.callproc('check_password', (username, password))
154
+            success = cur.fetchone()[0]
155
+            if success:
156
+                if 'ak' in request.args and request.args['ak']:
157
+                    ak = base64.b64encode(os.urandom(24))
158
+                    with database.get_db() as db:
159
+                        with db.cursor() as cur:
160
+                            cur.callproc('put_ak', (username, ak))
161
+                    result = {'success': True, 'ak': ak}
162
+                else:
163
+                    session['username'] = username
164
+                    result['status'] = True
165
+            else:
166
+                result['message'] = 'Wrong Username or Password'
163 167
     return json.dumps(result)
164 168
 
165 169
 @user_blueprint.route('/logout')
... ...
@@ -52,6 +52,17 @@ img {
52 52
 
53 53
 /* @end */
54 54
 
55
+.avatar-image {
56
+  display: inline-block;
57
+  vertical-align: middle;
58
+}
59
+.avatar-image img {
60
+  border-radius: 12px;
61
+}
62
+.bone-details {
63
+  display: inline-block;
64
+  vertical-align: middle;
65
+}
55 66
 .sub-ctrl {
56 67
   display: inline-block;
57 68
   vertical-align: middle;
... ...
@@ -167,6 +178,7 @@ main form input[type="text"] {
167 178
   white-space: nowrap;
168 179
   text-overflow: ellipsis;
169 180
   padding-right: 1em;
181
+  margin-bottom: 12px;
170 182
 }
171 183
 /* @end */
172 184
 
... ...
@@ -24,9 +24,11 @@
24 24
   <meta name="msapplication-config" content="/images/icons/browserconfig.xml">
25 25
   <meta name="theme-color" content="#000000">
26 26
   <!-- JS -->
27
+  <script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/md5.js"></script>
27 28
   <script src="/lib/angular.js"></script>
28 29
   <script src="/lib/angular-route.min.js"></script>
29 30
   <script src="/lib/angular-resource.min.js"></script>
31
+  <script src="/js/new/directives.js"></script>
30 32
   <script src="/js/new/services.js"></script>
31 33
   <script src="/js/new/controller.js"></script>
32 34
   <!-- CSS -->
... ...
@@ -1,4 +1,4 @@
1
-var marrowApp = angular.module('marrowApp', ['ngRoute', 'marrowApp.services']);
1
+var marrowApp = angular.module('marrowApp', ['ngRoute', 'marrowApp.services', 'marrowApp.directives']);
2 2
 
3 3
 var compareTo = function() { return {
4 4
   require: "ngModel",
... ...
@@ -150,8 +150,14 @@ function controllerFactory(name, getendpoint, cb, afterGet) {
150 150
     $scope.sectionTitle = "";
151 151
     $scope.friends = SubscribedTo.get();
152 152
 
153
+    $scope.gravURL = function(uid) {
154
+      var hash = CryptoJS.MD5(uid);
155
+      return '//gravatar.com/avatar/'+hash+'?d=identicon&s=24';
156
+    };
153 157
     $scope.update = function() {
154
-      return $http.get(getendpoint).success(function(data) {
158
+      var config = {params: $scope.args? $scope.args: {}};
159
+      q = config;
160
+      return $http.get(getendpoint, config).success(function(data) {
155 161
         $scope.sectionTitle = data.sectionTitle;
156 162
         $scope.bone = data.marrow;
157 163
       });
... ...
@@ -184,7 +190,7 @@ function toggleSubscribe($http,$scope) {
184 190
     } else {
185 191
       promise = $http.post('/api/bones/subscribe', postObj);
186 192
     }
187
-    
193
+
188 194
     return promise.success(function(result) {
189 195
         console.log('bing!');
190 196
         result = JSON.parse(result);
... ...
@@ -289,14 +295,19 @@ controllerFactory('RandomMarrowCtrl', '/api/bones/random',
289 295
 
290 296
   },
291 297
   function ($scope,$http) {
298
+    $scope.args = {last: $scope.sectionTitle};
292 299
     $http.get('/api/user/follows/'+$scope.sectionTitle).success(function(result) {
293 300
       $scope.subscribed = result.follows;
294 301
       $scope.subscribeLabel = $scope.subscribed ? 'unSubscribe': 'Subscribe';
295 302
   });
296 303
 });
297 304
 
298
-controllerFactory('SubscriptionCtrl', '/api/bones/subscriptions', 
305
+controllerFactory('SubscriptionCtrl', '/api/bones/subscriptions',
299 306
   function($scope, $http, Bones, SubscribedTo){
307
+    $scope.gravURL = function(uid) {
308
+      var hash = CryptoJS.MD5(uid);
309
+      return '//gravatar.com/avatar/'+hash+'?d=identicon&s=24';
310
+    };
300 311
     $scope.emptyOrEquals = function(actual, expected) {
301 312
       if (!expected) { return true;}
302 313
       else {return actual === expected;}
... ...
@@ -20,4 +20,3 @@ serviceModule.factory('SubscribedTo', ['$resource',
20 20
   function subscriberFactory($resource) {
21 21
     return $resource('/api/user/following', {}, {});
22 22
   }]);
23
-
... ...
@@ -2,6 +2,9 @@
2 2
   <h2 class="section-title">
3 3
     <a class="fa fa-cog user-settings" href="/settings"></a>
4 4
     <a class="user-link" ng-href="{{path('UserCtrl', {'user': sectionTitle})}}">{{path('UserCtrl', {'user': sectionTitle})}}</a>
5
+    <a class="avatar-image" href="{{ path('UserCtrl', {'user': marrow.poster}) }}" title="{{marrow.poster}}">
6
+      <img ng-src="{{gravURL(sectionTitle)}}" />
7
+    </a>
5 8
   </h2>
6 9
   <form>
7 10
     <input type="text" ng-model="url" placeholder="http:// . . ."/>
... ...
@@ -2,6 +2,9 @@
2 2
   <h2 class="section-title">
3 3
     <button type="submit" ng-class="['sub-ctrl']"   ng-click="toggleSubscribe()">{{subscribeLabel}}</button>
4 4
     <a class="user-link" ng-href="{{path('UserCtrl', {'user': sectionTitle})}}">{{path('UserCtrl', {'user': sectionTitle})}}</a>
5
+    <a class="avatar-image" href="{{ path('UserCtrl', {'user': marrow.poster}) }}" title="{{marrow.poster}}">
6
+      <img ng-src="{{gravURL(sectionTitle)}}" />
7
+    </a>
5 8
   </h2>
6 9
   <ul class="bone-list">
7 10
     <li ng-repeat="marrow in bone" class="bone-item" data-id="{{marrow.id}}" data-url="{{marrow.url}}" data-posted="{{marrow.posted}}" data-title="{{marrow.title}}">
... ...
@@ -12,8 +12,13 @@
12 12
   </form>
13 13
   <ul class="bone-list">
14 14
     <li ng-repeat="marrow in bone | filter:{poster:friend}:emptyOrEquals" class="bone-item" data-id="{{marrow.id}}" data-url="{{marrow.url}}" data-posted="{{marrow.posted}}" data-title="{{marrow.title}}" data-poster="{{marrow.poster}}">
15
-      <span ng-if="marrow.title"><a href="{{marrow.url}}" class="list-item" >{{marrow.title}}</a><br /></span>
16
-      <a href="{{marrow.url}}" class="{{marrow.title? 'de-emphasize' : ''}}" >{{marrow.url}}</a>
15
+      <div class="bone-details">
16
+        <span ng-if="marrow.title"><a href="{{marrow.url}}" class="list-item" >{{marrow.title}}</a><br /></span>
17
+        <a href="{{marrow.url}}" ng-class="{'de-emphasize':marrow.title}" >{{marrow.url}}</a>
18
+      </div>
19
+      <a class="avatar-image" href="{{ path('UserCtrl', {'user': marrow.poster}) }}" title="{{marrow.poster}}">
20
+        <img ng-src="{{gravURL(marrow.poster)}}" />
21
+      </a>
17 22
     </li>
18 23
   </ul>
19 24
 </section>