def test_change_password_good_is_password_changed(self): from c2cgeoportal_geoportal.views.login import Login import crypt request = self._create_request_obj( params={"lang": "en"}, POST={ "login": "******", "oldPassword": "******", "newPassword": "******", "confirmNewPassword": "******", }, ) from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User user = DBSession.query(User).filter_by(username="******").one() assert user.is_password_changed is False assert user._password == crypt.crypt("__test_user1", user._password) login = Login(request) self.assertNotEqual(login.change_password(), None) user = DBSession.query(User).filter_by(username="******").one() assert user.is_password_changed is True assert user._password == crypt.crypt("1234", user._password)
def test_web_client_functionalities(self): from tests.functional import create_dummy_request from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User request = create_dummy_request() request.static_url = lambda url: "http://example.com/dummy/static/url" request1 = create_dummy_request() request1.static_url = lambda url: "http://example.com/dummy/static/url" request1.user = DBSession.query(User).filter(User.username == "__test_user1").one() request2 = create_dummy_request() request2.static_url = lambda url: "http://example.com/dummy/static/url" request2.user = DBSession.query(User).filter(User.username == "__test_user2").one() fill_tech_user_functionality( "registered", (("__test_s", "registered"), ("__test_a", "r1"), ("__test_a", "r2")) ) fill_tech_user_functionality( "anonymous", (("__test_s", "anonymous"), ("__test_a", "a1"), ("__test_a", "a2")) ) settings = { "functionalities": {"available_in_templates": ["__test_s", "__test_a"]}, "admin_interface": {"available_functionalities": [{"name": "__test_a"}, {"name": "__test_s"}]}, } request.registry.settings.update(settings) request1.registry.settings.update(settings) request2.registry.settings.update(settings)
def init_db(settings: Dict[str, Any]) -> None: """ Initialize the SQLAlchemy Session. First test the connection, on wen environment it should be OK, with the command line we should get an exception ind initialise the connection. """ try: from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel from c2cgeoportal_commons.models.main import Theme # pylint: disable=import-outside-toplevel session = DBSession() session.query(Theme).count() except: # pylint: disable=bare-except # Init db sessions class R: settings: Dict[str, Any] = {} class C: registry = R() def get_settings(self) -> Dict[str, Any]: return self.registry.settings def add_tween(self, *args: Any, **kwargs: Any) -> None: pass config_ = C() config_.registry.settings = settings c2cgeoportal_geoportal.init_db_sessions(settings, config_)
def setup_method(self, _): setup_module() import transaction from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Role, Interface from c2cgeoportal_commons.models.static import User cleanup_db() self.metadata = None self.layer_ids = [] DBSession.query(User).delete() DBSession.query(User).filter(User.username == "__test_user").delete() self.role = Role(name="__test_role") self.user = User(username="******", password="******", settings_role=self.role, roles=[self.role]) self.main = Interface(name="main") DBSession.add(self.user) DBSession.add(self.role) DBSession.add(self.main) create_default_ogcserver() transaction.commit()
def __call__(self, filename, options): messages = [] try: self.env = bootstrap(filename, options=os.environ) try: from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Theme, LayerGroup, \ LayerWMS, LayerWMTS, FullTextSearch self._import(Theme, messages) self._import(LayerGroup, messages) self._import(LayerWMS, messages, self._import_layer_wms) self._import(LayerWMTS, messages, self._import_layer_wmts) for ln, in DBSession.query( FullTextSearch.layer_name).distinct().all(): if ln is not None and ln != "": messages.append( Message( None, ln, None, [], "", "", ("fts", ln.encode("ascii", errors="replace")))) for ln, in DBSession.query( FullTextSearch.actions).distinct().all(): if ln is not None and ln != "": action = json.loads(ln) messages.append( Message(None, action['data'], None, [], "", "", ("fts", action['data'].encode( "ascii", errors="replace")))) except ProgrammingError as e: print( colorize( "ERROR! The database is probably not up to date " "(should be ignored when happen during the upgrade)", RED)) print(colorize(e, RED)) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise except NoSuchTableError as e: print( colorize( "ERROR! The schema didn't seem to exists " "(should be ignored when happen during the deploy)", RED)) print(colorize(e, RED)) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise except OperationalError as e: print( colorize( "ERROR! The database didn't seem to exists " "(should be ignored when happen during the deploy)", RED)) print(colorize(e, RED)) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise return messages
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import Shorturl import transaction DBSession.query(Shorturl).delete() transaction.commit()
def teardown_method(self, _): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User DBSession.query(User).filter(User.username == "__test_user1").delete() transaction.commit() pyramid.security.remember = None pyramid.security.remember = self.old_remember
def get_ogcserver_byname(self, name): try: result = DBSession.query(OGCServer).filter(OGCServer.name == name).one() DBSession.expunge(result) return result except NoResultFound: # pragma nocover log.error("OGSServer '{}' does not exists (existing: {}).".format( name, ",".join([t[0] for t in DBSession.query(OGCServer.name).all()]))) raise
def test_json_extent(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Role role = DBSession.query(Role).filter(Role.name == "__test_role1").one() assert role.bounds is None role = DBSession.query(Role).filter(Role.name == "__test_role2").one() assert role.bounds == (1, 2, 3, 4)
def lux_cancel(self): ref = self.request.matchdict.get("ref") job = DBSession.query(LuxPrintJob).get(ref) print_url = job.print_url DBSession.query(LuxPrintJob).filter(LuxPrintJob.id == ref).delete() return self._proxy_response( "print", "%s/cancel/%s" % (print_url, ref), )
def teardown_method(self, _): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Role, LayerWMS, RestrictionArea, \ Interface, OGCServer from c2cgeoportal_commons.models.static import User DBSession.query(User).filter(User.username == "__test_user1").delete() ra = DBSession.query(RestrictionArea).filter( RestrictionArea.name == "__test_ra1").one() ra.roles = [] ra.layers = [] DBSession.delete(ra) r = DBSession.query(Role).filter(Role.name == "__test_role1").one() DBSession.delete(r) for layer in DBSession.query(LayerWMS).filter( LayerWMS.name.in_( ["testpoint_group_name", "testpoint_protected_2_name"])).all(): DBSession.delete(layer) DBSession.query(Interface).filter(Interface.name == "main").delete() DBSession.query(OGCServer).delete() transaction.commit()
def teardown_method(self, _): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Role, LayerWMS, RestrictionArea, \ Interface, OGCServer from c2cgeoportal_commons.models.static import User DBSession.query(User).filter(User.username == "__test_user1").delete() ra = DBSession.query(RestrictionArea).filter( RestrictionArea.name == "__test_ra1" ).one() ra.roles = [] ra.layers = [] DBSession.delete(ra) r = DBSession.query(Role).filter(Role.name == "__test_role1").one() DBSession.delete(r) for layer in DBSession.query(LayerWMS).filter( LayerWMS.name.in_(["testpoint_group_name", "testpoint_protected_2_name"]) ).all(): DBSession.delete(layer) DBSession.query(Interface).filter( Interface.name == "main" ).delete() DBSession.query(OGCServer).delete() transaction.commit()
def teardown_method(self, _): import transaction from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Role from c2cgeoportal_commons.models.static import User transaction.commit() DBSession.query(User).filter_by(username="******").delete() DBSession.query(Role).filter_by(name="__test_role").delete() transaction.commit()
def test_web_client_functionalities(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User from tests.functional import create_dummy_request from c2cgeoportal_geoportal.views.entry import Entry request = create_dummy_request() request.static_url = lambda url: "http://example.com/dummy/static/url" request1 = create_dummy_request() request1.static_url = lambda url: "http://example.com/dummy/static/url" request1.user = DBSession.query(User).filter( User.username == "__test_user1").one() request2 = create_dummy_request() request2.static_url = lambda url: "http://example.com/dummy/static/url" request2.user = DBSession.query(User).filter( User.username == "__test_user2").one() settings = { "functionalities": { "anonymous": { "__test_s": "anonymous", "__test_a": ["a1", "a2"] }, "registered": { "__test_s": "registered", "__test_a": ["r1", "r2"] }, "available_in_templates": ["__test_s", "__test_a"], }, "admin_interface": { "available_functionalities": ["__test_a", "__test_s"] }, } functionality.FUNCTIONALITIES_TYPES = None request.registry.settings.update(settings) request1.registry.settings.update(settings) request2.registry.settings.update(settings) annon = Entry(request).get_cgxp_viewer_vars() u1 = Entry(request1).get_cgxp_viewer_vars() u2 = Entry(request2).get_cgxp_viewer_vars() self.assertEqual(annon["functionality"], { "__test_s": ["anonymous"], "__test_a": ["a1", "a2"] }) self.assertEqual(u1["functionality"], { "__test_s": ["registered"], "__test_a": ["r1", "r2"] }) self.assertEqual(u2["functionality"], { "__test_s": ["db"], "__test_a": ["db1", "db2"] })
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import TreeItem, Interface, OGCServer for item in DBSession.query(TreeItem).all(): DBSession.delete(item) DBSession.query(OGCServer).delete() DBSession.query(Interface).filter(Interface.name == "main").delete() transaction.commit()
def _get_ogcserver_byname(self, name): # pylint: disable=no-self-use try: result = DBSession.query(OGCServer).filter( OGCServer.name == name).one() DBSession.expunge(result) return result except NoResultFound: # pragma nocover raise HTTPBadRequest( "OGSServer '{}' does not exists (existing: {}).".format( name, ",".join([ t[0] for t in DBSession.query(OGCServer.name).all() ])))
def main(): parser = argparse.ArgumentParser( description="Create and populate the database tables.") parser.add_argument('-i', '--iniconfig', default='production.ini', help='project .ini config file') parser.add_argument( '-n', '--app-name', default="app", help='The application name (optional, default is "app")') options = parser.parse_args() # read the configuration env = {} env.update(os.environ) env["LOG_LEVEL"] = "INFO" env["GUNICORN_ACCESS_LOG_LEVEL"] = "INFO" env["C2CGEOPORTAL_LOG_LEVEL"] = "WARN" fileConfig(options.iniconfig, defaults=env) get_app(options.iniconfig, options.app_name, options=env) from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Interface, OGCServer, Theme, LayerGroup, LayerWMS session = DBSession() interfaces = session.query(Interface).all() ogc_server = session.query(OGCServer).filter( OGCServer.name == "source for image/png").one() layer_borders = LayerWMS("Borders", "borders") layer_borders.interfaces = interfaces layer_borders.ogc_server = ogc_server layer_density = LayerWMS("Density", "density") layer_density.interfaces = interfaces layer_density.ogc_server = ogc_server group = LayerGroup("Demo") group.children = [layer_borders, layer_density] theme = Theme("Demo") theme.children = [group] theme.interfaces = interfaces session.add(theme) transaction.commit() print("Successfully added the demo theme")
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Interface, Metadata, TreeItem for t in DBSession.query(Metadata).all(): DBSession.delete(t) for item in DBSession.query(TreeItem).all(): DBSession.delete(item) DBSession.query(Interface).filter(Interface.name == "desktop").delete() transaction.commit()
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import TreeItem, Interface, OGCServer for item in DBSession.query(TreeItem).all(): DBSession.delete(item) DBSession.query(OGCServer).delete() DBSession.query(Interface).filter( Interface.name == "main" ).delete() transaction.commit()
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import TreeItem, Interface, Metadata for t in DBSession.query(Metadata).all(): DBSession.delete(t) for item in DBSession.query(TreeItem).all(): DBSession.delete(item) DBSession.query(Interface).filter( Interface.name == "desktop" ).delete() transaction.commit()
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import LayerGroup, LayerWMS, OGCServer, Theme for t in DBSession.query(Theme).filter(Theme.name == "__test_theme").all(): DBSession.delete(t) for g in DBSession.query(LayerGroup).all(): DBSession.delete(g) for layer in DBSession.query(LayerWMS).all(): DBSession.delete(layer) DBSession.query(OGCServer).delete() transaction.commit()
def test_theme(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User from c2cgeoportal_geoportal.views.theme import Theme request = self._create_request_obj() theme_view = Theme(request) # unautenticated themes, errors = theme_view._themes() assert {e[:90] for e in errors} == set() assert len(themes) == 1 groups = {g["name"] for g in themes[0]["children"]} assert groups == {"__test_layer_group"} layers = {l["name"] for l in themes[0]["children"][0]["children"]} assert layers == {"__test_public_layer"} # authenticated request.params = {} request.user = DBSession.query(User).filter_by( username="******").one() themes, errors = theme_view._themes() assert {e[:90] for e in errors} == set() assert len(themes) == 1 groups = {g["name"] for g in themes[0]["children"]} assert groups == {"__test_layer_group"} layers = {l["name"] for l in themes[0]["children"][0]["children"]} assert layers == { "__test_private_layer_edit", "__test_public_layer", "__test_private_layer" }
def _import_layer_wmts(self, layer, messages): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import OGCServer layers = [d.value for d in layer.metadatas if d.name == "queryLayers"] if len(layers) == 0: layers = [d.value for d in layer.metadatas if d.name == "wmsLayer"] server = [d.value for d in layer.metadatas if d.name == "ogcServer"] if len(server) >= 1 and len(layers) >= 1: for wms_layer in layers: try: db_server = DBSession.query(OGCServer).filter(OGCServer.name == server[0]).one() self._import_layer_attributes( db_server.url_wfs or db_server.url, wms_layer, layer.item_type, layer.name, messages ) except NoResultFound: print(colorize( "ERROR! the OGC server '{}' from the WMTS layer '{}' does not exist.".format( server[0], layer.name ), RED )) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise
def test_group_update(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import LayerGroup layer_group_3 = DBSession.query(LayerGroup).filter(LayerGroup.name == "__test_layer_group_3").one() layer_group_3.children = layer_group_3.children[:-1] transaction.commit() entry = self._create_entry_obj(params={ "version": "2", "group": "__test_layer_group_3", "catalogue": "true", }) themes = entry.themes() self.assertEqual(self._get_filtered_errors(themes), set()) self.assertEqual( self._only_name(themes["group"]), { "name": "__test_layer_group_3", # order is important "children": [{ "name": "__test_layer_wmts" }, { "name": "__test_layer_internal_wms" }] } )
def test_create_log(self): from datetime import datetime from geojson.feature import FeatureCollection from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Metadata from c2cgeoportal_commons.models.static import User from c2cgeoportal_geoportal.views.layers import Layers self.assertEqual( DBSession.query(User.username).all(), [("__test_user", )]) metadatas = [ Metadata("lastUpdateDateColumn", "last_update_date"), Metadata("lastUpdateUserColumn", "last_update_user"), ] layer_id = self._create_layer(metadatas=metadatas) request = self._get_request(layer_id, username="******") request.method = "POST" request.body = '{"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {"name": "foo", "child": "c1é"}, "geometry": {"type": "Point", "coordinates": [5, 45]}}]}' # noqa layers = Layers(request) collection = layers.create() self.assertEqual(request.response.status_int, 201) self.assertTrue(isinstance(collection, FeatureCollection)) self.assertEqual(len(collection.features), 1) properties = collection.features[0] self.assertEqual(request.user.username, "__test_user") self.assertEqual(properties.last_update_user, request.user.id) self.assertIsInstance(properties.last_update_date, datetime)
def invalidate_authorization_code( self, client_id: str, code: str, request: oauthlib.common.Request, *args: Any, **kwargs: Any, ) -> None: """ Invalidate an authorization code after use. Arguments: client_id: Unicode client identifier code: The authorization code grant (request.code). request: The HTTP Request Method is used by: - Authorization Code Grant """ del args, kwargs LOG.debug("invalidate_authorization_code %s", client_id) from c2cgeoportal_commons.models import DBSession, static # pylint: disable=import-outside-toplevel DBSession.delete( DBSession.query(static.OAuth2AuthorizationCode).join( static.OAuth2AuthorizationCode.client).filter( static.OAuth2AuthorizationCode.code == code).filter( static.OAuth2Client.client_id == client_id).filter( static.OAuth2AuthorizationCode.user_id == request.user.id).one())
def validate_client_id( self, client_id: str, request: oauthlib.common.Request, *args: Any, **kwargs: Any, ) -> bool: """ Ensure client_id belong to a valid and active client. Note, while not strictly necessary it can often be very convenient to set request.client to the client object associated with the given client_id. Arguments: client_id: Unicode client identifier request: oauthlib.common.Request Method is used by: - Authorization Code Grant - Implicit Grant """ del args, kwargs LOG.debug("validate_client_id") from c2cgeoportal_commons.models import DBSession, static # pylint: disable=import-outside-toplevel client = (DBSession.query(static.OAuth2Client).filter( static.OAuth2Client.client_id == client_id).one_or_none()) if client is not None: request.client = client return client is not None
def get_user_from_request(request, username=None): """ Return the User object for the request. Return ``None`` if: * user is anonymous * it does not exist in the database * the referer is invalid """ from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User try: if request.method == 'GET' and "auth" in request.params: auth_enc = request.params.get("auth") if auth_enc is not None: urllogin = request.registry.settings.get("urllogin", {}) aeskey = urllogin.get("aes_key") if aeskey is None: # pragma: nocover raise Exception("urllogin is not configured") now = int(time.time()) data = binascii.unhexlify(auth_enc.encode('ascii')) nonce = data[0:16] tag = data[16:32] ciphertext = data[32:] cipher = AES.new(aeskey.encode("ascii"), AES.MODE_EAX, nonce) auth = json.loads( cipher.decrypt_and_verify(ciphertext, tag).decode("utf-8")) if "t" in auth and "u" in auth and "p" in auth: timestamp = int(auth["t"]) if now < timestamp and request.registry.validate_user( request, auth["u"], auth["p"]): headers = pyramid.security.remember( request, auth["u"]) request.response.headerlist.extend(headers) except Exception as e: LOG.error("URL login error: %s.", e, exc_info=True) if not hasattr(request, "is_valid_referer"): request.is_valid_referer = is_valid_referer(request, settings) if not request.is_valid_referer: LOG.debug("Invalid referer for %s: %s", request.path_qs, repr(request.referer)) return None if not hasattr(request, "user_"): request.user_ = None if username is None: username = request.authenticated_userid if username is not None: # We know we will need the role object of the # user so we use joined loading request.user_ = DBSession.query(User) \ .filter_by(username=username) \ .first() return request.user_
def test_group_update(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import LayerGroup layer_group_3 = DBSession.query(LayerGroup).filter( LayerGroup.name == "__test_layer_group_3").one() layer_group_3.children = layer_group_3.children[:-1] transaction.commit() entry = self._create_entry_obj(params={ "group": "__test_layer_group_3", }) themes = entry.themes() self.assertEqual(self._get_filtered_errors(themes), set()) self.assertEqual( self._only_name(themes["group"]), { "name": "__test_layer_group_3", # order is important "children": [{ "name": "__test_layer_wmts" }, { "name": "__test_layer_internal_wms" }] })
def _import_layer_wmts(self, layer: "main.Layer", messages: List[str]) -> None: from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel from c2cgeoportal_commons.models.main import OGCServer # pylint: disable=import-outside-toplevel layers = [d.value for d in layer.metadatas if d.name == "queryLayers"] if not layers: layers = [d.value for d in layer.metadatas if d.name == "wmsLayer"] server = [d.value for d in layer.metadatas if d.name == "ogcServer"] if server and layers: layers = [layer for ls in layers for layer in ls.split(",")] for wms_layer in layers: try: db_server = DBSession.query(OGCServer).filter( OGCServer.name == server[0]).one() if db_server.wfs_support: self._import_layer_attributes( db_server.url_wfs or db_server.url, wms_layer, layer.item_type, layer.name, messages, ) except NoResultFound: print( colorize( "ERROR! the OGC server '{}' from the WMTS layer '{}' does not exist." .format(server[0], layer.name), Color.RED, )) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise
def add_association_proxy_xsd(self, tb: str, column_property: ColumnProperty) -> None: from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel column = column_property.columns[0] proxy = column.info["association_proxy"] attribute = column_property.class_attribute cls = attribute.parent.entity association_proxy = getattr(cls, proxy) relationship_property = class_mapper(cls).get_property(association_proxy.target) target_cls = relationship_property.argument query = DBSession.query(getattr(target_cls, association_proxy.value_attr)) if association_proxy.order_by is not None: query = query.order_by(getattr(target_cls, association_proxy.order_by)) attrs = {} if association_proxy.nullable: attrs["minOccurs"] = "0" attrs["nillable"] = "true" attrs["name"] = proxy with tag(tb, "xsd:element", attrs) as tb2: with tag(tb2, "xsd:simpleType") as tb3: with tag(tb3, "xsd:restriction", {"base": "xsd:string"}) as tb4: for (value,) in query: with tag(tb4, "xsd:enumeration", {"value": value}): pass self.element_callback(tb4, column)
def test_reset_password(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User from c2cgeoportal_geoportal.views.entry import Entry request = self._create_request_obj(POST={ "login": "******", }) entry = Entry(request) _, username, password, _ = entry._loginresetpassword() request = self._create_request_obj(POST={ "login": username, "password": password, }) response = Entry(request).login() assert response.status_int == 200 assert json.loads(response.body.decode("utf-8")) == { "success": True, "username": "******", 'email': '*****@*****.**', "is_password_changed": False, "roles": [{ "name": "__test_role1", "id": self.role1_id, }], "functionalities": {}, } user = DBSession.query(User).filter( User.username == '__test_user1').first() self.assertIsNone(user.temp_password) self.assertIsNotNone(user.password) self.assertNotEqual(len(user.password), 0)
def test_wrong_loginresetpassword(self): from c2cgeoportal_geoportal.views.login import Login from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User user = DBSession.query(User).filter_by(username="******").one() _2fa_totp_secret = pyotp.random_base32() totp = pyotp.TOTP(_2fa_totp_secret) user.tech_data["2fa_totp_secret"] = _2fa_totp_secret user.is_password_changed = True request = self._create_request_obj(POST={"otp": totp.now()}) with pytest.raises(pyramid.httpexceptions.HTTPBadRequest): Login(request).loginresetpassword() request = self._create_request_obj(POST={"login": "******"}) with pytest.raises(pyramid.httpexceptions.HTTPBadRequest): Login(request).loginresetpassword() request = self._create_request_obj(POST={ "login": "******", "otp": totp.now() }) with pytest.raises(pyramid.httpexceptions.HTTPUnauthorized): Login(request).loginresetpassword() request = self._create_request_obj(POST={ "login": "******", "otp": "wrong" }) with pytest.raises(pyramid.httpexceptions.HTTPUnauthorized): Login(request).loginresetpassword()
def test_private(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User entry = self._create_entry_obj(params={"version": "2"}, user=DBSession.query(User).filter_by( username=u"__test_user").one()) themes = entry.themes() self.assertEquals(self._get_filtered_errors(themes), set()) self.assertEquals([self._only_name(t) for t in themes["themes"]], [{ "name": u"__test_theme", "children": [{ "name": u"__test_layer_group", "children": [{ "name": u"__test_layer_wms" }, { "name": u"__test_layer_wms_private" }, { "name": u"__test_layer_wmts" }, { "name": u"__test_layer_wmts_private" }] }] }])
def test_private(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User entry = self._create_entry_obj(params={ "version": "2" }, user=DBSession.query(User).filter_by(username=u"__test_user").one()) themes = entry.themes() self.assertEquals(themes["errors"], []) self.assertEquals( [self._only_name(t) for t in themes["themes"]], [{ "name": u"__test_theme", "children": [{ "name": u"__test_layer_group", "children": [{ "name": u"__test_layer_wms" }, { "name": u"__test_layer_wms_private" }, { "name": u"__test_layer_wmts" }, { "name": u"__test_layer_wmts_private" }] }] }] )
def _create_getcap_request(username=None): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User request = create_dummy_request() request.user = None if username is None else \ DBSession.query(User).filter_by(username=username).one() return request
def get_private_layers(ogc_server_ids): q = DBSession.query(LayerWMS) \ .filter(LayerWMS.public.is_(False)) \ .join(LayerWMS.ogc_server) \ .filter(OGCServer.id.in_(ogc_server_ids)) results = q.all() DBSession.expunge_all() return {r.id: r for r in results}
def main(): parser = argparse.ArgumentParser( description="Create and populate the database tables." ) parser.add_argument( '-i', '--iniconfig', default='geoportal/production.ini', help='project .ini config file' ) parser.add_argument( '-n', '--app-name', default="app", help='The application name (optional, default is "app")' ) options = parser.parse_args() # read the configuration fileConfig(options.iniconfig, defaults=os.environ) get_app(options.iniconfig, options.app_name, options=os.environ) from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Interface, OGCServer, Theme, LayerGroup, LayerWMS session = DBSession() interfaces = session.query(Interface).all() ogc_server = session.query(OGCServer).filter(OGCServer.name == "source for image/png").one() layer_borders = LayerWMS("Borders", "borders") layer_borders.interfaces = interfaces layer_borders.ogc_server = ogc_server layer_density = LayerWMS("Density", "density") layer_density.interfaces = interfaces layer_density.ogc_server = ogc_server group = LayerGroup("Demo") group.children = [layer_borders, layer_density] theme = Theme("Demo") theme.children = [group] theme.interfaces = interfaces session.add(theme) transaction.commit()
def default_user_validator(request, username, password): """ Validate the username/password. This is c2cgeoportal's default user validator. Return none if we are anonymous, the string to remember otherwise. """ from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User user = DBSession.query(User).filter_by(username=username).first() return username if user and user.validate_password(password) else None
def _get_layers_query(role_id, what): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Layer, RestrictionArea, Role q = DBSession.query(what) q = q.join(Layer.restrictionareas) q = q.join(RestrictionArea.roles) q = q.filter(Role.id == role_id) return q
def test_web_client_functionalities(self): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User from tests.functional import create_dummy_request from c2cgeoportal_geoportal.views.entry import Entry request = create_dummy_request() request.static_url = lambda url: "http://example.com/dummy/static/url" request1 = create_dummy_request() request1.static_url = lambda url: "http://example.com/dummy/static/url" request1.user = DBSession.query(User).filter(User.username == "__test_user1").one() request2 = create_dummy_request() request2.static_url = lambda url: "http://example.com/dummy/static/url" request2.user = DBSession.query(User).filter(User.username == "__test_user2").one() settings = { "functionalities": { "anonymous": { "__test_s": "anonymous", "__test_a": ["a1", "a2"] }, "registered": { "__test_s": "registered", "__test_a": ["r1", "r2"] }, "available_in_templates": ["__test_s", "__test_a"], }, "admin_interface": { "available_functionalities": ["__test_a", "__test_s"] }, } functionality.FUNCTIONALITIES_TYPES = None request.registry.settings.update(settings) request1.registry.settings.update(settings) request2.registry.settings.update(settings) annon = Entry(request).get_cgxp_viewer_vars() u1 = Entry(request1).get_cgxp_viewer_vars() u2 = Entry(request2).get_cgxp_viewer_vars() self.assertEqual(annon["functionality"], {"__test_s": ["anonymous"], "__test_a": ["a1", "a2"]}) self.assertEqual(u1["functionality"], {"__test_s": ["registered"], "__test_a": ["r1", "r2"]}) self.assertEqual(u2["functionality"], {"__test_s": ["db"], "__test_a": ["db1", "db2"]})
def get_user_from_request(request, username=None): """ Return the User object for the request. Return ``None`` if: * user is anonymous * it does not exist in the database * the referer is invalid """ from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User try: if "auth" in request.params: auth_enc = request.params.get("auth") if auth_enc is not None: urllogin = request.registry.settings.get("urllogin", {}) aeskey = urllogin.get("aes_key") if aeskey is None: # pragma: nocover raise Exception("urllogin is not configured") now = int(time.time()) cipher = AES.new(aeskey) auth = json.loads(cipher.decrypt(binascii.unhexlify(auth_enc))) if "t" in auth and "u" in auth and "p" in auth: timestamp = int(auth["t"]) if now < timestamp and request.registry.validate_user( request, auth["u"], auth["p"] ): headers = pyramid.security.remember(request, auth["u"]) request.response.headerlist.extend(headers) except Exception as e: log.error("URL login error: {}".format(e)) if not hasattr(request, "is_valid_referer"): request.is_valid_referer = is_valid_referer(request, settings) if not request.is_valid_referer: log.warning( "Invalid referer for %s: %s", request.path_qs, repr(request.referer) ) return None if not hasattr(request, "user_"): request.user_ = None if username is None: username = request.authenticated_userid if username is not None: # We know we will need the role object of the # user so we use joined loading request.user_ = DBSession.query(User) \ .filter_by(username=username) \ .first() return request.user_
def _import(object_type, messages, callback=None): from c2cgeoportal_commons.models import DBSession items = DBSession.query(object_type) for item in items: messages.append(Message( None, item.name, None, [], "", "", (item.item_type, item.name.encode("ascii", errors="replace")) )) if callback is not None: callback(item, messages)
def __set__(self, obj, val): from c2cgeoportal_commons.models import DBSession o = getattr(obj, self.target) # if the obj as no child object or if the child object # does not correspond to the new value then we need to # read a new child object from the database if not o or getattr(o, self.value_attr) != val: relationship_property = class_mapper(obj.__class__) \ .get_property(self.target) child_cls = relationship_property.argument o = DBSession.query(child_cls).filter( getattr(child_cls, self.value_attr) == val).first() setattr(obj, self.target, o)
def __call__(self, filename, options): messages = [] try: self.env = bootstrap(filename) try: from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Theme, LayerGroup, \ LayerWMS, LayerWMTS, FullTextSearch self._import(Theme, messages) self._import(LayerGroup, messages) self._import(LayerWMS, messages, self._import_layer_wms) self._import(LayerWMTS, messages, self._import_layer_wmts) for ln, in DBSession.query(FullTextSearch.layer_name).distinct().all(): if ln is not None and ln != "": messages.append(Message( None, ln, None, [], "", "", ("fts", ln.encode("ascii", errors="replace")) )) except ProgrammingError as e: print(colorize( "ERROR! The database is probably not up to date " "(should be ignored when happen during the upgrade)", RED )) print(colorize(e, RED)) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise except NoSuchTableError as e: print(colorize( "ERROR! The schema didn't seem to exists " "(should be ignored when happen during the deploy)", RED )) print(colorize(e, RED)) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise except OperationalError as e: print(colorize( "ERROR! The database didn't seem to exists " "(should be ignored when happen during the deploy)", RED )) print(colorize(e, RED)) if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": raise return messages
def get(self): ref = self.request.matchdict["ref"] short_urls = DBSession.query(Shorturl).filter(Shorturl.ref == ref).all() if len(short_urls) != 1: raise HTTPNotFound("Ref '{0!s}' not found".format(ref)) short_urls[0].nb_hits += 1 short_urls[0].last_hit = datetime.now() set_common_headers( self.request, "shortener", NO_CACHE ) return HTTPFound(location=short_urls[0].url)
def clean(): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User from c2cgeoportal_commons.models.main import TreeItem, Interface, Role, RestrictionArea, OGCServer for o in DBSession.query(RestrictionArea).all(): o.roles = [] o.layers = [] DBSession.delete(o) for item in DBSession.query(TreeItem).all(): DBSession.delete(item) DBSession.query(OGCServer).delete() DBSession.query(Interface).filter( Interface.name == "main" ).delete() DBSession.query(User).filter( User.username == "__test_user" ).delete() DBSession.query(Role).filter( Role.name == "__test_role" ).delete() transaction.commit()
def difference(self): body = loads(self.request.body) if "geometries" not in body or \ not isinstance(body["geometries"], list) or \ len(body["geometries"]) != 2: # pragma: no cover raise HTTPBadRequest("""Wrong body, it should be like that: { "geometries": [geomA, geomB] } """) return to_shape(DBSession.query(func.ST_Difference( from_shape(asShape(body["geometries"][0])), from_shape(asShape(body["geometries"][1])) )).scalar())
def check(request): url = request.route_url("themes") session = requests.session() for interface, in DBSession.query(Interface.name).all(): params = {} params.update(default_params) params.update(interfaces_settings.get(interface, {}).get("params", {})) params["interface"] = interface interface_url_headers = build_url("checker_themes " + interface, url, request) response = session.get(params=params, **interface_url_headers) response.raise_for_status() result = response.json() if len(result["errors"]) != 0: raise Exception("Interface '{}': Theme with error\n{}".format( interface, "\n".join(result["errors"])))
def _create_dummy_request(username=None, params=None): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.static import User request = create_dummy_request({ "fulltextsearch": { "languages": { "fr": "french", "en": "english", "de": "german", } } }, params=params) request.response = Response() request.user = None if username: request.user = DBSession.query(User) \ .filter_by(username=username).one() return request
def get_ogc_server_wfs_url_ids(request): from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import OGCServer from c2cgeoportal_geoportal.lib.cacheversion import VersionCache global ogc_server_wfs_url_ids if ogc_server_wfs_url_ids is None: ogc_server_wfs_url_ids = VersionCache() errors = set() servers = ogc_server_wfs_url_ids.get() if servers is None: servers = dict() ogc_server_wfs_url_ids.set(servers) for ogc_server in DBSession.query(OGCServer).all(): url = get_url2(ogc_server.name, ogc_server.url_wfs or ogc_server.url, request, errors) if servers.get(url) is None: servers[url] = [] servers.get(url).append(ogc_server.id) return servers
def setup_method(self, _): # Always see the diff # https://docs.python.org/2/library/unittest.html#unittest.TestCase.maxDiff self.maxDiff = None cleanup_db() self._tables = [] import transaction from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Role, Interface, TreeItem, Theme, \ LayerGroup, OGCSERVER_AUTH_NOAUTH from c2cgeoportal_commons.models.static import User for treeitem in DBSession.query(TreeItem).all(): DBSession.delete(treeitem) self.role = Role(name="__test_role") self.user = User( username="******", password="******", role=self.role ) self.main = Interface(name="main") self.ogc_server, external_ogc_server = create_default_ogcserver() self.ogc_server.auth = OGCSERVER_AUTH_NOAUTH external_ogc_server.auth = OGCSERVER_AUTH_NOAUTH self.metadata = None self.layer_ids = [] self.layer_group_1 = LayerGroup(name="__test_layer_group_1") theme = Theme(name="__test_theme") theme.interfaces = [self.main] theme.children = [self.layer_group_1] DBSession.add_all([self.main, self.user, self.role, theme, self.layer_group_1]) transaction.commit()
def teardown_method(self, _): testing.tearDown() from c2cgeoportal_commons.models import DBSession from c2cgeoportal_commons.models.main import Layer, Theme, LayerGroup, OGCServer, Interface for layer in DBSession.query(Layer).all(): DBSession.delete(layer) for g in DBSession.query(LayerGroup).all(): DBSession.delete(g) for t in DBSession.query(Theme).all(): DBSession.delete(t) DBSession.query(OGCServer).delete() DBSession.query(Interface).filter( Interface.name == "main" ).delete() transaction.commit()
def xsd_sequence_callback(tb, cls): from c2cgeoportal_commons.models import DBSession for k, p in cls.__dict__.items(): if not isinstance(p, _AssociationProxy): continue relationship_property = class_mapper(cls) \ .get_property(p.target) target_cls = relationship_property.argument query = DBSession.query(getattr(target_cls, p.value_attr)) attrs = {} attrs["minOccurs"] = "0" attrs["nillable"] = "true" attrs["name"] = k with tag(tb, "xsd:element", attrs) as tb: with tag(tb, "xsd:simpleType") as tb: with tag(tb, "xsd:restriction", {"base": "xsd:string"}) as tb: for value, in query: with tag(tb, "xsd:enumeration", {"value": value}): pass
def fulltextsearch(self): lang = locale_negotiator(self.request) try: language = self.languages[lang] except KeyError: return HTTPInternalServerError( detail="{0!s} not defined in languages".format(lang)) if "query" not in self.request.params: return HTTPBadRequest(detail="no query") terms = self.request.params.get("query") maxlimit = self.settings.get("maxlimit", 200) try: limit = int(self.request.params.get( "limit", self.settings.get("defaultlimit", 30))) except ValueError: return HTTPBadRequest(detail="limit value is incorrect") if limit > maxlimit: limit = maxlimit try: partitionlimit = int(self.request.params.get("partitionlimit", 0)) except ValueError: return HTTPBadRequest(detail="partitionlimit value is incorrect") if partitionlimit > maxlimit: partitionlimit = maxlimit terms_ts = "&".join(w + ":*" for w in IGNORED_CHARS_RE.sub(" ", terms).split(" ") if w != "") _filter = FullTextSearch.ts.op("@@")(func.to_tsquery(language, terms_ts)) if self.request.user is None or self.request.user.role is None: _filter = and_(_filter, FullTextSearch.public.is_(True)) else: _filter = and_( _filter, or_( FullTextSearch.public.is_(True), FullTextSearch.role_id.is_(None), FullTextSearch.role_id == self.request.user.role.id ) ) if "interface" in self.request.params: _filter = and_(_filter, or_( FullTextSearch.interface_id.is_(None), FullTextSearch.interface_id == self._get_interface_id( self.request.params["interface"] ) )) else: _filter = and_(_filter, FullTextSearch.interface_id.is_(None)) _filter = and_(_filter, or_( FullTextSearch.lang.is_(None), FullTextSearch.lang == lang, )) # The numbers used in ts_rank_cd() below indicate a normalization method. # Several normalization methods can be combined using |. # 2 divides the rank by the document length # 8 divides the rank by the number of unique words in document # By combining them, shorter results seem to be preferred over longer ones # with the same ratio of matching words. But this relies only on testing it # and on some assumptions about how it might be calculated # (the normalization is applied two times with the combination of 2 and 8, # so the effect on at least the one-word-results is therefore stronger). rank = func.ts_rank_cd(FullTextSearch.ts, func.to_tsquery(language, terms_ts), 2 | 8) if partitionlimit: # Here we want to partition the search results based on # layer_name and limit each partition. row_number = func.row_number().over( partition_by=FullTextSearch.layer_name, order_by=(desc(rank), FullTextSearch.label) ).label("row_number") subq = DBSession.query(FullTextSearch) \ .add_columns(row_number).filter(_filter).subquery() query = DBSession.query( subq.c.id, subq.c.label, subq.c.params, subq.c.layer_name, subq.c.the_geom, subq.c.actions ) query = query.filter(subq.c.row_number <= partitionlimit) else: query = DBSession.query(FullTextSearch).filter(_filter) query = query.order_by(desc(rank)) query = query.order_by(FullTextSearch.label) query = query.limit(limit) objs = query.all() features = [] for o in objs: properties = { "label": o.label, } if o.layer_name is not None: properties["layer_name"] = o.layer_name if o.params is not None: properties["params"] = o.params if o.actions is not None: properties["actions"] = o.actions if o.actions is None and o.layer_name is not None: properties["actions"] = [{ "action": "add_layer", "data": o.layer_name, }] if o.the_geom is not None: geom = to_shape(o.the_geom) feature = Feature( id=o.id, geometry=geom, properties=properties, bbox=geom.bounds ) features.append(feature) else: feature = Feature( id=o.id, properties=properties ) features.append(feature) # TODO: add callback function if provided in self.request, else return geojson return FeatureCollection(features)