예제 #1
0
def organisation_by_schac_home():
    user = User.query.filter(User.id == current_user_id()).one()
    schac_home_organisation = user.schac_home_organisation
    if not schac_home_organisation:
        return None, 200
    # Because of subdomains we need the schac_home of which the users schac_home is a strict subdomain
    schac_homes = SchacHomeOrganisation.query.all()
    hits = list(filter(
        lambda schac_home: schac_home_organisation == schac_home.name or schac_home_organisation.endswith(
            f".{schac_home.name}"), schac_homes))
    if not hits:
        return None, 200

    org = Organisation.query.get(hits[0].organisation_id)

    entitlement = current_app.app_config.collaboration_creation_allowed_entitlement
    auto_aff = bool(user.entitlement) and entitlement in user.entitlement

    return {"id": org.id,
            "name": org.name,
            "logo": org.logo,
            "collaboration_creation_allowed": org.collaboration_creation_allowed,
            "collaboration_creation_allowed_entitlement": auto_aff,
            "required_entitlement": entitlement,
            "user_entitlement": user.entitlement,
            "has_members": len(org.organisation_memberships) > 0,
            "on_boarding_msg": org.on_boarding_msg,
            "short_name": org.short_name}, 200
예제 #2
0
파일: join_request.py 프로젝트: SURFscz/SBS
def _is_already_member(client_data):
    collaboration_id = client_data["collaborationId"]
    collaboration = Collaboration.query \
        .filter(Collaboration.id == collaboration_id).one()
    user_id = current_user_id()
    is_member = collaboration.is_member(user_id)
    return is_member
예제 #3
0
파일: service.py 프로젝트: SURFscz/SBS
def save_service():
    data = current_request.get_json()
    validate_ip_networks(data)
    _token_validity_days(data)

    data["status"] = STATUS_ACTIVE
    cleanse_short_name(data, "abbreviation")

    # Before the JSON is cleaned in the save method
    administrators = data.get("administrators", [])
    message = data.get("message", None)

    res = save(Service, custom_json=data, allow_child_cascades=False, allowed_child_collections=["ip_networks"])
    service = res[0]

    user = User.query.get(current_user_id())
    for administrator in administrators:
        invitation = ServiceInvitation(hash=generate_token(), message=message, invitee_email=administrator,
                                       service_id=service.id, user=user, intended_role="admin",
                                       expiry_date=default_expiry_date(),
                                       created_by=user.uid)
        invitation = db.session.merge(invitation)
        mail_service_invitation({
            "salutation": "Dear",
            "invitation": invitation,
            "base_url": current_app.app_config.base_url,
            "wiki_link": current_app.app_config.wiki_link,
            "recipient": administrator
        }, service, [administrator])

    mail_platform_admins(service)
    service.ip_networks
    return res
예제 #4
0
파일: service.py 프로젝트: SURFscz/SBS
def service_invites():
    data = current_request.get_json()
    service_id = data["service_id"]
    confirm_service_admin(service_id)

    administrators = data.get("administrators", [])
    message = data.get("message", None)
    intended_role = "admin"

    service = Service.query.get(service_id)
    user = User.query.get(current_user_id())

    for administrator in administrators:
        invitation = ServiceInvitation(hash=generate_token(), message=message, invitee_email=administrator,
                                       service=service, user=user, created_by=user.uid,
                                       intended_role=intended_role, expiry_date=default_expiry_date(json_dict=data))
        invitation = db.session.merge(invitation)
        mail_service_invitation({
            "salutation": "Dear",
            "invitation": invitation,
            "base_url": current_app.app_config.base_url,
            "wiki_link": current_app.app_config.wiki_link,
            "recipient": administrator
        }, service, [administrator])
    return None, 201
