def register_user(): data = {} try: data = json.loads(request.body.read()) schemas.register_user.validate(data) except jsonschema.ValidationError as err: raise errors.BadRequest(str(err)) except ValueError: raise errors.BadRequest() user = controller.register_user(data['username'], data['password'], data['full_name']) return user.to_json_dict()
def authenticate(): data = {} try: data = json.loads(request.body.read()) schemas.auth.validate(data) except jsonschema.ValidationError as err: raise errors.BadRequest(str(err)) except ValueError: raise errors.BadRequest() username = data['username'] password = data['password'] session_token = controller.authenticate(username, password) return {"session_token": session_token}
def create(event, context): """ taskListを作成 削除済みレコードは復活させない """ try: logger.info(event) # validation if not event['body']: raise errors.BadRequest('Bad request') body = json.loads(event['body']) validate_attributes(body) task_list = TaskListModel(str(uuid.uuid1()), name=body['name'], description=body['description']) # taskListの保存 try: task_list.save() except InvalidNameError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidDescriptionError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except PutError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({ 'statusCode': 200, 'taskList': dict(task_list) }) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def _decode_data(self, data, charset): """ Decode string data. @return unicode string """ try: return smart_unicode(data, charset) except UnicodeDecodeError: raise errors.BadRequest('wrong charset')
def _input_validation_failed(self, error, data, request): """ Always raises HttpStatusCodeError. Override to raise different status code when request data doesn't pass validation. todo: should format the content using the datamapper """ raise errors.BadRequest(str(error))
def _invalid_input_data(self, data, form): """ Always raises HttpStatusCodeError. Override to raise different status code when request data doesn't pass validation. todo: should format the content using the datamapper """ raise errors.BadRequest(repr(form.errors))
def tasks(event, context): """ taskListに紐づくtask一覧の取得 """ logger.info(event) logger.info(context) try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') task_list_id = event['pathParameters']['id'] # taskListが存在するか try: task_list = TaskListModel.get(task_list_id) except TaskListModel.DoesNotExist as e: logger.exception(e) raise errors.NotFound('The taskList does not exist') # tasksの取得 try: tasks = TaskModel.tasks_gsi_taskListId.query( task_list_id, TaskModel.deleteFlag == False ) except QueryError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps( { 'statusCode': 200, 'taskList': task_list_id, 'tasks': [dict(task) for task in tasks] } ) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def users(event, context): """ taskに所属するuser一覧を返す """ try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') task_id = event['pathParameters']['id'] # taskの取得 try: task = TaskModel.get(task_id) except TaskModel.DoesNotExist: raise errors.NotFound('The task does not exist') if not task.userIds: task.userIds = [] # usersの取得 try: users = task.get_users() except UserModel.DoesNotExist as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps( { 'statusCode': 200, 'taskId': task_id, 'users': [dict(user) for user in users] } ) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def done_undone(event, context): try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') task_id = event['pathParameters']['id'] # done or undone で ture or false if re.match('.*/done$', event['resource']): flag = True else: flag = False # taskを取得 try: task = TaskModel.get(task_id) except TaskModel.DoesNotExist: raise errors.NotFound('The task does not exist') # taskを更新 try: task.status_update(flag) except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({ 'statusCode': 200, 'task': dict(task) }) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def delete(event, context): """ delteFlagをfalseに変更 """ try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') task_id = event['pathParameters']['id'] # taskの取得 try: task = TaskModel.get(task_id) except TaskModel.DoesNotExist: raise errors.NotFound('The task does not exist') # taskの削除 try: task.logic_delete() except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({'statusCode': 200}) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def update(event, context): """ userの更新 updateでの更新対象はemail, name, phoneNumberのみ """ try: logger.info(event) if not (event['body'] and event['pathParameters']): raise errors.BadRequest('Bad request') data = json.loads(event['body']) # dataから不要なattributeを削除 data = { k: v for k, v in data.items() if k in ['name', 'email', 'phoneNumber'] } if not data: raise errors.BadRequest('Bad request') user_id = event['pathParameters']['id'] # user_idがauthorized_userのものか検証 if user_id != event['requestContext']['authorizer']['authorizedUserId']: raise errors.ForbiddenError('Access denied') # userが存在するか try: user = UserModel.get(user_id) except UserModel.DoesNotExist as e: raise errors.NotFound('This user does not exist') if 'name' in data: user.name = data['name'] if 'email' in data: user.email = data['email'] if 'phoneNumber' in data: user.phoneNumber = data['phoneNumber'] # userの更新 try: user.save() except InvalidNameError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidPhoneNumberError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidEmailError as e: logger.exception(e) if str(e.with_traceback( sys.exc_info()[2])) == 'This email has been registered': raise errors.UnprocessableEntity( str(e.with_traceback(sys.exc_info()[2]))) else: raise errors.BadRequest( str(e.with_traceback(sys.exc_info()[2]))) except PutError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({ 'statusCode': 200, 'user': dict(user) }) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.ForbiddenError as e: logger.exception(e) return build_response(e, 403) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.UnprocessableEntity as e: logger.exception(e) return build_response(e, 409) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def validate_attributes(body): if not ('name' in body and 'description' in body): raise errors.BadRequest( '"name" and "description" attributes are indispensable')
def delete(event, context): """ userを削除 また参加しているtaskのuserIdsから自身を取り除く """ try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') user_id = event['pathParameters']['id'] # user_idがauthorized_userのものか検証 if user_id != event['requestContext']['authorizer']['authorizedUserId']: raise errors.ForbiddenError('Access denied') # userの取得 try: user = UserModel.get(user_id) except UserModel.DoesNotExist: raise errors.NotFound('The user does not exist') # userが参加するtaskの取得 try: tasks = user.get_tasks() except ScanError as e: logger.exception(e) raise errors.InternalError('Internal server error') # userが参加するtaskのuserIdsからuser_idを削除 for task in tasks: try: task.update([TaskModel.userIds.delete([user_id])]) except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') # userを削除 try: user.logic_delete() except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({'statusCode': 200}) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def _parse_data(self, data, charset): try: return json.loads(data, charset, use_decimal=True) except ValueError: raise errors.BadRequest('unable to parse data')
def update(event, context): """ taskをupdate nameおよびdescription """ try: logger.info(event) if not (event['body'] and event['pathParameters']): raise errors.BadRequest('Bad request') data = json.loads(event['body']) # dataから不要なattributeを削除 data = {k: v for k, v in data.items() if k in ['name', 'description']} if not data: raise errors.BadRequest('Bad request') task_id = event['pathParameters']['id'] # taskの取得 try: task = TaskModel.get(task_id) except TaskModel.DoesNotExist: raise errors.NotFound('The task does not exist') if 'name' in data: task.name = data['name'] if 'description' in data: task.description = data['description'] if not task.userIds: task.userIds = [] try: task.save() except InvalidNameError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidDescriptionError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except PutError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({ 'statusCode': 200, 'task': dict(task) }) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def parse_date(date=None, date_format=None): try: return datetime.strptime(date, date_format) except Exception as e: raise errors.BadRequest('Not a valid date')
def add_remove(event, context): """ userをtaskに追加 """ try: logger.info(event) if not (event['pathParameters'] and event['body']): raise errors.BadRequest('Bad request') data = json.loads(event['body']) # dataから不要なattributeを削除 data = { k: v for k, v in data.items() if k == 'userIds' } if not data: raise errors.BadRequest('Bad request') else: if type(data['userIds']) != list: raise errors.BadRequest('"userIds" attribute must be array') task_id = event['pathParameters']['id'] user_ids = data['userIds'] # taskの取得 try: task = TaskModel.get(task_id) except TaskModel.DoesNotExist: raise errors.NotFound('The task does not exist') # add or remove if re.match('.*/add$', event['resource']): flag = True else: flag = False # taskのuserIdsを更新 try: task.user_ids_update(user_ids, flag) except InvalidUserError as e: logger.exception(e) raise errors.NotFound(str(e.with_traceback(sys.exc_info()[2]))) except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') task = TaskModel.get(task_id) return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps( { 'statusCode': 200, 'task': dict(task) } ) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500) except Exception as e: logger.exception(e) return { 'statusCode': 500, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps( { 'statusCode': 500, 'errorMessage': 'Internal server error' } ) }
def create(event, context): """ userの作成 emailは一意に保つ """ try: logger.info(event) if not event['body']: raise errors.BadRequest('Bad request') body = json.loads(event['body']) # bodyのvalidation validate_attributes(body) user = UserModel( id = str(uuid.uuid1()), name = body['name'], email = body['email'], phoneNumber = body['phoneNumber'], password = body['password'] ) # passwordのhash化 try: user.hash_password() except InvalidPasswordError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) # tokenの作成 user.create_token() # userの保存 try: user.save() except InvalidNameError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidPhoneNumberError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidEmailError as e: logger.exception(e) if str(e.with_traceback(sys.exc_info()[2])) == 'This email has been registered': raise errors.UnprocessableEntity(str(e.with_traceback(sys.exc_info()[2]))) else: raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except PutError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'access-token': user.userToken, 'expiry': user.get_expiry(), 'Content-Type': 'application/json' }, 'body': json.dumps( { 'statusCode': 200, 'user': dict(user) } ) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.UnprocessableEntity as e: logger.exception(e) return build_response(e, 409) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def create(event, context): """ taskを作成 name, descriptionは必須 userIdsは任意 """ try: logger.info(event) if not (event['body']): raise errors.BadRequest('Bad request') body = json.loads(event['body']) validate_attributes(body) if not 'userIds' in body: body['userIds'] = [] task = TaskModel(id=str(uuid.uuid1()), name=body['name'], description=body['description'], taskListId=body['taskListId'], userIds=body['userIds']) # taskの保存 try: task.save() except InvalidNameError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidDescriptionError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) except InvalidTaskListError as e: logger.exception(e) if str(e.with_traceback( sys.exc_info()[2])) == 'The taskList does not exist': raise errors.NotFound(str(e.with_traceback(sys.exc_info()[2]))) else: raise errors.BadRequest( str(e.with_traceback(sys.exc_info()[2]))) except InvalidUserError as e: logger.exception(e) if str(e.with_traceback(sys.exc_info()[2]) ) == 'The userIds contains a invalid userId does not exist': raise errors.NotFound(str(e.with_traceback(sys.exc_info()[2]))) else: raise errors.BadRequest( str(e.with_traceback(sys.exc_info()[2]))) except PutError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({ 'statusCode': 200, 'task': dict(task) }) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def tasks_taskLists(event, context): """ userが属するtasksおよびtaskListsを返す """ try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') user_id = event['pathParameters']['id'] # userを取得 try: user = UserModel.get(user_id) except UserModel.DoesNotExist: raise errors.NotFound('The user does not exist') # userの参加するtasksを取得 try: tasks = user.get_tasks() except ScanError as e: logger.exception(e) raise errors.InternalError('Internal server error') # taskListIdでグループ化 tasks_group = {} for task in tasks: if task.taskListId in tasks_group: tasks_group[task.taskListId].append(task) else: tasks_group[task.taskListId] = [task] # taskListsを取得 task_lists = [] for task_list_id in tasks_group.keys(): try: task_list = TaskListModel.get(task_list_id) except TaskListModel.DoesNotExist as e: logger.exception(e) continue except GetError as e: logger.exception(e) task_lists.append(task_list) # 結果の整形 task_lists = [dict(task_list) for task_list in task_lists] for task_list in task_lists: task_list['tasks'] = [dict(task) for task in tasks_group[task_list['id']]] return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps( { 'statusCode': 200, 'userId': user_id, 'taskLists': task_lists } ) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def delete(event, context): """ tasklistのdeleteFlagをfalseに変更 また関連するtaskのdeleteFlagもfalseに変更 """ try: logger.info(event) if not event['pathParameters']: raise errors.BadRequest('Bad request') task_list_id = event['pathParameters']['id'] # tasklistをget try: task_list = TaskListModel.get(task_list_id) except TaskListModel.DoesNotExist as e: logger.exception(e) raise errors.NotFound('The taskList does not exist') # tasklistを論理削除 try: task_list.logic_delete() except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') # 関連するtasksを論理削除 try: tasks = TaskModel.tasks_gsi_taskListId.query( task_list_id, TaskModel.deleteFlag == False) print(tasks) except QueryError as e: logger.exception(e) raise errors.InternalError('Internal server error') for task in tasks: try: task.logic_delete() except UpdateError as e: logger.exception(e) raise errors.InternalError('Internal server error') return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({'statusCode': 200}) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.NotFound as e: logger.exception(e) return build_response(e, 404) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def validate_attributes(body): if "email" not in body or "password" not in body: raise errors.BadRequest( '"email" and "password" attributes are indispensable')
def login(event, context): """ email, passwordを照合 okであればuserTokenを発行 """ try: logger.info(event) if not event['body']: raise errors.BadRequest('Bad request') body = json.loads(event['body']) # bodyのvalidation validate_attributes(body) # emailからuserを取得 user = [ _ for _ in UserModel.users_gsi_email.query( body['email'], UserModel.deleteFlag == False) ] if not user: raise errors.BadRequest('The email does not registered') else: user = user[0] # passwordの照合(一旦 == で照合) hashed_password = user.password user.password = body['password'] try: user.hash_password() except InvalidPasswordError as e: logger.exception(e) raise errors.BadRequest(str(e.with_traceback(sys.exc_info()[2]))) if hashed_password != user.password: raise errors.BadRequest('The email or password is wrong') # tokenの発行 user.create_token() user.update(actions=[ UserModel.lastLogin.set(datetime.now()), UserModel.userToken.set(user.userToken), UserModel.expiry.set(user.expiry) ]) return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'access-token': user.userToken, 'expiry': user.get_expiry(), 'Content-Type': 'application/json' }, 'body': json.dumps({ 'statusCode': 200, 'user': dict(user) }) } except errors.BadRequest as e: logger.exception(e) return build_response(e, 400) except errors.InternalError as e: logger.exception(e) return build_response(e, 500)
def validate_attributes(body): if "name" not in body or "email" not in body or "phoneNumber" not in body or "password" not in body: raise errors.BadRequest('"name", "email","phoneNumber" and "password" attributes are indispensable')