Пример #1
0
def test_participant_picture_rotate_deletes_all_old_files(app, user):
    pic = ProfilePictureFactory()
    filename = pic.value
    pic.custom_field.meeting.photo_field = pic.custom_field
    upload_dir = local(app.config['UPLOADED_CUSTOM_DEST'])
    crop_dir = local(app.config['UPLOADED_CROP_DEST'] /
                     app.config['PATH_CUSTOM_KEY'])
    thumb_crop_dir = local(app.config['UPLOADED_THUMBNAIL_DEST'] /
                           app.config['PATH_CROP_KEY'] /
                           app.config['PATH_CUSTOM_KEY'])
    thumb_dir = local(app.config['UPLOADED_THUMBNAIL_DEST'] /
                      app.config['PATH_CUSTOM_KEY'])
    image = Image.new('RGB', (250, 250), 'red')
    image.save(str(upload_dir.join(filename)))
    crop_dir.ensure(filename)
    thumb_name, thumb_fm = os.path.splitext(filename)
    thumb_full_name = Thumbnail._get_name(thumb_name, thumb_fm, '200x200', 85)
    thumb_crop_dir.ensure(thumb_full_name)
    thumb_dir.ensure(thumb_full_name)

    with app.test_request_context():
        with app.client.session_transaction() as sess:
            sess['user_id'] = user.id
        url = url_for('meetings.custom_field_rotate',
                      meeting_id=pic.custom_field.meeting.id,
                      participant_id=pic.participant.id,
                      field_slug=pic.custom_field.slug)

        resp = app.client.post(url)
        assert resp.status_code == 200
        assert not upload_dir.join(filename).check()
        assert not crop_dir.join(filename).check()
        assert not thumb_crop_dir.join(thumb_full_name).check()
        assert not thumb_dir.join(thumb_full_name).check()
Пример #2
0
def test_participant_picture_change_deletes_all_old_files(app, user):
    pic = ProfilePictureFactory()
    filename = pic.value
    pic.custom_field.meeting.photo_field = pic.custom_field
    upload_dir = local(app.config['UPLOADED_CUSTOM_DEST'])
    crop_dir = local(app.config['UPLOADED_CROP_DEST'] /
                     app.config['PATH_CUSTOM_KEY'])
    thumb_crop_dir = local(app.config['UPLOADED_THUMBNAIL_DEST'] /
                           app.config['PATH_CROP_KEY'] /
                           app.config['PATH_CUSTOM_KEY'])
    thumb_dir = local(app.config['UPLOADED_THUMBNAIL_DEST'] /
                      app.config['PATH_CUSTOM_KEY'])
    upload_dir.ensure(filename)
    crop_dir.ensure(filename)
    thumb_name, thumb_fm = os.path.splitext(filename)
    thumb_full_name = Thumbnail._get_name(thumb_name, thumb_fm, '200x200', 85)
    thumb_crop_dir.ensure(thumb_full_name)
    thumb_dir.ensure(thumb_full_name)

    data = {'picture': (StringIO('Test'), 'test_edit.png')}
    with app.test_request_context():
        with app.client.session_transaction() as sess:
            sess['user_id'] = user.id
        resp = app.client.post(url_for('meetings.custom_field_upload',
                                       meeting_id=pic.custom_field.meeting.id,
                                       participant_id=pic.participant.id,
                                       field_slug=pic.custom_field.slug),
                               data=data)
        assert resp.status_code == 200
        assert not upload_dir.join(filename).check()
        assert not crop_dir.join(filename).check()
        assert not thumb_crop_dir.join(thumb_full_name).check()
        assert not thumb_dir.join(thumb_full_name).check()
