mirror of
				http://git.whoc.org.uk/git/password-manager.git
				synced 2025-10-31 19:27:34 +01:00 
			
		
		
		
	
							
								
								
									
										6
									
								
								backend/flask/src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								backend/flask/src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| bin/ | ||||
| lib/ | ||||
| include/ | ||||
| clipperz.egg-info/ | ||||
| .Python | ||||
| app.db | ||||
| @@ -1,3 +1,4 @@ | ||||
| """Clipperz API handler.""" | ||||
| import json | ||||
| import random | ||||
| import hashlib | ||||
| @@ -12,27 +13,36 @@ from .exceptions import InvalidUsage | ||||
| from .models import User, Record, RecordVersion, OneTimePassword | ||||
|  | ||||
|  | ||||
| #============================================================================== | ||||
| # ============================================================================== | ||||
| # Helpers | ||||
| #============================================================================== | ||||
| # ============================================================================== | ||||
| def randomSeed(): | ||||
|     """Generate a random seed.""" | ||||
|     return hex(random.getrandbits(32*8))[2:-1] | ||||
|  | ||||
|  | ||||
| def clipperzHash(aString): | ||||
|     """Calculate a clipperz hash. | ||||
|  | ||||
|     sha256(sha256(aString)) | ||||
|     """ | ||||
|     firstRound = hashlib.sha256() | ||||
|     firstRound.update(aString) | ||||
|     result = hashlib.sha256() | ||||
|     result.update(firstRound.digest()) | ||||
|  | ||||
|     return result.hexdigest() | ||||
| #============================================================================== | ||||
| # ============================================================================== | ||||
| # Method handlers | ||||
| #============================================================================== | ||||
| # ============================================================================== | ||||
|  | ||||
|  | ||||
| class HandlerMixin: | ||||
|  | ||||
|     """Mixin for handling requests.""" | ||||
|  | ||||
|     def handle_request(self, request): | ||||
|         """Default method to handle a request.""" | ||||
|         parameters = json.loads(request.form['parameters']) | ||||
|         app.logger.debug('raw parameters: %s', parameters) | ||||
|         parameters = parameters['parameters'] | ||||
| @@ -50,7 +60,14 @@ class HandlerMixin: | ||||
|  | ||||
|  | ||||
| class registration(HandlerMixin): | ||||
|  | ||||
|     """Registration handler.""" | ||||
|  | ||||
|     def completeRegistration(self, parameters, request): | ||||
|         """Complete a registration. | ||||
|  | ||||
|         Create a new user. | ||||
|         """ | ||||
|         credentials = parameters['credentials'] | ||||
|         data = parameters['user'] | ||||
|         user = User() | ||||
| @@ -63,11 +80,21 @@ class registration(HandlerMixin): | ||||
|  | ||||
|  | ||||
| class handshake(HandlerMixin): | ||||
|  | ||||
|     """Handshake handler. | ||||
|  | ||||
|     This handles the logon process. | ||||
|     """ | ||||
|  | ||||
|     srp_n = '115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3' | ||||
|     srp_g = 2 | ||||
|     srp_n = long(srp_n, 16) | ||||
|  | ||||
|     def connect(self, parameters, request): | ||||
|         """Process a connect request. | ||||
|  | ||||
|         Attempt to log in by processing the parameters. | ||||
|         """ | ||||
|         result = {} | ||||
|         session['C'] = parameters['parameters']['C'] | ||||
|         session['A'] = parameters['parameters']['A'] | ||||
| @@ -127,8 +154,12 @@ class handshake(HandlerMixin): | ||||
|         return jsonify({'result': result}) | ||||
|  | ||||
|     def credentialCheck(self, parameters, request): | ||||
|         """Check credentials. | ||||
|  | ||||
|         Handles the SRP process. | ||||
|         """ | ||||
|         country = 'US' | ||||
|         # hard-coded for development | ||||
|         # hard-coded for development/personal use. | ||||
|         result = { | ||||
|             'accountInfo': { | ||||
|                 'features': [ | ||||
| @@ -203,14 +234,15 @@ class handshake(HandlerMixin): | ||||
|         return jsonify({'result': result}) | ||||
|  | ||||
|     def oneTimePassword(self, parameters, request): | ||||
|         #"parameters": { | ||||
|         #"message": "oneTimePassword", | ||||
|         #"version": "0.2", | ||||
|         #"parameters": { | ||||
|         #  "oneTimePasswordKey": "03bd882...396082c", | ||||
|         #  "oneTimePasswordKeyChecksum": "f73f629...041031d" | ||||
|         #} | ||||
|         #} | ||||
|         """Handle one time password logins.""" | ||||
|         # "parameters": { | ||||
|         # "message": "oneTimePassword", | ||||
|         # "version": "0.2", | ||||
|         # "parameters": { | ||||
|         #   "oneTimePasswordKey": "03bd882...396082c", | ||||
|         #   "oneTimePasswordKeyChecksum": "f73f629...041031d" | ||||
|         # } | ||||
|         # } | ||||
|         result = {} | ||||
|  | ||||
|         try: | ||||
| @@ -237,8 +269,12 @@ class handshake(HandlerMixin): | ||||
|  | ||||
|  | ||||
| class message(HandlerMixin): | ||||
|  | ||||
|     """Handle messages once logged in.""" | ||||
|  | ||||
|     @login_required | ||||
|     def getUserDetails(self, parameters, request): | ||||
|         """Get a user's details.""" | ||||
|         app.logger.debug(parameters) | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
| @@ -252,7 +288,7 @@ class message(HandlerMixin): | ||||
|         # Online results | ||||
|         # {"result": | ||||
|         #     { | ||||
|         #         "header": "{\"records\":{\"index\":{\"383036...eeefbe48\":\"0\"},\"data\":\"zrhb3/791SDdb48v3vXfPzeDrv0Jhs4rAaOKHx+jDF6pwm/qi9DGSR0JwrprOgwv3bjYJgU2xHA8cuA0bPvABHSHK6fnGwvhSlyYjskY2Cy/WbRJhcA4kw+VUsOjZPRxtM8bSJnSxViAXsghTcya6+5M3MdMJHE=\"},\"directLogins\":{\"index\":{},\"data\":\"s7KYzHwKISmjYufv9h0mpTiM\"},\"preferences\":{\"data\":\"mf8fWjpOQjlV18ukEO9FN3LP\"},\"oneTimePasswords\":{\"data\":\"8tV1yRHv30lsl3FadG9YnTOo\"},\"version\":\"0.1\"}", | ||||
|         #         "header": "{\"records\":{\"index\":{\"383036...eeefbe48\":\"0\"},\"data\":\"zrhb3/791SDdb48v3vXfPzeDrv0Jhs4rAaOKHx+jDF6pwm/qi9DGSR0JwrprOgwv3bjYJgU2xHA8cuA0bPvABHSHK6fnGwvhSlyYjskY2Cy/WbRJhcA4kw+VUsOjZPRxtM8bSJnSxViAXsghTcya6+5M3MdMJHE=\"},\"directLogins\":{\"index\":{},\"data\":\"s7KYzHwKISmjYufv9h0mpTiM\"},\"preferences\":{\"data\":\"mf8fWjpOQjlV18ukEO9FN3LP\"},\"oneTimePasswords\":{\"data\":\"8tV1yRHv30lsl3FadG9YnTOo\"},\"version\":\"0.1\"}",  # NOQA | ||||
|         #         "lock": "3D4B4501-D7A9-6E4F-A487-9428C0B6E79D", | ||||
|         #         "version": "0.4", | ||||
|         #         "recordsStats": { | ||||
| @@ -266,8 +302,8 @@ class message(HandlerMixin): | ||||
|         #     } | ||||
|         # } | ||||
|         # Dev results | ||||
|         #{"result": | ||||
|         #    {"header": "{\"records\":{\"index\":{\"843a95d8...5f734b\":\"1\"},\"data\":\"fKgc5Jt9JH/CibCIpcRmwyLuLIvufWchNJga7GoFcWT9K8LR+ai0BvzWBUxcPccivE9zPv2Swe5E8wPEIc+Lv0U73NobJEct7WqBcCdLxszBE1SokxPEZDUVdWVQtAiwgOS219inCFmI5CaB\"},\"directLogins\":{\"index\":{},\"data\":\"rnMQBB81ezh6JKNGXkDCyY+q\"},\"preferences\":{\"data\":\"9jzR9Goo5PGpXbAdmsXHuQGp\"},\"oneTimePasswords\":{\"data\":\"iXEUuQGskZhMyHEwU+3tRGQM\"},\"version\":\"0.1\"}", | ||||
|         # {"result": | ||||
|         #    {"header": "{\"records\":{\"index\":{\"843a95d8...5f734b\":\"1\"},\"data\":\"fKgc5Jt9JH/CibCIpcRmwyLuLIvufWchNJga7GoFcWT9K8LR+ai0BvzWBUxcPccivE9zPv2Swe5E8wPEIc+Lv0U73NobJEct7WqBcCdLxszBE1SokxPEZDUVdWVQtAiwgOS219inCFmI5CaB\"},\"directLogins\":{\"index\":{},\"data\":\"rnMQBB81ezh6JKNGXkDCyY+q\"},\"preferences\":{\"data\":\"9jzR9Goo5PGpXbAdmsXHuQGp\"},\"oneTimePasswords\":{\"data\":\"iXEUuQGskZhMyHEwU+3tRGQM\"},\"version\":\"0.1\"}",  # NOQA | ||||
|         #     "recordStats": { | ||||
|         #       "843a95d8...5f734b": { | ||||
|         #           "updateDate": "Sun, 12 Apr 2015 13:08:44 GMT" | ||||
| @@ -295,6 +331,7 @@ class message(HandlerMixin): | ||||
|  | ||||
|     @login_required | ||||
|     def saveChanges(self, parameters, request): | ||||
|         """Save changes to a user's settings.""" | ||||
|         result = {} | ||||
|         parameters = parameters['parameters'] | ||||
|         if ('user' not in parameters | ||||
| @@ -340,7 +377,8 @@ class message(HandlerMixin): | ||||
|  | ||||
|     @login_required | ||||
|     def getRecordDetail(self, parameters, request): | ||||
|         #{ | ||||
|         """Get details about a record.""" | ||||
|         # { | ||||
|         #  "parameters": { | ||||
|         #    "srpSharedSecret": "bf79ad3cf0c1...63462a9fb560", | ||||
|         #    "message": "getRecordDetail", | ||||
| @@ -348,7 +386,7 @@ class message(HandlerMixin): | ||||
|         #      "reference": "e3a5856...20e080fc97f13c14c" | ||||
|         #    } | ||||
|         #  } | ||||
|         #} | ||||
|         # } | ||||
|         app.logger.debug(parameters) | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
| @@ -404,13 +442,14 @@ class message(HandlerMixin): | ||||
|  | ||||
|     @login_required | ||||
|     def getOneTimePasswordsDetails(self, parameters, request): | ||||
|         #{ | ||||
|         """Get details about a one time password.""" | ||||
|         # { | ||||
|         #  "parameters": { | ||||
|         #    "srpSharedSecret": "bf79ad3cf0c1...63462a9fb560", | ||||
|         #    "message": "getOneTimePasswordsDetails", | ||||
|         #    "parameters": {} | ||||
|         #  } | ||||
|         #} | ||||
|         # } | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
|                 'Mal-formed message format.', | ||||
| @@ -425,20 +464,24 @@ class message(HandlerMixin): | ||||
|  | ||||
|         otps = OneTimePassword().query.filter_by(user=current_user).all() | ||||
|         for otp in otps: | ||||
|             #{"e8541...af0c6b951":{"status":"ACTIVE"}} | ||||
|             # {"e8541...af0c6b951":{"status":"ACTIVE"}} | ||||
|             result[otp.reference] = {'status': otp.status} | ||||
|  | ||||
|         return jsonify({'result': result}) | ||||
|  | ||||
|     @login_required | ||||
|     def getLoginHistory(self, parameters, request): | ||||
|         #{ | ||||
|         """Get login history. | ||||
|  | ||||
|         Not currently fully implemented. | ||||
|         """ | ||||
|         # { | ||||
|         #  "parameters": { | ||||
|         #    "srpSharedSecret": "bf79ad3cf0c1...63462a9fb560", | ||||
|         #    "message": "getOneTimePasswordsDetails", | ||||
|         #    "parameters": {} | ||||
|         #  } | ||||
|         #} | ||||
|         # } | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
|                 'Mal-formed message format.', | ||||
| @@ -462,6 +505,7 @@ class message(HandlerMixin): | ||||
|  | ||||
|     @login_required | ||||
|     def addNewOneTimePassword(self, parameters, request): | ||||
|         """Add a new one time password.""" | ||||
|         #  "parameters": { | ||||
|         #    "message": "addNewOneTimePassword", | ||||
|         #    "srpSharedSecret": "1e8e037a8...85680f931d45dfc20472cf9d1", | ||||
| @@ -481,7 +525,7 @@ class message(HandlerMixin): | ||||
|         #      } | ||||
|         #    } | ||||
|         #  } | ||||
|         #} | ||||
|         # } | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
|                 'Mal-formed message format.', | ||||
| @@ -524,6 +568,7 @@ class message(HandlerMixin): | ||||
|         return jsonify({'result': result}) | ||||
|  | ||||
|     def echo(self, parameters, request): | ||||
|         """Check the status of the session.""" | ||||
|         result = {} | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
| @@ -549,6 +594,7 @@ class message(HandlerMixin): | ||||
|  | ||||
|     @login_required | ||||
|     def deleteUser(self, parameters, request): | ||||
|         """Delete a user and all of its records.""" | ||||
|         result = {} | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
| @@ -573,7 +619,8 @@ class message(HandlerMixin): | ||||
|  | ||||
|     @login_required | ||||
|     def upgradeUserCredentials(self, parameters, request): | ||||
|         #{"parameters":{"message":"upgradeUserCredentials","srpSharedSecret":"36...d6","parameters":{"credentials":{"C":"59d02038fdb47cee5b7837a697bc8ff41cc66d8844c8fce844cdf45b0b08b1e4","s":"fe40513b99fbaca9bfe51b8d6e9b3eb42b1e01ce8b0ae32461bec0294c1030ed","v":"300b92f4a3e34034d78cd5081f8db36dbf2a4c5f7a41db6954518815a3554278","version":"0.2"},"user":{"header":"{\"records\":{\"index\":{},\"data\":\"VIIDc5vFNoIflyXF8syb8fRS\"},\"directLogins\":{\"index\":{},\"data\":\"9elg3tu2UqsJ0zbUAdQkLE69\"},\"preferences\":{\"data\":\"Sbwar35Ynd/XobuAm4K66lqj\"},\"oneTimePasswords\":{\"data\":\"tAcTsWVTwALSfxXvCChHi4FD\"},\"version\":\"0.1\"}","statistics":"","version":"0.4","lock":null}}}} | ||||
|         """Upgrade a user's credentials to a new password.""" | ||||
|         # {"parameters":{"message":"upgradeUserCredentials","srpSharedSecret":"36...d6","parameters":{"credentials":{"C":"59d02038fdb47cee5b7837a697bc8ff41cc66d8844c8fce844cdf45b0b08b1e4","s":"fe40513b99fbaca9bfe51b8d6e9b3eb42b1e01ce8b0ae32461bec0294c1030ed","v":"300b92f4a3e34034d78cd5081f8db36dbf2a4c5f7a41db6954518815a3554278","version":"0.2"},"user":{"header":"{\"records\":{\"index\":{},\"data\":\"VIIDc5vFNoIflyXF8syb8fRS\"},\"directLogins\":{\"index\":{},\"data\":\"9elg3tu2UqsJ0zbUAdQkLE69\"},\"preferences\":{\"data\":\"Sbwar35Ynd/XobuAm4K66lqj\"},\"oneTimePasswords\":{\"data\":\"tAcTsWVTwALSfxXvCChHi4FD\"},\"version\":\"0.1\"}","statistics":"","version":"0.4","lock":null}}}}  # NOQA | ||||
|         result = {} | ||||
|         if 'srpSharedSecret' not in parameters: | ||||
|             raise InvalidUsage( | ||||
| @@ -614,7 +661,11 @@ class message(HandlerMixin): | ||||
|  | ||||
|  | ||||
| class logout(HandlerMixin): | ||||
|  | ||||
|     """Logout handler.""" | ||||
|  | ||||
|     def handle_request(self, request): | ||||
|         """Handle a logout request.""" | ||||
|         result = {} | ||||
|         logout_user() | ||||
|         session.clear() | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| """Clipperz models.""" | ||||
| import datetime | ||||
|  | ||||
| from flask.ext.login import UserMixin | ||||
| @@ -6,15 +7,18 @@ from clipperz import app, db | ||||
|  | ||||
|  | ||||
| class User(db.Model, UserMixin): | ||||
|  | ||||
|     """Clipperz User model.""" | ||||
|  | ||||
|     id = db.Column(db.Integer, primary_key=True) | ||||
|     username = db.Column(db.String(), unique=True, index=True) | ||||
|     username = db.Column(db.String(255), unique=True, index=True) | ||||
|     srp_s = db.Column(db.String(128)) | ||||
|     srp_v = db.Column(db.String(128)) | ||||
|     header = db.Column(db.Text()) | ||||
|     statistics = db.Column(db.Text()) | ||||
|     auth_version = db.Column(db.String()) | ||||
|     version = db.Column(db.String()) | ||||
|     lock = db.Column(db.String()) | ||||
|     auth_version = db.Column(db.String(255)) | ||||
|     version = db.Column(db.String(255)) | ||||
|     lock = db.Column(db.String(255)) | ||||
|     records = db.relationship( | ||||
|         'Record', | ||||
|         backref='user', | ||||
| @@ -29,12 +33,14 @@ class User(db.Model, UserMixin): | ||||
|     update_date = db.Column(db.DateTime(), nullable=True) | ||||
|  | ||||
|     def updateCredentials(self, credentials): | ||||
|         """Update user credentials.""" | ||||
|         self.username = credentials['C'] | ||||
|         self.srp_s = credentials['s'] | ||||
|         self.srp_v = credentials['v'] | ||||
|         self.auth_version = credentials['version'] | ||||
|  | ||||
|     def update(self, data): | ||||
|         """Update user object.""" | ||||
|         self.header = data['header'] | ||||
|         self.statistics = data['statistics'] | ||||
|         self.version = data['version'] | ||||
| @@ -44,24 +50,33 @@ class User(db.Model, UserMixin): | ||||
|         self.offline_saved = False | ||||
|  | ||||
|     def __repr__(self): | ||||
|         """User representation.""" | ||||
|         return '<User %r>' % (self.username) | ||||
|  | ||||
| #------------------------------------------------------------------------------ | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| class RecordVersion(db.Model): | ||||
|  | ||||
|     """ | ||||
|     Model a RecordVersion. | ||||
|  | ||||
|     RecordVersion store attributes associated with a specific version of a | ||||
|     record. | ||||
|     """ | ||||
|  | ||||
|     id = db.Column(db.Integer(), primary_key=True) | ||||
|     reference = db.Column(db.String(), unique=True, index=True) | ||||
|     reference = db.Column(db.String(255), unique=True, index=True) | ||||
|     header = db.Column(db.Text()) | ||||
|     data = db.Column(db.Text()) | ||||
|     api_version = db.Column(db.String()) | ||||
|     api_version = db.Column(db.String(255)) | ||||
|     version = db.Column(db.Integer()) | ||||
|     previous_version_key = db.Column(db.String()) | ||||
|     previous_version_key = db.Column(db.String(255)) | ||||
|     previous_version_id = db.Column(db.Integer(), | ||||
|                                     db.ForeignKey('record_version.id')) | ||||
|     creation_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     update_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     access_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     creation_date = db.Column(db.DateTime()) | ||||
|     update_date = db.Column(db.DateTime()) | ||||
|     access_date = db.Column(db.DateTime()) | ||||
|  | ||||
|     record_id = db.Column(db.Integer(), | ||||
|                           db.ForeignKey('record.id'), | ||||
| @@ -72,7 +87,12 @@ class RecordVersion(db.Model): | ||||
|                                                 order_by=id, | ||||
|                                                 cascade='all,delete')) | ||||
|  | ||||
|     def __init__(self): | ||||
|         """Initialize a record version.""" | ||||
|         self.creation_date = datetime.datetime.utcnow() | ||||
|  | ||||
|     def update(self, someData): | ||||
|         """Update a record version.""" | ||||
|         app.logger.debug(someData) | ||||
|         recordVersionData = someData['currentRecordVersion'] | ||||
|         self.reference = recordVersionData['reference'] | ||||
| @@ -83,26 +103,37 @@ class RecordVersion(db.Model): | ||||
|         self.update_date = datetime.datetime.utcnow() | ||||
|  | ||||
|         self.record.update(someData['record'], self) | ||||
| #------------------------------------------------------------------------------ | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| class Record(db.Model): | ||||
|  | ||||
|     """Model a record. | ||||
|  | ||||
|     A Record has multiple record versions. | ||||
|     """ | ||||
|  | ||||
|     id = db.Column(db.Integer(), primary_key=True) | ||||
|     user_id = db.Column(db.ForeignKey('user.id')) | ||||
|     reference = db.Column(db.String(), unique=True, index=True) | ||||
|     reference = db.Column(db.String(255), unique=True, index=True) | ||||
|     data = db.Column(db.Text()) | ||||
|     api_version = db.Column(db.String()) | ||||
|     api_version = db.Column(db.String(255)) | ||||
|     version = db.Column(db.Integer(), default=0) | ||||
|     creation_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     update_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     access_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     creation_date = db.Column(db.DateTime()) | ||||
|     update_date = db.Column(db.DateTime()) | ||||
|     access_date = db.Column(db.DateTime()) | ||||
|  | ||||
|     current_record_version = db.relationship( | ||||
|         'RecordVersion', | ||||
|         uselist=False, | ||||
|         cascade='save-update, merge, delete, delete-orphan') | ||||
|  | ||||
|     def __init__(self): | ||||
|         """Initialize a record.""" | ||||
|         self.creation_date = datetime.datetime.utcnow() | ||||
|  | ||||
|     def update(self, data, record_version): | ||||
|         """Update a record.""" | ||||
|         self.reference = data['reference'] | ||||
|         self.data = data['data'] | ||||
|         self.api_version = data['version'] | ||||
| @@ -113,23 +144,34 @@ class Record(db.Model): | ||||
|         else: | ||||
|             self.version = 1 | ||||
|  | ||||
| #------------------------------------------------------------------------------ | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| class OneTimePassword(db.Model): | ||||
|  | ||||
|     """Model a OneTimePassword. | ||||
|  | ||||
|     OneTimePasswords are used to log in to clipperz only once. | ||||
|     """ | ||||
|  | ||||
|     id = db.Column(db.Integer(), primary_key=True) | ||||
|     user_id = db.Column(db.ForeignKey('user.id')) | ||||
|     status = db.Column(db.String()) | ||||
|     reference = db.Column(db.String(), unique=True) | ||||
|     key_value = db.Column(db.String()) | ||||
|     key_checksum = db.Column(db.String()) | ||||
|     status = db.Column(db.String(255)) | ||||
|     reference = db.Column(db.String(255), unique=True) | ||||
|     key_value = db.Column(db.String(255)) | ||||
|     key_checksum = db.Column(db.String(255)) | ||||
|     data = db.Column(db.Text()) | ||||
|     version = db.Column(db.String()) | ||||
|     creation_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     version = db.Column(db.String(255)) | ||||
|     creation_date = db.Column(db.DateTime()) | ||||
|     request_date = db.Column(db.DateTime()) | ||||
|     usage_date = db.Column(db.DateTime()) | ||||
|  | ||||
|     def __init__(self): | ||||
|         """Initialize a OneTimePassword.""" | ||||
|         self.creation_date = datetime.datetime.utcnow() | ||||
|  | ||||
|     def update(self, someParameters, aStatus): | ||||
|         """Update a one time password.""" | ||||
|         self.reference = someParameters['reference'] | ||||
|         self.key_value = someParameters['key'] | ||||
|         self.key_checksum = someParameters['keyChecksum'] | ||||
| @@ -138,14 +180,22 @@ class OneTimePassword(db.Model): | ||||
|         self.status = aStatus | ||||
|  | ||||
|     def reset(self, aStatus): | ||||
|         """Reset a one time password.""" | ||||
|         self.data = "" | ||||
|         self.status = aStatus | ||||
|         return self | ||||
|  | ||||
| #------------------------------------------------------------------------------ | ||||
| # ------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| class Session(db.Model): | ||||
|  | ||||
|     """Model a session.""" | ||||
|  | ||||
|     id = db.Column(db.Integer(), primary_key=True) | ||||
|     sessionId = db.Column(db.String()) | ||||
|     access_date = db.Column(db.DateTime(), default=datetime.datetime.utcnow) | ||||
|     sessionId = db.Column(db.String(255)) | ||||
|     access_date = db.Column(db.DateTime()) | ||||
|  | ||||
|     def __init__(self): | ||||
|         """Initialize a session.""" | ||||
|         self.access_date = datetime.datetime.utcnow() | ||||
|   | ||||
| @@ -1,23 +1,30 @@ | ||||
| from flask import session, request, g, jsonify | ||||
| """Clipperz views.""" | ||||
| from flask import session, request, g | ||||
| from clipperz import app, db, lm | ||||
| from .models import User | ||||
| from .api import * | ||||
| from .api import *  # NOQA | ||||
| from .exceptions import InvalidUsage | ||||
| from flask.ext.login import login_required | ||||
|  | ||||
|  | ||||
| @lm.user_loader | ||||
| def load_user(id): | ||||
|     """Load a user. | ||||
|  | ||||
|     Converts a user id in to a User object. | ||||
|     """ | ||||
|     return User.query.get(int(id)) | ||||
|  | ||||
|  | ||||
| @app.before_request | ||||
| def before_request(): | ||||
|     """Store the current user.""" | ||||
|     g.user = current_user | ||||
|  | ||||
|  | ||||
| @app.teardown_appcontext | ||||
| def shutdown_session(exception=None): | ||||
|     """Remove the session from the database.""" | ||||
|     db.session.remove() | ||||
|  | ||||
|  | ||||
| @@ -26,6 +33,7 @@ def shutdown_session(exception=None): | ||||
| @app.route('/delta/dump/<string:frontend_version>') | ||||
| @login_required | ||||
| def dump(frontend_version): | ||||
|     """Return JSON for a user's data.""" | ||||
|     user = User().query.filter_by(username=session['C']).one() | ||||
|  | ||||
|     if (user != g.user): | ||||
| @@ -104,21 +112,25 @@ def dump(frontend_version): | ||||
|  | ||||
| @app.route('/beta/<path:path>') | ||||
| def beta(path): | ||||
|     """Fallback for serving beta version.""" | ||||
|     return send_from_directory('beta', path) | ||||
|  | ||||
|  | ||||
| @app.route('/gamma/<path:path>') | ||||
| def gamma(path): | ||||
|     """Fallback for serving gamma version.""" | ||||
|     return send_from_directory('gamma', path) | ||||
|  | ||||
|  | ||||
| @app.route('/delta/<path:path>') | ||||
| def delta(path): | ||||
|     """Fallback for serving delta version.""" | ||||
|     return send_from_directory('delta', path) | ||||
|  | ||||
|  | ||||
| @app.route('/pm', methods=['GET', 'OPTIONS', 'POST']) | ||||
| def pm(): | ||||
|     """Main request handler.""" | ||||
|     method = request.form['method'] | ||||
|     if method not in globals(): | ||||
|         raise InvalidUsage('This method is not yet implemented', | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| from migrate.versioning import api | ||||
| from config import SQLALCHEMY_DATABASE_URI | ||||
| from config import SQLALCHEMY_MIGRATE_REPO | ||||
| from app import db | ||||
| from clipperz import db | ||||
| import os.path | ||||
| db.create_all() | ||||
| if not os.path.exists(SQLALCHEMY_MIGRATE_REPO): | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #!/usr/bin/env python | ||||
| import imp | ||||
| from migrate.versioning import api | ||||
| from app import db | ||||
| from clipperz import db | ||||
| from config import SQLALCHEMY_DATABASE_URI | ||||
| from config import SQLALCHEMY_MIGRATE_REPO | ||||
| v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) | ||||
|   | ||||
							
								
								
									
										97
									
								
								backend/flask/src/db_repository/versions/001_migration.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								backend/flask/src/db_repository/versions/001_migration.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| from sqlalchemy import * | ||||
| from migrate import * | ||||
|  | ||||
|  | ||||
| from migrate.changeset import schema | ||||
| pre_meta = MetaData() | ||||
| post_meta = MetaData() | ||||
| one_time_password = Table('one_time_password', post_meta, | ||||
|     Column('id', Integer, primary_key=True, nullable=False), | ||||
|     Column('user_id', Integer), | ||||
|     Column('status', String), | ||||
|     Column('reference', String), | ||||
|     Column('key_value', String), | ||||
|     Column('key_checksum', String), | ||||
|     Column('data', Text), | ||||
|     Column('version', String), | ||||
|     Column('creation_date', DateTime), | ||||
|     Column('request_date', DateTime), | ||||
|     Column('usage_date', DateTime), | ||||
| ) | ||||
|  | ||||
| record = Table('record', post_meta, | ||||
|     Column('id', Integer, primary_key=True, nullable=False), | ||||
|     Column('user_id', Integer), | ||||
|     Column('reference', String), | ||||
|     Column('data', Text), | ||||
|     Column('api_version', String), | ||||
|     Column('version', Integer, default=ColumnDefault(0)), | ||||
|     Column('creation_date', DateTime), | ||||
|     Column('update_date', DateTime), | ||||
|     Column('access_date', DateTime), | ||||
| ) | ||||
|  | ||||
| record_version = Table('record_version', post_meta, | ||||
|     Column('id', Integer, primary_key=True, nullable=False), | ||||
|     Column('reference', String), | ||||
|     Column('header', Text), | ||||
|     Column('data', Text), | ||||
|     Column('api_version', String), | ||||
|     Column('version', Integer), | ||||
|     Column('previous_version_key', String), | ||||
|     Column('previous_version_id', Integer), | ||||
|     Column('creation_date', DateTime), | ||||
|     Column('update_date', DateTime), | ||||
|     Column('access_date', DateTime), | ||||
|     Column('record_id', Integer, nullable=False), | ||||
| ) | ||||
|  | ||||
| session = Table('session', post_meta, | ||||
|     Column('id', Integer, primary_key=True, nullable=False), | ||||
|     Column('sessionId', String), | ||||
|     Column('access_date', DateTime), | ||||
| ) | ||||
|  | ||||
| sessions = Table('sessions', post_meta, | ||||
|     Column('key', String(length=250), primary_key=True, nullable=False), | ||||
|     Column('value', LargeBinary, nullable=False), | ||||
| ) | ||||
|  | ||||
| user = Table('user', post_meta, | ||||
|     Column('id', Integer, primary_key=True, nullable=False), | ||||
|     Column('username', String), | ||||
|     Column('srp_s', String(length=128)), | ||||
|     Column('srp_v', String(length=128)), | ||||
|     Column('header', Text), | ||||
|     Column('statistics', Text), | ||||
|     Column('auth_version', String), | ||||
|     Column('version', String), | ||||
|     Column('lock', String), | ||||
|     Column('offline_saved', Boolean, default=ColumnDefault(False)), | ||||
|     Column('update_date', DateTime), | ||||
| ) | ||||
|  | ||||
|  | ||||
| def upgrade(migrate_engine): | ||||
|     # Upgrade operations go here. Don't create your own engine; bind | ||||
|     # migrate_engine to your metadata | ||||
|     pre_meta.bind = migrate_engine | ||||
|     post_meta.bind = migrate_engine | ||||
|     post_meta.tables['one_time_password'].create() | ||||
|     post_meta.tables['record'].create() | ||||
|     post_meta.tables['record_version'].create() | ||||
|     post_meta.tables['session'].create() | ||||
|     post_meta.tables['sessions'].create() | ||||
|     post_meta.tables['user'].create() | ||||
|  | ||||
|  | ||||
| def downgrade(migrate_engine): | ||||
|     # Operations to reverse the above upgrade go here. | ||||
|     pre_meta.bind = migrate_engine | ||||
|     post_meta.bind = migrate_engine | ||||
|     post_meta.tables['one_time_password'].drop() | ||||
|     post_meta.tables['record'].drop() | ||||
|     post_meta.tables['record_version'].drop() | ||||
|     post_meta.tables['session'].drop() | ||||
|     post_meta.tables['sessions'].drop() | ||||
|     post_meta.tables['user'].drop() | ||||
| @@ -45,6 +45,7 @@ setup( | ||||
|     install_requires=['Flask>=0.10.1', | ||||
|                       'Flask-SQLAlchemy>=1.0', | ||||
|                       'SQLAlchemy>=0.8.2', | ||||
|                       'SQLAlchemy-migrate', | ||||
|                       'Flask-Login', | ||||
|                       'Flask-KVSession', | ||||
|                       ], | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Giulio Cesare Solaroli
					Giulio Cesare Solaroli