예제 #5
0
def save_organisation():
    confirm_write_access()
    data = current_request.get_json()

    _clear_api_keys(data)
    cleanse_short_name(data)
    data["identifier"] = str(uuid.uuid4())

    administrators = data.get("administrators", [])
    intended_role = data.get("intended_role", "admin")
    message = data.get("message", None)

    res = save(Organisation, custom_json=data)
    user = User.query.get(current_user_id())
    organisation = res[0]
    for administrator in administrators:
        invitation = OrganisationInvitation(hash=generate_token(), message=message, invitee_email=administrator,
                                            organisation_id=organisation.id, user_id=user.id,
                                            intended_role=intended_role,
                                            expiry_date=default_expiry_date(),
                                            created_by=user.uid)
        invitation = db.session.merge(invitation)
        mail_organisation_invitation({
            "salutation": "Dear",
            "invitation": invitation,
            "base_url": current_app.app_config.base_url,
            "recipient": administrator
        }, organisation, [administrator])

    mail_platform_admins(organisation)

    return res
예제 #6
0
def organisation_invites():
    data = current_request.get_json()
    organisation_id = data["organisation_id"]

    confirm_organisation_admin(organisation_id)

    administrators = data.get("administrators", [])
    intended_role = data.get("intended_role")
    intended_role = "manager" if intended_role not in ["admin", "manager"] else intended_role

    message = data.get("message", None)

    organisation = Organisation.query.get(organisation_id)
    user = User.query.get(current_user_id())

    for administrator in administrators:
        invitation = OrganisationInvitation(hash=generate_token(), intended_role=intended_role,
                                            message=message, invitee_email=administrator,
                                            organisation=organisation, user=user,
                                            expiry_date=default_expiry_date(json_dict=data),
                                            created_by=user.uid)
        invitation = db.session.merge(invitation)
        mail_organisation_invitation({
            "salutation": "Dear",
            "invitation": invitation,
            "base_url": current_app.app_config.base_url,
            "recipient": administrator
        }, organisation, [administrator])
    return None, 201
예제 #7
0
def collaboration_invites_preview():
    data = current_request.get_json()
    message = data.get("message", None)
    intended_role = data.get("intended_role", "member")

    collaboration = Collaboration.query.get(int(data["collaboration_id"]))
    confirm_collaboration_admin(collaboration.id)

    user = User.query.get(current_user_id())
    invitation = munchify({
        "user": user,
        "collaboration": collaboration,
        "intended_role": intended_role,
        "message": message,
        "hash": generate_token(),
        "expiry_date": default_expiry_date(data)
    })
    html = mail_collaboration_invitation({
        "salutation": "Dear",
        "invitation": invitation,
        "base_url": current_app.app_config.base_url,
        "wiki_link": current_app.app_config.wiki_link,

    }, collaboration, [], preview=True)
    return {"html": html}, 201
예제 #8
0
def my_organisations():
    user_id = current_user_id()
    organisations = Organisation.query \
        .join(Organisation.organisation_memberships) \
        .filter(OrganisationMembership.user_id == user_id) \
        .all()
    return organisations, 200
예제 #9
0
def organisation_by_id(organisation_id):
    query = Organisation.query \
        .options(selectinload(Organisation.organisation_memberships)
                 .selectinload(OrganisationMembership.user)) \
        .options(selectinload(Organisation.organisation_invitations)
                 .selectinload(OrganisationInvitation.user)) \
        .options(selectinload(Organisation.api_keys)) \
        .options(selectinload(Organisation.services)) \
        .options(selectinload(Organisation.collaboration_requests)
                 .selectinload(CollaborationRequest.requester)) \
        .options(selectinload(Organisation.collaborations)) \
        .filter(Organisation.id == organisation_id)

    if not request_context.is_authorized_api_call:
        is_admin = is_application_admin()

        if not is_admin:
            user_id = current_user_id()
            query = query \
                .join(Organisation.organisation_memberships) \
                .join(OrganisationMembership.user) \
                .filter(OrganisationMembership.role.in_(["admin", "manager"])) \
                .filter(OrganisationMembership.user_id == user_id)

    organisation = query.one()
    return organisation, 200
