Esempio n. 1
0
def validate_user(a_tuple: UserBasedTuple, user_service: UserService,
                  principal_service: PrincipalService) -> None:
    if not principal_service.is_admin():
        raise_403()

    if is_blank(a_tuple.userId):
        if principal_service.is_super_admin():
            raise_400('User id is required.')
        elif principal_service.is_tenant_admin():
            a_tuple.userId = principal_service.get_user_id()
        else:
            raise_403()
    else:
        if a_tuple.userId == principal_service.get_user_id():
            if principal_service.is_super_admin():
                raise_400(f'Incorrect user id[{a_tuple.userId}].')
        else:
            user: Optional[User] = user_service.find_by_id(a_tuple.userId)
            if user is None:
                raise_400('User id is required.')
            if principal_service.is_super_admin():
                if user.tenantId == principal_service.get_tenant_id():
                    raise_400(f'Incorrect user id[{a_tuple.userId}].')
            elif principal_service.is_tenant_admin():
                if user.tenantId != principal_service.get_tenant_id():
                    raise_400(f'Incorrect user id[{a_tuple.userId}].')
Esempio n. 2
0
def try_to_lock_scheduler(
    scheduler: TopicSnapshotScheduler, process_date: date,
    principal_service: PrincipalService
) -> Tuple[Optional[TopicSnapshotJobLock], bool]:
    if isinstance(process_date, datetime):
        process_date = process_date.date()

    lock_service = get_lock_service(principal_service)
    lock_service.begin_transaction()
    # noinspection PyBroadException
    try:
        lock = TopicSnapshotJobLock(
            tenantId=principal_service.get_tenant_id(),
            schedulerId=scheduler.schedulerId,
            frequency=scheduler.frequency,
            processDate=process_date,
            rowCount=0,
            status=TopicSnapshotJobLockStatus.READY,
            userId=principal_service.get_user_id(),
        )
        lock_service.create(lock)
        lock_service.commit_transaction()
        return lock, True
    except Exception:
        lock_service.rollback_transaction()
        return None, False
def try_to_lock_topic_for_monitor(
    topic: Topic, frequency: MonitorRuleStatisticalInterval,
    process_date: date, principal_service: PrincipalService
) -> Tuple[Optional[MonitorJobLock], bool]:
    if isinstance(process_date, datetime):
        process_date = process_date.date()

    lock_service = get_lock_service(principal_service)
    lock_service.begin_transaction()
    try:
        lock = MonitorJobLock(
            # lockId: MonitorJobLockId = None
            tenantId=principal_service.get_tenant_id(),
            topicId=topic.topicId,
            frequency=frequency,
            processDate=process_date,
            status=MonitorJobLockStatus.READY,
            userId=principal_service.get_user_id(),
        )
        lock_service.create(lock)
        lock_service.commit_transaction()
        return lock, True
    except Exception:
        lock_service.rollback_transaction()
        return None, False
def prepare_and_validate_request(
		request: MixImportDataRequest,
		user_service: UserService, principal_service: PrincipalService) -> None:
	tenant_id = validate_tenant_id(request, user_service, principal_service)
	clear_data_source_id(request.topics)
	clear_user_group_ids(request.spaces)

	def set_user_id_to_report(report: Report, user_id: UserId) -> None:
		report.userId = user_id

	def set_user_id_to_subject(subject: SubjectWithReports, user_id: UserId) -> None:
		subject.userId = user_id
		ArrayHelper(subject.reports) \
			.flatten() \
			.filter(lambda x: x is not None) \
			.each(lambda x: set_user_id_to_report(x, user_id))

	def set_user_id_to_connected_space(connected_space: ConnectedSpaceWithSubjects, user_id: UserId) -> None:
		connected_space.userId = user_id
		ArrayHelper(connected_space.subjects) \
			.flatten() \
			.filter(lambda x: x is not None) \
			.each(lambda x: set_user_id_to_subject(x, user_id))

	if principal_service.is_super_admin():
		# to find a tenant admin
		tenant_admin: Optional[User] = user_service.find_admin(tenant_id)
		if tenant_admin is None:
			raise_400(f'Admin user on tenant[{tenant_id}] to receive imported data is not found.')
	elif principal_service.is_tenant_admin():
		ArrayHelper(request.connectedSpaces).each(
			lambda x: set_user_id_to_connected_space(x, principal_service.get_user_id()))
	else:
		raise_403()
Esempio n. 5
0
async def load_user_by_id(
    user_id: Optional[UserId] = None,
    principal_service: PrincipalService = Depends(get_any_principal)
) -> User:
    if is_blank(user_id):
        raise_400('User id is required.')
    if not principal_service.is_admin():
        # console user cannot visit other users
        if user_id != principal_service.get_user_id():
            raise_403()

    user_service = get_user_service(principal_service)

    def action() -> User:
        # noinspection PyTypeChecker
        user: User = user_service.find_by_id(user_id)
        if user is None:
            raise_404()
        # check tenant id
        if not principal_service.is_super_admin():
            # tenant id must match current principal's, except current is super admin
            if user.tenantId != principal_service.get_tenant_id():
                raise_404()
        # remove password
        clear_pwd(user)
        return user

    return trans_readonly(user_service, action)
