def decorated_function(*args, **kwargs): if not g.info["session"]["login"]: # Not even logged in? session["redirect_url"] = request.url flash("You must be logged in to do that!") return redirect(url_for("account.login")) if g.info["session"]["role"] != "admin": logger.warning("User tried to access an Admin page, but wasn't allowed!") return redirect(url_for("index")) return f(*args, **kwargs)
def edit_photo(key, data): """Update a photo's data.""" index = get_index() if not key in index["map"]: logger.warning("Tried to delete photo {} but it wasn't found?".format(key)) return album = index["map"][key] logger.info("Updating data for the photo {} from album {}".format(key, album)) index["albums"][album][key].update(data) write_index(index)
def decorated_function(*args, **kwargs): if not g.info["session"]["login"]: # Not even logged in? session["redirect_url"] = request.url flash("You must be logged in to do that!") return redirect(url_for("account.login")) if g.info["session"]["role"] != "admin": logger.warning( "User tried to access an Admin page, but wasn't allowed!") return redirect(url_for("index")) return f(*args, **kwargs)
def create(username, password, name=None, uid=None, role="user"): """Create a new user account. Returns the user ID number assigned to this user.""" # Name defaults to username. if name is None: name = username username = username.lower() # Provided with a user ID? if uid is not None: # See if it's available. if exists(uid=uid): logger.warning("Wanted to use UID {} for user {} but it wasn't available.".format(uid, username)) uid = None # Need to generate a UID? if uid is None: uid = get_next_uid() uid = int(uid) # Username musn't exist. if exists(username): # The front-end shouldn't let this happen. raise Exception("Can't create username {}: already exists!".format(username)) # Crypt their password. hashedpass = hash_password(password) logger.info("Create user {} with username {}".format(uid, username)) # Create the user file. JsonDB.commit("users/by-id/{}".format(uid), dict( uid=uid, username=username, name=name, picture="", role=role, password=hashedpass, created=time.time(), )) # And their username to ID map. JsonDB.commit("users/by-name/{}".format(username), dict( uid=uid, )) return uid
def delete_entry(post_id): """Remove a blog entry.""" # Fetch the blog information. index = get_index() post = get_entry(post_id) if post is None: logger.warning("Can't delete post {}, it doesn't exist!".format(post_id)) # Delete the post. JsonDB.delete("blog/entries/{}".format(post_id)) # Update the index cache. del index[str(post_id)] # Python JSON dict keys must be strings, never ints JsonDB.commit("blog/index", index)
def edit_photo(key, data): """Update a photo's data.""" index = get_index() if not key in index["map"]: logger.warning( "Tried to delete photo {} but it wasn't found?".format(key)) return album = index["map"][key] logger.info("Updating data for the photo {} from album {}".format( key, album)) index["albums"][album][key].update(data) write_index(index)
def delete_entry(post_id): """Remove a blog entry.""" # Fetch the blog information. index = get_index() post = get_entry(post_id) if post is None: logger.warning( "Can't delete post {}, it doesn't exist!".format(post_id)) # Delete the post. JsonDB.delete("blog/entries/{}".format(post_id)) # Update the index cache. del index[str( post_id)] # Python JSON dict keys must be strings, never ints JsonDB.commit("blog/index", index)
def get_cache(key): """Get a cached item.""" key = Config.db.redis_prefix + key value = None client = get_redis() if not client: return try: value = client.get(key) if value: value = json.loads(value) except: logger.warning("Redis exception: couldn't get_cache {}".format(key)) value = None return value
def order_albums(order): """Reorder the albums according to the new order list.""" index = get_index() # Sanity check, make sure all albums are included. if len(order) != len(index["album-order"]): logger.warning("Can't reorganize albums because the order lists don't match!") return None for album in index["album-order"]: if album not in order: logger.warning("Tried reorganizing albums, but {} was missing!".format(album)) return None index["album-order"] = order write_index(index)
def order_albums(order): """Reorder the albums according to the new order list.""" index = get_index() # Sanity check, make sure all albums are included. if len(order) != len(index["album-order"]): logger.warning( "Can't reorganize albums because the order lists don't match!") return None for album in index["album-order"]: if album not in order: logger.warning( "Tried reorganizing albums, but {} was missing!".format(album)) return None index["album-order"] = order write_index(index)
def delete_photo(key): """Delete a photo.""" index = get_index() if not key in index["map"]: logger.warning( "Tried to delete photo {} but it wasn't found?".format(key)) return album = index["map"][key] logger.info("Completely deleting the photo {} from album {}".format( key, album)) photo = index["albums"][album][key] # Delete all the images. for size in ["large", "thumb", "avatar"]: logger.info("Delete: {}".format(photo[size])) fname = os.path.join(Config.photo.root_private, photo[size]) if os.path.isfile(fname): os.unlink(fname) # Delete it from the sort list. index["photo-order"][album].remove(key) del index["map"][key] del index["albums"][album][key] # Was this the album cover? if index["covers"][album] == key: # Try to pick a new one. if len(index["photo-order"][album]) > 0: index["covers"][album] = index["photo-order"][album][0] else: index["covers"][album] = "" # If the album is empty now too, delete it as well. if len(index["albums"][album].keys()) == 0: del index["albums"][album] del index["photo-order"][album] del index["covers"][album] index["album-order"].remove(album) write_index(index)
def delete_photo(key): """Delete a photo.""" index = get_index() if not key in index["map"]: logger.warning("Tried to delete photo {} but it wasn't found?".format(key)) return album = index["map"][key] logger.info("Completely deleting the photo {} from album {}".format(key, album)) photo = index["albums"][album][key] # Delete all the images. for size in ["large", "thumb", "avatar"]: logger.info("Delete: {}".format(photo[size])) fname = os.path.join(Config.photo.root_private, photo[size]) if os.path.isfile(fname): os.unlink(fname) # Delete it from the sort list. index["photo-order"][album].remove(key) del index["map"][key] del index["albums"][album][key] # Was this the album cover? if index["covers"][album] == key: # Try to pick a new one. if len(index["photo-order"][album]) > 0: index["covers"][album] = index["photo-order"][album][0] else: index["covers"][album] = "" # If the album is empty now too, delete it as well. if len(index["albums"][album].keys()) == 0: del index["albums"][album] del index["photo-order"][album] del index["covers"][album] index["album-order"].remove(album) write_index(index)
def order_photos(album, order): """Reorder the photos according to the new order list.""" index = get_index() if not album in index["albums"]: logger.warning("Album not found: {}".format(album)) return None # Sanity check, make sure all albums are included. if len(order) != len(index["photo-order"][album]): logger.warning("Can't reorganize photos because the order lists don't match!") return None for key in index["photo-order"][album]: if key not in order: logger.warning("Tried reorganizing photos, but {} was missing!".format(key)) return None index["photo-order"][album] = order write_index(index)
def order_photos(album, order): """Reorder the photos according to the new order list.""" index = get_index() if not album in index["albums"]: logger.warning("Album not found: {}".format(album)) return None # Sanity check, make sure all albums are included. if len(order) != len(index["photo-order"][album]): logger.warning( "Can't reorganize photos because the order lists don't match!") return None for key in index["photo-order"][album]: if key not in order: logger.warning( "Tried reorganizing photos, but {} was missing!".format(key)) return None index["photo-order"][album] = order write_index(index)
def resize_photo(filename, size, crop=None): """Resize a photo from the target filename into the requested size. Optionally the photo can be cropped with custom parameters. """ # Find the file type. filetype = filename.rsplit(".", 1)[1] if filetype == "jpeg": filetype = "jpg" # Open the image. img = Image.open(filename) # Make up a unique filename. outfile = random_name(filetype) target = os.path.join(Config.photo.root_private, outfile) logger.debug("Output file for {} scale: {}".format(size, target)) # Get the image's dimensions. orig_width, orig_height = img.size new_width = PHOTO_SCALES[size] logger.debug("Original photo dimensions: {}x{}".format( orig_width, orig_height)) # For the large version, only scale it, don't crop it. if size == "large": # Do we NEED to scale it? if orig_width <= new_width: logger.debug("Don't need to scale down the large image!") img.save(target) return outfile # Scale it down. ratio = float(new_width) / float(orig_width) new_height = int(float(orig_height) * float(ratio)) logger.debug("New image dimensions: {}x{}".format( new_width, new_height)) img = img.resize((new_width, new_height), Image.ANTIALIAS) img.save(target) return outfile # For all other versions, crop them into a square. x, y, length = 0, 0, 0 # Use 0,0 and find the shortest dimension for the length. if orig_width > orig_height: length = orig_height else: length = orig_width # Did they give us crop coordinates? if crop is not None: x = crop["x"] y = crop["y"] if crop["length"] > 0: length = crop["length"] # Adjust the coords if they're impossible. if x < 0: logger.warning("X-Coord is less than 0; fixing!") x = 0 if y < 0: logger.warning("Y-Coord is less than 0; fixing!") y = 0 if x > orig_width: logger.warning("X-Coord is greater than image width; fixing!") x = orig_width - length if x < 0: x = 0 if y > orig_height: logger.warning("Y-Coord is greater than image height; fixing!") y = orig_height - length if y < 0: y = 0 # Make sure the crop box fits. if x + length > orig_width: diff = x + length - orig_width logger.warning( "Crop box is outside the right edge of the image by {}px; fixing!". format(diff)) length -= diff if y + length > orig_height: diff = y + length - orig_height logger.warning( "Crop box is outside the bottom edge of the image by {}px; fixing!" .format(diff)) length -= diff # Do we need to scale? if new_width == length: logger.debug("Image doesn't need to be cropped or scaled!") img.save(target) return outfile # Crop to the requested box. logger.debug("Cropping the photo") img = img.crop((x, y, x + length, y + length)) # Scale it to the proper dimensions. img = img.resize((new_width, new_width), Image.ANTIALIAS) img.save(target) return outfile
def process_photo(form, filename): """Formats an incoming photo.""" # Resize the photo to each of the various sizes and collect their names. sizes = dict() for size in PHOTO_SCALES.keys(): sizes[size] = resize_photo(filename, size) # Remove the temp file. os.unlink(filename) # What album are the photos going to? album = form.get("album", "") new_album = form.get("new-album", None) new_desc = form.get("new-description", None) if album == "" and new_album: album = new_album # Sanitize the name. album = sanitize_name(album) if album == "": logger.warning( "Album name didn't pass sanitization! Fall back to default album name." ) album = Config.photo.default_album # Make up a unique public key for this set of photos. key = random_hash() while photo_exists(key): key = random_hash() logger.debug("Photo set public key: {}".format(key)) # Get the album index to manipulate ordering. index = get_index() # Update the photo data. if not album in index["albums"]: index["albums"][album] = {} if not "settings" in index: index["settings"] = dict() if not album in index["settings"]: index["settings"][album] = { "format": "classic", "description": new_desc, } index["albums"][album][key] = dict(ip=remote_addr(), author=g.info["session"]["uid"], uploaded=int(time.time()), caption=form.get("caption", ""), description=form.get("description", ""), **sizes) # Maintain a photo map to album. index["map"][key] = album # Add this pic to the front of the album. if not album in index["photo-order"]: index["photo-order"][album] = [] index["photo-order"][album].insert(0, key) # If this is a new album, add it to the front of the album ordering. if not album in index["album-order"]: index["album-order"].insert(0, album) # Set the album cover for a new album. if not album in index["covers"] or len(index["covers"][album]) == 0: index["covers"][album] = key # Save changes to the index. write_index(index) return dict(success=True, photo=key)
def resize_photo(filename, size, crop=None): """Resize a photo from the target filename into the requested size. Optionally the photo can be cropped with custom parameters. """ # Find the file type. filetype = filename.rsplit(".", 1)[1] if filetype == "jpeg": filetype = "jpg" # Open the image. img = Image.open(filename) # Make up a unique filename. outfile = random_name(filetype) target = os.path.join(Config.photo.root_private, outfile) logger.debug("Output file for {} scale: {}".format(size, target)) # Get the image's dimensions. orig_width, orig_height = img.size new_width = PHOTO_SCALES[size] logger.debug("Original photo dimensions: {}x{}".format(orig_width, orig_height)) # For the large version, only scale it, don't crop it. if size == "large": # Do we NEED to scale it? if orig_width <= new_width: logger.debug("Don't need to scale down the large image!") img.save(target) return outfile # Scale it down. ratio = float(new_width) / float(orig_width) new_height = int(float(orig_height) * float(ratio)) logger.debug("New image dimensions: {}x{}".format(new_width, new_height)) img = img.resize((new_width, new_height), Image.ANTIALIAS) img.save(target) return outfile # For all other versions, crop them into a square. x, y, length = 0, 0, 0 # Use 0,0 and find the shortest dimension for the length. if orig_width > orig_height: length = orig_height else: length = orig_width # Did they give us crop coordinates? if crop is not None: x = crop["x"] y = crop["y"] if crop["length"] > 0: length = crop["length"] # Adjust the coords if they're impossible. if x < 0: logger.warning("X-Coord is less than 0; fixing!") x = 0 if y < 0: logger.warning("Y-Coord is less than 0; fixing!") y = 0 if x > orig_width: logger.warning("X-Coord is greater than image width; fixing!") x = orig_width - length if x < 0: x = 0 if y > orig_height: logger.warning("Y-Coord is greater than image height; fixing!") y = orig_height - length if y < 0: y = 0 # Make sure the crop box fits. if x + length > orig_width: diff = x + length - orig_width logger.warning("Crop box is outside the right edge of the image by {}px; fixing!".format(diff)) length -= diff if y + length > orig_height: diff = y + length - orig_height logger.warning("Crop box is outside the bottom edge of the image by {}px; fixing!".format(diff)) length -= diff # Do we need to scale? if new_width == length: logger.debug("Image doesn't need to be cropped or scaled!") img.save(target) return outfile # Crop to the requested box. logger.debug("Cropping the photo") img = img.crop((x, y, x+length, y+length)) # Scale it to the proper dimensions. img = img.resize((new_width, new_width), Image.ANTIALIAS) img.save(target) return outfile
def process_photo(form, filename): """Formats an incoming photo.""" # Resize the photo to each of the various sizes and collect their names. sizes = dict() for size in PHOTO_SCALES.keys(): sizes[size] = resize_photo(filename, size) # Remove the temp file. os.unlink(filename) # What album are the photos going to? album = form.get("album", "") new_album = form.get("new-album", None) new_desc = form.get("new-description", None) if album == "" and new_album: album = new_album # Sanitize the name. album = sanitize_name(album) if album == "": logger.warning("Album name didn't pass sanitization! Fall back to default album name.") album = Config.photo.default_album # Make up a unique public key for this set of photos. key = random_hash() while photo_exists(key): key = random_hash() logger.debug("Photo set public key: {}".format(key)) # Get the album index to manipulate ordering. index = get_index() # Update the photo data. if not album in index["albums"]: index["albums"][album] = {} if not "settings" in index: index["settings"] = dict() if not album in index["settings"]: index["settings"][album] = { "format": "classic", "description": new_desc, } index["albums"][album][key] = dict( ip=remote_addr(), author=g.info["session"]["uid"], uploaded=int(time.time()), caption=form.get("caption", ""), description=form.get("description", ""), **sizes ) # Maintain a photo map to album. index["map"][key] = album # Add this pic to the front of the album. if not album in index["photo-order"]: index["photo-order"][album] = [] index["photo-order"][album].insert(0, key) # If this is a new album, add it to the front of the album ordering. if not album in index["album-order"]: index["album-order"].insert(0, album) # Set the album cover for a new album. if not album in index["covers"] or len(index["covers"][album]) == 0: index["covers"][album] = key # Save changes to the index. write_index(index) return dict(success=True, photo=key)