コード例 #1
0
def info(query_id, collection_name):
    def groups_permission(group_id):
        coll_id = Group.query.get(group_id).collaboration_id
        return confirm_group_member(group_id) or is_current_user_collaboration_admin(
            coll_id) or is_current_user_organisation_admin_or_manager(coll_id)

    def collaboration_permission(collaboration_id):
        return is_current_user_collaboration_admin(collaboration_id) or is_current_user_organisation_admin_or_manager(
            collaboration_id)

    override_func = collaboration_permission if collection_name == "collaborations" \
        else groups_permission if collection_name == "groups" \
        else is_organisation_admin_or_manager if collection_name == "organisations" else None
    confirm_read_access(query_id, override_func=override_func)

    audit_logs = AuditLog.query \
        .filter(or_(and_(AuditLog.parent_id == query_id, AuditLog.parent_name == collection_name),
                    and_(AuditLog.target_id == query_id, AuditLog.target_type == collection_name))) \
        .order_by(desc(AuditLog.created_at)) \
        .limit(150) \
        .all()

    res = _add_references(audit_logs)

    return res, 200
コード例 #2
0
ファイル: service.py プロジェクト: SURFscz/SBS
def service_by_id(service_id):
    confirm_read_access(service_id, override_func=user_service)

    query = Service.query \
        .options(selectinload(Service.service_memberships).selectinload(ServiceMembership.user))

    api_call = request_context.is_authorized_api_call
    add_admin_info = not api_call and (is_application_admin() or is_service_admin(service_id))
    if add_admin_info:
        query = query \
            .options(selectinload(Service.collaborations).selectinload(Collaboration.organisation)) \
            .options(selectinload(Service.service_memberships).selectinload(ServiceMembership.user)) \
            .options(selectinload(Service.organisations)) \
            .options(selectinload(Service.service_invitations)) \
            .options(selectinload(Service.allowed_organisations)) \
            .options(selectinload(Service.ip_networks)) \
            .options(selectinload(Service.service_groups))
        service = query.filter(Service.id == service_id).one()
        res = jsonify(service).json
        res["service_organisation_collaborations"] = []
        # To prevent circular references value error
        if len(res["organisations"]) > 0:
            collaborations = Collaboration.query \
                .options(selectinload(Collaboration.organisation)) \
                .join(Collaboration.organisation) \
                .join(Organisation.services) \
                .filter(Service.id == service_id) \
                .all()
            res["service_organisation_collaborations"] = jsonify(collaborations).json
        return res, 200
    if api_call:
        query = query \
            .options(selectinload(Service.ip_networks))
        service = query.filter(Service.id == service_id).one()
        res = jsonify(service).json
        del res["logo"]
        return res, 200

    return query.filter(Service.id == service_id).one(), 200
コード例 #3
0
def attribute_aggregation():
    confirm_read_access()

    edu_person_principal_name = query_param("edu_person_principal_name")
    email = query_param("email", required=False)

    users = User.query \
        .join(User.collaboration_memberships) \
        .join(CollaborationMembership.collaboration) \
        .options(selectinload(User.collaboration_memberships)
                 .selectinload(CollaborationMembership.collaboration)) \
        .filter(or_(User.uid == edu_person_principal_name,
                    User.email == email)) \
        .all()

    # preference over edu_person_principal_name
    if len(users) == 0:
        return None, 404

    users_eppn_match = list(filter(lambda u: u.uid == edu_person_principal_name, users))
    user = users[0] if len(users) == 1 else users_eppn_match[0] if len(users_eppn_match) == 1 else users[0]

    return [cm.collaboration.name for cm in user.collaboration_memberships], 200