Esempio n. 6
0
def validate_reports(
		dashboard: Dashboard, dashboard_service: DashboardService, principal_service: PrincipalService) -> None:
	reports = dashboard.reports
	if reports is None:
		dashboard.reports = []
		return
	if len(reports) == 0:
		return

	report_ids = ArrayHelper(reports).map(lambda x: x.reportId).distinct().to_list()
	if len(report_ids) == 0:
		dashboard.reports = []
		return

	report_service = get_report_service(dashboard_service)

	for report_id in report_ids:
		existing_one = report_service.find_tenant_and_user(report_id)
		if existing_one is None:
			raise_400('Report ids do not match.')
		existing_tenant_id, existing_user_id = existing_one
		if existing_tenant_id != principal_service.get_tenant_id():
			raise_403()
		if existing_user_id != principal_service.get_user_id():
			raise_403()
def fake_to_tenant(principal_service: PrincipalService,
                   tenant_id: TenantId) -> PrincipalService:
    if principal_service.is_super_admin():
        # fake principal as tenant admin
        return PrincipalService(
            User(userId=principal_service.get_user_id(),
                 tenantId=tenant_id,
                 name=principal_service.get_user_name(),
                 role=UserRole.ADMIN))
    else:
        return principal_service
Esempio n. 8
0
def filter_indicators(
		indicators: List[Indicator], indicator_service: IndicatorService,
		principal_service: PrincipalService
) -> List[Indicator]:
	if principal_service.is_admin():
		return indicators

	user_id = principal_service.get_user_id()
	user_service = get_user_service(indicator_service)
	user: Optional[User] = user_service.find_by_id(user_id)
	if user is None:
		raise_403()
	group_ids = user.groupIds
	return ArrayHelper(indicators).filter(lambda x: ArrayHelper(x.groupIds).some(lambda y: y in group_ids)).to_list()
def do_load_inspection_by_id(
        inspection_id: InspectionId, inspection_service: InspectionService,
        principal_service: PrincipalService) -> Inspection:
    # noinspection PyTypeChecker
    inspection: Inspection = inspection_service.find_by_id(inspection_id)
    if inspection is None:
        raise_404()
    # user id must match current principal's
    if inspection.userId != principal_service.get_user_id():
        raise_404()
    # tenant id must match current principal's
    if inspection.tenantId != principal_service.get_tenant_id():
        raise_404()
    return inspection
Esempio n. 10
0
async def exchange_user(principal_service: PrincipalService = Depends(get_any_principal)) -> Optional[User]:
	"""
	returns current principal
	"""
	user_id = principal_service.get_user_id()
	user_service = UserService(ask_meta_storage(), ask_snowflake_generator(), principal_service)
	user_service.begin_transaction()
	try:
		# noinspection PyTypeChecker
		user: User = user_service.find_by_id(user_id)
		if user is None:
			return None
		else:
			del user.password
			return user
	finally:
		user_service.close_transaction()
Esempio n. 11
0
def ask_principal_service(principal_service: PrincipalService,
                          tenant_id: Optional[TenantId]) -> PrincipalService:
    if principal_service.is_tenant_admin():
        if is_blank(tenant_id):
            return principal_service
        elif tenant_id != principal_service.get_tenant_id():
            raise_400(
                f'Tenant id[{tenant_id}] does not match current principal.')
        else:
            return principal_service
    elif principal_service.is_super_admin():
        if is_blank(tenant_id):
            raise_400('Tenant id is required.')
        tenant_service = get_tenant_service(principal_service)
        tenant: Optional[Tenant] = tenant_service.find_by_id(tenant_id)
        if tenant is None:
            raise_404(f'Tenant[id={tenant_id}] not found.')
        return PrincipalService(
            User(tenantId=tenant_id,
                 userId=principal_service.get_user_id(),
                 name=principal_service.get_user_name(),
                 role=UserRole.ADMIN))
Esempio n. 12
0
async def fetch_pipeline_logs(
		criteria: PipelineMonitorLogCriteria, principal_service: PrincipalService = Depends(get_any_admin_principal)
) -> PipelineMonitorLogDataPage:
	if principal_service.is_super_admin():
		if is_blank(criteria.tenantId):
			raise_400('Tenant id is required.')
		# fake principal as tenant admin
		principal_service = PrincipalService(User(
			userId=principal_service.get_user_id(), tenantId=criteria.tenantId,
			name=principal_service.get_user_name(), role=UserRole.ADMIN))
	else:
		criteria.tenantId = principal_service.get_tenant_id()

	page = PipelineMonitorLogDataService(principal_service).page(criteria)

	# translate dataId to string
	def translate_data_id_to_str(log: PipelineMonitorLog) -> None:
		log.dataId = str(log.dataId)

	page.data = ArrayHelper(page.data).each(translate_data_id_to_str).to_list()
	# noinspection PyTypeChecker
	return page
