def post(self): result = {"error": None, "data": {}} parser = reqparse.RequestParser() parser.add_argument("password", type=str, required=True) parser.add_argument("email", type=str, required=True) args = parser.parse_args() account = UserService.get_by_email(args["email"]) if account is None: return abort("account", "not-found") login = UserService.login(args["password"], account.password) if not login: return abort("account", "login-failed") UserService.update(account, login=datetime.now) token = Token.create("login", account.username) data = Token.validate(token) result["data"] = { "token": token, "expire": data["payload"]["expire"], "username": data["payload"]["meta"] } return result
def update_comment(): result = {"error": None, "data": {}} parser = RequestParser() parser.argument("counter", type=int, required=True) parser.argument("params", type=dict, default={}) args = parser.parse() params_parser = RequestParser() params_parser.argument("text", type=helpers.string, required=True, location=("params")) params_args = params_parser.parse(req=args) comment = CommentService.get_by_counter(args["counter"], request.account) if comment is None: return abort("comment", "not-found") if datetime.utcnow() - comment.created > timedelta(minutes=20): return abort("comment", "not-editable") comment.text = params_args["text"] comment.updated = datetime.utcnow() comment.save() result["data"] = comment.dict() return result
def post(self): result = {"error": None, "data": {}} parser = reqparse.RequestParser() parser.add_argument("service", type=str, required=True, choices=choices) parser.add_argument("slug", type=str, required=True) parser.add_argument("params", type=dict, default={}) args = parser.parse_args() descriptor = DescriptorService.get_by_slug(args["service"], args["slug"]) if descriptor is None: return abort(args["service"], "not-found") keys = ["name", "slug", "description"] update = utils.filter_dict(args["params"], keys) update_document(descriptor, update) try: descriptor.save() except Exception: return abort("general", "empty-required") result["data"] = descriptor.dict() return result
def post(self): result = {"error": None, "data": {}} parser = reqparse.RequestParser() parser.add_argument("position", type=int, required=True) parser.add_argument("team", type=str, required=True) parser.add_argument("slug", type=str, required=True) args = parser.parse_args() team = TeamService.get_by_slug(args["team"]) if team is None: return abort("team", "not-found") if request.account not in team.members: return abort("account", "not-team-member") anime = AnimeService.get_by_slug(args["slug"]) if anime is None: return abort("anime", "not-found") episode = AnimeService.find_position(anime, args["position"]) if episode is None: return abort("episodes", "not-found") FileService.destroy(episode.video) AnimeService.remove_episode(anime, episode) result["data"] = anime.dict(True) return result
def load(self, size, index, total, offset): if size != self.chunk_size: self.clean(self.publisher) return abort("file", "invalid-size") if index >= total or index < 0: self.clean(self.publisher) return abort("file", "invalid-index") if not self.publisher: if self.chunk_size > max_size: return abort("file", "too-big") if os.path.isfile(self.blob_file): if os.path.getsize(self.blob_file) > max_size: return abort("file", "too-big") if not os.path.isdir(self.tmp_dir): os.makedirs(self.tmp_dir) tmp_ls = os.listdir(self.tmp_dir) if self.uuid not in tmp_ls: if not self.publisher: self.clean() os.makedirs(self.tmp_dir) os.mkdir(self.uuid_dir) with open(self.blob_file, "ab") as blob: blob.seek(offset) blob.write(self.file.stream.read())
def join(args): result = {"error": None, "data": {}} if UserService.get_by_username(args["username"]): return abort("account", "username-exist") if UserService.get_by_email(args["email"]): return abort("account", "email-exist") account = UserService.create( args["username"], auth.hashpwd(args["password"]), args["email"] ) email = mail.Email() activation_token = Token.create("activation", account.username) email.account_confirmation(account, activation_token) result["data"] = { "login": int(datetime.timestamp(account.login)), "username": account.username } # Display activation code only in debug mode if config.debug: result["data"]["code"] = activation_token # ToDo: Add permissions here return result
def post(self): result = {"error": None, "data": {}} parser = reqparse.RequestParser() parser.add_argument("token", type=str, required=True) args = parser.parse_args() data = Token.validate(args["token"]) if not data["valid"]: return abort("general", "token-invalid-type") account = UserService.get_by_username(data["payload"]["meta"]) if account is None: return abort("account", "not-found") if data["payload"]["action"] != "activation": return abort("general", "token-invalid-type") activated = PermissionService.check(account, "global", "activated") if activated: return abort("account", "activated") PermissionService.add(account, "global", "activated") result["data"] = {"username": account.username, "activated": True} return result
def activate(args): result = {"error": None, "data": {}} if not Token.validate(args["token"]): return abort("general", "token-invalid") payload = Token.payload(args["token"]) if not (account := UserService.get_by_username(payload["meta"])): return abort("account", "not-found")
def password(data): if type(data) is not str: response = abort("general", "not-found") flask_abort(response) if len(data) < 8 or len(data) > 32: response = abort("general", "password-length") flask_abort(response) return data
def upload_image(self): if not self.is_image(): return abort("file", "bad-mime-type") if self.size() > image_max_size: return abort("file", "too-big") storage_file_name = self.file.name + "." + "jpg" os.makedirs(self.tmp_dir) self.upload.save(self.tmp_dir + self.file.name + "." + self.file_type) pil = Image.open(self.tmp_dir + self.file.name + "." + self.file_type) width, height = pil.size if self.upload_type == "avatar": avatar_size = 250 if width != height: self.clean() return abort("image", "not-square") if width < avatar_size: self.clean() return abort("image", "small-image") pil = pil.resize((avatar_size, avatar_size), Image.LANCZOS) if self.upload_type == "poster": max_width = 500 if width > max_width: new_width = max_width new_height = int(new_width * height / width) pil = pil.resize((new_width, new_height), Image.LANCZOS) tmp_path = self.tmp_dir + storage_file_name pil.save(tmp_path, optimize=True, quality=95) storage_path = self.storage_dir + storage_file_name self.fs.put(tmp_path, storage_path) self.fs.chmod(storage_path, 'public-read') self.clean() self.file.path = f"/{self.branch}/{self.upload_type}/{self.folder}/{storage_file_name}" self.file.uploaded = True self.file.save() return self.file
def genre(slug): genre = static.key("genres", slug) if not genre: response = abort("genre", "not-found") flask_abort(response) return genre
def parse(self, req=None, strict=False, http_error_code=400): if req is None: req = request namespace = self.namespace_class() req.unparsed_arguments = dict( self.argument_class("").source(req)) if strict else {} errors = {} for arg in self.args: value, found = arg.parse(req, self.bundle_errors) if isinstance(value, ValueError): errors.update(found) found = None if found or arg.store_missing: namespace[arg.dest or arg.name] = value if type(value) is Response: flask_abort(value) if errors: response = abort("general", "missing-field") flask_abort(response) if strict and req.unparsed_arguments: raise exceptions.BadRequest( "Unknown arguments: %s" % ", ".join(req.unparsed_arguments.keys())) return namespace
def status(slug): status = static.key("statuses", slug) if not status: response = abort("status", "not-found") flask_abort(response) return status
def uuid(data): expression = r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" if not bool(re.search(expression, data)): response = abort("general", "bad-regex") flask_abort(response) return data
def email(data): expression = r"[^@]+@[^@]+\.[^@]+" if not bool(re.search(expression, data)): response = abort("general", "bad-regex") flask_abort(response) return data
def descriptor_service(slug): descriptor = static.key("descriptors", slug) if not descriptor: response = abort("descriptors", "not-found") flask_abort(response) return descriptor
def team(slug): team = TeamService.get_by_slug(slug) if not team: response = abort("team", "not-found") flask_abort(response) return team
def account(username): account = UserService.get_by_username(username) if not account: response = abort("account", "not-found") flask_abort(response) return account
def new_team(): result = {"error": None, "data": {}} parser = RequestParser() parser.argument("members", type=list, default=[], location="json") parser.argument("admins", type=list, default=[], location="json") parser.argument("description", type=str, required=True) parser.argument("name", type=str, required=True) parser.argument("slug", type=str, required=True) args = parser.parse() team = TeamService.get_by_slug(args["slug"]) if team: return abort("team", "slug-exists") team = TeamService.create(args["name"], args["slug"], args["description"]) for username in args["members"]: account = helpers.account(username) TeamService.add_member(team, account) if account.username in args["admins"]: PermissionService.add(account, "global", "publishing") result["data"] = team.dict(True) return result
def category(slug): category = static.key("categories", slug) if not category: response = abort("category", "not-found") flask_abort(response) return category
def franchise(slug): franchise = DescriptorService.get_by_slug("franchise", slug) if not franchise: response = abort("franchise", "not-found") flask_abort(response) return franchise
def content(slug): content = static.key("content", slug) if not content: response = abort("content", "not-found") flask_abort(response) return content
def decorator(*args, **kwargs): account = UserService.auth(request.headers.get("Authentication")) if account is None: return abort("account", "login-failed") request.account = account return view_function(*args, **kwargs)
def put(self): result = {"error": None, "data": []} choices = ("poster", "banner") parser = reqparse.RequestParser() parser.add_argument("file", type=FileStorage, location="files") parser.add_argument("type", type=str, choices=choices) parser.add_argument("slug", type=str, required=True) args = parser.parse_args() anime = AnimeService.get_by_slug(args["slug"]) if anime is None: return abort("anime", "not-found") if args["file"] is not None: helper = UploadHelper(request.account, args["file"], args["type"]) data = helper.upload_image() if type(data) is Response: return data if anime[args["type"]] is not None: FileService.destroy(anime[args["type"]]) anime[args["type"]] = data anime.save() result["data"] = anime.dict() return result
def state(slug): state = static.key("states", slug) if not state: response = abort("state", "not-found") flask_abort(response) return state
def post(self): result = {"error": None, "data": {}} parser = reqparse.RequestParser() parser.add_argument("descriptors", type=list, default=[], location="json") args = parser.parse_args() result["data"]["search"] = {} data = {} for service in args["descriptors"]: if service not in choices: return abort("general", "service-not-found") data[service] = [] descriptors = DescriptorService.list(service) for descriptor in descriptors: data[service].append(descriptor.dict()) result["data"]["search"]["descriptors"] = data result["data"]["search"]["years"] = AnimeService.years() return result
def post(self): result = {"error": None, "data": {}} parser = reqparse.RequestParser() parser.add_argument("action", type=str, required=True, choices=("add", "remove")) parser.add_argument("username", type=str, required=True) parser.add_argument("scope", type=str, required=True) parser.add_argument("name", type=str, required=True) args = parser.parse_args() account = UserService.get_by_username(args["username"]) if account is None: return abort("account", "not-found") if args["action"] == "add": PermissionService.add(account, args["scope"], args["name"]) elif args["action"] == "remove": PermissionService.remove(account, args["scope"], args["name"]) result["data"] = account.list_permissions() return result
def upload_video(self): if not self.is_video(): response = abort("file", "bad-mime-type") flask_abort(response) if not self.is_h264(): response = abort("file", "bad-codec") flask_abort(response) storage_file_name = self.file.name + ".mp4" storage_path = self.storage_dir + storage_file_name tmp_path = self.path self.finish(tmp_path, storage_path, storage_file_name) return self.file
def image_link(data): # Based on # https://stackoverflow.com/a/51493215/9217774 expression = r"^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+(?:png|jpg|jpeg)+$" if not bool(re.search(expression, data)): response = abort("general", "not-file-link") flask_abort(response) return data
def get(self, slug): result = {"error": None, "data": {}} team = TeamService.get_by_slug(slug) if team is None: return abort("team", "not-found") result["data"] = team.dict(True) return result