예제 #10
0
def may_request_collaboration():
    user = User.query.get(current_user_id())
    sho = user.schac_home_organisation
    if not sho:
        return False, 200
    return Organisation.query \
               .join(Organisation.schac_home_organisations) \
               .filter(SchacHomeOrganisation.name == sho).count() > 0, 200
예제 #11
0
def agreed_aup():
    user_id = current_user_id()
    version = str(current_app.app_config.aup.version)
    if Aup.query.filter(Aup.user_id == user_id, Aup.au_version == version).count() == 0:
        aup = Aup(au_version=version, user_id=user_id)
        save(Aup, custom_json=jsonify(aup).json, allow_child_cascades=False)
    session["user"] = {**session["user"], **{"user_accepted_aup": True}}
    location = session.get("original_destination", current_app.app_config.base_url)
    return {"location": location}, 201
예제 #12
0
def me():
    headers = current_request.headers
    user_id = current_user_id()

    impersonate_id = headers.get("X-IMPERSONATE-ID", default=None, type=int)
    if impersonate_id:
        confirm_allow_impersonation(confirm_feature_impersonation_allowed=False)

    return _user_activity(user_id)
예제 #13
0
def resend_service_connection_request(service_connection_request_id):
    service_connection_request = ServiceConnectionRequest.query.get(service_connection_request_id)
    service = service_connection_request.service
    collaboration = service_connection_request.collaboration

    confirm_collaboration_admin(collaboration.id)
    user = User.query.get(current_user_id())
    _do_mail_request(collaboration, service, service_connection_request, True, user)
    return {}, 200
예제 #14
0
 def override_func():
     user_id = current_user_id()
     organisation_id = current_request.get_json()["id"]
     count = OrganisationMembership.query \
         .filter(OrganisationMembership.user_id == user_id) \
         .filter(OrganisationMembership.organisation_id == organisation_id) \
         .filter(OrganisationMembership.role == "admin") \
         .count()
     return count > 0
예제 #15
0
def identity_provider_display_name():
    user = User.query.filter(User.id == current_user_id()).one()
    schac_home_organisation = user.schac_home_organisation
    if not schac_home_organisation:
        return None, 200

    lang = query_param("lang", required=False, default="en")
    idp_name = idp_display_name(schac_home_organisation, lang)
    return {"display_name": idp_name}, 200
예제 #16
0
def my_organisations_lite():
    user_id = current_user_id()
    query = Organisation.query
    if not is_application_admin():
        query = query \
            .join(Organisation.organisation_memberships) \
            .filter(OrganisationMembership.user_id == user_id) \
            .filter(OrganisationMembership.role.in_(["admin", "manager"]))
    organisations = query.all()
    return organisations, 200
예제 #17
0
파일: mfa.py 프로젝트: SURFscz/SBS
def reset2fa():
    user = User.query.filter(User.id == current_user_id()).one()
    data = current_request.get_json()
    token = data["token"]
    if not token or token != user.mfa_reset_token:
        raise Forbidden()
    user.second_factor_auth = None
    user.mfa_reset_token = None
    db.session.merge(user)
    db.session.commit()
    return {}, 201
예제 #18
0
def delete_organisation_membership(organisation_id, user_id):
    if current_user_id() != int(user_id):
        confirm_organisation_admin(organisation_id)

    memberships = OrganisationMembership.query \
        .filter(OrganisationMembership.organisation_id == organisation_id) \
        .filter(OrganisationMembership.user_id == user_id) \
        .all()
    for membership in memberships:
        db.session.delete(membership)
    return (None, 204) if len(memberships) > 0 else (None, 404)
예제 #19
0
파일: system.py 프로젝트: SURFscz/SBS
def feedback():
    cfg = current_app.app_config
    if not cfg.feature.feedback_enabled:
        raise BadRequest("feedback is not enabled")

    data = current_request.get_json()
    message = data["message"]
    mail_conf = cfg.mail
    user = User.query.get(current_user_id())
    mail_feedback(mail_conf.environment, message, user, [mail_conf.info_email])
    return {}, 201
