Example #1
0
    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)
Example #2
0
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)
Example #3
0
    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)
Example #4
0
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
Example #5
0
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)
Example #6
0
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)
Example #7
0
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)
Example #8
0
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
Example #9
0
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)
Example #10
0
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
Example #11
0
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)
Example #12
0
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)
Example #13
0
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)
Example #14
0
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)
Example #15
0
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)
Example #16
0
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
Example #17
0
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)
Example #18
0
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
Example #19
0
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)