コード例 #4
0
ファイル: plsc.py プロジェクト: SURFscz/SBS
def sync():
    confirm_read_access()
    result = {"organisations": [], "users": []}

    rs = db.engine.execute("SELECT name, organisation_id FROM schac_home_organisations")
    schac_home_organisations = [{"name": row[0], "organisation_id": row[1]} for row in rs]

    rs = db.engine.execute("SELECT id, name, entity_id, contact_email, uuid4, ldap_password, accepted_user_policy, "
                           "support_email, security_email FROM services")
    services = [{"id": row[0], "name": row[1], "entity_id": row[2], "contact_email": row[3],
                 "logo": logo_url("services", row[4]), "ldap_password": row[5],
                 "accepted_user_policy": row[6], "support_email": row[7], "security_email": row[6]} for row in rs]
    for service in services:
        if not service["contact_email"]:
            rs = db.engine.execute(f"select u.email from users u where id in "
                                   f"(select user_id from service_memberships where service_id = {service['id']}) limit 1")
            for row in rs:
                service["contact_email"] = row[0]

    rs = db.engine.execute("SELECT service_id, organisation_id FROM services_organisations")
    services_organisations = [{"service_id": row[0], "organisation_id": row[1]} for row in rs]

    rs = db.engine.execute("SELECT service_id, collaboration_id FROM services_collaborations")
    services_collaborations = [{"service_id": row[0], "collaboration_id": row[1]} for row in rs]

    rs = db.engine.execute("SELECT role, user_id, organisation_id FROM organisation_memberships")
    organisation_memberships = [{"role": row[0], "user_id": row[1], "organisation_id": row[2]} for row in rs]

    rs = db.engine.execute("SELECT id, role, user_id, collaboration_id, status FROM collaboration_memberships")
    collaboration_memberships = [
        {"id": row[0], "role": row[1], "user_id": row[2], "collaboration_id": row[3], "status": row[4]} for row
        in rs]

    rs = db.engine.execute("SELECT collaboration_membership_id, group_id FROM collaboration_memberships_groups")
    collaboration_memberships_groups = [{"collaboration_membership_id": row[0], "group_id": row[1]} for row in rs]

    rs = db.engine.execute("SELECT id, identifier, name, short_name, global_urn, organisation_id, status, description, "
                           "uuid4, website_url from collaborations")
    collaborations = [
        {"id": row[0], "identifier": row[1], "name": row[2], "short_name": row[3], "global_urn": row[4],
         'organisation_id': row[5], "status": row[6], "description": row[7],
         "logo": logo_url("collaborations", row[8]), "website_url": row[9]} for row in rs]

    rs = db.engine.execute(
        "SELECT id, name, short_name, global_urn, identifier, collaboration_id, description FROM `groups`")
    groups = [
        {"id": row[0], "name": row[1], "short_name": row[2], "global_urn": row[3], "identifier": row[4],
         "collaboration_id": row[5], "description": row[6]}
        for row in rs]

    for coll in collaborations:
        collaboration_id = coll["id"]
        coll["groups"] = _find_by_id(groups, "collaboration_id", collaboration_id)
        for group in coll["groups"]:
            group["collaboration_memberships"] = _find_by_id(collaboration_memberships_groups, "group_id", group["id"])
            for collaboration_membership in group["collaboration_memberships"]:
                collaboration_membership["user_id"] = _find_user_id(collaboration_memberships,
                                                                    collaboration_membership[
                                                                        "collaboration_membership_id"])
        service_identifiers = _find_by_id(services_collaborations, "collaboration_id", collaboration_id)
        coll["services"] = _identifiers_only(
            _find_by_identifiers(services, "id", [si["service_id"] for si in service_identifiers]))
        coll["collaboration_memberships"] = _find_by_id(collaboration_memberships, "collaboration_id", collaboration_id)

    rs = db.engine.execute("SELECT id, name, identifier, short_name, uuid4 FROM organisations")
    for row in rs:
        organisation_id = row[0]
        service_identifiers = _find_by_id(services_organisations, "organisation_id", organisation_id)
        result["organisations"].append({
            "id": organisation_id, "name": row[1], "identifier": row[2], "short_name": row[3],
            "logo": logo_url("organisations", row[4]),
            "schac_home_organisations": _find_by_id(schac_home_organisations, "organisation_id", organisation_id),
            "organisation_memberships": _find_by_id(organisation_memberships, "organisation_id", organisation_id),
            "collaborations": _find_by_id(collaborations, "organisation_id", organisation_id),
            "services": _identifiers_only(
                _find_by_identifiers(services, "id", [si["service_id"] for si in service_identifiers]))
        })

    result["services"] = services

    rs = db.engine.execute("SELECT id, uid, name, given_name, family_name, email, scoped_affiliation, "
                           "eduperson_principal_name, username, last_login_date FROM users")
    for row in rs:
        user_row = {"id": row[0], "uid": row[1], "name": row[2], "given_name": row[3], "family_name": row[4],
                    "email": row[5], "scoped_affiliation": row[6], "eduperson_principal_name": row[7],
                    "username": row[8], "last_login_date": str(row[9])}
        rs_ssh_keys = db.engine.execute(f"SELECT ssh_value FROM ssh_keys WHERE user_id = {row[0]}")
        user_row["ssh_keys"] = [r[0] for r in rs_ssh_keys]
        user_ip_networks = db.engine.execute(f"SELECT network_value FROM user_ip_networks WHERE user_id = {row[0]}")
        user_row["user_ip_networks"] = [r[0] for r in user_ip_networks]
        service_aups = db.engine.execute(f"SELECT aup_url, service_id, agreed_at FROM service_aups "
                                         f"WHERE user_id = {row[0]}")
        user_row["accepted_aups"] = [{"url": r[0], "service_id": r[1], "agreed_at": str(r[2])} for r in service_aups]
        result["users"].append(user_row)

    return result, 200