예제 #20
0
파일: mfa.py 프로젝트: SURFscz/SBS
def get2fa():
    user = User.query.filter(User.id == current_user_id()).one()
    secret = pyotp.random_base32()
    session["second_factor_auth"] = secret
    name = current_app.app_config.oidc.totp_token_name
    secret_url = pyotp.totp.TOTP(secret).provisioning_uri(user.email, name)
    img = qrcode.make(secret_url)
    buffered = BytesIO()
    img.save(buffered, format="PNG")
    img_str = base64.b64encode(buffered.getvalue()).decode()
    idp_name = idp_display_name(user.schac_home_organisation, "en")
    return {"qr_code_base64": img_str, "secret": secret, "idp_name": idp_name}, 200
예제 #21
0
파일: mfa.py 프로젝트: SURFscz/SBS
def token_reset_request_post():
    data = current_request.get_json()
    email = data["email"]
    user = User.query.filter(User.id == current_user_id()).one()
    admins = eligible_users_to_reset_token(user)
    if len(list(filter(lambda admin: admin["email"] == email, admins))) == 0:
        raise Forbidden()
    user.mfa_reset_token = generate_token()
    db.session.merge(user)
    db.session.commit()
    mail_reset_token(email, user, data["message"])
    return {}, 201
예제 #22
0
def invitations_accept():
    invitation = _invitation_query() \
        .filter(Invitation.hash == current_request.get_json()["hash"]) \
        .one()
    if invitation.status != "open":
        raise Conflict(f"The invitation has status {invitation.status}")

    if invitation.expiry_date and invitation.expiry_date < datetime.datetime.now():
        if invitation.external_identifier:
            invitation.status = "expired"
            db.session.merge(invitation)
            db.session.commit()
        else:
            delete(Invitation, invitation.id)
        raise Conflict(f"The invitation has expired at {invitation.expiry_date}")

    collaboration = invitation.collaboration
    user_id = current_user_id()
    if collaboration.is_member(user_id):
        delete(Invitation, invitation.id)
        raise Conflict(f"User {user_id} is already a member of {collaboration.name}")

    role = invitation.intended_role if invitation.intended_role else "member"
    collaboration_membership = CollaborationMembership(user_id=user_id,
                                                       collaboration_id=collaboration.id,
                                                       role=role,
                                                       expiry_date=invitation.membership_expiry_date,
                                                       created_by=invitation.user.uid,
                                                       updated_by=invitation.user.uid)
    if invitation.external_identifier:
        collaboration_membership.invitation_id = invitation.id

    collaboration_membership = db.session.merge(collaboration_membership)
    # We need the persistent identifier of the collaboration_membership which will be generated after the delete-commit
    if invitation.external_identifier:
        invitation.status = "accepted"
        db.session.merge(invitation)
        db.session.commit()
    else:
        delete(Invitation, invitation.id)

    # ensure all authorisation group membership are added
    groups = invitation.groups + list(filter(lambda ag: ag.auto_provision_members, collaboration.groups))

    for group in set(list({ag.id: ag for ag in groups}.values())):
        group.collaboration_memberships.append(collaboration_membership)
        db.session.merge(group)

    add_user_aups(collaboration, user_id)

    res = {'collaboration_id': collaboration.id, 'user_id': user_id}
    return res, 201
예제 #23
0
def save_collaboration():
    data = current_request.get_json()
    if "organisation_id" in data:
        confirm_organisation_admin_or_manager(data["organisation_id"])
        organisation = Organisation.query.get(data["organisation_id"])
        user = User.query.get(current_user_id())
    else:
        raise BadRequest("No organisation_id in POST data")
    current_user_admin = data.get("current_user_admin", False)
    if "current_user_admin" in data:
        del data["current_user_admin"]
    res = do_save_collaboration(data, organisation, user, current_user_admin)
    return res
