def sqlalchemy_session_setup(request, app, tmpdir, realdburl): from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Boolean, DateTime, Column, Integer, String, ForeignKey f, path = tempfile.mkstemp(prefix="flask-security-test-db", suffix=".db", dir=str(tmpdir)) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + path engine = create_engine(app.config["SQLALCHEMY_DATABASE_URI"], convert_unicode=True) db_session = scoped_session( sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() Base.query = db_session.query_property() class RolesUsers(Base): __tablename__ = "roles_users" id = Column(Integer(), primary_key=True) user_id = Column("user_id", Integer(), ForeignKey("user.id")) role_id = Column("role_id", Integer(), ForeignKey("role.id")) class Role(Base, RoleMixin): __tablename__ = "role" id = Column(Integer(), primary_key=True) name = Column(String(80), unique=True) description = Column(String(255)) class User(Base, UserMixin): __tablename__ = "user" id = Column(Integer, primary_key=True) email = Column(String(255), unique=True) username = Column(String(255)) password = Column(String(255)) security_number = Column(Integer, unique=True) last_login_at = Column(DateTime()) current_login_at = Column(DateTime()) tf_primary_method = Column(String(255), nullable=True) tf_totp_secret = Column(String(255), nullable=True) tf_phone_number = Column(String(255), nullable=True) last_login_ip = Column(String(100)) current_login_ip = Column(String(100)) login_count = Column(Integer) active = Column(Boolean()) confirmed_at = Column(DateTime()) roles = relationship("Role", secondary="roles_users", backref=backref("users", lazy="dynamic")) with app.app_context(): Base.metadata.create_all(bind=engine) def tear_down(): db_session.close() os.close(f) os.remove(path) request.addfinalizer(tear_down) return SQLAlchemySessionUserDatastore(db_session, User, Role)
minutes=WEB_SERVICE_CONFIG["session_timeout_in_minutes"]) web_service.config['SESSION_REFRESH_EACH_REQUEST'] = WEB_SERVICE_CONFIG[ "refresh_session_on_each_request"] # Flask-SQLAlchemy db = SQLAlchemy(web_service) import server.database.models # Do NOT remove this import - it pulls up all models for SQLAlchemy module. db.create_all() # Flask-Security from server.database.models.user.users import Users from server.database.models.user.roles import Roles from server.web.utils import ModifiedLoginForm user_datastore = SQLAlchemySessionUserDatastore(db.session, Users, Roles) security = Security(web_service, user_datastore, login_form=ModifiedLoginForm) # Then we import modules with routes import server.web.routes # Since we cannot properly create after_create hook for user model (it's bound to context-based Flask-Security module), # we validate if there are any users existing. If not - we create default one by creating before_first call hook. # TODO: Rework it to use static-file stored parameters (i.e. JSON data provider) if len(Users.query.all()) == 0: @web_service.before_first_request def create_default_user(): user_datastore.create_user(email="*****@*****.**", password=hash_password("password"), roles=["admin", "user"])
def create_app(): app = Flask(__name__) app.config["DEBUG"] = True # SECRET_KEY generated using: secrets.token_urlsafe() app.config["SECRET_KEY"] = "pf9Wkove4IKEAXvy-cQkeDPhv9Cb3Ag-wyJILbq_dFw" # PASSWORD_SALT secrets.SystemRandom().getrandbits(128) app.config[ "SECURITY_PASSWORD_SALT"] = "156043940537155509276282232127182067465" app.config["LOGIN_DISABLED"] = False app.config["WTF_CSRF_ENABLED"] = False app.config["SECURITY_USER_IDENTITY_ATTRIBUTES"] = [ { "email": { "mapper": uia_email_mapper, "case_insensitive": True } }, { "us_phone_number": { "mapper": uia_phone_mapper } }, ] # app.config["SECURITY_US_ENABLED_METHODS"] = ["password"] # app.config["SECURITY_US_ENABLED_METHODS"] = ["authenticator", "password"] # app.config["SECURITY_US_SIGNIN_REPLACES_LOGIN"] = True app.config["SECURITY_TOTP_SECRETS"] = { "1": "TjQ9Qa31VOrfEzuPy4VHQWPCTmRzCnFzMKLxXYiZu9B" } app.config["SECURITY_FRESHNESS"] = datetime.timedelta(minutes=0.5) app.config["SECURITY_FRESHNESS_GRACE_PERIOD"] = datetime.timedelta( minutes=2) # Turn on all features (except passwordless since that removes normal login) for opt in [ "changeable", "recoverable", "registerable", "trackable", "NOTpasswordless", "confirmable", "two_factor", "unified_signin", ]: app.config["SECURITY_" + opt.upper()] = True if os.environ.get("SETTINGS"): # Load settings from a file pointed to by SETTINGS app.config.from_envvar("SETTINGS") # Allow any SECURITY_ config to be set in environment. for ev in os.environ: if ev.startswith("SECURITY_"): app.config[ev] = _find_bool(os.environ.get(ev)) mail = FlashMail(app) app.mail = mail app.json_encoder = JSONEncoder # Setup Flask-Security user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role) security = Security(app, user_datastore) # This is NOT ideal since it basically changes entire APP (which is fine for # this test - but not fine for general use). babel = flask_babelex.Babel(app, default_domain=security.i18n_domain) @babel.localeselector def get_locale(): # For a given session - set lang based on first request. # Honor explicit url request first if "lang" not in session: locale = request.args.get("lang", None) if not locale: locale = request.accept_languages.best if not locale: locale = "en" if locale: session["lang"] = locale return session.get("lang", None).replace("-", "_") # Create a user to test with @app.before_first_request def create_user(): init_db() db_session.commit() test_acct = "*****@*****.**" if not user_datastore.find_user(email=test_acct): add_user(user_datastore, test_acct, "password", ["admin"]) print("Created User: {} with password {}".format( test_acct, "password")) @user_registered.connect_via(app) def on_user_registered(myapp, user, confirm_token, **extra): flash(f"To confirm {user.email} - go to /confirm/{confirm_token}") @reset_password_instructions_sent.connect_via(app) def on_reset(myapp, user, token, **extra): flash(f"Go to /reset/{token}") @tf_security_token_sent.connect_via(app) def on_token_sent(myapp, user, token, method, **extra): flash("User {} was sent two factor token {} via {}".format( user.calc_username(), token, method)) @us_security_token_sent.connect_via(app) def on_us_token_sent(myapp, user, token, method, **extra): flash("User {} was sent sign in code {} via {}".format( user.calc_username(), token, method)) # Views @app.route("/") @login_required def home(): return render_template_string( "{% include 'security/_messages.html' %}" "{{ _fsdomain('Welcome') }} {{email}} !", email=current_user.email, ) return app
def add_charging_station_assets(db: SQLAlchemy, setup_roles_users, setup_markets): """Add uni- and bi-directional charging station assets, set their capacity value and their initial SOC.""" db.session.add( AssetType( name="one-way_evse", is_consumer=True, is_producer=False, can_curtail=True, can_shift=True, daily_seasonality=True, weekly_seasonality=True, yearly_seasonality=True, ) ) db.session.add( AssetType( name="two-way_evse", is_consumer=True, is_producer=True, can_curtail=True, can_shift=True, daily_seasonality=True, weekly_seasonality=True, yearly_seasonality=True, ) ) from flexmeasures.data.models.user import User, Role user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) test_prosumer = user_datastore.find_user(email="*****@*****.**") epex_da = Market.query.filter(Market.name == "epex_da").one_or_none() charging_station = Asset( name="Test charging station", asset_type_name="one-way_evse", event_resolution=timedelta(minutes=15), capacity_in_mw=2, max_soc_in_mwh=5, min_soc_in_mwh=0, soc_in_mwh=2.5, soc_datetime=as_server_time(datetime(2015, 1, 1)), soc_udi_event_id=203, latitude=10, longitude=100, market_id=epex_da.id, unit="MW", ) charging_station.owner = test_prosumer db.session.add(charging_station) bidirectional_charging_station = Asset( name="Test charging station (bidirectional)", asset_type_name="two-way_evse", event_resolution=timedelta(minutes=15), capacity_in_mw=2, max_soc_in_mwh=5, min_soc_in_mwh=0, soc_in_mwh=2.5, soc_datetime=as_server_time(datetime(2015, 1, 1)), soc_udi_event_id=203, latitude=10, longitude=100, market_id=epex_da.id, unit="MW", ) bidirectional_charging_station.owner = test_prosumer db.session.add(bidirectional_charging_station)
#!/usr/bin/env python import os from datetime import datetime from flask_security import Security, SQLAlchemySessionUserDatastore from manager.setup import app from manager.setup_db import init_db, db from manager.user import User, Role # with app.app_context(): # Create any database tables that don't exist yet. init_db() user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) security = Security(app, user_datastore) # this sets some app.config # Create the Roles "admin" and "end-user" -- unless they already exist user_datastore.find_or_create_role(name='admin', description='Administrator') user_datastore.find_or_create_role(name='user', description='End user') admin_email = os.environ['ADMIN_EMAIL'] # create admin user if not user_datastore.get_user(admin_email): user_datastore.create_user( email=admin_email, username='******', password=os.environ['ADMIN_PASSWORD'], active=True, confirmed_at=datetime.now(), )
def create_app(test_config=None): # Create and configure the app app = Flask(__name__, instance_relative_config=True) app.config.from_mapping( DEBUG=False, # TODO: Replace in production 'secrets.token_hex()' SECRET_KEY="6d67cace9a6e4525e2b945191ad8f1d4702c3186ea914ca80db86adb258bd850", TOPIC_STORE_USER=database_username, TOPIC_STORE_PASSWORD=database_password, TOPIC_STORE_DBNAME=database_name, TOPIC_STORE_HOST=database_host, TOPIC_STORE_PORT=database_port, SECURITY_PASSWORD_SALT="fff78df7dffdb745be561d9d8075c69ce6a6b4a8c8bce17377601a66fed72542", SECURITY_REGISTERABLE=True, SECURITY_RECOVERABLE=True, SECURITY_CHANGEABLE=True, SECURITY_EMAIL_SENDER=email_sender, SECURITY_URL_PREFIX="/auth", SECURITY_POST_LOGIN_VIEW="/maps", MAIL_SERVER=email_server, MAIL_PORT=587, MAIL_USE_SSL=False, MAIL_USERNAME=email_username, MAIL_PASSWORD=email_password, MAX_CONTENT_LENGTH=4 * 1024 * 1024, # 4 megabytes (temporarily - will be 2) ) mail = Mail(app) csrf = SeaSurf(app) if test_config is None: # Load the instance config, if it exists, when not testing app.config.from_pyfile("config.py", silent=True) else: # Load the test config if passed in app.config.from_mapping(test_config) # Ensure the instance folder exists try: os.makedirs(app.instance_path) except OSError: pass @app.route("/") def home(): return render_template("index.html") @app.route("/health") def hello(): return "Healthy!" # HTTP error handlers def forbidden(e): return render_template("403.html"), 403 app.register_error_handler(403, forbidden) def page_not_found(e): return render_template("404.html"), 404 app.register_error_handler(404, page_not_found) def internal_server_error(e): return render_template("500.html"), 500 app.register_error_handler(500, internal_server_error) def request_entity_too_large(e): return render_template("413.html"), 413 app.register_error_handler(413, request_entity_too_large) # Setup Flask-Security user_datastore = SQLAlchemySessionUserDatastore( user_store.db_session, user_models.User, user_models.Role ) security = Security(app, user_datastore) @user_registered.connect_via(app) def user_registered_handler(app, user, confirm_token): default_role = user_datastore.find_role("user") user_datastore.add_role_to_user(user, default_role) user_store.db_session.commit() @app.before_first_request def create_user(): user_store.init_db() # Create roles user_datastore.find_or_create_role(name="admin", description="Administrator") user_datastore.find_or_create_role(name="user", description="End user") # Create users if not user_datastore.get_user("*****@*****.**"): user_datastore.create_user( email="*****@*****.**", password="******" ) if not user_datastore.get_user("*****@*****.**"): user_datastore.create_user( email="*****@*****.**", password="******" ) if not user_datastore.get_user("*****@*****.**"): user_datastore.create_user( email="*****@*****.**", password="******" ) user_store.db_session.commit() # Assign roles user_datastore.add_role_to_user("*****@*****.**", "user") user_datastore.add_role_to_user("*****@*****.**", "admin") user_datastore.add_role_to_user("*****@*****.**", "user") user_datastore.add_role_to_user("*****@*****.**", "admin") user_store.db_session.commit() @app.teardown_request def checkin_db(exc): user_store.db_session.remove() # Register custom filters filters.register_filters(app) # Register Blueprints from contextualise import api app.register_blueprint(api.bp) from contextualise import map app.register_blueprint(map.bp) from contextualise import topic app.register_blueprint(topic.bp) from contextualise import image app.register_blueprint(image.bp) from contextualise import file app.register_blueprint(file.bp) from contextualise import link app.register_blueprint(link.bp) from contextualise import video app.register_blueprint(video.bp) from contextualise import association app.register_blueprint(association.bp) from contextualise import note app.register_blueprint(note.bp) from contextualise import three_d app.register_blueprint(three_d.bp) from contextualise import attribute app.register_blueprint(attribute.bp) # Add topic store from contextualise import topic_store topic_store.init_app(app) return app
def sqlalchemy_session_datastore(request, app, tmpdir): from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker, relationship, \ backref from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Boolean, DateTime, Column, Integer, String, \ ForeignKey f, path = tempfile.mkstemp(prefix='flask-security-test-db', suffix='.db', dir=str(tmpdir)) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + path engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'], convert_unicode=True) db_session = scoped_session( sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() Base.query = db_session.query_property() class RolesUsers(Base): __tablename__ = 'roles_users' id = Column(Integer(), primary_key=True) user_id = Column('user_id', Integer(), ForeignKey('user.id')) role_id = Column('role_id', Integer(), ForeignKey('role.id')) class Role(Base, RoleMixin): __tablename__ = 'role' id = Column(Integer(), primary_key=True) name = Column(String(80), unique=True) description = Column(String(255)) class User(Base, UserMixin): __tablename__ = 'user' id = Column(Integer, primary_key=True) email = Column(String(255), unique=True) username = Column(String(255)) password = Column(String(255)) last_login_at = Column(DateTime()) current_login_at = Column(DateTime()) last_login_ip = Column(String(100)) current_login_ip = Column(String(100)) login_count = Column(Integer) active = Column(Boolean()) confirmed_at = Column(DateTime()) roles = relationship('Role', secondary='roles_users', backref=backref('users', lazy='dynamic')) with app.app_context(): Base.metadata.create_all(bind=engine) def tear_down(): db_session.close() os.close(f) os.remove(path) request.addfinalizer(tear_down) return SQLAlchemySessionUserDatastore(db_session, User, Role)
import warnings from phd import settings if settings.DB_ENGINE == "ndb": from phd.security.ndb import datastore, models user_datastore = datastore.NDBUserDatastore(models.User, models.Role) elif settings.DB_ENGINE == "ds": with warnings.catch_warnings(): warnings.simplefilter("ignore") from google.cloud import datastore as gcp_ds from phd.security.ds import datastore, models user_datastore = datastore.DSUserDatastore( gcp_ds.Client(), models.User, models.Role ) else: from flask_security import SQLAlchemySessionUserDatastore from phd.security.sql import datastore, models user_datastore = SQLAlchemySessionUserDatastore( datastore.db_session, models.User, models.Role ) datastore.init_db()
def setup_api_test_data(db): """ Set up data for API v1.1 tests. """ print("Setting up data for API v1.1 tests on %s" % db.engine) from flexmeasures.data.models.user import User, Role from flexmeasures.data.models.assets import Asset, AssetType from flexmeasures.data.models.weather import WeatherSensor, WeatherSensorType user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) # Create a user without proper registration as a data source user = user_datastore.create_user( username="******", email="*****@*****.**", password=hash_password("testtest"), ) role = user_datastore.find_role("Prosumer") user_datastore.add_role_to_user(user, role) # Create a test user without a USEF role create_user( username="******", email="*****@*****.**", password=hash_password("testtest"), ) # Create 3 test assets for the test_prosumer user test_prosumer = user_datastore.find_user(email="*****@*****.**") test_asset_type = AssetType(name="test-type") db.session.add(test_asset_type) asset_names = ["CS 1", "CS 2", "CS 3"] assets: List[Asset] = [] for asset_name in asset_names: asset = Asset( name=asset_name, asset_type_name="test-type", event_resolution=timedelta(minutes=15), capacity_in_mw=1, latitude=100, longitude=100, unit="MW", ) asset.owner = test_prosumer assets.append(asset) db.session.add(asset) # Add power forecasts to the assets cs_1 = Asset.query.filter(Asset.name == "CS 1").one_or_none() cs_2 = Asset.query.filter(Asset.name == "CS 2").one_or_none() cs_3 = Asset.query.filter(Asset.name == "CS 3").one_or_none() data_source = DataSource.query.filter( DataSource.user == test_prosumer).one_or_none() power_forecasts = [] for i in range(6): p_1 = Power( datetime=isodate.parse_datetime("2015-01-01T00:00:00Z") + timedelta(minutes=15 * i), horizon=timedelta(hours=6), value=(300 + i) * -1, asset_id=cs_1.id, data_source_id=data_source.id, ) p_2 = Power( datetime=isodate.parse_datetime("2015-01-01T00:00:00Z") + timedelta(minutes=15 * i), horizon=timedelta(hours=6), value=(300 - i) * -1, asset_id=cs_2.id, data_source_id=data_source.id, ) p_3 = Power( datetime=isodate.parse_datetime("2015-01-01T00:00:00Z") + timedelta(minutes=15 * i), horizon=timedelta(hours=6), value=(0 + i) * -1, asset_id=cs_3.id, data_source_id=data_source.id, ) power_forecasts.append(p_1) power_forecasts.append(p_2) power_forecasts.append(p_3) db.session.bulk_save_objects(power_forecasts) # Create 2 weather sensors test_sensor_type = WeatherSensorType(name="wind_speed") db.session.add(test_sensor_type) sensor = WeatherSensor( name="wind_speed_sensor", weather_sensor_type_name="wind_speed", event_resolution=timedelta(minutes=5), latitude=33.4843866, longitude=126, unit="m/s", ) db.session.add(sensor) test_sensor_type = WeatherSensorType(name="temperature") db.session.add(test_sensor_type) sensor = WeatherSensor( name="temperature_sensor", weather_sensor_type_name="temperature", event_resolution=timedelta(minutes=5), latitude=33.4843866, longitude=126, unit="°C", ) db.session.add(sensor) print("Done setting up data for API v1.1 tests")
def create_user( # noqa: C901 password: str = None, user_roles: Union[Dict[str, str], List[Dict[str, str]], str, List[str]] = None, check_email_deliverability: bool = True, account_name: Optional[str] = None, **kwargs, ) -> User: """ Convenience wrapper to create a new User object. It hashes the password. In addition to the user, this function can create - new Role objects (if user roles do not already exist) - an Account object (if it does not exist yet) - a new DataSource object that corresponds to the user Remember to commit the session after calling this function! """ # Check necessary input explicitly before anything happens if password is None or password == "": raise InvalidFlexMeasuresUser("No password provided.") if "email" not in kwargs: raise InvalidFlexMeasuresUser("No email address provided.") email = kwargs.pop("email").strip() try: email_info = validate_email(email, check_deliverability=False) # The mx check talks to the SMTP server. During testing, we skip it because it # takes a bit of time and without internet connection it fails. if check_email_deliverability and not current_app.testing: try: validate_email_deliverability(email_info.domain, email_info["domain_i18n"]) except EmailUndeliverableError as eue: raise InvalidFlexMeasuresUser( "The email address %s does not seem to be deliverable: %s" % (email, str(eue))) except EmailNotValidError as enve: raise InvalidFlexMeasuresUser("%s is not a valid email address: %s" % (email, str(enve))) if "username" not in kwargs: username = email.split("@")[0] else: username = kwargs.pop("username").strip() # Check integrity explicitly before anything happens existing_user_by_email = User.query.filter_by(email=email).one_or_none() if existing_user_by_email is not None: raise InvalidFlexMeasuresUser("User with email %s already exists." % email) existing_user_by_username = User.query.filter_by( username=username).one_or_none() if existing_user_by_username is not None: raise InvalidFlexMeasuresUser("User with username %s already exists." % username) # check if we can link/create an account if account_name is None: raise InvalidFlexMeasuresUser( "Cannot create user without knowing the name of the account which this user is associated with." ) account = db.session.query(Account).filter_by( name=account_name).one_or_none() if account is None: print(f"Creating account {account_name} ...") account = Account(name=account_name) db.session.add(account) user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) kwargs.update(password=hash_password(password), email=email, username=username) user = user_datastore.create_user(**kwargs) user.account = account # add roles to user (creating new roles if necessary) if user_roles: if not isinstance(user_roles, list): user_roles = [user_roles] # type: ignore for user_role in user_roles: if isinstance(user_role, dict): role = user_datastore.find_role(user_role["name"]) else: role = user_datastore.find_role(user_role) if role is None: if isinstance(user_role, dict): role = user_datastore.create_role(**user_role) else: role = user_datastore.create_role(name=user_role) user_datastore.add_role_to_user(user, role) # create data source db.session.add(DataSource(user=user)) return user
def create_user( # noqa: C901 user_roles: Union[Dict[str, str], List[Dict[str, str]], str, List[str]] = None, check_deliverability: bool = True, **kwargs) -> User: """ Convenience wrapper to create a new User object and new Role objects (if user roles do not already exist), and new DataSource object that corresponds to the user. Remember to commit the session after calling this function! """ # Check necessary input explicitly before anything happens if "email" not in kwargs: raise InvalidFlexMeasuresUser("No email address provided.") email = kwargs.pop("email").strip() try: email_info = validate_email(email, check_deliverability=False) # The mx check talks to the SMTP server. During testing, we skip it because it # takes a bit of time and without internet connection it fails. if check_deliverability and not current_app.testing: try: validate_email_deliverability(email_info.domain, email_info["domain_i18n"]) except EmailUndeliverableError as eue: raise InvalidFlexMeasuresUser( "The email address %s does not seem to be deliverable: %s" % (email, str(eue))) except EmailNotValidError as enve: raise InvalidFlexMeasuresUser("%s is not a valid email address: %s" % (email, str(enve))) if "username" not in kwargs: username = email.split("@")[0] else: username = kwargs.pop("username").strip() # Check integrity explicitly before anything happens existing_user_by_email = User.query.filter_by(email=email).one_or_none() if existing_user_by_email is not None: raise InvalidFlexMeasuresUser("User with email %s already exists." % email) existing_user_by_username = User.query.filter_by( username=username).one_or_none() if existing_user_by_username is not None: raise InvalidFlexMeasuresUser("User with username %s already exists." % username) user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) kwargs.update(email=email, username=username) user = user_datastore.create_user(**kwargs) if user.password is None: set_random_password(user) # add roles to user (creating new roles if necessary) if user_roles: if not isinstance(user_roles, list): user_roles = [user_roles] # type: ignore for user_role in user_roles: if isinstance(user_role, dict): role = user_datastore.find_role(user_role["name"]) else: role = user_datastore.find_role(user_role) if role is None: if isinstance(user_role, dict): role = user_datastore.create_role(**user_role) else: role = user_datastore.create_role(name=user_role) user_datastore.add_role_to_user(user, role) # create data source db.session.add(DataSource(user=user)) return user
def sqlalchemy_session_setup(request, app, tmpdir, realdburl): pytest.importorskip("sqlalchemy") from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql import func from sqlalchemy import ( Boolean, DateTime, Column, Integer, String, Text, ForeignKey, UnicodeText, ) f, path = tempfile.mkstemp(prefix="flask-security-test-db", suffix=".db", dir=str(tmpdir)) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + path engine = create_engine(app.config["SQLALCHEMY_DATABASE_URI"]) db_session = scoped_session( sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() Base.query = db_session.query_property() class RolesUsers(Base): __tablename__ = "roles_users" id = Column(Integer(), primary_key=True) user_id = Column("user_id", Integer(), ForeignKey("user.myuserid")) role_id = Column("role_id", Integer(), ForeignKey("role.myroleid")) class Role(Base, RoleMixin): __tablename__ = "role" myroleid = Column(Integer(), primary_key=True) name = Column(String(80), unique=True) description = Column(String(255)) permissions = Column(UnicodeText, nullable=True) update_datetime = Column( DateTime, nullable=False, server_default=func.now(), onupdate=datetime.utcnow, ) class User(Base, UserMixin): __tablename__ = "user" myuserid = Column(Integer, primary_key=True) fs_uniquifier = Column(String(64), unique=True, nullable=False) email = Column(String(255), unique=True) username = Column(String(255), unique=True, nullable=True) password = Column(String(255)) security_number = Column(Integer, unique=True) last_login_at = Column(DateTime()) current_login_at = Column(DateTime()) tf_primary_method = Column(String(255), nullable=True) tf_totp_secret = Column(String(255), nullable=True) tf_phone_number = Column(String(255), nullable=True) us_totp_secrets = Column(Text, nullable=True) us_phone_number = Column(String(64), nullable=True) last_login_ip = Column(String(100)) current_login_ip = Column(String(100)) login_count = Column(Integer) active = Column(Boolean()) confirmed_at = Column(DateTime()) roles = relationship("Role", secondary="roles_users", backref=backref("users", lazy="dynamic")) update_datetime = Column( DateTime, nullable=False, server_default=func.now(), onupdate=datetime.utcnow, ) def get_security_payload(self): # Make sure we still properly hook up to flask JSONEncoder return { "email": str(self.email), "last_update": self.update_datetime } with app.app_context(): Base.metadata.create_all(bind=engine) def tear_down(): db_session.close() os.close(f) os.remove(path) request.addfinalizer(tear_down) return SQLAlchemySessionUserDatastore(db_session, User, Role)
def setup_api_test_data(db, setup_accounts, setup_roles_users, add_market_prices): """ Set up data for API v1.1 tests. """ print("Setting up data for API v1.1 tests on %s" % db.engine) from flexmeasures.data.models.user import User, Role from flexmeasures.data.models.assets import Asset, AssetType user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) # Create a user without proper registration as a data source user_datastore.create_user( username="******", email="*****@*****.**", password=hash_password("testtest"), account_id=setup_accounts["Prosumer"].id, ) # Create 3 test assets for the test_user test_user = setup_roles_users["Test Prosumer User"] test_asset_type = AssetType(name="test-type") db.session.add(test_asset_type) asset_names = ["CS 1", "CS 2", "CS 3"] assets: List[Asset] = [] for asset_name in asset_names: asset = Asset( name=asset_name, owner_id=test_user.id, asset_type_name="test-type", event_resolution=timedelta(minutes=15), capacity_in_mw=1, latitude=100, longitude=100, unit="MW", ) assets.append(asset) db.session.add(asset) # Add power forecasts to the assets cs_1 = Asset.query.filter(Asset.name == "CS 1").one_or_none() cs_2 = Asset.query.filter(Asset.name == "CS 2").one_or_none() cs_3 = Asset.query.filter(Asset.name == "CS 3").one_or_none() data_source = DataSource.query.filter(DataSource.user == test_user).one_or_none() cs1_beliefs = [ TimedBelief( event_start=isodate.parse_datetime("2015-01-01T00:00:00Z") + timedelta(minutes=15 * i), belief_horizon=timedelta(hours=6), event_value=(300 + i) * -1, sensor=cs_1.corresponding_sensor, source=data_source, ) for i in range(6) ] cs2_beliefs = [ TimedBelief( event_start=isodate.parse_datetime("2015-01-01T00:00:00Z") + timedelta(minutes=15 * i), belief_horizon=timedelta(hours=6), event_value=(300 - i) * -1, sensor=cs_2.corresponding_sensor, source=data_source, ) for i in range(6) ] cs3_beliefs = [ TimedBelief( event_start=isodate.parse_datetime("2015-01-01T00:00:00Z") + timedelta(minutes=15 * i), belief_horizon=timedelta(hours=6), event_value=(0 + i) * -1, sensor=cs_3.corresponding_sensor, source=data_source, ) for i in range(6) ] db.session.add_all(cs1_beliefs + cs2_beliefs + cs3_beliefs) add_legacy_weather_sensors(db) print("Done setting up data for API v1.1 tests")
def sqlalchemy_session_setup(request, app, tmpdir, realdburl): """ Note that we test having a different user id column name here. """ pytest.importorskip("sqlalchemy") from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker, relationship, backref from sqlalchemy.ext.declarative import declarative_base, declared_attr from sqlalchemy.sql import func from sqlalchemy import ( Boolean, DateTime, Column, Integer, LargeBinary, String, Text, ForeignKey, UnicodeText, ) from flask_security.models.fsqla_v3 import AsaList f, path = tempfile.mkstemp( prefix="flask-security-test-db", suffix=".db", dir=str(tmpdir) ) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + path engine = create_engine(app.config["SQLALCHEMY_DATABASE_URI"]) db_session = scoped_session( sessionmaker(autocommit=False, autoflush=False, bind=engine) ) Base = declarative_base() Base.query = db_session.query_property() class RolesUsers(Base): __tablename__ = "roles_users" id = Column(Integer(), primary_key=True) user_id = Column("user_id", Integer(), ForeignKey("user.myuserid")) role_id = Column("role_id", Integer(), ForeignKey("role.myroleid")) class Role(Base, RoleMixin): __tablename__ = "role" myroleid = Column(Integer(), primary_key=True) name = Column(String(80), unique=True) description = Column(String(255)) permissions = Column(UnicodeText, nullable=True) update_datetime = Column( DateTime, nullable=False, server_default=func.now(), onupdate=datetime.utcnow, ) class User(Base, UserMixin): __tablename__ = "user" myuserid = Column(Integer, primary_key=True) fs_uniquifier = Column(String(64), unique=True, nullable=False) fs_webauthn_user_handle = Column(String(64), unique=True, nullable=True) email = Column(String(255), unique=True) username = Column(String(255), unique=True, nullable=True) password = Column(String(255)) security_number = Column(Integer, unique=True) last_login_at = Column(DateTime()) current_login_at = Column(DateTime()) tf_primary_method = Column(String(255), nullable=True) tf_totp_secret = Column(String(255), nullable=True) tf_phone_number = Column(String(255), nullable=True) us_totp_secrets = Column(Text, nullable=True) us_phone_number = Column(String(64), nullable=True) last_login_ip = Column(String(100)) current_login_ip = Column(String(100)) login_count = Column(Integer) active = Column(Boolean()) confirmed_at = Column(DateTime()) roles = relationship( "Role", secondary="roles_users", backref=backref("users", lazy="dynamic") ) update_datetime = Column( DateTime, nullable=False, server_default=func.now(), onupdate=datetime.utcnow, ) @declared_attr def webauthn(cls): return relationship("WebAuthn", backref="users", cascade="all, delete") def get_security_payload(self): # Make sure we still properly hook up to flask JSONEncoder return {"email": str(self.email), "last_update": self.update_datetime} class WebAuthn(Base, WebAuthnMixin): __tablename__ = "webauthn" id = Column(Integer, primary_key=True) credential_id = Column( LargeBinary(1024), index=True, unique=True, nullable=False ) public_key = Column(LargeBinary, nullable=False) sign_count = Column(Integer, default=0) transports = Column(AsaList(255), nullable=True) # comma separated # a JSON string as returned from registration extensions = Column(String(255), nullable=True) create_datetime = Column( type_=DateTime, nullable=False, server_default=func.now() ) lastuse_datetime = Column(type_=DateTime, nullable=False) # name is provided by user - we make sure is unique per user name = Column(String(64), nullable=False) usage = Column(String(64), nullable=False) @declared_attr def myuser_id(cls): return Column( Integer, ForeignKey("user.myuserid", ondelete="CASCADE"), nullable=False, ) def get_user_mapping(self) -> t.Dict[str, t.Any]: """ Return the filter needed by find_user() to get the user associated with this webauthn credential. """ return dict(myuserid=self.myuser_id) with app.app_context(): Base.metadata.create_all(bind=engine) def tear_down(): db_session.close() os.close(f) os.remove(path) request.addfinalizer(tear_down) return SQLAlchemySessionUserDatastore(db_session, User, Role, WebAuthn)
def create_app(test_config=None): # Create and configure the app app = Flask(__name__, instance_relative_config=True) app.config.from_mapping( DEBUG=False, SECRET_KEY=os.environ.get( "SECRET_KEY", "ppBcUQ5AL7gEmvb0blMDyEOpiBEQUupGmk_a3DMaF34"), TOPIC_STORE_USER=database_username, TOPIC_STORE_PASSWORD=database_password, TOPIC_STORE_DBNAME=database_name, TOPIC_STORE_HOST=database_host, TOPIC_STORE_PORT=database_port, SECURITY_PASSWORD_SALT=os.environ.get( "SECURITY_PASSWORD_SALT", "139687009245803364536588051620840970665"), SECURITY_REGISTERABLE=True, SECURITY_RECOVERABLE=True, SECURITY_CHANGEABLE=True, SECURITY_EMAIL_SENDER=email_sender, SECURITY_URL_PREFIX="/auth", SECURITY_POST_LOGIN_VIEW="/maps/", SECURITY_POST_REGISTER_VIEW="/maps/", MAIL_SERVER=email_server, MAIL_PORT=587, MAIL_USE_SSL=False, MAIL_USERNAME=email_username, MAIL_PASSWORD=email_password, MAX_CONTENT_LENGTH=4 * 1024 * 1024, # 4 megabytes (temporarily - will be 2) ) mail = Mail(app) csrf = SeaSurf(app) if test_config is None: # Load the instance config, if it exists, when not testing app.config.from_pyfile("config.py", silent=True) else: # Load the test config if passed in app.config.from_mapping(test_config) # Ensure the instance folder exists try: os.makedirs(app.instance_path) except OSError: pass @app.route("/") def home(): return render_template("index.html") @app.route("/health") def hello(): return "Healthy!" # HTTP error handlers def forbidden(e): return render_template("403.html"), 403 app.register_error_handler(403, forbidden) def page_not_found(e): return render_template("404.html"), 404 app.register_error_handler(404, page_not_found) def internal_server_error(e): return render_template("500.html"), 500 app.register_error_handler(500, internal_server_error) def request_entity_too_large(e): return render_template("413.html"), 413 app.register_error_handler(413, request_entity_too_large) # Setup Flask-Security user_datastore = SQLAlchemySessionUserDatastore(user_store.db_session, user_models.User, user_models.Role) security = Security(app, user_datastore) @user_registered.connect_via(app) def user_registered_handler(app, user, confirm_token): default_role = user_datastore.find_role("user") user_datastore.add_role_to_user(user, default_role) user_store.db_session.commit() @app.before_first_request def create_user(): user_store.init_db() # Create roles user_datastore.find_or_create_role(name="admin", description="Administrator") user_datastore.find_or_create_role(name="user", description="End user") # Create users if not user_datastore.get_user("*****@*****.**"): user_datastore.create_user(email="*****@*****.**", password=hash_password("Passw0rd1")) if not user_datastore.get_user("*****@*****.**"): user_datastore.create_user(email="*****@*****.**", password=hash_password("Passw0rd1")) user_store.db_session.commit() # Assign roles user_datastore.add_role_to_user("*****@*****.**", "user") user_datastore.add_role_to_user("*****@*****.**", "admin") user_store.db_session.commit() @app.teardown_request def checkin_db(exc): user_store.db_session.remove() # Register custom filters filters.register_filters(app) # Register Blueprints from contextualise import api app.register_blueprint(api.bp) from contextualise import map app.register_blueprint(map.bp) from contextualise import topic app.register_blueprint(topic.bp) from contextualise import image app.register_blueprint(image.bp) from contextualise import file app.register_blueprint(file.bp) from contextualise import link app.register_blueprint(link.bp) from contextualise import video app.register_blueprint(video.bp) from contextualise import association app.register_blueprint(association.bp) from contextualise import note app.register_blueprint(note.bp) from contextualise import three_d app.register_blueprint(three_d.bp) from contextualise import attribute app.register_blueprint(attribute.bp) from contextualise import visualisation app.register_blueprint(visualisation.bp) # Add topic store from contextualise import topic_store topic_store.init_app(app) # Set up logging if not app.debug: if not os.path.exists("logs"): os.mkdir("logs") file_handler = RotatingFileHandler("logs/contextualise.log", maxBytes=10240, backupCount=10) file_handler.setFormatter( logging.Formatter( "%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]" )) file_handler.setLevel(logging.INFO) app.logger.addHandler(file_handler) app.logger.setLevel(logging.INFO) app.logger.info("Contextualise startup") return app
def create_app(test_config=None): from . import models, routes # app = Flask(__name__, static_folder="static/") ### FLASK CONFIG app = Flask(__name__, instance_relative_config=True, static_folder="static/") CORS(app, supports_credentials=True) if test_config is None: # load the instance config, if it exists, when not testing app.config.from_pyfile("config.py", silent=True) else: # load the test config if passed in app.config.from_mapping(test_config) # ensure the instance folder exists try: # os.makedirs(app.instance_path) pass except OSError: pass #### END basedir = os.path.abspath(os.path.dirname(__file__)) # Database app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + os.path.join( basedir, "database/db.sqlite") print(app.config["SQLALCHEMY_DATABASE_URI"]) app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False app.config["SECRET_KEY"] = "super-secret" app.config["SECURITY_PASSWORD_SALT"] = "super-secret" app.config["SECURITY_TRACKABLE"] = True app.config["SECURITY_REGISTERABLE"] = True app.config["WTF_CSRF_ENABLED"] = False app.config["SECURITY_SEND_REGISTER_EMAIL"] = False # Mail config app.config["MAIL_SERVER"] = "smtp.gmail.com" app.config["MAIL_PORT"] = 465 app.config["MAIL_USERNAME"] = "******" app.config["MAIL_PASSWORD"] = "******" app.config["MAIL_USE_TLS"] = False app.config["MAIL_USE_SSL"] = True from src.models.user import User, Role, db from flask_security import ( SQLAlchemySessionUserDatastore, Security, login_required, current_user, ) # Setup Flask-Security user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) security = Security(app, user_datastore) import src.mail as mail models.init_app(app) routes.init_app(app) mail.init_app(app) from flask import send_from_directory # Serve React App @app.route("/", defaults={"path": ""}) @app.route("/<path:path>") @login_required def serve(path): if path != "" and os.path.exists(app.static_folder + "/" + path): return send_from_directory(app.static_folder, path) else: return send_from_directory(app.static_folder, "index.html") @app.errorhandler(404) def page_not_found(e): return redirect("/"), 404 @app.route("/schema") def get_schema(): return render_template("schema.html") return app
def __init__(self, root_path, template_folders, **kwargs): """ work with Flask constructor args """ AdminIndexView = kwargs.get('admin_index_view', None) try: del kwargs['admin_index_view'] except: pass """ app """ Flask.__init__(self, __name__, **kwargs) base.app = self base.app.root_path = root_path self.config.from_envvar('SETTINGS') self.secret_key = 'super secret key' """ set custom jinja loader """ tfs = [base.app.jinja_loader] for tf in template_folders: tfs.append(jinja2.FileSystemLoader(tf)) loader = jinja2.ChoiceLoader(tfs) base.app.jinja_loader = loader """ cors """ CORS(self, resources={ r"/v2/*": { "origins": "*" }, r"/api/*": { "origins": "*" }, r"/spec": { "origins": "*" }, }) """ collect """ Collect(base.app) """ sqlalchemy """ base.db = SQLAlchemy(base.app) """ migrate """ Migrate(base.app, base.db) """ DebugToolbar """ if base.app.config.get('DEBUG', False): DebugToolbarExtension(base.app) """ admin """ if not AdminIndexView: from .admin_index_view import AdminIndexView base_url = self.config.get('FLASK_ADMIN_URL', '/admin') base.admin = Admin( self, url=base_url, name=self.config.get('APPNAME', 'flask app'), template_mode='bootstrap3', base_template='admin/base_.html', index_view=AdminIndexView(url=base_url), ) """ swagger """ from .swagger import get_swaggerui_blueprint from flask_swagger import swagger SWAGGER_URL = self.config.get('SWAGGER_URL', '/api/docs') API_URL = '/spec' swaggerui_blueprint = get_swaggerui_blueprint( SWAGGER_URL, API_URL, config={ # Swagger UI config overrides 'app_name': '%s API' % self.config.get('APPNAME', 'flask app'), }, oauth_config={ 'clientId': "swagger", } ) self.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL) @self.route("/spec") def spec(): swag = swagger(self) swag_from_file = yaml.load(open('./swagger/spec.yaml')) swag.update(swag_from_file) return jsonify(swag) """ internal blueprint """ base.internal_bp = Blueprint('internal', 'internal_bp') """ oauth """ from flask_oauthlib.provider import OAuth2Provider base.oauth = OAuth2Provider(self) from . import oauth """ flask login """ from .models import session, User, Role user_datastore = SQLAlchemySessionUserDatastore(session, User, Role) security = Security(self, user_datastore) """ modules """ from . import views, admins self.register_blueprint(base.internal_bp, url_prefix=base.app.config.get( 'CANTEEN_URL_PREFIX', ''))
from .base.routes import base_bp from .apis.routes import anytable_ns from .anytable.routes import anytable_bp from .anytable.models import AnyTable APP_ROOT_FOLDER = os.path.abspath(os.path.dirname(app_root.__file__)) TEMPLATE_FOLDER = os.path.join(APP_ROOT_FOLDER, 'templates') STATIC_FOLDER = os.path.join(APP_ROOT_FOLDER, 'static') app = Flask(__name__, template_folder=TEMPLATE_FOLDER, static_folder=STATIC_FOLDER) FlaskDynaconf(app) db.init_app(app) bootstrap.init_app(app) security.init_app(app, SQLAlchemySessionUserDatastore(db.session, User, Role)) api.init_app(app) ma.init_app(app) app.register_blueprint(base_bp) app.register_blueprint(anytable_bp) api.add_namespace(anytable_ns) @app.before_first_request def create_db(): db.create_all() try:
def setup_security(app): user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role) security.init_app(app, user_datastore) return user_datastore
from flask import Flask, render_template, jsonify, request, session, redirect, url_for import re, sqlite3, json from flask_security import Security, login_required, \ SQLAlchemySessionUserDatastore, roles_accepted from flask_security.utils import hash_password from database import db_session, init_db from models import User, Role app = Flask(__name__) app.config['DEBUG'] = True app.config['SECRET_KEY'] = 'secret string' app.config['SECURITY_PASSWORD_SALT'] = 'some arbitrary super secret string' app.config['SECURITY_TRACKABLE'] = True # Setup Flask-Security user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role) security = Security(app, user_datastore) conn_purchase = sqlite3.connect('user_purchase_data.db') cur_purchase = conn_purchase.cursor() cur_purchase.executescript(''' CREATE TABLE IF NOT EXISTS CART ( ID INTEGER NOT NULL PRIMARY KEY, USER_ID INTEGER NOT NULL UNIQUE, ITEMS TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS HISTORY ( ID INTEGER NOT NULL PRIMARY KEY, USER_ID INTEGER NOT NULL, ITEMS TEXT NOT NULL,
def create_app(): app = Flask(__name__) app.config["DEBUG"] = True app.config["SECRET_KEY"] = "super-secret" app.config["LOGIN_DISABLED"] = False app.config["WTF_CSRF_ENABLED"] = False # Don't actually send any email - instead we subscribe to signals # and print out required info. app.config["MAIL_SUPPRESS_SEND"] = True app.config["SECURITY_TWO_FACTOR_SECRET"] = { "1": "TjQ9Qa31VOrfEzuPy4VHQWPCTmRzCnFzMKLxXYiZu9B" } app.config["SECURITY_PASSWORD_SALT"] = "salty" # Make this plaintext for most tests - reduces unit test time by 50% app.config["SECURITY_PASSWORD_HASH"] = "plaintext" # Make this hex_md5 for token tests app.config["SECURITY_HASHING_SCHEMES"] = ["hex_md5"] app.config["SECURITY_DEPRECATED_HASHING_SCHEMES"] = [] for opt in [ "changeable", "recoverable", "registerable", "trackable", "NOTpasswordless", "confirmable", "two_factor", ]: app.config["SECURITY_" + opt.upper()] = True if os.environ.get("SETTINGS"): app.config.from_envvar("SETTINGS") mail = Mail(app) app.json_encoder = JSONEncoder app.mail = mail # Setup Flask-Security user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role) security = Security(app, user_datastore) # This is NOT ideal since it basically changes entire APP (which is fine for # this test - but not fine for general use). babel = flask_babelex.Babel(app, default_domain=security.i18n_domain) @babel.localeselector def get_locale(): # For a given session - set lang based on first request. # Honor explicit url request first if "lang" not in session: locale = request.args.get("lang", None) if not locale: locale = request.accept_languages.best if not locale: locale = "en" if locale: session["lang"] = locale return session.get("lang", None).replace("-", "_") # Create a user to test with @app.before_first_request def create_user(): init_db() db_session.commit() test_acct = "*****@*****.**" if not user_datastore.get_user(test_acct): add_user(user_datastore, test_acct, "password", ["admin"]) print("Created User: {} with password {}".format( test_acct, "password")) @user_registered.connect_via(app) def on_user_registerd(myapp, user, confirm_token): print("User {} registered with token {}".format( user.email, confirm_token)) @reset_password_instructions_sent.connect_via(app) def on_reset(myapp, user, token): print("User {} started password reset with token {}".format( user.email, token)) @tf_security_token_sent.connect_via(app) def on_token_sent(myapp, user, token, method): print("User {} was sent two factor token {} via {}".format( user.email, token, method)) # Views @app.route("/") @login_required def home(): return render_template_string("{{ _('Welcome') }} {{email}} !", email=current_user.email) return app