def getProductConfiguration(self, product_id): """ Get the product configuration --- WITHOUT THE DB PASSWORD --- of the given product. """ with DBSession(self.__session) as session: product = session.query(Product).get(product_id) if product is None: msg = "Product with ID {0} does not exist!".format(product_id) LOG.error(msg) raise codechecker_api_shared.ttypes.RequestFailed( codechecker_api_shared.ttypes.ErrorCode.DATABASE, msg) # Put together the database connection's descriptor. args = SQLServer.connection_string_to_args(product.connection) if args['postgresql']: db_engine = 'postgresql' db_host = args['dbaddress'] db_port = args['dbport'] db_user = args['dbusername'] db_name = args['dbname'] else: db_engine = 'sqlite' db_host = "" db_port = 0 db_user = "" db_name = args['sqlite'] dbc = ttypes.DatabaseConnection( engine=db_engine, host=db_host, port=db_port, username_b64=convert.to_b64(db_user), # DO NOT TRANSPORT PASSWORD BACK TO THE USER! database=db_name) # Put together the product configuration. descr = convert.to_b64(product.description) \ if product.description else None is_review_status_change_disabled = \ product.is_review_status_change_disabled prod = ttypes.ProductConfiguration( id=product.id, endpoint=product.endpoint, displayedName_b64=convert.to_b64(product.display_name), description_b64=descr, connection=dbc, runLimit=product.run_limit, isReviewStatusChangeDisabled=is_review_status_change_disabled) return prod
def __get_product(self, session, product): """ Retrieve the product connection object and create a Thrift Product object for the given product record in the database. """ server_product = self.__server.get_product(product.endpoint) if not server_product: LOG.info( "Product '%s' was found in the configuration " "database but no database connection was " "present. Mounting analysis run database...", product.endpoint) self.__server.add_product(product) server_product = self.__server.get_product(product.endpoint) descr = convert.to_b64(product.description) \ if product.description else None args = {'config_db_session': session, 'productID': product.id} product_access = permissions.require_permission( permissions.PRODUCT_VIEW, args, self.__auth_session) admin_perm_name = permissions.PRODUCT_ADMIN.name admins = session.query(ProductPermission). \ filter(and_(ProductPermission.permission == admin_perm_name, ProductPermission.product_id == product.id)) \ .all() connected = server_product.db_status ==\ codechecker_api_shared.ttypes.DBStatus.OK latest_storage_date = str(product.latest_storage_date) \ if product.latest_storage_date else None if product.confidentiality is None: confidentiality = ttypes.Confidentiality.CONFIDENTIAL else: confidentiality = \ confidentiality_enum(product.confidentiality) return server_product, ttypes.Product( id=product.id, endpoint=product.endpoint, displayedName_b64=convert.to_b64(product.display_name), description_b64=descr, runCount=product.num_of_runs, latestStoreToProduct=latest_storage_date, connected=connected, accessible=product_access, administrating=self.__administrating(args), databaseStatus=server_product.db_status, admins=[admin.name for admin in admins], confidentiality=confidentiality)
def handle_add_product(args): init_logger(args.verbose if 'verbose' in args else None) protocol, host, port = split_server_url(args.server_url) client = setup_product_client(protocol, host, port) # Put together the database connection's descriptor. if 'postgresql' in args: db_engine = 'postgresql' db_host = args.dbaddress db_port = args.dbport db_user = args.dbusername db_pass = args.dbpassword db_name = args.dbname else: db_engine = 'sqlite' db_host = "" db_port = 0 db_user = "" db_pass = "" db_name = args.sqlite dbc = DatabaseConnection( engine=db_engine, host=db_host, port=db_port, username_b64=convert.to_b64(db_user), password_b64=convert.to_b64(db_pass), database=db_name) # Put together the product configuration. name = convert.to_b64(args.display_name) \ if 'display_name' in args else None desc = convert.to_b64(args.description) \ if 'description' in args else None prod = ProductConfiguration( endpoint=args.endpoint, displayedName_b64=name, description_b64=desc, connection=dbc) LOG.debug("Sending request to add product...") success = client.addProduct(prod) if success: LOG.info("Product added successfully.") else: LOG.error("Adding the product has failed.") sys.exit(1)
def test_auth_su_notification_edit(self): """ Test that SUPERADMINS can edit the notification text. """ # Create a SUPERUSER login. self.sessionToken = self.auth_client.performLogin( "Username:Password", "root:root") ret = self.auth_client.addPermission(Permission.SUPERUSER, "root", False, "") self.assertTrue(ret) # we got the permission su_auth_client = \ env.setup_auth_client(self._test_workspace, session_token=self.sessionToken) su_config_client = \ env.setup_config_client(self._test_workspace, session_token=self.sessionToken) user = su_auth_client.getLoggedInUser() self.assertEqual(user, "root") # we are root su_config_client.setNotificationBannerText( convert.to_b64('su notification')) self.assertEqual( convert.from_b64(su_config_client.getNotificationBannerText()), 'su notification')
def create_test_product(product_name, product_endpoint): # Create a new product on the secondary server. name = convert.to_b64(product_name) return ProductConfiguration(endpoint=product_endpoint, displayedName_b64=name, description_b64=name, connection=DatabaseConnection( engine='sqlite', host='', port=0, username_b64='', password_b64='', database=os.path.join( self.test_workspace_secondary, 'data.sqlite')))
def test_noauth_notification_edit(self): """ Test for editing the notification text on a non authenting server. """ # A non-authenticated session should return an empty user. user = self.auth_client.getLoggedInUser() self.assertEqual(user, "") # Server without authentication should allow notification setting. self.config_client.setNotificationBannerText( convert.to_b64('noAuth notif')) self.assertEqual( convert.from_b64(self.config_client.getNotificationBannerText()), 'noAuth notif')
def getNotificationBannerText(self): """ Retrieves the notification banner text. """ notificationString = '' with DBSession(self.__session) as session: notificationQuery = session.query(Configuration) \ .filter( Configuration.config_key == 'notification_banner_text') \ .one_or_none() if notificationQuery is not None: notificationString = notificationQuery.config_value return convert.to_b64(notificationString)
def test_unicode_string(self): """ Test for non ascii strings. Needed because the used Thrift version won't eat them. """ # A non-authenticated session should return an empty user. user = self.auth_client.getLoggedInUser() self.assertEqual(user, "") # Check if utf-8 encoded strings are okay. self.config_client.setNotificationBannerText( convert.to_b64('árvíztűrő tükörfúrógép')) self.assertEqual( convert.from_b64(self.config_client.getNotificationBannerText()), 'árvíztűrő tükörfúrógép')
def test_auth_non_su_notification_edit(self): """ Test that non SUPERADMINS can't edit the notification text. """ self.sessionToken = self.auth_client.performLogin( "Username:Password", "cc:test") authd_auth_client = \ env.setup_auth_client(self._test_workspace, session_token=self.sessionToken) authd_config_client = \ env.setup_config_client(self._test_workspace, session_token=self.sessionToken) user = authd_auth_client.getLoggedInUser() self.assertEqual(user, "cc") with self.assertRaises(RequestFailed): authd_config_client.setNotificationBannerText( convert.to_b64('non su notification')) print("You are not authorized to modify notifications!")
def test_editing(self): """ Test editing the product details (without reconnecting it). """ pr_client = env.setup_product_client(self.test_workspace, product=self.product_name) product_id = pr_client.getCurrentProduct().id config = self._pr_client.getProductConfiguration(product_id) old_name = config.displayedName_b64 new_name = convert.to_b64("edited product name") config.displayedName_b64 = new_name with self.assertRaises(RequestFailed): self._pr_client.editProduct(product_id, config) print("Product was edited through non-superuser!") self.assertTrue(self._root_client.editProduct(product_id, config), "Product edit didn't conclude.") config = self._pr_client.getProductConfiguration(product_id) self.assertEqual( config.endpoint, self.product_name, "The product edit changed the endpoint, when it " "shouldn't have!") self.assertEqual(config.displayedName_b64, new_name, "The product edit didn't change the name.") # Restore the configuration of the product. config.displayedName_b64 = old_name self.assertTrue(self._root_client.editProduct(product_id, config), "Product config restore didn't conclude.") config = self._pr_client.getProductConfiguration(product_id) self.assertEqual(config.displayedName_b64, old_name, "The product edit didn't change the name back.")
def test_add_invalid_product(self): """ Test the server prohibiting the addition of bogus product configs. """ error = convert.to_b64("bogus") product_cfg = ProductConfiguration(displayedName_b64=error, description_b64=error) # Test setting up product with valid endpoint but no database # connection. with self.assertRaises(RequestFailed): cfg = deepcopy(product_cfg) cfg.endpoint = "valid" self._root_client.addProduct(cfg) # Test some invalid strings based on pattern. dbc = DatabaseConnection(engine='sqlite', host='', port=0, username_b64='', password_b64='', database="valid.sqlite") product_cfg.connection = dbc with self.assertRaises(RequestFailed): product_cfg.endpoint = "$$$$$$$" self._root_client.addProduct(product_cfg) # Test some forbidden URI parts. with self.assertRaises(RequestFailed): product_cfg.endpoint = "index.html" self._root_client.addProduct(product_cfg) with self.assertRaises(RequestFailed): product_cfg.endpoint = "CodeCheckerService" self._root_client.addProduct(product_cfg)
def __get_product(self, session, product): """ Retrieve the product connection object and create a Thrift Product object for the given product record in the database. """ server_product = self.__server.get_product(product.endpoint) if not server_product: LOG.info( "Product '%s' was found in the configuration " "database but no database connection was " "present. Mounting analysis run database...", product.endpoint) self.__server.add_product(product) server_product = self.__server.get_product(product.endpoint) num_of_runs = 0 runs_in_progress = set() latest_store_to_product = "" # Try to get product details. It may throw different error messages # depending on the used SQL driver adapter in case of connection error, # so we should try to connect to the database and get the results # again on failure. try: num_of_runs, runs_in_progress, latest_store_to_product = \ server_product.get_details() except Exception: # Try to connect to the product and try to get details again. server_product.connect() if server_product.db_status ==\ codechecker_api_shared.ttypes.DBStatus.OK: num_of_runs, runs_in_progress, latest_store_to_product = \ server_product.get_details() descr = convert.to_b64(product.description) \ if product.description else None args = {'config_db_session': session, 'productID': product.id} product_access = permissions.require_permission( permissions.PRODUCT_ACCESS, args, self.__auth_session) product_admin = permissions.require_permission( permissions.PRODUCT_ADMIN, args, self.__auth_session) admin_perm_name = permissions.PRODUCT_ADMIN.name admins = session.query(ProductPermission). \ filter(and_(ProductPermission.permission == admin_perm_name, ProductPermission.product_id == product.id)) \ .all() connected = server_product.db_status ==\ codechecker_api_shared.ttypes.DBStatus.OK return server_product, ttypes.Product( id=product.id, endpoint=product.endpoint, displayedName_b64=convert.to_b64(product.display_name), description_b64=descr, runCount=num_of_runs, latestStoreToProduct=str(latest_store_to_product), connected=connected, accessible=product_access, administrating=product_admin, databaseStatus=server_product.db_status, admins=[admin.name for admin in admins], runStoreInProgress=runs_in_progress)