def put(self, id_): ''' Update data about the application identified by `id`. Omitted fields are not changed. **Example Request** .. sourcecode:: json { "agency": "Department Of Justice", "email": "*****@*****.**", "is_admin": true, "location": "Washington, DC", "name": "Lt. John Doe", "password": "******", "phone": "+12025551234", "credits": 10, "thumb": "iVBORw0KGgoAAAANS..." } **Example Response** .. sourcecode:: json { "agency": "Department Of Justice", "created": "2015-05-05T14:30:09.676268", "email": "*****@*****.**", "id": 2029, "is_admin": true, "location": "Washington, DC", "modified": "2015-05-05T14:30:09.676294", "name": "Lt. John Doe", "phone": "202-555-1234", "thumb": "iVBORw0KGgoAAAANS...", "credits": 10, "url": "https://quickpin/api/user/2029" } :<header Content-Type: application/json :<header X-Auth: the client's auth token :<json str agency: the name of the organization/agency that this person is affiliated with :<json str email: e-mail address :<json bool is_admin: true if this user should have admin privileges, false otherwise (this field can only be modified by an admin user) :<json str location: location name, e.g. city or state (default: null) :<json str name: user's full name, optionally including title or other salutation information (default: null) :<json str password: new password, must be >=8 characters, mixed case, and contain numbers :<json str phone: phone number (any reasonable format is okay) :<json str thumb: PNG thumbnail for this user, base64 encoded :<json int credits: the user credits :>header Content-Type: application/json :>json str agency: the name of the organization/agency that this person is affiliated with (default: null) :>json str created: record creation timestamp in ISO-8601 format :>json str email: e-mail address :>json bool is_admin: true if this user has admin privileges, false otherwise :>json str location: location name, e.g. city or state (default: null) :>json str modified: record modification timestamp in ISO-8601 format :>json str name: user's full name, optionally including title or other salutation information (default: null) :>json str phone: phone number :>json str phone_e164: phone number in E.164 format :>json str thumb: PNG thumbnail for this user, base64 encoded :>json int credits: the user credits :>json str url: url to view data about this user :status 200: ok :status 400: invalid request body :status 401: authentication required :status 403: not authorized to make the requested changes ''' request_json = request.get_json() user = g.db.query(User).filter(User.id == id_).first() if not g.user.is_admin and g.user.id != user.id: raise Forbidden('You may only modify your own profile.') if 'is_admin' in request_json: if not g.user.is_admin: raise Forbidden('Only admins can change user roles.') if g.user.id == int(id_): raise BadRequest('You may not modify your own role.') user.is_admin = request_json['is_admin'] if 'credits' in request_json: if not g.user.is_admin: raise Forbidden('Only admins can change user credits.') try: user.credits = int(request_json['credits']) except ValueError: raise ValueError('Credits must be an integer number.') self._update_string_field(request_json, 'agency', user, 'agency') self._update_string_field(request_json, 'location', user, 'location') self._update_string_field(request_json, 'name', user, 'name') if 'email' in request_json: email = request_json['email'].strip() if email == '': raise BadRequest('E-mail may not be blank.') if '@' not in email and email != 'admin': raise BadRequest('Invalid e-mail address.') user.email = email if 'phone' in request_json: if request_json['phone'].strip() == '': user.phone = None else: try: phone = phonenumbers.parse(request_json['phone'], 'US') if not phonenumbers.is_valid_number(phone): raise ValueError() except: raise BadRequest('Invalid phone number.') user.phone = phonenumbers.format_number( phone, phonenumbers.PhoneNumberFormat.E164) if 'thumb' in request_json: try: img_data = base64.b64decode(request_json['thumb']) img = Image.open(BytesIO(img_data)) if img.format != 'PNG': # or img.size != (32,32): raise ValueError() except: raise BadRequest('Thumbnail image must be 32x32 px,' ' PNG format, base64 encoded.') user.thumb = img_data if 'password' in request_json: password = request_json['password'].strip() if not valid_password(password): raise BadRequest('Password does not meet complexity ' 'requirements.') user.password_hash = hash_password( password, g.config.get('password_hash', 'algorithm'), int(g.config.get('password_hash', 'rounds'))) g.db.commit() g.db.expire(user) return jsonify(**self._user_dict(user))
def put(self, id_): ''' Update data about the application identified by `id`. Omitted fields are not changed. **Example Request** .. sourcecode:: json { "agency": "Department Of Justice", "email": "*****@*****.**", "is_admin": true, "location": "Washington, DC", "name": "Lt. John Doe", "password": "******", "phone": "+12025551234", "thumb": "iVBORw0KGgoAAAANS..." } **Example Response** .. sourcecode:: json { "agency": "Department Of Justice", "created": "2015-05-05T14:30:09.676268", "email": "*****@*****.**", "id": 2029, "is_admin": true, "location": "Washington, DC", "modified": "2015-05-05T14:30:09.676294", "name": "Lt. John Doe", "phone": "202-555-1234", "thumb": "iVBORw0KGgoAAAANS...", "url": "https://quickpin/api/user/2029" } :<header Content-Type: application/json :<header X-Auth: the client's auth token :>json str agency: the name of the organization/agency that this person is affiliated with :>json str email: e-mail address :>json bool is_admin: true if this user should have admin privileges, false otherwise (this field can only be modified by an admin user) :>json str location: location name, e.g. city or state (default: null) :>json str name: user's full name, optionally including title or other salutation information (default: null) :>json str password: new password, must be >=8 characters, mixed case, and contain numbers :>json str phone: phone number (any reasonable format is okay) :>json str thumb: PNG thumbnail for this user, base64 encoded :>header Content-Type: application/json :>json str agency: the name of the organization/agency that this person is affiliated with (default: null) :>json str created: record creation timestamp in ISO-8601 format :>json str email: e-mail address :>json bool is_admin: true if this user has admin privileges, false otherwise :>json str location: location name, e.g. city or state (default: null) :>json str modified: record modification timestamp in ISO-8601 format :>json str name: user's full name, optionally including title or other salutation information (default: null) :>json str phone: phone number :>json str phone_e164: phone number in E.164 format :>json str thumb: PNG thumbnail for this user, base64 encoded :>json str url: url to view data about this user :status 200: ok :status 400: invalid request body :status 401: authentication required :status 403: not authorized to make the requested changes ''' request_json = request.get_json() user = g.db.query(User).filter(User.id == id_).first() if not g.user.is_admin and g.user.id != user.id: raise Forbidden('You may only modify your own profile.') if 'is_admin' in request_json: if not g.user.is_admin: raise Forbidden('Only admins can change user roles.') if g.user.id == int(id_): raise BadRequest('You may not modify your own role.') user.is_admin = request_json['is_admin'] self._update_string_field(request_json, 'agency', user, 'agency') self._update_string_field(request_json, 'location', user, 'location') self._update_string_field(request_json, 'name', user, 'name') if 'email' in request_json: email = request_json['email'].strip() if email == '': raise BadRequest('E-mail may not be blank.') if '@' not in email and email != 'admin': raise BadRequest('Invalid e-mail address.') user.email = email if 'phone' in request_json: if request_json['phone'].strip() == '': user.phone = None else: try: phone = phonenumbers.parse(request_json['phone'], 'US') if not phonenumbers.is_valid_number(phone): raise ValueError() except: raise BadRequest('Invalid phone number.') user.phone = phonenumbers.format_number( phone, phonenumbers.PhoneNumberFormat.E164 ) if 'thumb' in request_json: try: img_data = base64.b64decode(request_json['thumb']) img = Image.open(BytesIO(img_data)) if img.format != 'PNG':# or img.size != (32,32): raise ValueError() except: raise BadRequest('Thumbnail image must be 32x32 px,' \ ' PNG format, base64 encoded.') user.thumb = img_data if 'password' in request_json: password = request_json['password'].strip() if not valid_password(password): raise BadRequest('Password does not meet complexity requirements.') user.password_hash = hash_password( password, g.config.get('password_hash', 'algorithm'), int(g.config.get('password_hash', 'rounds')) ) g.db.commit() g.db.expire(user) return jsonify(**self._user_dict(user))
def post(self): ''' Create a new application user. **Example Request** .. sourcecode:: json { "email": "*****@*****.**", "password": "******" } **Example Response** .. sourcecode:: json { "agency": null, "created": "2015-05-05T14:30:09.676268", "email": "*****@*****.**", "id": 2029, "is_admin": false, "location": null, "modified": "2015-05-05T14:30:09.676294", "name": null, "phone": null, "thumb": null, "credits": 0, "url": "https://quickpin/api/user/2029" } :<header Content-Type: application/json :<header X-Auth: the client's auth token :>json str email: e-mail address :>json str password: new password, must be >=8 characters, mixed case, :>header Content-Type: application/json :>json str agency: the name of the organization/agency that this person is affiliated with (default: null) :>json str created: record creation timestamp in ISO-8601 format :>json str email: e-mail address :>json bool is_admin: true if this user has admin privileges, false otherwise :>json str location: location name, e.g. city or state (default: null) :>json str modified: record modification timestamp in ISO-8601 format :>json str name: user's full name, optionally including title or other salutation information (default: null) :>json str phone: phone number :>json str phone_e164: phone number in E.164 format :>json str thumb: PNG thumbnail for this user, base64 encoded :>json int credits: the user credits :>json str url: url to view data about this user :status 200: ok :status 400: invalid request body :status 401: authentication required :status 403: not authorized to create accounts :status 409: e-mail address already in use ''' request_json = request.get_json() if 'email' not in request_json or '@' not in request_json['email']: raise BadRequest('Invalid or missing email.') user = User(request_json['email'].strip()) if 'password' not in request_json: raise BadRequest('Password is required') password = request_json['password'].strip() if not valid_password(password): raise BadRequest('Password does not meet complexity requirements.') user.password_hash = hash_password( password, g.config.get('password_hash', 'algorithm'), int(g.config.get('password_hash', 'rounds'))) try: g.db.add(user) g.db.commit() except IntegrityError: raise Conflict('This e-mail address is already in use.') g.db.expire(user) return jsonify(**self._user_dict(user))
def post(self): ''' Create a new application user. **Example Request** .. sourcecode:: json { "email": "*****@*****.**", "password": "******" } **Example Response** .. sourcecode:: json { "agency": null, "created": "2015-05-05T14:30:09.676268", "email": "*****@*****.**", "id": 2029, "is_admin": false, "location": null, "modified": "2015-05-05T14:30:09.676294", "name": null, "phone": null, "thumb": null, "url": "https://quickpin/api/user/2029" } :<header Content-Type: application/json :<header X-Auth: the client's auth token :>json str email: e-mail address :>json str password: new password, must be >=8 characters, mixed case, :>header Content-Type: application/json :>json str agency: the name of the organization/agency that this person is affiliated with (default: null) :>json str created: record creation timestamp in ISO-8601 format :>json str email: e-mail address :>json bool is_admin: true if this user has admin privileges, false otherwise :>json str location: location name, e.g. city or state (default: null) :>json str modified: record modification timestamp in ISO-8601 format :>json str name: user's full name, optionally including title or other salutation information (default: null) :>json str phone: phone number :>json str phone_e164: phone number in E.164 format :>json str thumb: PNG thumbnail for this user, base64 encoded :>json str url: url to view data about this user :status 200: ok :status 400: invalid request body :status 401: authentication required :status 403: not authorized to create accounts :status 409: e-mail address already in use ''' request_json = request.get_json() if 'email' not in request_json or '@' not in request_json['email']: raise BadRequest('Invalid or missing email.') user = User(request_json['email'].strip()) if 'password' not in request_json: raise BadRequest('Password is required') password = request_json['password'].strip() if not valid_password(password): raise BadRequest('Password does not meet complexity requirements.') user.password_hash = hash_password( password, g.config.get('password_hash', 'algorithm'), int(g.config.get('password_hash', 'rounds')) ) try: g.db.add(user) g.db.commit() except IntegrityError: raise Conflict('This e-mail address is already in use.') g.db.expire(user) return jsonify(**self._user_dict(user))