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()
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()
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()
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)
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
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')
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)
# -*- 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()
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()
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')
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)
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
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