def wrapper(*args, **kwargs): user = User.query.get(get_jwt_identity()) if user is not None: app.logger.info("User requesting access: {}".format(user.id)) else: app.logger.info("None-existing user tried to request for access") return mk_response( "The user with such access token does " + "not exist", 401) if user.admin: return func(*args, **kwargs) return mk_response("Admin permissions required", 401)
def post(self): """ Create a new user account endpoint To create, access token and admin permissions are required Args: uid (str): user id admin (bool): admin status of user Returns: obj: details of the new user with a password provided """ args = usr_parser.parse_args() if isinstance(args, current_app.response_class): return args # convert admin parameter into a boolean admin = False if 'admin' not in args else args['admin'] # check if the id of user is provided if args['uid'] is not None: user = User.new_user(admin, args['uid']) else: user = User.new_user(admin) """ check if the user is created, if the user with the same id exists it won't be created """ if user is None: return mk_response("User id already exists", 422) """ create an object to represent the user with the password provided and return it as a response """ userToReturn = { 'uid': user.id, 'password': user.password, 'admin': user.admin } return userToReturn
def get(self, lang_iso): """ Accent list endpoint Args: lang_iso (str): language in iso format Returns: obj: a list of accents of the language in a two letter format """ accents = (db.session.query( Voice.accent).filter(Voice.language == lang_iso).distinct().all()) if not accents: return mk_response('Language could not be found', 404) ret_accents = [] for a in accents: ret_accents.append(a[0]) if len(ret_accents) == 0: return mk_response('NO CONTENT', 204) return {'language': lang_iso, 'accents': ret_accents}
def post(self, user_id): """ Reset password endpoint To reset, access token and admin permissions are required Takes in an id of a user that needs to have its password reset Returns the new changed password """ user = User.query.get(user_id) if user is None: return mk_response("User does not exist", 422) password = user.generate_new_pass() return {'password': password}
def parse_args(self): """ Parses request based on arguments provided through add_argument method. Returns: :dict: if the request is correctly processed returns a dict with arguments and their values :obj:'flask.wrappers.Response': if the parser failed to process returns a response object with an error message """ data = {} locations = { 'json': request.get_json(), 'form': request.form.to_dict(), 'args': request.args.to_dict(), 'values': request.values.to_dict(), 'text': request.get_data(), 'headers': dict( zip([i[0] for i in request.headers.to_wsgi_list()], [i[1] for i in request.headers.to_wsgi_list()])), 'cookies': request.cookies } for loc in locations: if len(self.reqschema[loc].fields) > 0: try: req = self.reqschema['json'].load(locations[loc]) if req.data is not None: data.update(req.data) error = {} for i in self.reqschema['json'].fields: f = self.reqschema['json'].fields[i] if f.required and (req.data is None or i not in req.data): error[i] = [f.error_messages['required']] if len(error) > 0: raise ValidationError(error) except ValidationError as err: for r in err.messages: if r in self.help: err.messages[r].append(self.help[r]) for i in err.messages: err.messages[i] = ' '.join(err.messages[i]) return mk_response(err.messages, 422) return data
def get(self, voice_id): """ Voice details endpoint Args: voice_id (str): voice id Returns: dict: details of a voice """ # get voice details voice = Voice.query.get(voice_id) if voice is None: return mk_response("Voice could not be found", 404) return voice.to_dict()
def get(self): """ Language list endpoint Returns: obj: a list of available languages in iso format """ langs = db.session.query( Voice.language.distinct().label("language")).all() """ convert language list into a returnable format """ ret_langs = [l[0] for l in langs] if len(ret_langs) == 0: return mk_response('NO CONTENT', 204) return {'languages': ret_langs}
def post(self, user_id): """ Toggle user admin status endpoint To toggle, access token and admin permissions are required Args: uid (str): user id Returns: obj: an error or success message """ user = User.query.get(user_id) if user is None: return mk_response("User does not exist", 422) """ check if user's the only admin if it's an admin """ admins = User.query.filter_by(admin=True).all() if user.admin and len(admins) == 1: return mk_response( "User is the only admin, there must " + "be at least one admin in the system", 422) user.toggle_admin() return {'uid': user.id, 'admin': user.admin}
def post(self): """ Expire token endpoint Args: access_token (str) : access token from header Returns: str: success or error message """ # get access token from header header_name = current_app.config['JWT_HEADER_NAME'] jwt_header = request.headers.get(header_name, None) if len(jwt_header.split()) == 1: access_token = jwt_header elif len(jwt_header.split()) == 2: access_token = jwt_header.split()[1] user_id = decode_jwt(access_token) if user_id is not None: EXPIRED.append(access_token) current_app.logger.info("Expire token for user " + user_id['sub']) return mk_response("The token has been manually expired.", 200) else: return mk_response("The token could not expire.", 400)
def delete(self, user_id): """ Delete user endpoint To delete, access token and admin permissions are required Args: uid (str): user id Returns: obj: an error or success message """ user = User.query.get(user_id) if user is None: return mk_response("User does not exist", 422) # check if the user is an admin and is the only one admins = User.query.filter_by(admin=True).all() if user.id == get_jwt_identity() and len(admins) == 1: return mk_response( "User is the only admin, there must " + "be at least one admin in the system", 422) user.delete() return mk_response("User '{}' has been deleted".format(user.id))
def post(self): """ Voices enpoint Args: language (str, optional) accent (str, optional) gender (str, optional) Returns: obj: a list of voiced based on the optional parameters, if no options are provided all voices are returned with their details """ # get available voices args = vcs_parser.parse_args() if isinstance(args, current_app.response_class): return args """ create a query based on the parameters """ query = db.session.query(Voice) if 'language' in args: query = query.filter(Voice.language == args['language']) if 'language' in args and 'accent' in args: query = query.filter(Voice.accent == args['accent']) if 'gender' in args: query = query.filter(Voice.gender == args['gender']) """ get voices based on the query """ voices = query.all() """ check if the query returned any voices """ if 'accent' in args and 'language' not in args: return mk_response("For accent to be queried, language has " + "to be provided as well.", 400) if not voices: return mk_response("No voices were found", 204) """ create a returnable list of voices and return it as response """ ret_voices = [v.to_dict() for v in voices] return {'voices': ret_voices}
def wrapper(*args, **kwargs): # get access token from header header_name = app.config['JWT_HEADER_NAME'] jwt_header = request.headers.get(header_name, None) if len(jwt_header.split()) == 1: token = jwt_header elif len(jwt_header.split()) == 2: token = jwt_header.split()[1] # remove manually expired tokens that have actually expired remove_expired() if token in EXPIRED: return mk_response("Access token has expired", 401) else: return func(*args, **kwargs)
def post(self): """ Authentication endpoint Args: uid (str) : user id password (str) : user password Returns: str: access token if login details are correct, otherwise returns an error message """ args = usr_parser.parse_args() if isinstance(args, current_app.response_class): return args user = User.query.get(args['uid']) if user and sha256.verify(args['password'], user.password): return {'access_token': create_jwt(identity=user.id)} return mk_response("Login details are incorrect", 401)
def post(self): """ Speech endpoint Args: voice_id (str): id of the voice audio_format (str, optional): wav|ogg|mp3 text (str): text to process Returns: streamed audio file of the processed speech """ args = spch_parser.parse_args() if isinstance(args, current_app.response_class): return args voice = Voice.query.filter_by(id=args['voice_id']).first() if voice is None: return mk_response("Voice could not be found", 400) # creating syntesised speech and saving into file tanglevoice = TangleVoice(voice_dir=os.path.abspath(voice.directory), loglvl=current_app.logger.level) audio_fn = os.path.abspath(uuid.uuid4().hex[:8] + '.wav') waveform = tanglevoice.speak(args['text']) _wav_to_file(waveform, audio_fn) # convert to requested type if 'audio_format' in args and args['audio_format'] != "wav": old_audio_fn = audio_fn audio_fn = _convert_to(args['audio_format'], audio_fn) os.remove(old_audio_fn) elif 'audio_format' not in args: args['audio_format'] = "wav" # get the audio as bytes, delete the file and return audio as bytes with open(audio_fn, 'rb') as audio_f: wavefile = b''.join(audio_f.readlines()) os.remove(audio_fn) response = current_app.make_response(wavefile) response.headers['Content-Type'] = 'audio/' + args['audio_format'] return response
def unauthorized_token(error_msg): return mk_response(error_msg, 401)
def invalid_token(error_msg): return mk_response("Access token is invalid", 401)
def expired_token(): return mk_response("Access token has expired", 401)