Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 0 additions & 103 deletions photobackup_bottle/init.py

This file was deleted.

135 changes: 61 additions & 74 deletions photobackup_bottle/photobackup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,89 +31,48 @@
"""

# stlib
import configparser

import os
import sys
from functools import wraps # better decorators
# pipped
import bcrypt
from bottle import abort, redirect, request, route, run
import bottle
from docopt import docopt
from logbook import info, warn, error, Logger, StreamHandler
from logbook import Logger, StreamHandler
# local
from . import __version__, init


def create_logger():
""" Creates the logger fpr this module. """
StreamHandler(sys.stdout).push_application()
return Logger('PhotoBackup')


def init_config(username=None):
""" Launch init.py script to create configuration file on user's disk. """
init.init(username)
sys.exit("\nCreated, now launch PhotoBackup server with 'photobackup run'")


def print_list():
""" Print the existing PhotoBackup configurations. """
sections = '\n'.join(get_config().sections())
sections = sections.replace('photobackup-', '- ')
sections = sections.replace('photobackup', '<unnamed one>')
print('Runnable PhotoBackup configurations are:')
print(sections)


def read_config(username=None):
""" Set configuration file data into local dictionnary. """
config_file = os.path.expanduser("~/.photobackup")
config = configparser.RawConfigParser()
config.optionxform = lambda option: option # to keep case of keys
try:
config.read_file(open(config_file))
except EnvironmentError:
log.error("can't read configuration file, running 'photobackup init'")
init_config(username)

suffix = '-' + username if username else ''
config_key = 'photobackup' + suffix

values = None
try:
values = config[config_key]
except KeyError:
values = None
return values
from . import __version__, serverconfig


# Server functions
def end(code, message):
""" Aborts the request and returns the given error. """
log.error(message)
abort(code, message)


def validate_password(request, isTest=False):
""" Validates the password given in the request
against the stored Bcrypted one. """
password = None
try:
password = request.forms.get('password').encode('utf-8')
except AttributeError:
end(403, "No password in request")

if 'PasswordBcrypt' in config:
def validate_password(func):
""" Validates the password given in the request against the stored Bcrypted one. """
@wraps(func)
def wrapper(*args, **kwargs):
password = None
try:
password = request.forms.get('password').encode('utf-8')
except AttributeError:
end(403, 'No password in request')
passcrypt = config['PasswordBcrypt'].encode('utf-8')
if bcrypt.hashpw(password, passcrypt) != passcrypt:
end(403, "wrong password!")
elif 'Password' in config and config['Password'] != password:
end(403, "wrong password!")
elif isTest:
end(401, "There's no password in server configuration!")
if not bcrypt.checkpw(password, passcrypt):
end(403, 'wrong password!')

return func(*args, **kwargs)

return wrapper


def save_file(upfile, filesize):
""" Saves the sent file locally. """
""" Saves the received file locally. """
path = os.path.join(config['MediaRoot'], os.path.basename(upfile.raw_filename))
if not os.path.exists(path):

Expand Down Expand Up @@ -148,10 +107,9 @@ def index():


@route('/', method='POST')
@validate_password
def save_image():
""" Saves the given image to the parameterized directory. """
validate_password(request)

""" Saves the given image to the directory set in the configured. """
upfile = request.files.get('upfile')
if not upfile:
end(401, "no file in the request!")
Expand All @@ -166,10 +124,9 @@ def save_image():


@route('/test', method='POST')
@validate_password
def test():
""" Tests the server capabilities to handle POST requests. """
validate_password(request, True)

""" Tests the server capabilities to handle a POST requests. """
if not os.path.exists(config['MediaRoot']):
end(500, "'MediaRoot' directory does not exist!")

Expand All @@ -184,22 +141,52 @@ def test():
log.info("Test succeeded \o/")


# CLI handlers - they don't use the log, but print()
def init_config(section=None):
""" Creates the configuration file.
param section: Optional argument of a custom section that'll be created in the config file.
"""
serverconfig.init(section)
print("Created, now launch PhotoBackup server with 'photobackup run'")
sys.exit(0)


def print_list():
""" Prints the existing PhotoBackup configuration sections. """
print(serverconfig.return_config_sections())
sys.exit(0)


# internal helpers
def _create_logger():
""" Creates the logger fpr this module. """
StreamHandler(sys.stdout).push_application()
return Logger('PhotoBackup')

# variables
arguments = docopt(__doc__, version='PhotoBackup ' + __version__)
log = create_logger()
config = read_config(arguments['<username>'])

# the server configuraiton dict; will be filled-in in main()
config = None

log = _create_logger()


def main():
""" Prepares and launches the bottle app. """
if (arguments['init']):
if arguments['init']:
init_config(arguments['<username>'])
elif (arguments['run']):
sys.exit(0)

global config
config = serverconfig.read_config(arguments['<username>'])

if arguments['run']:
app = bottle.default_app()
if 'HTTPPrefix' in config:
app.mount(config['HTTPPrefix'], app)
app.run(port=config['Port'], host=config['BindAddress'])
elif (arguments['list']):
elif arguments['list']:
print_list()


Expand Down
Loading