コード例 #5
0
ファイル: user_saml.py プロジェクト: SURFscz/SBS
def _do_attributes(uid, service_entity_id, not_authorized_func, authorized_func, require_2fa=False, issuer_id=None):
    confirm_read_access()
    logger = ctx_logger("user_api")

    service = Service.query.filter(Service.entity_id == service_entity_id).first()
    if not service:
        msg = f"Returning unauthorized for user {uid} and service_entity_id {service_entity_id} " \
              f"as the service is unknown"
        logger.error(msg)
        send_error_mail(tb=msg, session_exists=False)
        return not_authorized_func(service_entity_id, SERVICE_UNKNOWN)
    no_free_ride = not service.non_member_users_access_allowed
    user = User.query.filter(User.uid == uid).first()
    if not user:
        logger.error(f"Returning unauthorized for user {uid} and service_entity_id {service_entity_id}"
                     f" as the user is unknown")
        return not_authorized_func(service.name, USER_UNKNOWN)
    if user.suspended and no_free_ride:
        logger.error(f"Returning unauthorized for user {uid} and service_entity_id {service_entity_id}"
                     f" as the user is suspended")
        return not_authorized_func(service.name, USER_IS_SUSPENDED)

    connected_collaborations = []
    memberships = []
    for cm in user.collaboration_memberships:
        connected = list(filter(lambda s: s.id == service.id, cm.collaboration.services))
        if connected or list(filter(lambda s: s.id == service.id, cm.collaboration.organisation.services)):
            connected_collaborations.append(cm.collaboration)
            memberships.append(cm)

    if not connected_collaborations and no_free_ride:
        logger.error(f"Returning unauthorized for user {uid} and service_entity_id {service_entity_id}"
                     f" as the service is not connected to any of the user collaborations")
        return not_authorized_func(service.name, SERVICE_NOT_CONNECTED)

    if all(coll.status != STATUS_ACTIVE for coll in connected_collaborations) and no_free_ride:
        logger.error(f"Returning unauthorized for user {uid} and service_entity_id {service_entity_id}"
                     f" as the service is not connected to any active collaborations")
        return not_authorized_func(service.name, COLLABORATION_NOT_ACTIVE)

    if all(m.is_expired() for m in memberships) and no_free_ride:
        logger.error(f"Returning unauthorized for user {uid} and service_entity_id {service_entity_id}"
                     f" as none of the collaboration memberships are active")
        return not_authorized_func(service.name, MEMBERSHIP_NOT_ACTIVE)

    # Leave the 2FAand AUP checks as the last checks as these are the only exceptions that can be recovered from
    if require_2fa:
        idp_allowed = mfa_idp_allowed(user, user.schac_home_organisation, issuer_id)
        if not idp_allowed:
            logger.debug(f"Returning interrupt for user {uid} from issuer {issuer_id} to perform 2fa")
            return not_authorized_func(user, SECOND_FA_REQUIRED)

    if not has_agreed_with(user, service):
        logger.debug(f"Returning interrupt for user {uid} and service_entity_id {service_entity_id} to accept AUP")
        return not_authorized_func(service, AUP_NOT_AGREED)

    now = datetime.now()
    for coll in connected_collaborations:
        coll.last_activity_date = now
        db.session.merge(coll)

    user.last_accessed_date = now
    user.last_login_date = now
    user.suspend_notifications = []
    user = db.session.merge(user)
    db.session.commit()

    all_memberships = user_memberships(user, connected_collaborations)
    all_attributes, http_status = authorized_func(user, all_memberships)

    logger.info(f"Returning attributes {all_attributes} for user {uid} and service_entity_id {service_entity_id}")

    return all_attributes, http_status