Esempio n. 13
0
def load_standalone_dashboard(
		admin_dashboard_id: Optional[DashboardId],
		dashboard_service: DashboardService, principal_service: PrincipalService
) -> StandaloneDashboard:
	if is_blank(admin_dashboard_id):
		return as_empty_dashboard()
	dashboard: Optional[Dashboard] = dashboard_service.find_by_id(admin_dashboard_id)
	if dashboard is None:
		return as_empty_dashboard()
	if dashboard.tenantId != principal_service.get_tenant_id() or dashboard.userId != principal_service.get_user_id():
		raise_403()
	report_ids = ArrayHelper(dashboard.reports).map(lambda x: x.reportId).to_list()
	if len(report_ids) == 0:
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))
	report_service = get_report_service(dashboard_service)
	reports: List[Report] = ArrayHelper(report_ids).map(lambda x: report_service.find_by_id(x)).to_list()
	if len(reports) == 0:
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))
	if ArrayHelper(reports).some(
			lambda x: x.tenantId != principal_service.get_tenant_id() and x.userId != principal_service.get_user_id()):
		# something wrong with data
		logger.error(f'Something wrong with report data for dashboard[{dashboard.dashboardId}]')
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))
	report_map: Dict[SubjectId, List[Report]] = ArrayHelper(reports).group_by(lambda x: x.subjectId)
	subject_ids = ArrayHelper(reports).map(lambda x: x.subjectId).distinct().to_list()
	subject_service = get_subject_service(dashboard_service)
	subjects = ArrayHelper(subject_ids).map(lambda x: subject_service.find_by_id(x)).to_list()
	if len(subjects) == 0:
		logger.error(f'Subject data not found for dashboard[{dashboard.dashboardId}]')
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))
	if ArrayHelper(subjects).some(
			lambda x: x.tenantId != principal_service.get_tenant_id() and x.userId != principal_service.get_user_id()):
		# something wrong with data
		logger.error(f'Something wrong with subject data for dashboard[{dashboard.dashboardId}]')
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))

	def get_my_reports(subject_id: SubjectId) -> List[Report]:
		my_reports = report_map.get(subject_id)
		return [] if my_reports is None else my_reports

	subject_map: Dict[ConnectedSpaceId, List[SubjectWithReports]] = ArrayHelper(subjects) \
		.map(lambda x: SubjectWithReports(**x.dict(), reports=get_my_reports(x.subjectId))) \
		.filter(lambda x: x.reports is not None and len(x.reports) != 0) \
		.group_by(lambda x: x.connectId)
	connect_ids = ArrayHelper(subjects).map(lambda x: x.connectId).distinct().to_list()
	connected_space_service = get_connected_space_service(dashboard_service)
	connected_spaces = ArrayHelper(connect_ids).map(lambda x: connected_space_service.find_by_id(x)).to_list()
	if len(connected_spaces) == 0:
		logger.error(f'Connected space data not found for dashboard[{dashboard.dashboardId}]')
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))
	if ArrayHelper(connected_spaces).some(
			lambda x: x.tenantId != principal_service.get_tenant_id() and x.userId != principal_service.get_user_id()):
		# something wrong with data
		logger.error(f'Something wrong with connected space data for dashboard[{dashboard.dashboardId}]')
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))

	def get_my_subjects(connect_id: ConnectedSpaceId) -> List[SubjectWithReports]:
		my_subjects = subject_map.get(connect_id)
		return [] if my_subjects is None else my_subjects

	connected_spaces_with_subjects = ArrayHelper(connected_spaces) \
		.map(lambda x: ConnectedSpaceWithSubjects(**x.dict(), subjects=get_my_subjects(x.connectId))) \
		.filter(lambda x: x.subjects is not None and len(x.subjects) != 0) \
		.to_list()
	if len(connected_spaces_with_subjects) == 0:
		# something wrong with data
		logger.error(f'Something wrong with connected space data for dashboard[{dashboard.dashboardId}]')
		return as_empty_dashboard(dashboard=Dashboard(**dashboard.dict(), reports=[]))

	# get available reports
	available_report_map = ArrayHelper(reports).to_map(lambda x: x.reportId, lambda x: x)

	return StandaloneDashboard(
		dashboard=Dashboard(
			# **dashboard.dict(),
			dashboardId=dashboard.dashboardId,
			name=dashboard.name,
			paragraphs=dashboard.paragraphs,
			autoRefreshInterval=dashboard.autoRefreshInterval,
			# remove useless report data from dashboard
			reports=ArrayHelper(dashboard.reports).filter(
				lambda x: available_report_map[x.reportId] is not None).to_list()
		),
		connected_spaces=connected_spaces_with_subjects
	)