Пример #3
0
def test_participant_picture_remove_crop(app, user):
    pic = ProfilePictureFactory()
    pic.custom_field.meeting.photo_field = pic.custom_field
    upload_dir = local(app.config['UPLOADED_CUSTOM_DEST'])
    crop_dir = local(app.config['UPLOADED_CROP_DEST'] /
                     app.config['PATH_CUSTOM_KEY'])
    thumb_crop_dir = local(app.config['UPLOADED_THUMBNAIL_DEST'] /
                           app.config['PATH_CROP_KEY'] /
                           app.config['PATH_CUSTOM_KEY'])
    image = Image.new('RGB', (300, 300), 'green')
    image.save(str(upload_dir.join(pic.value)))
    data = {
        'y1': 0,
        'y2': 150,
        'x1': 0,
        'x2': 150,
        'w': 150,
        'h': 150,
    }

    with app.test_request_context():
        with app.client.session_transaction() as sess:
            sess['user_id'] = user.id
        url = url_for('meetings.custom_field_crop',
                      meeting_id=pic.custom_field.meeting.id,
                      participant_id=pic.participant.id,
                      field_slug=pic.custom_field.slug)
        resp = app.client.post(url, data=data)
        assert resp.status_code == 302
        assert crop_dir.join(pic.value).check()

        url = url_for('meetings.participant_detail',
                      meeting_id=pic.custom_field.meeting.id,
                      participant_id=pic.participant.id)
        resp = app.client.get(url)
        thumb_name, thumb_fm = os.path.splitext(pic.value)
        thumb_full_name = Thumbnail._get_name(thumb_name, thumb_fm, '200x200',
                                              85)
        assert thumb_crop_dir.join(thumb_full_name).check()

        url = url_for('meetings.custom_field_upload',
                      meeting_id=pic.custom_field.meeting.id,
                      participant_id=pic.participant.id,
                      field_slug=pic.custom_field.slug)
        resp = app.client.delete(url)
        assert resp.status_code == 200
        assert not crop_dir.join(pic.value).check()
        assert not thumb_crop_dir.join(thumb_full_name).check()
Пример #4
0
def _configure_uploads(app):
    app.config['FILES_PATH'] = files_path = Path(app.instance_path) / 'files'
    app.config['PATH_BACKGROUNDS_KEY'] = path_backgrounds_key = 'backgrounds'
    app.config['PATH_CROP_KEY'] = path_crop_key = 'crops'
    app.config['PATH_CUSTOM_KEY'] = path_custom_key = 'custom_uploads'
    app.config['PATH_LOGOS_KEY'] = path_logos_key = 'logos'
    app.config['PATH_THUMB_KEY'] = path_thumb_key = 'thumbnails'
    app.config['PATH_PRINTOUTS_KEY'] = path_printouts_key = 'printouts'

    if 'UPLOADED_BACKGROUNDS_DEST' not in app.config:
        app.config['UPLOADED_BACKGROUNDS_DEST'] = (files_path /
                                                   path_backgrounds_key)
    if 'UPLOADED_CROP_DEST' not in app.config:
        app.config['UPLOADED_CROP_DEST'] = files_path / path_crop_key
    if 'UPLOADED_CUSTOM_DEST' not in app.config:
        app.config['UPLOADED_CUSTOM_DEST'] = files_path / path_custom_key
    if 'UPLOADED_LOGOS_DEST' not in app.config:
        app.config['UPLOADED_LOGOS_DEST'] = files_path / path_logos_key
    if 'UPLOADED_PRINTOUTS_DEST' not in app.config:
        app.config['UPLOADED_PRINTOUTS_DEST'] = files_path / path_printouts_key

    # ensure logos and printouts folders exist
    app.config['UPLOADED_LOGOS_DEST'].makedirs_p()
    app.config['UPLOADED_PRINTOUTS_DEST'].makedirs_p()

    if 'MEDIA_FOLDER' not in app.config:
        app.config['MEDIA_FOLDER'] = files_path
    if 'MEDIA_THUMBNAIL_FOLDER' not in app.config:
        app.config['MEDIA_THUMBNAIL_FOLDER'] = \
            app.config['UPLOADED_THUMBNAIL_DEST'] = files_path / path_thumb_key
    app.config['MEDIA_THUMBNAIL_URL'] = '/static/files/thumbnails/'

    app.add_url_rule('/static/files/<filename>', 'files', build_only=True)
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
        '/static/files': files_path,
    })

    # limit upload size to 1MB
    patch_request_class(app, app.config.get(
        'MAX_UPLOAD_SIZE', 1 * 1024 * 1024))
    configure_uploads(app, (backgrounds, custom_upload, logos_upload))
    Thumbnail(app)
    def get(self):
        participants = search_for_participant(request.args['search'])
        results = []
        for p in participants:
            if p.photo:
                image_url = Path(app.config['PATH_CUSTOM_KEY']) / p.photo
                image_url = Thumbnail(app).thumbnail(image_url, '50x50')
            else:
                image_url = url_for('static', filename='images/no-avatar.jpg')

            results.append({
                'image_url':
                image_url,
                'value':
                p.name,
                'url':
                url_for('.participant_detail', participant_id=p.id),
                'country':
                p.country.name if p.country else ''
            })
        return json.dumps(results)