예제 #24
0
def request_service_connection():
    data = current_request.get_json()
    service = Service.query.get(int(data["service_id"]))
    collaboration = Collaboration.query.get(int(data["collaboration_id"]))

    confirm_collaboration_member(collaboration.id)

    user = User.query.get(current_user_id())
    is_admin = collaboration.is_admin(user.id)

    request_new_service_connection(collaboration, data.get("message"), is_admin, service, user)

    return {}, 201
예제 #25
0
파일: mfa.py 프로젝트: SURFscz/SBS
def verify2fa():
    user = User.query.filter(User.id == current_user_id()).one()
    secret = user.second_factor_auth if user.second_factor_auth else session["second_factor_auth"]
    valid_totp = _do_verify_2fa(user, secret)
    if valid_totp:
        location = session.get("original_destination", current_app.app_config.base_url)
        in_proxy_flow = session.get("in_proxy_flow", False)
        if in_proxy_flow:
            oidc_config = current_app.app_config.oidc
            id_token = _construct_jwt(user, str(uuid4()), oidc_config)
            location = f"{oidc_config.sfo_eduteams_redirect_uri}?id_token={id_token}"
        return {"location": location, "in_proxy_flow": in_proxy_flow}, 201
    else:
        return {"new_totp": False}, 400
예제 #26
0
def my_collaborations_lite():
    include_services = query_param("includeServices", False)
    user_id = current_user_id()
    query = Collaboration.query \
        .join(Collaboration.collaboration_memberships) \
        .options(selectinload(Collaboration.organisation))
    if include_services:
        query = query \
            .options(selectinload(Collaboration.services).selectinload(Service.allowed_organisations))

    collaborations = query \
        .filter(CollaborationMembership.user_id == user_id) \
        .all()
    return collaborations, 200
예제 #27
0
def create_collaboration_membership_role():
    client_data = current_request.get_json()
    collaboration_id = client_data["collaborationId"]
    collaboration = Collaboration.query.get(collaboration_id)

    confirm_organisation_admin_or_manager(collaboration.organisation_id)

    user_id = current_user_id()
    collaboration_membership = CollaborationMembership(user_id=user_id,
                                                       collaboration_id=collaboration.id,
                                                       role="admin",
                                                       created_by=current_user_uid(),
                                                       updated_by=current_user_uid())

    collaboration_membership = db.session.merge(collaboration_membership)
    return collaboration_membership, 201
예제 #28
0
def _sanitize_and_verify(hash_token=True):
    data = current_request.get_json()
    if data["user_id"] != current_user_id():
        raise Forbidden("Can not create user_token for someone else")
    if hash_token:
        data = hash_secret_key(data, "hashed_token")

    service_id = data["service_id"]
    service = Service.query.get(service_id)

    if not user_service(service_id):
        raise Forbidden(f"User has no access to  {service.name}")
    if not service.token_enabled:
        raise Forbidden(f"Can not create user_token for service {service.name}")

    return data
예제 #29
0
파일: mfa.py 프로젝트: SURFscz/SBS
def update2fa():
    user = User.query.filter(User.id == current_user_id()).one()
    current_secret = user.second_factor_auth
    new_secret = session["second_factor_auth"]
    data = current_request.get_json()
    current_totp_value = data["current_totp"]
    new_totp_value = data["new_totp_value"]
    verified_current = pyotp.TOTP(current_secret).verify(current_totp_value)
    verified_new = pyotp.TOTP(new_secret).verify(new_totp_value)
    if not verified_current or not verified_new:
        return {"current_totp": not verified_current, "new_totp": not verified_new}, 400

    user.second_factor_auth = new_secret
    db.session.merge(user)
    db.session.commit()
    return {}, 201
예제 #30
0
def delete_user():
    user_id = current_user_id()
    user = User.query.get(user_id)
    mail_account_deletion(user)
    db.session.delete(user)

    if user.username:
        history_not_exists = UserNameHistory.query.filter(UserNameHistory.username == user.username).count() == 0
        if history_not_exists:
            user_name_history = UserNameHistory(username=user.username)
            db.session.merge(user_name_history)
    db.session.commit()

    session["user"] = None
    session.clear()
    return user, 204