Пример #6
0
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_class
from flask_thumbnails import Thumbnail

app = Flask(__name__)
app.config.from_object(Config)

db = SQLAlchemy(app)
migrate = Migrate(app, db)

login = LoginManager(app)
login.login_view = 'login'

photos = UploadSet('photos', IMAGES)
configure_uploads(app, photos)
patch_request_class(
    app)  # default is 16 MB, to set use ...(app, 32 * 1024 * 1024 )

thumb = Thumbnail(app)

# from app.errors import bp as errors_bp
# app.register_blueprint(errors_bp)

# from app.auth import bp as auth_bp
# app.register_blueprint(auth_bp, url_prefix='/auth')

from app import routes, models
Пример #7
0
    def setUp(self):
        self.app = Flask(__name__)
        self.thumbnail = Thumbnail(app=self.app)
        self.client = self.app.test_client()

        self.image = Image.new('RGB', (100, 100), 'black')
Пример #8
0
class CoreTestCase(unittest.TestCase):
    def setUp(self):
        self.app = Flask(__name__)
        self.thumbnail = Thumbnail(app=self.app)
        self.client = self.app.test_client()

        self.image = Image.new('RGB', (100, 100), 'black')

    def test_root_directory(self):
        self.app.config['THUMBNAIL_MEDIA_ROOT'] = 'media'
        self.assertEqual(
            self.thumbnail.root_directory,
            os.path.join(self.app.root_path, self.app.config['THUMBNAIL_MEDIA_ROOT'])
        )

        self.app.config['THUMBNAIL_MEDIA_ROOT'] = '/tmp/media'
        self.assertEqual(self.thumbnail.root_directory, self.app.config['THUMBNAIL_MEDIA_ROOT'])

    def test_thumbnail_directory(self):
        self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = 'media'
        self.assertEqual(
            self.thumbnail.thumbnail_directory,
            os.path.join(self.app.root_path, self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'])
        )

        self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = '/tmp/media'
        self.assertEqual(
            self.thumbnail.thumbnail_directory,
            self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT']
        )

    def test_root_url(self):
        self.app.config['THUMBNAIL_MEDIA_URL'] = '/media'
        self.assertEqual(self.thumbnail.root_url, self.app.config['THUMBNAIL_MEDIA_URL'])

    def test_thumbnail_url(self):
        self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_URL'] = '/media'
        self.assertEqual(self.thumbnail.thumbnail_url, self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_URL'])

    def test_storage_backend(self):
        self.assertEqual(self.thumbnail.storage_backend, self.app.config['THUMBNAIL_STORAGE_BACKEND'])

    def test_get_storage_backend(self):
        self.assertIsInstance(self.thumbnail.get_storage_backend(), FilesystemStorageBackend)

    def test_colormode(self):
        image = Image.new('L', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGB')

        image = Image.new('LA', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGBA')

        image = Image.new('RGBA', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGBA')

        image = Image.new('RGB', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGB')

    def test_get_format(self):
        image = Image.new('RGB', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGB')

        options = {'format': 'PNG'}
        self.assertEqual(self.thumbnail._get_format(image, **options), 'PNG')

        options = {}
        self.assertEqual(self.thumbnail._get_format(image, **options), self.app.config['THUMBNAIL_DEFAUL_FORMAT'])

    def test_get_raw_data(self):
        image = Image.new('L', (10, 10))

        options = {'format': 'JPEG'}
        data = self.thumbnail.get_raw_data(image, **options)

        new_image = Image.open(BytesIO(data))
        self.assertEqual(image.mode, new_image.mode)
        self.assertEqual(image.size, new_image.size)
        self.assertEqual(new_image.format, 'JPEG')

    def test_create_thumbnail(self):
        image = Image.new('L', (100, 100))

        new_image = self.thumbnail._create_thumbnail(image, size=(50, 50))

        self.assertEqual(new_image.size, (50, 50))

        new_image = self.thumbnail._create_thumbnail(image, size=(50, 50), crop=None)

        self.assertEqual(new_image.size, (50, 50))

    @mock.patch('flask_thumbnails.utils.generate_filename')
    def test_get_thumbnail(self, mock_thumb_name):
        with tempfile.NamedTemporaryFile(suffix='.jpg') as original:
            with tempfile.NamedTemporaryFile(suffix='.jpg') as thumb:
                mock_thumb_name.return_value = os.path.basename(thumb.name)
                self.app.config['THUMBNAIL_MEDIA_ROOT'] = os.path.dirname(original.name)
                self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = os.path.dirname(thumb.name)

                image = Image.new('RGB', (100, 100), 'black')
                image.save(original.name)

                thumb_url = self.thumbnail.get_thumbnail(os.path.basename(original.name), '200x200')

                self.assertTrue(thumb_url)
Пример #9
0
# -*- coding: utf-8 -*-
"""Extensions module. Each extension is initialized in the app factory located
in app.py
"""

from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_cache import Cache
from flask_mail import Mail
from flask_session import Session
from flask_debugtoolbar import DebugToolbarExtension
from flask_thumbnails import Thumbnail

bcrypt = Bcrypt()
login_manager = LoginManager()
db = SQLAlchemy()
migrate = Migrate()
cache = Cache()
mail = Mail()
sess = Session()
debug_toolbar = DebugToolbarExtension()
thumb = Thumbnail()
Пример #10
0
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_login import LoginManager
from flask_mail import Mail
from flask_migrate import Migrate
from flask_ckeditor import CKEditor
from flask_thumbnails import Thumbnail

# урезать количество запросов к странице
limiter = Limiter(key_func=get_remote_address)
# работа с логином и паролем
lm = LoginManager()
mail = Mail()
migrate = Migrate()
ck_editor = CKEditor()
thum = Thumbnail()
Пример #11
0
    def setUp(self):
        self.app = Flask(__name__)
        self.thumbnail = Thumbnail(app=self.app)
        self.client = self.app.test_client()

        self.image = Image.new('RGB', (100, 100), 'black')
Пример #12
0
class CoreTestCase(unittest.TestCase):
    def setUp(self):
        self.app = Flask(__name__)
        self.thumbnail = Thumbnail(app=self.app)
        self.client = self.app.test_client()

        self.image = Image.new('RGB', (100, 100), 'black')

    def test_root_directory(self):
        self.app.config['THUMBNAIL_MEDIA_ROOT'] = 'media'
        self.assertEqual(
            self.thumbnail.root_directory,
            os.path.join(self.app.root_path,
                         self.app.config['THUMBNAIL_MEDIA_ROOT']))

        self.app.config['THUMBNAIL_MEDIA_ROOT'] = '/tmp/media'
        self.assertEqual(self.thumbnail.root_directory,
                         self.app.config['THUMBNAIL_MEDIA_ROOT'])

    def test_thumbnail_directory(self):
        self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = 'media'
        self.assertEqual(
            self.thumbnail.thumbnail_directory,
            os.path.join(self.app.root_path,
                         self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT']))

        self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = '/tmp/media'
        self.assertEqual(self.thumbnail.thumbnail_directory,
                         self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'])

    def test_root_url(self):
        self.app.config['THUMBNAIL_MEDIA_URL'] = '/media'
        self.assertEqual(self.thumbnail.root_url,
                         self.app.config['THUMBNAIL_MEDIA_URL'])

    def test_thumbnail_url(self):
        self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_URL'] = '/media'
        self.assertEqual(self.thumbnail.thumbnail_url,
                         self.app.config['THUMBNAIL_MEDIA_THUMBNAIL_URL'])

    def test_storage_backend(self):
        self.assertEqual(self.thumbnail.storage_backend,
                         self.app.config['THUMBNAIL_STORAGE_BACKEND'])

    def test_get_storage_backend(self):
        self.assertIsInstance(self.thumbnail.get_storage_backend(),
                              FilesystemStorageBackend)

    def test_colormode(self):
        image = Image.new('L', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGB')

        image = Image.new('LA', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGBA')

        image = Image.new('RGBA', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGBA')

        image = Image.new('RGB', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGB')

    def test_get_format(self):
        image = Image.new('RGB', (10, 10))
        new_image = self.thumbnail.colormode(image)

        self.assertEqual(new_image.mode, 'RGB')

        options = {'format': 'PNG'}
        self.assertEqual(self.thumbnail._get_format(image, **options), 'PNG')

        options = {}
        self.assertEqual(self.thumbnail._get_format(image, **options),
                         self.app.config['THUMBNAIL_DEFAUL_FORMAT'])

    def test_get_raw_data(self):
        image = Image.new('L', (10, 10))

        options = {'format': 'JPEG'}
        data = self.thumbnail.get_raw_data(image, **options)

        new_image = Image.open(BytesIO(data))
        self.assertEqual(image.mode, new_image.mode)
        self.assertEqual(image.size, new_image.size)
        self.assertEqual(new_image.format, 'JPEG')

    def test_create_thumbnail(self):
        image = Image.new('L', (100, 100))

        new_image = self.thumbnail._create_thumbnail(image, size=(50, 50))

        self.assertEqual(new_image.size, (50, 50))

        new_image = self.thumbnail._create_thumbnail(image,
                                                     size=(50, 50),
                                                     crop=None)

        self.assertEqual(new_image.size, (50, 50))

    @mock.patch('flask_thumbnails.utils.generate_filename')
    def test_get_thumbnail(self, mock_thumb_name):
        with tempfile.NamedTemporaryFile(suffix='.jpg') as original:
            with tempfile.NamedTemporaryFile(suffix='.jpg') as thumb:
                mock_thumb_name.return_value = os.path.basename(thumb.name)
                self.app.config['THUMBNAIL_MEDIA_ROOT'] = os.path.dirname(
                    original.name)
                self.app.config[
                    'THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = os.path.dirname(
                        thumb.name)

                image = Image.new('RGB', (100, 100), 'black')
                image.save(original.name)

                thumb_url = self.thumbnail.get_thumbnail(
                    os.path.basename(original.name), '200x200')

                self.assertTrue(thumb_url)
Пример #13
0
def get_app():
    print("create app now")
    app = Flask(__name__)
    thumb = Thumbnail(app)
    app.secret_key = "Zcg,ddh}k^Q(uh/~qM*PT!cJ5?/Q$3QQ"
    app.config['THUMBNAIL_MEDIA_ROOT'] = os.getcwd(
    ) + '/' + cfg._destinationFolder
    app.config['THUMBNAIL_MEDIA_URL'] = cfg._destinationFolder
    app.config['THUMBNAIL_MEDIA_THUMBNAIL_ROOT'] = (os.getcwd() + '/' +
                                                    cfg._destinationFolder +
                                                    '/thumbnail/')
    app.config['THUMBNAIL_MEDIA_THUMBNAIL_URL'] = '/thumbnail/'

    print('path to pics', os.getcwd() + '/' + cfg._destinationFolder)

    @app.route('/')
    @app.route('/', methods=['GET', 'POST'])
    def index():
        list = db.getListOfFiles(cfg._destinationFolder, add_path=False)
        if request.method == 'GET':
            return load_pics(list, title='List of Pictures')

        else:
            payload = request.get_data().decode("utf-8")
            # only shows debug if in demo mode
            if cfg._test:
                flash(payload, 'debug')

            if request.form.get('left'):
                rotate(payload, list, 'left')
                title = 'ROTATED Pictures'

            elif request.form.get('right'):
                rotate(payload, list, 'right')
                title = 'ROTATED Pictures'

            elif request.form.get('180'):
                rotate(payload, list, '180')
                title = 'UPSIDE-DOWN Pictures'

            elif request.form.get('favorite'):
                faves = db.common(payload, list)
                flash('FAVORITED {} pics'.format(len(faves)), 'warning')
                db.append_multiple_lines('data/whitelist.txt', faves)
                title = 'FAVORITE Pictures'

            elif request.form.get('delete'):
                delete(payload, list)
                black = db.common(payload, list)
                # Check for common with whitelist
                fave_removed = db.remove_common_from_file(
                    'data/whitelist.txt', black)
                # only shows debug if in demo mode
                if cfg._test:
                    flash('Removed {} Fave pics'.format(len(fave_removed)),
                          'debug')

                flash('BLACKLISTED {} pics'.format(len(black)), 'info')
                db.append_multiple_lines('data/blacklist.txt', black)
                title = 'Remaining Pictures'

            elif request.form.get('copy_job'):
                db.copy_job()
                flash('Copy Job completed.', 'warning')
                title = 'New Set of Pictures'

            else:
                # This should never be triggered
                flash('No option selected, try again.', 'error')
                title = 'List of Pictures'

            list = db.getListOfFiles(cfg._destinationFolder, add_path=False)
            return load_pics(list, title=title)

    def load_pics(list, page='index.html', title=''):
        flash('Files loaded: ' + str(len(list)), 'message')
        return render_template(page,
                               title=title,
                               images=list,
                               len_list=len(list),
                               path=cfg._destinationFolder[7:],
                               extra_list=(read_file('data/whitelist.txt')))

    def rotate(payload, list, side):
        pic = 0
        for i in range(len(list)):
            if list[i] in payload:
                pic += 1
                # flash(list[i], 'warning')
                db.fileRotate(cfg._destinationFolder, list[i], side)
        flash('Rotating {} pics to {}'.format(pic, side), 'warning')

    def delete(payload, list):
        # flash(request.get_data(), 'message')
        pic = 0
        for i in range(len(list)):
            if list[i] in payload:
                pic += 1
                # flash(list[i], 'warning')
                db.filePrunning(cfg._destinationFolder, list[i])
        flash('Deleting {} pics'.format(pic), 'warning')

    def read_file(file):
        try:
            with open(file, 'r') as f:
                return f.read()
        except IOError as e:
            flash('Operation failed: {}'.format(e.strerror), 'error')

    def write_file(file, content):
        try:
            if os.path.exists(file + '_old'):
                os.remove(file + '_old')
                flash('removing backup file', 'info')
            os.rename(file, file + '_old')
            flash('Backup original configuration to {}_old'.format(file),
                  'info')
            with open(file, 'w') as f:
                f.write(content)
                flash('File saved on {}'.format(file), 'info')
        except IOError as e:
            flash(e, 'error')

    @app.route('/copy_job')
    def copy_job():
        db.copy_job()
        flash('Copy Job completed.', 'warning')
        title = 'New Set of Pictures'
        list = db.getListOfFiles(cfg._destinationFolder, add_path=False)
        return load_pics(list, title=title)

    @app.route('/config', methods=['GET', 'POST'])
    def config():
        if request.method == 'GET':
            mode = ('demo' if cfg._test else 'normal')
            return render_template('config.html',
                                   config_file=read_file('data/config.ini'),
                                   mode=mode,
                                   title='Configuration')
        else:
            write_file('data/config.ini', request.form.get('config'))
            flash('RESTART THE APPLICATION IF SETTINGS FAIL TO BE APPLIED',
                  'critical')
            reload()
            return redirect('/config')

    @app.route('/blacklist', methods=['GET', 'POST'])
    def blacklist():
        if request.method == 'GET':
            return render_template('blacklist.html',
                                   blacklist=read_file('data/blacklist.txt'),
                                   title='Blacklisted files')
        else:
            write_file('data/blacklist.txt', request.form.get('blacklist'))
            return redirect('/blacklist')

    @app.route('/whitelist', methods=['GET', 'POST'])
    def whitelist():
        if request.method == 'GET':
            return render_template('whitelist.html',
                                   whitelist=read_file('data/whitelist.txt'),
                                   title='whitelisted files')
        else:
            write_file('data/whitelist.txt', request.form.get('whitelist'))
            flash('New whitelist file saved', 'info')
            return redirect('/whitelist')

    @app.route('/reload')
    def reload():
        global to_reload
        to_reload = True
        cfg.load_config()
        flash('Reloading completed', 'info')
        return 'reloaded'

    @app.route('/reset')
    def reset():
        db.reset_config(True)
        reload()
        flash('Restore completed', 'info')
        flash('RESTART THE APPLICATION IF SETTINGS FAIL TO BE APPLIED',
              'critical')
        return redirect('/config')

    @app.route('/clear')
    def clear():
        db.reset_config(False)
        flash('non-essential content removed. Ready for packaging', 'info')
        return redirect('/config')

    @app.route('/slideshow')
    def slideshow():
        list = db.getListOfFiles(cfg._destinationFolder, add_path=False)
        return load_pics(list, page='slideshow.html', title='Slideshow')

    return app
Пример #14
0
def create_app(config_filename="config.py",
               app_name=None,
               register_blueprints=True):
    # App configuration
    app = Flask(app_name or __name__)

    env_cfg = os.getenv("CUSTOM_CONFIG", config_filename)
    app.config.from_pyfile(env_cfg)

    Bootstrap(app)

    app.jinja_env.add_extension("jinja2.ext.with_")
    app.jinja_env.add_extension("jinja2.ext.do")
    app.jinja_env.globals.update(is_admin=is_admin)
    app.jinja_env.filters["state_to_str"] = state_str

    if HAS_SENTRY:
        app.config["SENTRY_RELEASE"] = raven.fetch_git_sha(
            os.path.dirname(__file__))
        sentry = Sentry(app, dsn=app.config["SENTRY_DSN"])  # noqa: F841
        print(" * Sentry support activated")
        print(" * Sentry DSN: %s" % app.config["SENTRY_DSN"])

    if app.config["DEBUG"] is True:
        app.jinja_env.auto_reload = True
        app.logger.setLevel(logging.DEBUG)

    # Logging
    if not app.debug:
        formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s "
                                      "[in %(pathname)s:%(lineno)d]")
        file_handler = RotatingFileHandler("%s/errors_app.log" % os.getcwd(),
                                           "a", 1000000, 1)
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(formatter)
        app.logger.addHandler(file_handler)

    mail.init_app(app)
    migrate = Migrate(app, db)  # noqa: F841
    babel = Babel(app)  # noqa: F841
    toolbar = DebugToolbarExtension(app)  # noqa: F841

    db.init_app(app)

    # Setup Flask-Security
    security = Security(  # noqa: F841
        app,
        user_datastore,
        register_form=ExtendedRegisterForm,
        confirm_register_form=ExtendedRegisterForm)

    @FlaskSecuritySignals.password_reset.connect_via(app)
    @FlaskSecuritySignals.password_changed.connect_via(app)
    def log_password_reset(sender, user):
        if not user:
            return
        add_user_log(user.id, user.id, "user", "info",
                     "Your password has been changed !")

    @FlaskSecuritySignals.reset_password_instructions_sent.connect_via(app)
    def log_reset_password_instr(sender, user, token):
        if not user:
            return
        add_user_log(user.id, user.id, "user", "info",
                     "Password reset instructions sent.")

    git_version = ""
    gitpath = os.path.join(os.getcwd(), ".git")
    if os.path.isdir(gitpath):
        git_version = subprocess.check_output(
            ["git", "rev-parse", "--short", "HEAD"])
        if git_version:
            git_version = git_version.strip().decode("UTF-8")

    @babel.localeselector
    def get_locale():
        # if a user is logged in, use the locale from the user settings
        identity = getattr(g, "identity", None)
        if identity is not None and identity.id:
            return identity.user.locale
        # otherwise try to guess the language from the user accept
        # header the browser transmits.  We support fr/en in this
        # example.  The best match wins.
        return request.accept_languages.best_match(["fr", "en"])

    @babel.timezoneselector
    def get_timezone():
        identity = getattr(g, "identity", None)
        if identity is not None and identity.id:
            return identity.user.timezone

    @app.before_request
    def before_request():
        cfg = {
            "CAMGEAR_VERSION_VER": VERSION,
            "CAMGEAR_VERSION_GIT": git_version,
            "CAMGEAR_VERSION": "{0} ({1})".format(VERSION, git_version),
        }
        g.cfg = cfg

    @app.errorhandler(InvalidUsage)
    def handle_invalid_usage(error):
        response = jsonify(error.to_dict())
        response.status_code = error.status_code
        return response

    pictures = UploadSet("pictures", IMAGES)
    configure_uploads(app, pictures)
    patch_request_class(app, 10 * 1024 * 1024)  # 10m limit

    thumb = Thumbnail(app)  # noqa: F841

    if register_blueprints:
        from controllers.main import bp_main

        app.register_blueprint(bp_main)

        from controllers.users import bp_users

        app.register_blueprint(bp_users)

        from controllers.admin import bp_admin

        app.register_blueprint(bp_admin)

        from controllers.accessories import bp_accessories

        app.register_blueprint(bp_accessories)

        from controllers.cameras import bp_cameras

        app.register_blueprint(bp_cameras)

        from controllers.lenses import bp_lenses

        app.register_blueprint(bp_lenses)

        from controllers.autocompletion import bp_autocomplete

        app.register_blueprint(bp_autocomplete)

    @app.route("/uploads/<string:thing>/<path:stuff>", methods=["GET"])
    def get_uploads_stuff(thing, stuff):
        if app.debug:
            directory = safe_join(app.config["UPLOADS_DEFAULT_DEST"], thing)
            app.logger.debug(f"serving {stuff} from {directory}")
            return send_from_directory(directory, stuff, as_attachment=True)
        else:
            app.logger.debug(f"X-Accel-Redirect serving {stuff}")
            resp = Response("")
            resp.headers[
                "Content-Disposition"] = f"attachment; filename={stuff}"
            resp.headers[
                "X-Accel-Redirect"] = f"/_protected/media/tracks/{thing}/{stuff}"
            return resp

    @app.errorhandler(404)
    def page_not_found(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 404,
            "message": gettext("Page not found"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 404

    @app.errorhandler(403)
    def err_forbidden(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 403,
            "message": gettext("Access forbidden"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 403

    @app.errorhandler(410)
    def err_gone(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 410,
            "message": gettext("Gone"),
            "e": msg
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 410

    if not app.debug:

        @app.errorhandler(500)
        def err_failed(msg):
            pcfg = {
                "title": gettext("Whoops, something failed."),
                "error": 500,
                "message": gettext("Something is broken"),
                "e": msg,
            }
            return render_template("error_page.jinja2", pcfg=pcfg), 500

    @app.after_request
    def set_x_powered_by(response):
        response.headers["X-Powered-By"] = "camgear"
        return response

    # Other commands
    @app.cli.command()
    def routes():
        """Dump all routes of defined app"""
        table = texttable.Texttable()
        table.set_deco(texttable.Texttable().HEADER)
        table.set_cols_dtype(["t", "t", "t"])
        table.set_cols_align(["l", "l", "l"])
        table.set_cols_width([50, 30, 80])

        table.add_rows([["Prefix", "Verb", "URI Pattern"]])

        for rule in sorted(app.url_map.iter_rules(), key=lambda x: str(x)):
            methods = ",".join(rule.methods)
            table.add_row([rule.endpoint, methods, rule])

        print(table.draw())

    @app.cli.command()
    def config():
        """Dump config"""
        pp(app.config)

    @app.cli.command()
    def seed():
        """Seed database with default content"""
        make_db_seed(db)

    @app.cli.command()
    def createuser():
        """Create an user"""
        username = click.prompt("Username", type=str)
        email = click.prompt("Email", type=str)
        password = click.prompt("Password",
                                type=str,
                                hide_input=True,
                                confirmation_prompt=True)
        while True:
            role = click.prompt("Role [admin/user]", type=str)
            if role == "admin" or role == "user":
                break

        if click.confirm("Do you want to continue ?"):
            role = Role.query.filter(Role.name == role).first()
            if not role:
                raise click.UsageError("Roles not present in database")
            u = user_datastore.create_user(name=username,
                                           email=email,
                                           password=hash_password(password),
                                           roles=[role])

            db.session.commit()

            if FSConfirmable.requires_confirmation(u):
                FSConfirmable.send_confirmation_instructions(u)
                print("Look at your emails for validation instructions.")

    return app